mirror of
https://github.com/denoland/deno.git
synced 2025-03-04 01:44:26 -05:00
Merge branch 'master' into v1.1
This commit is contained in:
commit
f73a47d21c
62 changed files with 992 additions and 283 deletions
|
@ -2,6 +2,7 @@ cli/compilers/wasm_wrap.js
|
|||
cli/tests/error_syntax.js
|
||||
cli/tests/badly_formatted.js
|
||||
cli/tests/top_level_for_await.js
|
||||
cli/tests/swc_syntax_error.ts
|
||||
std/**/testdata
|
||||
std/**/vendor
|
||||
std/node_modules
|
||||
|
|
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -460,7 +460,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"base64 0.12.0",
|
||||
|
@ -514,7 +514,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_core"
|
||||
version = "0.45.1"
|
||||
version = "0.45.2"
|
||||
dependencies = [
|
||||
"derive_deref",
|
||||
"downcast-rs",
|
||||
|
@ -530,7 +530,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_typescript"
|
||||
version = "0.45.1"
|
||||
version = "0.45.2"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"serde",
|
||||
|
@ -625,9 +625,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "dprint-plugin-typescript"
|
||||
version = "0.18.4"
|
||||
version = "0.18.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9789e9282a2fef314dd58df1e203de44035b0f032923b52f751c7917f7adff3"
|
||||
checksum = "8f4b628385a13a592afdd6391167921f62f1c1adc1f7b098ecf7e930ab5cc702"
|
||||
dependencies = [
|
||||
"dprint-core",
|
||||
"serde",
|
||||
|
|
20
Releases.md
20
Releases.md
|
@ -6,6 +6,24 @@ https://github.com/denoland/deno/releases
|
|||
We also have one-line install commands at
|
||||
https://github.com/denoland/deno_install
|
||||
|
||||
### 1.0.2 / 2020.05.22
|
||||
|
||||
Changes in the CLI:
|
||||
|
||||
- fix: --inspect flag working like --inspect-brk (#5697)
|
||||
- fix: Disallow http imports for modules loaded over https (#5680)
|
||||
- fix: Redirects handling in module analysis (#5726)
|
||||
- fix: SWC lexer settings and silent errors (#5752)
|
||||
- fix: TS type imports (#5733)
|
||||
- fix(fmt): Do not panic on new expr with no parens. (#5734)
|
||||
- fix(cli/js/streams): High water mark validation (#5681)
|
||||
|
||||
Changes in std version 0.53.0:
|
||||
|
||||
- fix(std/http): file_server's target directory (#5695)
|
||||
- feat(std/hash): add md5 (#5719)
|
||||
- refactor: Move std/fmt/sprintf.ts to std/fmt/printf.ts (#4567)
|
||||
|
||||
### 1.0.1 / 2020.05.20
|
||||
|
||||
Changes in the CLI:
|
||||
|
@ -1562,7 +1580,7 @@ Changes since v0.1.7:
|
|||
- Use constructor.name to print out function type #664
|
||||
- Rename deno.argv to deno.args
|
||||
- Add deno.trace() #795
|
||||
- Continuous benchmarks https://denoland.github.io/deno/
|
||||
- Continuous benchmarks
|
||||
|
||||
### v0.1.5 / 2018.09.21
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
license = "MIT"
|
||||
authors = ["the Deno authors"]
|
||||
edition = "2018"
|
||||
|
@ -30,7 +30,7 @@ clap = "2.33.0"
|
|||
dirs = "2.0.2"
|
||||
dissimilar = "1.0"
|
||||
dlopen = "0.1.8"
|
||||
dprint-plugin-typescript = "0.18.4"
|
||||
dprint-plugin-typescript = "0.18.5"
|
||||
futures = { version = "0.3.4", features = ["compat", "io-compat"] }
|
||||
glob = "0.3.0"
|
||||
http = "0.2.1"
|
||||
|
|
|
@ -1041,7 +1041,7 @@ report results to standard output:
|
|||
deno test src/fetch_test.ts src/signal_test.ts
|
||||
|
||||
Directory arguments are expanded to all contained files matching the glob
|
||||
{*_,}test.{js,ts,jsx,tsx}:
|
||||
{*_,*.,}test.{js,ts,jsx,tsx}:
|
||||
deno test src/",
|
||||
)
|
||||
}
|
||||
|
|
|
@ -585,7 +585,6 @@ function buildSourceFileCache(
|
|||
sourceFileMap: Record<string, SourceFileMapEntry>
|
||||
): void {
|
||||
for (const entry of Object.values(sourceFileMap)) {
|
||||
assert(entry.sourceCode.length > 0);
|
||||
SourceFile.addToCache({
|
||||
url: entry.url,
|
||||
filename: entry.url,
|
||||
|
@ -596,7 +595,15 @@ function buildSourceFileCache(
|
|||
for (const importDesc of entry.imports) {
|
||||
let mappedUrl = importDesc.resolvedSpecifier;
|
||||
const importedFile = sourceFileMap[importDesc.resolvedSpecifier];
|
||||
// IMPORTANT: due to HTTP redirects we might end up in situation
|
||||
// where URL points to a file with completely different URL.
|
||||
// In that case we take value of `redirect` field and cache
|
||||
// resolved specifier pointing to the value of the redirect.
|
||||
// It's not very elegant solution and should be rethinked.
|
||||
assert(importedFile);
|
||||
if (importedFile.redirect) {
|
||||
mappedUrl = importedFile.redirect;
|
||||
}
|
||||
const isJsOrJsx =
|
||||
importedFile.mediaType === MediaType.JavaScript ||
|
||||
importedFile.mediaType === MediaType.JSX;
|
||||
|
@ -1032,6 +1039,7 @@ interface SourceFileMapEntry {
|
|||
url: string;
|
||||
sourceCode: string;
|
||||
mediaType: MediaType;
|
||||
redirect?: string;
|
||||
imports: ImportDescriptor[];
|
||||
referencedFiles: ReferenceDescriptor[];
|
||||
libDirectives: ReferenceDescriptor[];
|
||||
|
|
24
cli/js/lib.deno.ns.d.ts
vendored
24
cli/js/lib.deno.ns.d.ts
vendored
|
@ -456,6 +456,11 @@ declare namespace Deno {
|
|||
* It is possible for a read to successfully return with `0` bytes. This does
|
||||
* not indicate EOF.
|
||||
*
|
||||
* This function is one of the lowest level APIs and most users should not
|
||||
* work with this directly, but rather use Deno.readAllSync() instead.
|
||||
*
|
||||
* **It is not guaranteed that the full buffer will be read in a single call.**
|
||||
*
|
||||
* ```ts
|
||||
* // if "/foo/bar.txt" contains the text "hello world":
|
||||
* const file = Deno.openSync("/foo/bar.txt");
|
||||
|
@ -475,6 +480,11 @@ declare namespace Deno {
|
|||
* It is possible for a read to successfully return with `0` bytes. This does
|
||||
* not indicate EOF.
|
||||
*
|
||||
* This function is one of the lowest level APIs and most users should not
|
||||
* work with this directly, but rather use Deno.readAll() instead.
|
||||
*
|
||||
* **It is not guaranteed that the full buffer will be read in a single call.**
|
||||
*
|
||||
* ```ts
|
||||
* // if "/foo/bar.txt" contains the text "hello world":
|
||||
* const file = await Deno.open("/foo/bar.txt");
|
||||
|
@ -489,7 +499,12 @@ declare namespace Deno {
|
|||
/** Synchronously write to the resource ID (`rid`) the contents of the array
|
||||
* buffer (`data`).
|
||||
*
|
||||
* Returns the number of bytes written.
|
||||
* Returns the number of bytes written. This function is one of the lowest
|
||||
* level APIs and most users should not work with this directly, but rather use
|
||||
* Deno.writeAllSync() instead.
|
||||
*
|
||||
* **It is not guaranteed that the full buffer will be written in a single
|
||||
* call.**
|
||||
*
|
||||
* ```ts
|
||||
* const encoder = new TextEncoder();
|
||||
|
@ -503,7 +518,12 @@ declare namespace Deno {
|
|||
|
||||
/** Write to the resource ID (`rid`) the contents of the array buffer (`data`).
|
||||
*
|
||||
* Resolves to the number of bytes written.
|
||||
* Resolves to the number of bytes written. This function is one of the lowest
|
||||
* level APIs and most users should not work with this directly, but rather use
|
||||
* Deno.writeAll() instead.
|
||||
*
|
||||
* **It is not guaranteed that the full buffer will be written in a single
|
||||
* call.**
|
||||
*
|
||||
* ```ts
|
||||
* const encoder = new TextEncoder();
|
||||
|
|
2
cli/js/lib.deno.unstable.d.ts
vendored
2
cli/js/lib.deno.unstable.d.ts
vendored
|
@ -1207,7 +1207,7 @@ declare namespace Deno {
|
|||
* ```ts
|
||||
* const status = await Deno.permissions.request({ name: "env" });
|
||||
* if (status.state === "granted") {
|
||||
* console.log(Deno.homeDir());
|
||||
* console.log(Deno.dir("home");
|
||||
* } else {
|
||||
* console.log("'env' permission is denied.");
|
||||
* }
|
||||
|
|
|
@ -140,7 +140,7 @@ function createReadableStream<T>(
|
|||
highWaterMark = 1,
|
||||
sizeAlgorithm: SizeAlgorithm<T> = (): number => 1
|
||||
): ReadableStreamImpl<T> {
|
||||
assert(isNonNegativeNumber(highWaterMark));
|
||||
highWaterMark = validateAndNormalizeHighWaterMark(highWaterMark);
|
||||
const stream: ReadableStreamImpl<T> = Object.create(
|
||||
ReadableStreamImpl.prototype
|
||||
);
|
||||
|
@ -168,7 +168,7 @@ function createWritableStream<W>(
|
|||
highWaterMark = 1,
|
||||
sizeAlgorithm: SizeAlgorithm<W> = (): number => 1
|
||||
): WritableStreamImpl<W> {
|
||||
assert(isNonNegativeNumber(highWaterMark));
|
||||
highWaterMark = validateAndNormalizeHighWaterMark(highWaterMark);
|
||||
const stream = Object.create(WritableStreamImpl.prototype);
|
||||
initializeWritableStream(stream);
|
||||
const controller = Object.create(
|
||||
|
@ -311,26 +311,7 @@ export function isDetachedBuffer(value: object): boolean {
|
|||
}
|
||||
|
||||
function isFiniteNonNegativeNumber(v: unknown): v is number {
|
||||
if (!isNonNegativeNumber(v)) {
|
||||
return false;
|
||||
}
|
||||
if (v === Infinity) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isNonNegativeNumber(v: unknown): v is number {
|
||||
if (typeof v !== "number") {
|
||||
return false;
|
||||
}
|
||||
if (v === NaN) {
|
||||
return false;
|
||||
}
|
||||
if (v < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return Number.isFinite(v) && (v as number) >= 0;
|
||||
}
|
||||
|
||||
export function isReadableByteStreamController(
|
||||
|
@ -1872,7 +1853,7 @@ export function validateAndNormalizeHighWaterMark(
|
|||
highWaterMark: number
|
||||
): number {
|
||||
highWaterMark = Number(highWaterMark);
|
||||
if (highWaterMark === NaN || highWaterMark < 0) {
|
||||
if (Number.isNaN(highWaterMark) || highWaterMark < 0) {
|
||||
throw new RangeError(
|
||||
`highWaterMark must be a positive number or Infinity. Received: ${highWaterMark}.`
|
||||
);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import { DOMExceptionImpl as DOMException } from "./dom_exception.ts";
|
||||
import * as base64 from "./base64.ts";
|
||||
import { decodeUtf8 } from "./decode_utf8.ts";
|
||||
import { core } from "../core.ts";
|
||||
|
@ -101,8 +102,10 @@ export function atob(s: string): string {
|
|||
|
||||
const rem = s.length % 4;
|
||||
if (rem === 1 || /[^+/0-9A-Za-z]/.test(s)) {
|
||||
// TODO: throw `DOMException`
|
||||
throw new TypeError("The string to be decoded is not correctly encoded");
|
||||
throw new DOMException(
|
||||
"The string to be decoded is not correctly encoded",
|
||||
"DataDecodeError"
|
||||
);
|
||||
}
|
||||
|
||||
// base64-js requires length exactly times of 4
|
||||
|
|
|
@ -19,6 +19,7 @@ use futures::FutureExt;
|
|||
use serde::Serialize;
|
||||
use serde::Serializer;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::hash::BuildHasher;
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
|
@ -76,6 +77,7 @@ pub struct ReferenceDescriptor {
|
|||
pub struct ModuleGraphFile {
|
||||
pub specifier: String,
|
||||
pub url: String,
|
||||
pub redirect: Option<String>,
|
||||
pub filename: String,
|
||||
pub imports: Vec<ImportDescriptor>,
|
||||
pub referenced_files: Vec<ReferenceDescriptor>,
|
||||
|
@ -87,13 +89,14 @@ pub struct ModuleGraphFile {
|
|||
}
|
||||
|
||||
type SourceFileFuture =
|
||||
Pin<Box<dyn Future<Output = Result<SourceFile, ErrBox>>>>;
|
||||
Pin<Box<dyn Future<Output = Result<(ModuleSpecifier, SourceFile), ErrBox>>>>;
|
||||
|
||||
pub struct ModuleGraphLoader {
|
||||
permissions: Permissions,
|
||||
file_fetcher: SourceFileFetcher,
|
||||
maybe_import_map: Option<ImportMap>,
|
||||
pending_downloads: FuturesUnordered<SourceFileFuture>,
|
||||
has_downloaded: HashSet<ModuleSpecifier>,
|
||||
pub graph: ModuleGraph,
|
||||
is_dyn_import: bool,
|
||||
analyze_dynamic_imports: bool,
|
||||
|
@ -112,6 +115,7 @@ impl ModuleGraphLoader {
|
|||
permissions,
|
||||
maybe_import_map,
|
||||
pending_downloads: FuturesUnordered::new(),
|
||||
has_downloaded: HashSet::new(),
|
||||
graph: ModuleGraph(HashMap::new()),
|
||||
is_dyn_import,
|
||||
analyze_dynamic_imports,
|
||||
|
@ -131,8 +135,9 @@ impl ModuleGraphLoader {
|
|||
self.download_module(specifier.clone(), None)?;
|
||||
|
||||
loop {
|
||||
let source_file = self.pending_downloads.next().await.unwrap()?;
|
||||
self.visit_module(&source_file.url.clone().into(), source_file)?;
|
||||
let (specifier, source_file) =
|
||||
self.pending_downloads.next().await.unwrap()?;
|
||||
self.visit_module(&specifier, source_file)?;
|
||||
if self.pending_downloads.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
@ -183,6 +188,7 @@ impl ModuleGraphLoader {
|
|||
};
|
||||
|
||||
let (import_descs, ref_descs) = analyze_dependencies_and_references(
|
||||
&specifier,
|
||||
&source_code,
|
||||
self.analyze_dynamic_imports,
|
||||
)?;
|
||||
|
@ -260,6 +266,7 @@ impl ModuleGraphLoader {
|
|||
ModuleGraphFile {
|
||||
specifier: specifier.to_string(),
|
||||
url: specifier.to_string(),
|
||||
redirect: None,
|
||||
media_type: map_file_extension(&PathBuf::from(specifier.clone()))
|
||||
as i32,
|
||||
filename: specifier,
|
||||
|
@ -274,15 +281,29 @@ impl ModuleGraphLoader {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// TODO(bartlomieju): decorate errors with import location in the source code
|
||||
// https://github.com/denoland/deno/issues/5080
|
||||
fn download_module(
|
||||
&mut self,
|
||||
module_specifier: ModuleSpecifier,
|
||||
maybe_referrer: Option<ModuleSpecifier>,
|
||||
) -> Result<(), ErrBox> {
|
||||
if self.graph.0.contains_key(&module_specifier.to_string()) {
|
||||
if self.has_downloaded.contains(&module_specifier) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Disallow http:// imports from modules loaded over https://
|
||||
if let Some(referrer) = maybe_referrer.as_ref() {
|
||||
if let "https" = referrer.as_url().scheme() {
|
||||
if let "http" = module_specifier.as_url().scheme() {
|
||||
let e = OpError::permission_denied(
|
||||
"Modules loaded over https:// are not allowed to import modules over http://".to_string()
|
||||
);
|
||||
return Err(e.into());
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if !self.is_dyn_import {
|
||||
// Verify that remote file doesn't try to statically import local file.
|
||||
if let Some(referrer) = maybe_referrer.as_ref() {
|
||||
|
@ -293,7 +314,9 @@ impl ModuleGraphLoader {
|
|||
match specifier_url.scheme() {
|
||||
"http" | "https" => {}
|
||||
_ => {
|
||||
let e = OpError::permission_denied("Remote module are not allowed to statically import local modules. Use dynamic import instead.".to_string());
|
||||
let e = OpError::permission_denied(
|
||||
"Remote modules are not allowed to statically import local modules. Use dynamic import instead.".to_string()
|
||||
);
|
||||
return Err(e.into());
|
||||
}
|
||||
}
|
||||
|
@ -303,6 +326,7 @@ impl ModuleGraphLoader {
|
|||
}
|
||||
}
|
||||
|
||||
self.has_downloaded.insert(module_specifier.clone());
|
||||
let spec = module_specifier;
|
||||
let file_fetcher = self.file_fetcher.clone();
|
||||
let perms = self.permissions.clone();
|
||||
|
@ -312,13 +336,7 @@ impl ModuleGraphLoader {
|
|||
let source_file = file_fetcher
|
||||
.fetch_source_file(&spec_, maybe_referrer, perms)
|
||||
.await?;
|
||||
// FIXME(bartlomieju):
|
||||
// because of redirects we may end up with wrong URL,
|
||||
// substitute with original one
|
||||
Ok(SourceFile {
|
||||
url: spec_.as_url().to_owned(),
|
||||
..source_file
|
||||
})
|
||||
Ok((spec_.clone(), source_file))
|
||||
}
|
||||
.boxed_local();
|
||||
|
||||
|
@ -337,6 +355,33 @@ impl ModuleGraphLoader {
|
|||
let mut types_directives = vec![];
|
||||
let mut type_headers = vec![];
|
||||
|
||||
// IMPORTANT: source_file.url might be different than requested
|
||||
// module_specifier because of HTTP redirects. In such
|
||||
// situation we add an "empty" ModuleGraphFile with 'redirect'
|
||||
// field set that will be later used in TS worker when building
|
||||
// map of available source file. It will perform substitution
|
||||
// for proper URL point to redirect target.
|
||||
if module_specifier.as_url() != &source_file.url {
|
||||
// TODO(bartlomieju): refactor, this is a band-aid
|
||||
self.graph.0.insert(
|
||||
module_specifier.to_string(),
|
||||
ModuleGraphFile {
|
||||
specifier: module_specifier.to_string(),
|
||||
url: module_specifier.to_string(),
|
||||
redirect: Some(source_file.url.to_string()),
|
||||
filename: source_file.filename.to_str().unwrap().to_string(),
|
||||
media_type: source_file.media_type as i32,
|
||||
source_code: "".to_string(),
|
||||
imports: vec![],
|
||||
referenced_files: vec![],
|
||||
lib_directives: vec![],
|
||||
types_directives: vec![],
|
||||
type_headers: vec![],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let module_specifier = ModuleSpecifier::from(source_file.url.clone());
|
||||
let source_code = String::from_utf8(source_file.source_code)?;
|
||||
|
||||
if source_file.media_type == MediaType::JavaScript
|
||||
|
@ -358,6 +403,7 @@ impl ModuleGraphLoader {
|
|||
}
|
||||
|
||||
let (import_descs, ref_descs) = analyze_dependencies_and_references(
|
||||
&module_specifier.to_string(),
|
||||
&source_code,
|
||||
self.analyze_dynamic_imports,
|
||||
)?;
|
||||
|
@ -454,7 +500,8 @@ impl ModuleGraphLoader {
|
|||
module_specifier.to_string(),
|
||||
ModuleGraphFile {
|
||||
specifier: module_specifier.to_string(),
|
||||
url: source_file.url.to_string(),
|
||||
url: module_specifier.to_string(),
|
||||
redirect: None,
|
||||
filename: source_file.filename.to_str().unwrap().to_string(),
|
||||
media_type: source_file.media_type as i32,
|
||||
source_code,
|
||||
|
|
23
cli/state.rs
23
cli/state.rs
|
@ -279,6 +279,21 @@ impl ModuleLoader for State {
|
|||
is_dyn_import: bool,
|
||||
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
||||
let module_specifier = module_specifier.clone();
|
||||
|
||||
// TODO(bartlomieju): this code is duplicated from module_graph.
|
||||
// It should be removed when `prepare_load` will be used to load modules.
|
||||
// Disallow http:// imports from modules loaded over https://
|
||||
if let Some(referrer) = maybe_referrer.as_ref() {
|
||||
if let "https" = referrer.as_url().scheme() {
|
||||
if let "http" = module_specifier.as_url().scheme() {
|
||||
let e = OpError::permission_denied(
|
||||
"Modules loaded over https:// are not allowed to import modules over http://".to_string()
|
||||
);
|
||||
return async move { Err(e.into()) }.boxed_local();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if is_dyn_import {
|
||||
if let Err(e) = self.check_dyn_import(&module_specifier) {
|
||||
return async move { Err(e.into()) }.boxed_local();
|
||||
|
@ -293,7 +308,9 @@ impl ModuleLoader for State {
|
|||
match specifier_url.scheme() {
|
||||
"http" | "https" => {}
|
||||
_ => {
|
||||
let e = OpError::permission_denied("Remote module are not allowed to statically import local modules. Use dynamic import instead.".to_string());
|
||||
let e = OpError::permission_denied(
|
||||
"Remote modules are not allowed to statically import local modules. Use dynamic import instead.".to_string()
|
||||
);
|
||||
return async move { Err(e.into()) }.boxed_local();
|
||||
}
|
||||
}
|
||||
|
@ -535,7 +552,9 @@ impl State {
|
|||
#[inline]
|
||||
pub fn should_inspector_break_on_first_statement(&self) -> bool {
|
||||
let state = self.borrow();
|
||||
state.inspector.is_some() && state.is_main
|
||||
state.inspector.is_some()
|
||||
&& state.is_main
|
||||
&& state.global_state.flags.inspect_brk.is_some()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -29,45 +29,63 @@ use std::sync::RwLock;
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SwcDiagnosticBuffer {
|
||||
pub diagnostics: Vec<Diagnostic>,
|
||||
pub diagnostics: Vec<String>,
|
||||
}
|
||||
|
||||
impl Error for SwcDiagnosticBuffer {}
|
||||
|
||||
impl fmt::Display for SwcDiagnosticBuffer {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let msg = self
|
||||
.diagnostics
|
||||
.iter()
|
||||
.map(|d| d.message())
|
||||
.collect::<Vec<String>>()
|
||||
.join(",");
|
||||
let msg = self.diagnostics.join(",");
|
||||
|
||||
f.pad(&msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl SwcDiagnosticBuffer {
|
||||
pub fn from_swc_error(
|
||||
error_buffer: SwcErrorBuffer,
|
||||
parser: &AstParser,
|
||||
) -> Self {
|
||||
let s = error_buffer.0.read().unwrap().clone();
|
||||
|
||||
let diagnostics = s
|
||||
.iter()
|
||||
.map(|d| {
|
||||
let mut msg = d.message();
|
||||
|
||||
if let Some(span) = d.span.primary_span() {
|
||||
let location = parser.get_span_location(span);
|
||||
let filename = match &location.file.name {
|
||||
FileName::Custom(n) => n,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
msg = format!(
|
||||
"{} at {}:{}:{}",
|
||||
msg, filename, location.line, location.col_display
|
||||
);
|
||||
}
|
||||
|
||||
msg
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
Self { diagnostics }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SwcErrorBuffer(Arc<RwLock<SwcDiagnosticBuffer>>);
|
||||
pub struct SwcErrorBuffer(Arc<RwLock<Vec<Diagnostic>>>);
|
||||
|
||||
impl SwcErrorBuffer {
|
||||
pub fn default() -> Self {
|
||||
Self(Arc::new(RwLock::new(SwcDiagnosticBuffer {
|
||||
diagnostics: vec![],
|
||||
})))
|
||||
Self(Arc::new(RwLock::new(vec![])))
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SwcErrorBuffer {
|
||||
fn emit(&mut self, db: &DiagnosticBuilder) {
|
||||
self.0.write().unwrap().diagnostics.push((**db).clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SwcErrorBuffer> for SwcDiagnosticBuffer {
|
||||
fn from(buf: SwcErrorBuffer) -> Self {
|
||||
let s = buf.0.read().unwrap();
|
||||
s.clone()
|
||||
self.0.write().unwrap().push((**db).clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,8 +143,10 @@ impl AstParser {
|
|||
handler: &self.handler,
|
||||
};
|
||||
|
||||
// TODO(bartlomieju): lexer should be configurable by the caller
|
||||
let mut ts_config = TsConfig::default();
|
||||
ts_config.dynamic_import = true;
|
||||
ts_config.decorators = true;
|
||||
let syntax = Syntax::Typescript(ts_config);
|
||||
|
||||
let lexer = Lexer::new(
|
||||
|
@ -143,8 +163,8 @@ impl AstParser {
|
|||
parser
|
||||
.parse_module()
|
||||
.map_err(move |mut err: DiagnosticBuilder| {
|
||||
err.cancel();
|
||||
SwcDiagnosticBuffer::from(buffered_err)
|
||||
err.emit();
|
||||
SwcDiagnosticBuffer::from_swc_error(buffered_err, self)
|
||||
});
|
||||
|
||||
callback(parse_result)
|
||||
|
@ -307,6 +327,20 @@ impl Visit for NewDependencyVisitor {
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_ts_import_type(
|
||||
&mut self,
|
||||
ts_import_type: &swc_ecma_ast::TsImportType,
|
||||
_parent: &dyn Node,
|
||||
) {
|
||||
// TODO(bartlomieju): possibly add separate DependencyKind
|
||||
let src_str = ts_import_type.arg.value.to_string();
|
||||
self.dependencies.push(DependencyDescriptor {
|
||||
specifier: src_str,
|
||||
kind: DependencyKind::Import,
|
||||
span: ts_import_type.arg.span,
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_call_expr(
|
||||
&mut self,
|
||||
call_expr: &swc_ecma_ast::CallExpr,
|
||||
|
@ -397,6 +431,7 @@ pub struct TsReferenceDescriptor {
|
|||
}
|
||||
|
||||
pub fn analyze_dependencies_and_references(
|
||||
file_name: &str,
|
||||
source_code: &str,
|
||||
analyze_dynamic_imports: bool,
|
||||
) -> Result<
|
||||
|
@ -404,7 +439,7 @@ pub fn analyze_dependencies_and_references(
|
|||
SwcDiagnosticBuffer,
|
||||
> {
|
||||
let parser = AstParser::new();
|
||||
parser.parse_module("root.ts", source_code, |parse_result| {
|
||||
parser.parse_module(file_name, source_code, |parse_result| {
|
||||
let module = parse_result?;
|
||||
let mut collector = NewDependencyVisitor {
|
||||
dependencies: vec![],
|
||||
|
@ -512,7 +547,8 @@ console.log(qat.qat);
|
|||
"#;
|
||||
|
||||
let (imports, references) =
|
||||
analyze_dependencies_and_references(source, true).expect("Failed to parse");
|
||||
analyze_dependencies_and_references("some/file.ts", source, true)
|
||||
.expect("Failed to parse");
|
||||
|
||||
assert_eq!(
|
||||
imports,
|
||||
|
|
2
cli/tests/disallow_http_from_https.js
Normal file
2
cli/tests/disallow_http_from_https.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
// Trying to import "http://", while this file is accessed by "https://"
|
||||
import "http://localhost:4545/cli/tests/001_hello.js";
|
2
cli/tests/disallow_http_from_https.ts
Normal file
2
cli/tests/disallow_http_from_https.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
// Trying to import "http://", while this file is accessed by "https://"
|
||||
import "http://localhost:4545/cli/tests/001_hello.js";
|
1
cli/tests/disallow_http_from_https_js.out
Normal file
1
cli/tests/disallow_http_from_https_js.out
Normal file
|
@ -0,0 +1 @@
|
|||
error: Modules loaded over https:// are not allowed to import modules over http://
|
1
cli/tests/disallow_http_from_https_ts.out
Normal file
1
cli/tests/disallow_http_from_https_ts.out
Normal file
|
@ -0,0 +1 @@
|
|||
error: Modules loaded over https:// are not allowed to import modules over http://
|
|
@ -1 +1 @@
|
|||
[WILDCARD]error: Uncaught TypeError: Cannot resolve module "[WILDCARD]/bad-module.ts"
|
||||
error: Cannot resolve module "[WILDCARD]/bad-module.ts" from "[WILDCARD]/error_005_missing_dynamic_import.ts"
|
||||
|
|
|
@ -1 +1 @@
|
|||
[WILDCARD]error: Uncaught TypeError: relative import path "bad-module.ts" not prefixed with / or ./ or ../ Imported from "[WILDCARD]/error_012_bad_dynamic_import_specifier.ts"
|
||||
error: relative import path "bad-module.ts" not prefixed with / or ./ or ../ Imported from "[WILDCARD]/error_012_bad_dynamic_import_specifier.ts"
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[WILDCARD]
|
||||
error: Remote module are not allowed to statically import local modules. Use dynamic import instead.
|
||||
error: Remote modules are not allowed to statically import local modules. Use dynamic import instead.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[WILDCARD]
|
||||
error: Remote module are not allowed to statically import local modules. Use dynamic import instead.
|
||||
error: Remote modules are not allowed to statically import local modules. Use dynamic import instead.
|
||||
|
|
5
cli/tests/inspector4.js
Normal file
5
cli/tests/inspector4.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
console.log("hello");
|
||||
|
||||
setInterval(() => {
|
||||
console.log("hello from interval");
|
||||
}, 1000);
|
|
@ -1582,6 +1582,29 @@ itest!(type_directives_js_main {
|
|||
exit_code: 0,
|
||||
});
|
||||
|
||||
itest!(type_directives_redirect {
|
||||
args: "run --reload type_directives_redirect.ts",
|
||||
output: "type_directives_redirect.ts.out",
|
||||
http_server: true,
|
||||
});
|
||||
|
||||
itest!(ts_type_imports {
|
||||
args: "run --reload ts_type_imports.ts",
|
||||
output: "ts_type_imports.ts.out",
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(ts_decorators {
|
||||
args: "run --reload -c tsconfig.decorators.json ts_decorators.ts",
|
||||
output: "ts_decorators.ts.out",
|
||||
});
|
||||
|
||||
itest!(swc_syntax_error {
|
||||
args: "run --reload swc_syntax_error.ts",
|
||||
output: "swc_syntax_error.ts.out",
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(types {
|
||||
args: "types",
|
||||
output: "types.out",
|
||||
|
@ -1703,6 +1726,20 @@ itest_ignore!(cafile_info {
|
|||
http_server: true,
|
||||
});
|
||||
|
||||
itest!(disallow_http_from_https_js {
|
||||
args: "run --quiet --reload --cert tls/RootCA.pem https://localhost:5545/cli/tests/disallow_http_from_https.js",
|
||||
output: "disallow_http_from_https_js.out",
|
||||
http_server: true,
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(disallow_http_from_https_ts {
|
||||
args: "run --quiet --reload --cert tls/RootCA.pem https://localhost:5545/cli/tests/disallow_http_from_https.ts",
|
||||
output: "disallow_http_from_https_ts.out",
|
||||
http_server: true,
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(fix_js_import_js {
|
||||
args: "run --quiet --reload fix_js_import_js.ts",
|
||||
output: "fix_js_import_js.ts.out",
|
||||
|
@ -2468,6 +2505,31 @@ async fn inspector_does_not_hang() {
|
|||
assert!(child.wait().unwrap().success());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn inspector_without_brk_runs_code() {
|
||||
let script = util::tests_path().join("inspector4.js");
|
||||
let mut child = util::deno_cmd()
|
||||
.arg("run")
|
||||
// Warning: each inspector test should be on its own port to avoid
|
||||
// conflicting with another inspector test.
|
||||
.arg("--inspect=127.0.0.1:9233")
|
||||
.arg(script)
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
extract_ws_url_from_stderr(child.stderr.as_mut().unwrap());
|
||||
|
||||
// Check that inspector actually runs code without waiting for inspector
|
||||
// connection
|
||||
let mut stdout = std::io::BufReader::new(child.stdout.as_mut().unwrap());
|
||||
let mut stdout_first_line = String::from("");
|
||||
let _ = stdout.read_line(&mut stdout_first_line).unwrap();
|
||||
assert_eq!(stdout_first_line, "hello\n");
|
||||
|
||||
child.kill().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_path() {
|
||||
let output = util::deno_cmd()
|
||||
|
|
3
cli/tests/swc_syntax_error.ts
Normal file
3
cli/tests/swc_syntax_error.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
for await (const req of s) {
|
||||
let something:
|
||||
}
|
1
cli/tests/swc_syntax_error.ts.out
Normal file
1
cli/tests/swc_syntax_error.ts.out
Normal file
|
@ -0,0 +1 @@
|
|||
error: Unexpected token Some(RBrace) at [WILDCARD]syntax_error.ts:3:0
|
14
cli/tests/ts_decorators.ts
Normal file
14
cli/tests/ts_decorators.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* eslint-disable */
|
||||
|
||||
function Decorate() {
|
||||
return function (constructor: any): any {
|
||||
return class extends constructor {
|
||||
protected someField: string = "asdf";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@Decorate()
|
||||
class SomeClass {}
|
||||
|
||||
console.log(new SomeClass());
|
2
cli/tests/ts_decorators.ts.out
Normal file
2
cli/tests/ts_decorators.ts.out
Normal file
|
@ -0,0 +1,2 @@
|
|||
Compile [WILDCARD]
|
||||
SomeClass { someField: "asdf" }
|
5
cli/tests/ts_type_imports.ts
Normal file
5
cli/tests/ts_type_imports.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
/* eslint-disable */
|
||||
|
||||
type Foo = import("./ts_type_imports_foo.ts").Foo;
|
||||
|
||||
const foo: Foo = new Map<string, string>();
|
6
cli/tests/ts_type_imports.ts.out
Normal file
6
cli/tests/ts_type_imports.ts.out
Normal file
|
@ -0,0 +1,6 @@
|
|||
Compile [WILDCARD]ts_type_imports.ts
|
||||
error: TS2322 [ERROR]: Type 'Map<string, string>' is not assignable to type 'Foo'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
const foo: Foo = new Map<string, string>();
|
||||
~~~
|
||||
at [WILDCARD]ts_type_imports.ts:5:7
|
1
cli/tests/ts_type_imports_foo.ts
Normal file
1
cli/tests/ts_type_imports_foo.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export type Foo = Map<string, number>;
|
5
cli/tests/tsconfig.decorators.json
Normal file
5
cli/tests/tsconfig.decorators.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true
|
||||
}
|
||||
}
|
1
cli/tests/type_directives_redirect.ts
Normal file
1
cli/tests/type_directives_redirect.ts
Normal file
|
@ -0,0 +1 @@
|
|||
import "http://localhost:4545/type_directives_redirect.js";
|
5
cli/tests/type_directives_redirect.ts.out
Normal file
5
cli/tests/type_directives_redirect.ts.out
Normal file
|
@ -0,0 +1,5 @@
|
|||
Download [WILDCARD]type_directives_redirect.js
|
||||
Download [WILDCARD]xTypeScriptTypesRedirect.d.ts
|
||||
Download [WILDCARD]xTypeScriptTypesRedirect.d.ts
|
||||
Download [WILDCARD]xTypeScriptTypesRedirected.d.ts
|
||||
Compile [WILDCARD]type_directives_redirect.ts
|
79
cli/tests/unit/streams_internal_test.ts
Normal file
79
cli/tests/unit/streams_internal_test.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { unitTest, assertThrows } from "./test_util.ts";
|
||||
|
||||
unitTest(function streamReadableHwmError() {
|
||||
const invalidHwm = [NaN, Number("NaN"), {}, -1, "two"];
|
||||
for (const highWaterMark of invalidHwm) {
|
||||
assertThrows(
|
||||
() => {
|
||||
new ReadableStream<number>(
|
||||
undefined,
|
||||
// @ts-ignore
|
||||
{ highWaterMark }
|
||||
);
|
||||
},
|
||||
RangeError,
|
||||
"highWaterMark must be a positive number or Infinity. Received:"
|
||||
);
|
||||
}
|
||||
|
||||
assertThrows(() => {
|
||||
new ReadableStream<number>(
|
||||
undefined,
|
||||
// @ts-ignore
|
||||
{ highWaterMark: Symbol("hwk") }
|
||||
);
|
||||
}, TypeError);
|
||||
});
|
||||
|
||||
unitTest(function streamWriteableHwmError() {
|
||||
const invalidHwm = [NaN, Number("NaN"), {}, -1, "two"];
|
||||
for (const highWaterMark of invalidHwm) {
|
||||
assertThrows(
|
||||
() => {
|
||||
new WritableStream(
|
||||
undefined,
|
||||
// @ts-ignore
|
||||
new CountQueuingStrategy({ highWaterMark })
|
||||
);
|
||||
},
|
||||
RangeError,
|
||||
"highWaterMark must be a positive number or Infinity. Received:"
|
||||
);
|
||||
}
|
||||
|
||||
assertThrows(() => {
|
||||
new WritableStream(
|
||||
undefined,
|
||||
// @ts-ignore
|
||||
new CountQueuingStrategy({ highWaterMark: Symbol("hwmk") })
|
||||
);
|
||||
}, TypeError);
|
||||
});
|
||||
|
||||
unitTest(function streamTransformHwmError() {
|
||||
const invalidHwm = [NaN, Number("NaN"), {}, -1, "two"];
|
||||
for (const highWaterMark of invalidHwm) {
|
||||
assertThrows(
|
||||
() => {
|
||||
new TransformStream(
|
||||
undefined,
|
||||
undefined,
|
||||
// @ts-ignore
|
||||
{ highWaterMark }
|
||||
);
|
||||
},
|
||||
RangeError,
|
||||
"highWaterMark must be a positive number or Infinity. Received:"
|
||||
);
|
||||
}
|
||||
|
||||
assertThrows(() => {
|
||||
new TransformStream(
|
||||
undefined,
|
||||
undefined,
|
||||
// @ts-ignore
|
||||
{ highWaterMark: Symbol("hwmk") }
|
||||
);
|
||||
}, TypeError);
|
||||
});
|
|
@ -52,6 +52,7 @@ import "./request_test.ts";
|
|||
import "./resources_test.ts";
|
||||
import "./signal_test.ts";
|
||||
import "./stat_test.ts";
|
||||
import "./streams_internal_test.ts";
|
||||
import "./streams_piping_test.ts";
|
||||
import "./streams_transform_test.ts";
|
||||
import "./streams_writable_test.ts";
|
||||
|
|
|
@ -31,7 +31,7 @@ function handleAsyncMsgFromWorker(
|
|||
if (promise === null) {
|
||||
throw new Error(`Failed to find promise: cmdId: ${msg.cmdId}, msg: ${msg}`);
|
||||
}
|
||||
promise.resolve(data);
|
||||
promise?.resolve(data);
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
|
|
|
@ -459,14 +459,13 @@ impl TsCompiler {
|
|||
import_map,
|
||||
permissions.clone(),
|
||||
is_dyn_import,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
|
||||
module_graph_loader.add_to_graph(&module_specifier).await?;
|
||||
let module_graph = module_graph_loader.get_graph();
|
||||
let module_graph_json =
|
||||
serde_json::to_value(module_graph).expect("Failed to serialize data");
|
||||
|
||||
let target = match target {
|
||||
TargetLib::Main => "main",
|
||||
TargetLib::Worker => "worker",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_core"
|
||||
version = "0.45.1"
|
||||
version = "0.45.2"
|
||||
edition = "2018"
|
||||
description = "A secure JavaScript/TypeScript runtime built with V8, Rust, and Tokio"
|
||||
authors = ["the Deno authors"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "deno_typescript"
|
||||
version = "0.45.1"
|
||||
version = "0.45.2"
|
||||
license = "MIT"
|
||||
description = "To compile TypeScript to a snapshot during build.rs"
|
||||
repository = "https://github.com/denoland/deno"
|
||||
|
|
|
@ -27,12 +27,22 @@ $ deno run --allow-read=/etc https://deno.land/std/examples/cat.ts /etc/passwd
|
|||
|
||||
`--allow-write` works the same as `--allow-read`.
|
||||
|
||||
This example restricts network access by whitelisting the allowed hosts:
|
||||
### Network access:
|
||||
|
||||
_fetch.ts_:
|
||||
|
||||
```ts
|
||||
const result = await fetch("https://deno.land/");
|
||||
```
|
||||
|
||||
This is an example on how to whitelist hosts/urls:
|
||||
|
||||
```shell
|
||||
$ deno run --allow-net=deno.land https://deno.land/std/examples/curl.ts https://deno.land/
|
||||
$ deno run --allow-net=github.com,deno.land fetch.ts
|
||||
```
|
||||
|
||||
Allow net calls to any host/url:
|
||||
|
||||
```shell
|
||||
$ deno run --allow-net fetch.ts
|
||||
```
|
||||
|
|
|
@ -24,7 +24,7 @@ takes the form of a compiler hint. Compiler hints inform Deno the location of
|
|||
`.d.ts` files and the JavaScript code that is imported that they relate to. The
|
||||
hint is `@deno-types` and when specified the value will be used in the compiler
|
||||
instead of the JavaScript module. For example, if you had `foo.js`, but you know
|
||||
that along side of it was `foo.d.ts` which was the types for the file, the code
|
||||
that alongside of it was `foo.d.ts` which was the types for the file, the code
|
||||
would look like this:
|
||||
|
||||
```ts
|
||||
|
@ -48,7 +48,7 @@ If you are hosting modules which you want to be consumed by Deno, and you want
|
|||
to inform Deno about the location of the type definitions, you can utilize a
|
||||
triple-slash directive in the actual code. For example, if you have a JavaScript
|
||||
module and you would like to provide Deno with the location of the type
|
||||
definitions which happen to be alongside that file, your JavaScript module named
|
||||
definition which happens to be alongside that file, your JavaScript module named
|
||||
`foo.js` might look like this:
|
||||
|
||||
```js
|
||||
|
|
|
@ -100,6 +100,6 @@ deno test my_test.ts
|
|||
```
|
||||
|
||||
You can also omit the file name, in which case all tests in the current
|
||||
directory (recursively) that match the glob `{*_,}test.{js,ts,jsx,tsx}` will be
|
||||
run. If you pass a directory, all files in the directory that match this glob
|
||||
directory (recursively) that match the glob `{*_,*.,}test.{js,ts,jsx,tsx}` will
|
||||
be run. If you pass a directory, all files in the directory that match this glob
|
||||
will be run.
|
||||
|
|
|
@ -60,7 +60,12 @@ As soon as we've added the breakpoint Devtools automatically opened up source
|
|||
map file, which allows us step through the actual source code that includes
|
||||
types.
|
||||
|
||||
Let's send a request and inspect it in Devtools:
|
||||
Now that we have our breakpoints set, we can resume the execution of our script
|
||||
so that we might inspect an incoming request. Hit the Resume script execution
|
||||
button to do so. You might even need to hit it twice!
|
||||
|
||||
Once our script is running again, let's send a request and inspect it in
|
||||
Devtools:
|
||||
|
||||
```
|
||||
$ curl http://0.0.0.0:4500/
|
||||
|
|
|
@ -1,3 +1,75 @@
|
|||
## Dependency Inspector
|
||||
|
||||
<!-- TODO(lucacasonto): write things -->
|
||||
`deno info [URL]` will inspect ES module and all of its dependencies.
|
||||
|
||||
```shell
|
||||
deno info https://deno.land/std@0.52.0/http/file_server.ts
|
||||
Download https://deno.land/std@0.52.0/http/file_server.ts
|
||||
...
|
||||
local: /Users/deno/Library/Caches/deno/deps/https/deno.land/5bd138988e9d20db1a436666628ffb3f7586934e0a2a9fe2a7b7bf4fb7f70b98
|
||||
type: TypeScript
|
||||
compiled: /Users/deno/Library/Caches/deno/gen/https/deno.land/std@0.52.0/http/file_server.ts.js
|
||||
map: /Users/deno/Library/Caches/deno/gen/https/deno.land/std@0.52.0/http/file_server.ts.js.map
|
||||
deps:
|
||||
https://deno.land/std@0.52.0/http/file_server.ts
|
||||
├─┬ https://deno.land/std@0.52.0/path/mod.ts
|
||||
│ ├─┬ https://deno.land/std@0.52.0/path/win32.ts
|
||||
│ │ ├── https://deno.land/std@0.52.0/path/_constants.ts
|
||||
│ │ ├─┬ https://deno.land/std@0.52.0/path/_util.ts
|
||||
│ │ │ └── https://deno.land/std@0.52.0/path/_constants.ts
|
||||
│ │ └─┬ https://deno.land/std@0.52.0/testing/asserts.ts
|
||||
│ │ ├── https://deno.land/std@0.52.0/fmt/colors.ts
|
||||
│ │ └── https://deno.land/std@0.52.0/testing/diff.ts
|
||||
│ ├─┬ https://deno.land/std@0.52.0/path/posix.ts
|
||||
│ │ ├── https://deno.land/std@0.52.0/path/_constants.ts
|
||||
│ │ └── https://deno.land/std@0.52.0/path/_util.ts
|
||||
│ ├─┬ https://deno.land/std@0.52.0/path/common.ts
|
||||
│ │ └── https://deno.land/std@0.52.0/path/separator.ts
|
||||
│ ├── https://deno.land/std@0.52.0/path/separator.ts
|
||||
│ ├── https://deno.land/std@0.52.0/path/interface.ts
|
||||
│ └─┬ https://deno.land/std@0.52.0/path/glob.ts
|
||||
│ ├── https://deno.land/std@0.52.0/path/separator.ts
|
||||
│ ├── https://deno.land/std@0.52.0/path/_globrex.ts
|
||||
│ ├── https://deno.land/std@0.52.0/path/mod.ts
|
||||
│ └── https://deno.land/std@0.52.0/testing/asserts.ts
|
||||
├─┬ https://deno.land/std@0.52.0/http/server.ts
|
||||
│ ├── https://deno.land/std@0.52.0/encoding/utf8.ts
|
||||
│ ├─┬ https://deno.land/std@0.52.0/io/bufio.ts
|
||||
│ │ ├─┬ https://deno.land/std@0.52.0/io/util.ts
|
||||
│ │ │ ├── https://deno.land/std@0.52.0/path/mod.ts
|
||||
│ │ │ └── https://deno.land/std@0.52.0/encoding/utf8.ts
|
||||
│ │ └── https://deno.land/std@0.52.0/testing/asserts.ts
|
||||
│ ├── https://deno.land/std@0.52.0/testing/asserts.ts
|
||||
│ ├─┬ https://deno.land/std@0.52.0/async/mod.ts
|
||||
│ │ ├── https://deno.land/std@0.52.0/async/deferred.ts
|
||||
│ │ ├── https://deno.land/std@0.52.0/async/delay.ts
|
||||
│ │ └─┬ https://deno.land/std@0.52.0/async/mux_async_iterator.ts
|
||||
│ │ └── https://deno.land/std@0.52.0/async/deferred.ts
|
||||
│ └─┬ https://deno.land/std@0.52.0/http/_io.ts
|
||||
│ ├── https://deno.land/std@0.52.0/io/bufio.ts
|
||||
│ ├─┬ https://deno.land/std@0.52.0/textproto/mod.ts
|
||||
│ │ ├── https://deno.land/std@0.52.0/io/util.ts
|
||||
│ │ ├─┬ https://deno.land/std@0.52.0/bytes/mod.ts
|
||||
│ │ │ └── https://deno.land/std@0.52.0/io/util.ts
|
||||
│ │ └── https://deno.land/std@0.52.0/encoding/utf8.ts
|
||||
│ ├── https://deno.land/std@0.52.0/testing/asserts.ts
|
||||
│ ├── https://deno.land/std@0.52.0/encoding/utf8.ts
|
||||
│ ├── https://deno.land/std@0.52.0/http/server.ts
|
||||
│ └── https://deno.land/std@0.52.0/http/http_status.ts
|
||||
├─┬ https://deno.land/std@0.52.0/flags/mod.ts
|
||||
│ └── https://deno.land/std@0.52.0/testing/asserts.ts
|
||||
└── https://deno.land/std@0.52.0/testing/asserts.ts
|
||||
```
|
||||
|
||||
Dependency inspector works with any local or remote ES modules.
|
||||
|
||||
## Cache location
|
||||
|
||||
`deno info` can be used to display information about cache location:
|
||||
|
||||
```shell
|
||||
deno info
|
||||
DENO_DIR location: "/Users/deno/Library/Caches/deno"
|
||||
Remote modules cache: "/Users/deno/Library/Caches/deno/deps"
|
||||
TypeScript compiler cache: "/Users/deno/Library/Caches/deno/gen"
|
||||
```
|
||||
|
|
|
@ -55,22 +55,6 @@ This is very much a work-in-progress. I'm actively soliciting feedback.
|
|||
are not likely useful) are missing, namely %q (print quoted), %U (unicode
|
||||
format)
|
||||
|
||||
## Author
|
||||
|
||||
Tim Becker (tim@presseverykey.com)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
The implementation is inspired by POSIX and Golang (see above) but does not port
|
||||
implementation code. A number of Golang test-cases based on:
|
||||
|
||||
https://golang.org/src/fmt/fmt_test.go
|
||||
( BSD: Copyright (c) 2009 The Go Authors. All rights reserved. )
|
||||
|
||||
were used.
|
||||
|
||||
# printf: prints formatted output
|
||||
|
||||
sprintf converts and formats a variable number of arguments as is specified by a
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
export * from "./colors.ts";
|
||||
export * from "./sprintf.ts";
|
|
@ -1,3 +1,8 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
//
|
||||
// This implementation is inspired by POSIX and Golang but does not port
|
||||
// implementation code.
|
||||
|
||||
enum State {
|
||||
PASSTHROUGH,
|
||||
PERCENT,
|
||||
|
@ -5,6 +10,7 @@ enum State {
|
|||
PRECISION,
|
||||
WIDTH,
|
||||
}
|
||||
|
||||
enum WorP {
|
||||
WIDTH,
|
||||
PRECISION,
|
||||
|
@ -21,14 +27,11 @@ class Flags {
|
|||
precision = -1;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
const min = Math.min;
|
||||
|
||||
const UNICODE_REPLACEMENT_CHARACTER = "\ufffd";
|
||||
const DEFAULT_PRECISION = 6;
|
||||
|
||||
const FLOAT_REGEXP = /(-?)(\d)\.?(\d*)e([+-])(\d+)/;
|
||||
|
||||
enum F {
|
||||
sign = 1,
|
||||
mantissa,
|
||||
|
@ -39,8 +42,7 @@ enum F {
|
|||
|
||||
class Printf {
|
||||
format: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
args: any[];
|
||||
args: unknown[];
|
||||
i: number;
|
||||
|
||||
state: State = State.PASSTHROUGH;
|
||||
|
@ -54,8 +56,7 @@ class Printf {
|
|||
// barf, store precision and width errors for later processing ...
|
||||
tmpError?: string;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
constructor(format: string, ...args: any[]) {
|
||||
constructor(format: string, ...args: unknown[]) {
|
||||
this.format = format;
|
||||
this.args = args;
|
||||
this.haveSeen = new Array(args.length);
|
||||
|
@ -166,6 +167,7 @@ class Printf {
|
|||
} // switch state
|
||||
}
|
||||
}
|
||||
|
||||
handleWidthOrPrecisionRef(wOrP: WorP): void {
|
||||
if (this.argNum >= this.args.length) {
|
||||
// handle Positional should have already taken care of it...
|
||||
|
@ -187,6 +189,7 @@ class Printf {
|
|||
}
|
||||
this.argNum++;
|
||||
}
|
||||
|
||||
handleWidthAndPrecision(flags: Flags): void {
|
||||
const fmt = this.format;
|
||||
for (; this.i !== this.format.length; ++this.i) {
|
||||
|
@ -270,8 +273,10 @@ class Printf {
|
|||
this.argNum = err ? this.argNum : positional - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
handleLessThan(): string {
|
||||
const arg = this.args[this.argNum];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const arg = this.args[this.argNum] as any;
|
||||
if ((arg || {}).constructor.name !== "Array") {
|
||||
throw new Error(`arg ${arg} is not an array. Todo better error handling`);
|
||||
}
|
||||
|
@ -282,6 +287,7 @@ class Printf {
|
|||
}
|
||||
return str + " ]";
|
||||
}
|
||||
|
||||
handleVerb(): void {
|
||||
const verb = this.format[this.i];
|
||||
this.verb = verb;
|
||||
|
@ -649,8 +655,7 @@ class Printf {
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
fmtV(val: any): string {
|
||||
fmtV(val: object): string {
|
||||
if (this.flags.sharp) {
|
||||
const options =
|
||||
this.flags.precision !== -1 ? { depth: this.flags.precision } : {};
|
||||
|
@ -661,14 +666,17 @@ class Printf {
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
fmtJ(val: any): string {
|
||||
fmtJ(val: unknown): string {
|
||||
return JSON.stringify(val);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function sprintf(format: string, ...args: any[]): string {
|
||||
export function sprintf(format: string, ...args: unknown[]): string {
|
||||
const printf = new Printf(format, ...args);
|
||||
return printf.doPrintf();
|
||||
}
|
||||
|
||||
export function printf(format: string, ...args: unknown[]): void {
|
||||
const s = sprintf(format, ...args);
|
||||
Deno.stdout.writeSync(new TextEncoder().encode(s));
|
||||
}
|
|
@ -1,5 +1,11 @@
|
|||
import { sprintf } from "./sprintf.ts";
|
||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
//
|
||||
// A number of test-cases based on:
|
||||
//
|
||||
// https://golang.org/src/fmt/fmt_test.go
|
||||
// BSD: Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
import { sprintf } from "./printf.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import { cyan, yellow } from "./colors.ts";
|
||||
|
249
std/hash/md5.ts
Normal file
249
std/hash/md5.ts
Normal file
|
@ -0,0 +1,249 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import * as hex from "../encoding/hex.ts";
|
||||
|
||||
const TYPE_ERROR_MSG = "md5: `data` is invalid type";
|
||||
const BLOCK_SIZE = 64;
|
||||
|
||||
export type Message = string | ArrayBuffer;
|
||||
|
||||
/** Md5 hash */
|
||||
export class Md5 {
|
||||
#a: number;
|
||||
#b: number;
|
||||
#c: number;
|
||||
#d: number;
|
||||
#block: Uint8Array;
|
||||
#pos: number;
|
||||
#n0: number;
|
||||
#n1: number;
|
||||
|
||||
constructor() {
|
||||
this.#a = 0x67452301;
|
||||
this.#b = 0xefcdab89;
|
||||
this.#c = 0x98badcfe;
|
||||
this.#d = 0x10325476;
|
||||
this.#block = new Uint8Array(BLOCK_SIZE);
|
||||
this.#pos = 0;
|
||||
this.#n0 = 0;
|
||||
this.#n1 = 0;
|
||||
}
|
||||
|
||||
private addLength(len: number): void {
|
||||
let n0 = this.#n0;
|
||||
n0 += len;
|
||||
if (n0 > 0xffffffff) this.#n1 += 1;
|
||||
this.#n0 = n0 >>> 0;
|
||||
}
|
||||
|
||||
private hash(block: Uint8Array): void {
|
||||
let a = this.#a;
|
||||
let b = this.#b;
|
||||
let c = this.#c;
|
||||
let d = this.#d;
|
||||
|
||||
const blk = (i: number): number =>
|
||||
block[i] |
|
||||
(block[i + 1] << 8) |
|
||||
(block[i + 2] << 16) |
|
||||
(block[i + 3] << 24);
|
||||
|
||||
const rol32 = (x: number, n: number): number => (x << n) | (x >>> (32 - n));
|
||||
|
||||
const x0 = blk(0);
|
||||
const x1 = blk(4);
|
||||
const x2 = blk(8);
|
||||
const x3 = blk(12);
|
||||
const x4 = blk(16);
|
||||
const x5 = blk(20);
|
||||
const x6 = blk(24);
|
||||
const x7 = blk(28);
|
||||
const x8 = blk(32);
|
||||
const x9 = blk(36);
|
||||
const xa = blk(40);
|
||||
const xb = blk(44);
|
||||
const xc = blk(48);
|
||||
const xd = blk(52);
|
||||
const xe = blk(56);
|
||||
const xf = blk(60);
|
||||
|
||||
// round 1
|
||||
a = b + rol32((((c ^ d) & b) ^ d) + a + x0 + 0xd76aa478, 7);
|
||||
d = a + rol32((((b ^ c) & a) ^ c) + d + x1 + 0xe8c7b756, 12);
|
||||
c = d + rol32((((a ^ b) & d) ^ b) + c + x2 + 0x242070db, 17);
|
||||
b = c + rol32((((d ^ a) & c) ^ a) + b + x3 + 0xc1bdceee, 22);
|
||||
a = b + rol32((((c ^ d) & b) ^ d) + a + x4 + 0xf57c0faf, 7);
|
||||
d = a + rol32((((b ^ c) & a) ^ c) + d + x5 + 0x4787c62a, 12);
|
||||
c = d + rol32((((a ^ b) & d) ^ b) + c + x6 + 0xa8304613, 17);
|
||||
b = c + rol32((((d ^ a) & c) ^ a) + b + x7 + 0xfd469501, 22);
|
||||
a = b + rol32((((c ^ d) & b) ^ d) + a + x8 + 0x698098d8, 7);
|
||||
d = a + rol32((((b ^ c) & a) ^ c) + d + x9 + 0x8b44f7af, 12);
|
||||
c = d + rol32((((a ^ b) & d) ^ b) + c + xa + 0xffff5bb1, 17);
|
||||
b = c + rol32((((d ^ a) & c) ^ a) + b + xb + 0x895cd7be, 22);
|
||||
a = b + rol32((((c ^ d) & b) ^ d) + a + xc + 0x6b901122, 7);
|
||||
d = a + rol32((((b ^ c) & a) ^ c) + d + xd + 0xfd987193, 12);
|
||||
c = d + rol32((((a ^ b) & d) ^ b) + c + xe + 0xa679438e, 17);
|
||||
b = c + rol32((((d ^ a) & c) ^ a) + b + xf + 0x49b40821, 22);
|
||||
|
||||
// round 2
|
||||
a = b + rol32((((b ^ c) & d) ^ c) + a + x1 + 0xf61e2562, 5);
|
||||
d = a + rol32((((a ^ b) & c) ^ b) + d + x6 + 0xc040b340, 9);
|
||||
c = d + rol32((((d ^ a) & b) ^ a) + c + xb + 0x265e5a51, 14);
|
||||
b = c + rol32((((c ^ d) & a) ^ d) + b + x0 + 0xe9b6c7aa, 20);
|
||||
a = b + rol32((((b ^ c) & d) ^ c) + a + x5 + 0xd62f105d, 5);
|
||||
d = a + rol32((((a ^ b) & c) ^ b) + d + xa + 0x02441453, 9);
|
||||
c = d + rol32((((d ^ a) & b) ^ a) + c + xf + 0xd8a1e681, 14);
|
||||
b = c + rol32((((c ^ d) & a) ^ d) + b + x4 + 0xe7d3fbc8, 20);
|
||||
a = b + rol32((((b ^ c) & d) ^ c) + a + x9 + 0x21e1cde6, 5);
|
||||
d = a + rol32((((a ^ b) & c) ^ b) + d + xe + 0xc33707d6, 9);
|
||||
c = d + rol32((((d ^ a) & b) ^ a) + c + x3 + 0xf4d50d87, 14);
|
||||
b = c + rol32((((c ^ d) & a) ^ d) + b + x8 + 0x455a14ed, 20);
|
||||
a = b + rol32((((b ^ c) & d) ^ c) + a + xd + 0xa9e3e905, 5);
|
||||
d = a + rol32((((a ^ b) & c) ^ b) + d + x2 + 0xfcefa3f8, 9);
|
||||
c = d + rol32((((d ^ a) & b) ^ a) + c + x7 + 0x676f02d9, 14);
|
||||
b = c + rol32((((c ^ d) & a) ^ d) + b + xc + 0x8d2a4c8a, 20);
|
||||
|
||||
// round 3
|
||||
a = b + rol32((b ^ c ^ d) + a + x5 + 0xfffa3942, 4);
|
||||
d = a + rol32((a ^ b ^ c) + d + x8 + 0x8771f681, 11);
|
||||
c = d + rol32((d ^ a ^ b) + c + xb + 0x6d9d6122, 16);
|
||||
b = c + rol32((c ^ d ^ a) + b + xe + 0xfde5380c, 23);
|
||||
a = b + rol32((b ^ c ^ d) + a + x1 + 0xa4beea44, 4);
|
||||
d = a + rol32((a ^ b ^ c) + d + x4 + 0x4bdecfa9, 11);
|
||||
c = d + rol32((d ^ a ^ b) + c + x7 + 0xf6bb4b60, 16);
|
||||
b = c + rol32((c ^ d ^ a) + b + xa + 0xbebfbc70, 23);
|
||||
a = b + rol32((b ^ c ^ d) + a + xd + 0x289b7ec6, 4);
|
||||
d = a + rol32((a ^ b ^ c) + d + x0 + 0xeaa127fa, 11);
|
||||
c = d + rol32((d ^ a ^ b) + c + x3 + 0xd4ef3085, 16);
|
||||
b = c + rol32((c ^ d ^ a) + b + x6 + 0x04881d05, 23);
|
||||
a = b + rol32((b ^ c ^ d) + a + x9 + 0xd9d4d039, 4);
|
||||
d = a + rol32((a ^ b ^ c) + d + xc + 0xe6db99e5, 11);
|
||||
c = d + rol32((d ^ a ^ b) + c + xf + 0x1fa27cf8, 16);
|
||||
b = c + rol32((c ^ d ^ a) + b + x2 + 0xc4ac5665, 23);
|
||||
|
||||
// round 4
|
||||
a = b + rol32((c ^ (b | ~d)) + a + x0 + 0xf4292244, 6);
|
||||
d = a + rol32((b ^ (a | ~c)) + d + x7 + 0x432aff97, 10);
|
||||
c = d + rol32((a ^ (d | ~b)) + c + xe + 0xab9423a7, 15);
|
||||
b = c + rol32((d ^ (c | ~a)) + b + x5 + 0xfc93a039, 21);
|
||||
a = b + rol32((c ^ (b | ~d)) + a + xc + 0x655b59c3, 6);
|
||||
d = a + rol32((b ^ (a | ~c)) + d + x3 + 0x8f0ccc92, 10);
|
||||
c = d + rol32((a ^ (d | ~b)) + c + xa + 0xffeff47d, 15);
|
||||
b = c + rol32((d ^ (c | ~a)) + b + x1 + 0x85845dd1, 21);
|
||||
a = b + rol32((c ^ (b | ~d)) + a + x8 + 0x6fa87e4f, 6);
|
||||
d = a + rol32((b ^ (a | ~c)) + d + xf + 0xfe2ce6e0, 10);
|
||||
c = d + rol32((a ^ (d | ~b)) + c + x6 + 0xa3014314, 15);
|
||||
b = c + rol32((d ^ (c | ~a)) + b + xd + 0x4e0811a1, 21);
|
||||
a = b + rol32((c ^ (b | ~d)) + a + x4 + 0xf7537e82, 6);
|
||||
d = a + rol32((b ^ (a | ~c)) + d + xb + 0xbd3af235, 10);
|
||||
c = d + rol32((a ^ (d | ~b)) + c + x2 + 0x2ad7d2bb, 15);
|
||||
b = c + rol32((d ^ (c | ~a)) + b + x9 + 0xeb86d391, 21);
|
||||
|
||||
this.#a = (this.#a + a) >>> 0;
|
||||
this.#b = (this.#b + b) >>> 0;
|
||||
this.#c = (this.#c + c) >>> 0;
|
||||
this.#d = (this.#d + d) >>> 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update internal state
|
||||
* @param data data to update, data cannot exceed 2^32 bytes
|
||||
*/
|
||||
update(data: Message): this {
|
||||
let msg: Uint8Array;
|
||||
|
||||
if (typeof data === "string") {
|
||||
msg = new TextEncoder().encode(data as string);
|
||||
} else if (typeof data === "object") {
|
||||
if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
|
||||
msg = new Uint8Array(data);
|
||||
} else {
|
||||
throw new Error(TYPE_ERROR_MSG);
|
||||
}
|
||||
} else {
|
||||
throw new Error(TYPE_ERROR_MSG);
|
||||
}
|
||||
|
||||
let pos = this.#pos;
|
||||
const free = BLOCK_SIZE - pos;
|
||||
|
||||
if (msg.length < free) {
|
||||
this.#block.set(msg, pos);
|
||||
pos += msg.length;
|
||||
} else {
|
||||
// hash first block
|
||||
this.#block.set(msg.slice(0, free), pos);
|
||||
this.hash(this.#block);
|
||||
|
||||
// hash as many blocks as possible
|
||||
let i = free;
|
||||
while (i + BLOCK_SIZE <= msg.length) {
|
||||
this.hash(msg.slice(i, i + BLOCK_SIZE));
|
||||
i += BLOCK_SIZE;
|
||||
}
|
||||
|
||||
// store leftover
|
||||
this.#block.fill(0).set(msg.slice(i), 0);
|
||||
pos = msg.length - i;
|
||||
}
|
||||
|
||||
this.#pos = pos;
|
||||
this.addLength(msg.length);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns final hash */
|
||||
digest(): ArrayBuffer {
|
||||
let padLen = BLOCK_SIZE - this.#pos;
|
||||
if (padLen < 9) padLen += BLOCK_SIZE;
|
||||
|
||||
const pad = new Uint8Array(padLen);
|
||||
|
||||
pad[0] = 0x80;
|
||||
|
||||
const n0 = this.#n0 << 3;
|
||||
const n1 = (this.#n1 << 3) | (this.#n0 >>> 29);
|
||||
pad[pad.length - 8] = n0 & 0xff;
|
||||
pad[pad.length - 7] = (n0 >>> 8) & 0xff;
|
||||
pad[pad.length - 6] = (n0 >>> 16) & 0xff;
|
||||
pad[pad.length - 5] = (n0 >>> 24) & 0xff;
|
||||
pad[pad.length - 4] = n1 & 0xff;
|
||||
pad[pad.length - 3] = (n1 >>> 8) & 0xff;
|
||||
pad[pad.length - 2] = (n1 >>> 16) & 0xff;
|
||||
pad[pad.length - 1] = (n1 >>> 24) & 0xff;
|
||||
|
||||
this.update(pad.buffer);
|
||||
|
||||
const hash = new ArrayBuffer(16);
|
||||
const hashView = new DataView(hash);
|
||||
hashView.setUint32(0, this.#a, true);
|
||||
hashView.setUint32(4, this.#b, true);
|
||||
hashView.setUint32(8, this.#c, true);
|
||||
hashView.setUint32(12, this.#d, true);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hash as a string of given format
|
||||
* @param format format of output string (hex or base64). Default is hex
|
||||
*/
|
||||
toString(format: "hex" | "base64" = "hex"): string {
|
||||
const hash = this.digest();
|
||||
|
||||
switch (format) {
|
||||
case "hex":
|
||||
return hex.encodeToString(new Uint8Array(hash));
|
||||
case "base64":
|
||||
const data = new Uint8Array(hash);
|
||||
let dataString = "";
|
||||
for (let i = 0; i < data.length; ++i) {
|
||||
dataString += String.fromCharCode(data[i]);
|
||||
}
|
||||
return window.btoa(dataString);
|
||||
default:
|
||||
throw new Error("md5: invalid format");
|
||||
}
|
||||
}
|
||||
}
|
56
std/hash/md5_test.ts
Normal file
56
std/hash/md5_test.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
const { test } = Deno;
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import { Md5 } from "./md5.ts";
|
||||
|
||||
const millionAs = "a".repeat(1000000);
|
||||
|
||||
const testSetHex = [
|
||||
["", "d41d8cd98f00b204e9800998ecf8427e"],
|
||||
["abc", "900150983cd24fb0d6963f7d28e17f72"],
|
||||
["deno", "c8772b401bc911da102a5291cc4ec83b"],
|
||||
[
|
||||
"The quick brown fox jumps over the lazy dog",
|
||||
"9e107d9d372bb6826bd81d3542a419d6",
|
||||
],
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"3b0c8ac703f828b04c6c197006d17218",
|
||||
],
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"014842d480b571495a4a0363793f7367",
|
||||
],
|
||||
[millionAs, "7707d6ae4e027c70eea2a935c2296f21"],
|
||||
];
|
||||
|
||||
const testSetBase64 = [
|
||||
["", "1B2M2Y8AsgTpgAmY7PhCfg=="],
|
||||
["abc", "kAFQmDzST7DWlj99KOF/cg=="],
|
||||
["deno", "yHcrQBvJEdoQKlKRzE7IOw=="],
|
||||
["The quick brown fox jumps over the lazy dog", "nhB9nTcrtoJr2B01QqQZ1g=="],
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"OwyKxwP4KLBMbBlwBtFyGA==",
|
||||
],
|
||||
[
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"AUhC1IC1cUlaSgNjeT9zZw==",
|
||||
],
|
||||
[millionAs, "dwfWrk4CfHDuoqk1wilvIQ=="],
|
||||
];
|
||||
|
||||
test("[hash/md5] testMd5Hex", () => {
|
||||
for (const [input, output] of testSetHex) {
|
||||
const md5 = new Md5();
|
||||
assertEquals(md5.update(input).toString(), output);
|
||||
}
|
||||
});
|
||||
|
||||
test("[hash/md5] testMd5Base64", () => {
|
||||
for (const [input, output] of testSetBase64) {
|
||||
const md5 = new Md5();
|
||||
assertEquals(md5.update(input).toString("base64"), output);
|
||||
}
|
||||
});
|
|
@ -36,7 +36,7 @@ const encoder = new TextEncoder();
|
|||
const serverArgs = parse(args) as FileServerArgs;
|
||||
|
||||
const CORSEnabled = serverArgs.cors ? true : false;
|
||||
const target = posix.resolve(serverArgs._[1] ?? "");
|
||||
const target = posix.resolve(serverArgs._[0] ?? "");
|
||||
const addr = `0.0.0.0:${serverArgs.port ?? serverArgs.p ?? 4507}`;
|
||||
|
||||
const MEDIA_TYPES: Record<string, string> = {
|
||||
|
|
|
@ -7,7 +7,15 @@ import { serveFile } from "./file_server.ts";
|
|||
const { test } = Deno;
|
||||
let fileServer: Deno.Process;
|
||||
|
||||
async function startFileServer(): Promise<void> {
|
||||
type FileServerCfg = {
|
||||
target?: string;
|
||||
port?: number;
|
||||
};
|
||||
|
||||
async function startFileServer({
|
||||
target = ".",
|
||||
port = 4507,
|
||||
}: FileServerCfg = {}): Promise<void> {
|
||||
fileServer = Deno.run({
|
||||
cmd: [
|
||||
Deno.execPath(),
|
||||
|
@ -15,8 +23,10 @@ async function startFileServer(): Promise<void> {
|
|||
"--allow-read",
|
||||
"--allow-net",
|
||||
"http/file_server.ts",
|
||||
".",
|
||||
target,
|
||||
"--cors",
|
||||
"-p",
|
||||
`${port}`,
|
||||
],
|
||||
stdout: "piped",
|
||||
stderr: "null",
|
||||
|
@ -40,7 +50,7 @@ async function killFileServer(): Promise<void> {
|
|||
fileServer.stdout!.close();
|
||||
}
|
||||
|
||||
test("file_server serveFile", async (): Promise<void> => {
|
||||
test("file_server serveFile in ./", async (): Promise<void> => {
|
||||
await startFileServer();
|
||||
try {
|
||||
const res = await fetch("http://localhost:4507/README.md");
|
||||
|
@ -57,6 +67,24 @@ test("file_server serveFile", async (): Promise<void> => {
|
|||
}
|
||||
});
|
||||
|
||||
test("file_server serveFile in ./http", async (): Promise<void> => {
|
||||
await startFileServer({ target: "./http" });
|
||||
try {
|
||||
const res = await fetch("http://localhost:4507/README.md");
|
||||
assert(res.headers.has("access-control-allow-origin"));
|
||||
assert(res.headers.has("access-control-allow-headers"));
|
||||
assertEquals(res.headers.get("content-type"), "text/markdown");
|
||||
const downloadedFile = await res.text();
|
||||
const localFile = new TextDecoder().decode(
|
||||
await Deno.readFile("./http/README.md")
|
||||
);
|
||||
console.log(downloadedFile, localFile);
|
||||
assertEquals(downloadedFile, localFile);
|
||||
} finally {
|
||||
await killFileServer();
|
||||
}
|
||||
});
|
||||
|
||||
test("serveDirectory", async function (): Promise<void> {
|
||||
await startFileServer();
|
||||
try {
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
const { test } = Deno;
|
||||
import { readlink, readlinkSync } from "./_fs_readlink.ts";
|
||||
import { assertEquals, assert } from "../../testing/asserts.ts";
|
||||
import * as path from "../path.ts";
|
||||
|
||||
const testDir = Deno.makeTempDirSync();
|
||||
const oldname = testDir + "/oldname";
|
||||
const newname = testDir + "/newname";
|
||||
const oldname = path.join(testDir, "oldname");
|
||||
const newname = path.join(testDir, "newname");
|
||||
|
||||
if (Deno.build.os !== "windows") {
|
||||
if (Deno.build.os === "windows") {
|
||||
Deno.symlinkSync(oldname, newname, { type: "file" });
|
||||
} else {
|
||||
Deno.symlinkSync(oldname, newname);
|
||||
}
|
||||
|
||||
test({
|
||||
name: "readlinkSuccess",
|
||||
ignore: Deno.build.os === "windows",
|
||||
async fn() {
|
||||
const data = await new Promise((res, rej) => {
|
||||
readlink(newname, (err, data) => {
|
||||
|
@ -30,7 +32,6 @@ test({
|
|||
|
||||
test({
|
||||
name: "readlinkEncodeBufferSuccess",
|
||||
ignore: Deno.build.os === "windows",
|
||||
async fn() {
|
||||
const data = await new Promise((res, rej) => {
|
||||
readlink(newname, { encoding: "buffer" }, (err, data) => {
|
||||
|
@ -48,7 +49,6 @@ test({
|
|||
|
||||
test({
|
||||
name: "readlinkSyncSuccess",
|
||||
ignore: Deno.build.os === "windows",
|
||||
fn() {
|
||||
const data = readlinkSync(newname);
|
||||
assertEquals(typeof data, "string");
|
||||
|
@ -58,7 +58,6 @@ test({
|
|||
|
||||
test({
|
||||
name: "readlinkEncodeBufferSuccess",
|
||||
ignore: Deno.build.os === "windows",
|
||||
fn() {
|
||||
const data = readlinkSync(newname, { encoding: "buffer" });
|
||||
assert(data instanceof Uint8Array);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { notImplemented } from "../_utils.ts";
|
||||
import { fromFileUrl } from "../path.ts";
|
||||
|
||||
import {
|
||||
WriteFileOptions,
|
||||
|
@ -10,7 +11,7 @@ import {
|
|||
} from "./_fs_common.ts";
|
||||
|
||||
export function writeFile(
|
||||
pathOrRid: string | number,
|
||||
pathOrRid: string | number | URL,
|
||||
data: string | Uint8Array,
|
||||
optOrCallback: string | CallbackWithError | WriteFileOptions | undefined,
|
||||
callback?: CallbackWithError
|
||||
|
@ -24,6 +25,8 @@ export function writeFile(
|
|||
throw new TypeError("Callback must be a function.");
|
||||
}
|
||||
|
||||
pathOrRid = pathOrRid instanceof URL ? fromFileUrl(pathOrRid) : pathOrRid;
|
||||
|
||||
const flag: string | undefined = isFileOptions(options)
|
||||
? options.flag
|
||||
: undefined;
|
||||
|
@ -65,10 +68,12 @@ export function writeFile(
|
|||
}
|
||||
|
||||
export function writeFileSync(
|
||||
pathOrRid: string | number,
|
||||
pathOrRid: string | number | URL,
|
||||
data: string | Uint8Array,
|
||||
options?: string | WriteFileOptions
|
||||
): void {
|
||||
pathOrRid = pathOrRid instanceof URL ? fromFileUrl(pathOrRid) : pathOrRid;
|
||||
|
||||
const flag: string | undefined = isFileOptions(options)
|
||||
? options.flag
|
||||
: undefined;
|
||||
|
|
|
@ -8,7 +8,9 @@ import {
|
|||
assertThrows,
|
||||
} from "../../testing/asserts.ts";
|
||||
import { writeFile, writeFileSync } from "./_fs_writeFile.ts";
|
||||
import * as path from "../../path/mod.ts";
|
||||
|
||||
const testDataDir = path.resolve(path.join("node", "_fs", "testdata"));
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
|
||||
test("Callback must be a function error", function fn() {
|
||||
|
@ -128,27 +130,6 @@ test("Data is written to correct rid", async function testCorrectWriteUsingRid()
|
|||
assertEquals(decoder.decode(data), "hello world");
|
||||
});
|
||||
|
||||
test("Data is written to correct rid", async function testCorrectWriteUsingRid() {
|
||||
const tempFile: string = await Deno.makeTempFile();
|
||||
const file: Deno.File = await Deno.open(tempFile, {
|
||||
create: true,
|
||||
write: true,
|
||||
read: true,
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
writeFile(file.rid, "hello world", (err) => {
|
||||
if (err) return reject(err);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
Deno.close(file.rid);
|
||||
|
||||
const data = await Deno.readFile(tempFile);
|
||||
await Deno.remove(tempFile);
|
||||
assertEquals(decoder.decode(data), "hello world");
|
||||
});
|
||||
|
||||
test("Data is written to correct file", async function testCorrectWriteUsingPath() {
|
||||
const res = await new Promise((resolve) => {
|
||||
writeFile("_fs_writeFile_test_file.txt", "hello world", resolve);
|
||||
|
@ -160,6 +141,27 @@ test("Data is written to correct file", async function testCorrectWriteUsingPath
|
|||
assertEquals(decoder.decode(data), "hello world");
|
||||
});
|
||||
|
||||
test("Path can be an URL", async function testCorrectWriteUsingURL() {
|
||||
const url = new URL(
|
||||
Deno.build.os === "windows"
|
||||
? "file:///" +
|
||||
path
|
||||
.join(testDataDir, "_fs_writeFile_test_file_url.txt")
|
||||
.replace(/\\/g, "/")
|
||||
: "file://" + path.join(testDataDir, "_fs_writeFile_test_file_url.txt")
|
||||
);
|
||||
const filePath = path.fromFileUrl(url);
|
||||
const res = await new Promise((resolve) => {
|
||||
writeFile(url, "hello world", resolve);
|
||||
});
|
||||
assert(res === null);
|
||||
|
||||
const data = await Deno.readFile(filePath);
|
||||
await Deno.remove(filePath);
|
||||
assertEquals(res, null);
|
||||
assertEquals(decoder.decode(data), "hello world");
|
||||
});
|
||||
|
||||
test("Mode is correctly set", async function testCorrectFileMode() {
|
||||
if (Deno.build.os === "windows") return;
|
||||
const filename = "_fs_writeFile_test_file.txt";
|
||||
|
@ -225,6 +227,23 @@ test("Data is written synchronously to correct file", function testCorrectWriteS
|
|||
assertEquals(decoder.decode(data), "hello world");
|
||||
});
|
||||
|
||||
test("sync: Path can be an URL", function testCorrectWriteSyncUsingURL() {
|
||||
const filePath = path.join(
|
||||
testDataDir,
|
||||
"_fs_writeFileSync_test_file_url.txt"
|
||||
);
|
||||
const url = new URL(
|
||||
Deno.build.os === "windows"
|
||||
? "file:///" + filePath.replace(/\\/g, "/")
|
||||
: "file://" + filePath
|
||||
);
|
||||
writeFileSync(url, "hello world");
|
||||
|
||||
const data = Deno.readFileSync(filePath);
|
||||
Deno.removeSync(filePath);
|
||||
assertEquals(decoder.decode(data), "hello world");
|
||||
});
|
||||
|
||||
test("Mode is correctly set when writing synchronously", function testCorrectFileModeSync() {
|
||||
if (Deno.build.os === "windows") return;
|
||||
const filename = "_fs_writeFileSync_test_file.txt";
|
||||
|
|
|
@ -4,7 +4,7 @@ import { WriteFileOptions } from "../_fs_common.ts";
|
|||
import { writeFile as writeFileCallback } from "../_fs_writeFile.ts";
|
||||
|
||||
export function writeFile(
|
||||
pathOrRid: string | number,
|
||||
pathOrRid: string | number | URL,
|
||||
data: string | Uint8Array,
|
||||
options?: string | WriteFileOptions
|
||||
): Promise<void> {
|
||||
|
|
|
@ -31,6 +31,7 @@ import * as nodeQueryString from "./querystring.ts";
|
|||
|
||||
import * as path from "../path/mod.ts";
|
||||
import { assert } from "../testing/asserts.ts";
|
||||
import { pathToFileURL, fileURLToPath } from "./url.ts";
|
||||
|
||||
const CHAR_FORWARD_SLASH = "/".charCodeAt(0);
|
||||
const CHAR_BACKWARD_SLASH = "\\".charCodeAt(0);
|
||||
|
@ -1162,103 +1163,6 @@ function stripBOM(content: string): string {
|
|||
return content;
|
||||
}
|
||||
|
||||
const forwardSlashRegEx = /\//g;
|
||||
const CHAR_LOWERCASE_A = "a".charCodeAt(0);
|
||||
const CHAR_LOWERCASE_Z = "z".charCodeAt(0);
|
||||
|
||||
function getPathFromURLWin32(url: URL): string {
|
||||
// const hostname = url.hostname;
|
||||
let pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === "%") {
|
||||
const third = pathname.codePointAt(n + 2)! | 0x20;
|
||||
if (
|
||||
(pathname[n + 1] === "2" && third === 102) || // 2f 2F /
|
||||
(pathname[n + 1] === "5" && third === 99)
|
||||
) {
|
||||
// 5c 5C \
|
||||
throw new Error(
|
||||
"Invalid file url path: must not include encoded \\ or / characters"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
pathname = pathname.replace(forwardSlashRegEx, "\\");
|
||||
pathname = decodeURIComponent(pathname);
|
||||
// TODO: handle windows hostname case (needs bindings)
|
||||
const letter = pathname.codePointAt(1)! | 0x20;
|
||||
const sep = pathname[2];
|
||||
if (
|
||||
letter < CHAR_LOWERCASE_A ||
|
||||
letter > CHAR_LOWERCASE_Z || // a..z A..Z
|
||||
sep !== ":"
|
||||
) {
|
||||
throw new Error("Invalid file URL path: must be absolute");
|
||||
}
|
||||
return pathname.slice(1);
|
||||
}
|
||||
|
||||
function getPathFromURLPosix(url: URL): string {
|
||||
if (url.hostname !== "") {
|
||||
throw new Error("Invalid file URL host");
|
||||
}
|
||||
const pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === "%") {
|
||||
const third = pathname.codePointAt(n + 2)! | 0x20;
|
||||
if (pathname[n + 1] === "2" && third === 102) {
|
||||
throw new Error(
|
||||
"Invalid file URL path: must not include encoded / characters"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return decodeURIComponent(pathname);
|
||||
}
|
||||
|
||||
function fileURLToPath(path: string | URL): string {
|
||||
if (typeof path === "string") {
|
||||
path = new URL(path);
|
||||
}
|
||||
if (path.protocol !== "file:") {
|
||||
throw new Error("Protocol has to be file://");
|
||||
}
|
||||
return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path);
|
||||
}
|
||||
|
||||
const percentRegEx = /%/g;
|
||||
const backslashRegEx = /\\/g;
|
||||
const newlineRegEx = /\n/g;
|
||||
const carriageReturnRegEx = /\r/g;
|
||||
const tabRegEx = /\t/g;
|
||||
function pathToFileURL(filepath: string): URL {
|
||||
let resolved = path.resolve(filepath);
|
||||
// path.resolve strips trailing slashes so we must add them back
|
||||
const filePathLast = filepath.charCodeAt(filepath.length - 1);
|
||||
if (
|
||||
(filePathLast === CHAR_FORWARD_SLASH ||
|
||||
(isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&
|
||||
resolved[resolved.length - 1] !== path.sep
|
||||
) {
|
||||
resolved += "/";
|
||||
}
|
||||
const outURL = new URL("file://");
|
||||
if (resolved.includes("%")) resolved = resolved.replace(percentRegEx, "%25");
|
||||
// In posix, "/" is a valid character in paths
|
||||
if (!isWindows && resolved.includes("\\")) {
|
||||
resolved = resolved.replace(backslashRegEx, "%5C");
|
||||
}
|
||||
if (resolved.includes("\n")) {
|
||||
resolved = resolved.replace(newlineRegEx, "%0A");
|
||||
}
|
||||
if (resolved.includes("\r")) {
|
||||
resolved = resolved.replace(carriageReturnRegEx, "%0D");
|
||||
}
|
||||
if (resolved.includes("\t")) resolved = resolved.replace(tabRegEx, "%09");
|
||||
outURL.pathname = resolved;
|
||||
return outURL;
|
||||
}
|
||||
|
||||
export const builtinModules = Module.builtinModules;
|
||||
export const createRequire = Module.createRequire;
|
||||
export default Module;
|
||||
|
|
|
@ -72,7 +72,7 @@ function getPathFromURLWin(url: URL): string {
|
|||
return `\\\\${hostname}${pathname}`;
|
||||
} else {
|
||||
// Otherwise, it's a local path that requires a drive letter
|
||||
const letter = pathname.codePointAt(1) || 0x20;
|
||||
const letter = pathname.codePointAt(1)! | 0x20;
|
||||
const sep = pathname[2];
|
||||
if (
|
||||
letter < CHAR_LOWERCASE_A ||
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* the cli's API is stable. In the future when std becomes stable, likely we
|
||||
* will match versions with cli as we have in the past.
|
||||
*/
|
||||
export const VERSION = "0.52.0";
|
||||
export const VERSION = "0.53.0";
|
||||
|
|
|
@ -18,20 +18,20 @@ from http_benchmark import http_benchmark
|
|||
import throughput_benchmark
|
||||
import http_server
|
||||
|
||||
# The list of the tuples of the benchmark name and arguments
|
||||
# The list of the tuples of the benchmark name, arguments and return code
|
||||
exec_time_benchmarks = [
|
||||
("hello", ["run", "cli/tests/002_hello.ts"]),
|
||||
("relative_import", ["run", "cli/tests/003_relative_import.ts"]),
|
||||
("error_001", ["run", "cli/tests/error_001.ts"]),
|
||||
("cold_hello", ["run", "--reload", "cli/tests/002_hello.ts"]),
|
||||
("hello", ["run", "cli/tests/002_hello.ts"], None),
|
||||
("relative_import", ["run", "cli/tests/003_relative_import.ts"], None),
|
||||
("error_001", ["run", "cli/tests/error_001.ts"], 1),
|
||||
("cold_hello", ["run", "--reload", "cli/tests/002_hello.ts"], None),
|
||||
("cold_relative_import",
|
||||
["run", "--reload", "cli/tests/003_relative_import.ts"]),
|
||||
["run", "--reload", "cli/tests/003_relative_import.ts"], None),
|
||||
("workers_startup",
|
||||
["run", "--allow-read", "cli/tests/workers_startup_bench.ts"]),
|
||||
["run", "--allow-read", "cli/tests/workers_startup_bench.ts"], None),
|
||||
("workers_round_robin",
|
||||
["run", "--allow-read", "cli/tests/workers_round_robin_bench.ts"]),
|
||||
("text_decoder", ["run", "cli/tests/text_decoder_perf.js"]),
|
||||
("text_encoder", ["run", "cli/tests/text_encoder_perf.js"]),
|
||||
["run", "--allow-read", "cli/tests/workers_round_robin_bench.ts"], None),
|
||||
("text_decoder", ["run", "cli/tests/text_decoder_perf.js"], None),
|
||||
("text_encoder", ["run", "cli/tests/text_encoder_perf.js"], None),
|
||||
]
|
||||
|
||||
|
||||
|
@ -145,7 +145,7 @@ def run_throughput(deno_exe):
|
|||
def run_strace_benchmarks(deno_exe, new_data):
|
||||
thread_count = {}
|
||||
syscall_count = {}
|
||||
for (name, args) in exec_time_benchmarks:
|
||||
for (name, args, _) in exec_time_benchmarks:
|
||||
s = get_strace_summary([deno_exe] + args)
|
||||
thread_count[name] = s["clone"]["calls"] + 1
|
||||
syscall_count[name] = s["total"]["calls"]
|
||||
|
@ -164,12 +164,15 @@ def find_max_mem_in_bytes(time_v_output):
|
|||
|
||||
def run_max_mem_benchmark(deno_exe):
|
||||
results = {}
|
||||
for (name, args) in exec_time_benchmarks:
|
||||
for (name, args, return_code) in exec_time_benchmarks:
|
||||
cmd = ["/usr/bin/time", "-v", deno_exe] + args
|
||||
try:
|
||||
out = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
except subprocess.CalledProcessError as e:
|
||||
if (return_code is e.returncode):
|
||||
pass
|
||||
else:
|
||||
raise e
|
||||
mem = find_max_mem_in_bytes(out)
|
||||
results[name] = mem
|
||||
return results
|
||||
|
@ -178,16 +181,22 @@ def run_max_mem_benchmark(deno_exe):
|
|||
def run_exec_time(deno_exe, build_dir):
|
||||
hyperfine_exe = third_party.get_prebuilt_tool_path("hyperfine")
|
||||
benchmark_file = os.path.join(build_dir, "hyperfine_results.json")
|
||||
run([
|
||||
hyperfine_exe, "--ignore-failure", "--export-json", benchmark_file,
|
||||
"--warmup", "3"
|
||||
] + [
|
||||
deno_exe + " " + " ".join(args) for [_, args] in exec_time_benchmarks
|
||||
|
||||
def benchmark_command(deno_exe, args, return_code):
|
||||
# Bash test which asserts the return code value of the previous command
|
||||
# $? contains the return code of the previous command
|
||||
return_code_test = "; test $? -eq {}".format(
|
||||
return_code) if return_code is not None else ""
|
||||
return "{} {}{}".format(deno_exe, " ".join(args), return_code_test)
|
||||
|
||||
run([hyperfine_exe, "--export-json", benchmark_file, "--warmup", "3"] + [
|
||||
benchmark_command(deno_exe, args, return_code)
|
||||
for (_, args, return_code) in exec_time_benchmarks
|
||||
])
|
||||
hyperfine_results = read_json(benchmark_file)
|
||||
results = {}
|
||||
for [[name, _], data] in zip(exec_time_benchmarks,
|
||||
hyperfine_results["results"]):
|
||||
for [[name, _, _], data] in zip(exec_time_benchmarks,
|
||||
hyperfine_results["results"]):
|
||||
results[name] = {
|
||||
"mean": data["mean"],
|
||||
"stddev": data["stddev"],
|
||||
|
|
|
@ -122,6 +122,34 @@ class ContentTypeHandler(QuietSimpleHTTPRequestHandler):
|
|||
self.wfile.write(bytes("export const foo = 'foo';"))
|
||||
return
|
||||
|
||||
if "type_directives_redirect.js" in self.path:
|
||||
self.protocol_version = "HTTP/1.1"
|
||||
self.send_response(200, 'OK')
|
||||
self.send_header('Content-type', 'application/javascript')
|
||||
self.send_header(
|
||||
'X-TypeScript-Types',
|
||||
'http://localhost:4547/xTypeScriptTypesRedirect.d.ts')
|
||||
self.end_headers()
|
||||
self.wfile.write(bytes("export const foo = 'foo';"))
|
||||
return
|
||||
|
||||
if "xTypeScriptTypesRedirect.d.ts" in self.path:
|
||||
self.protocol_version = "HTTP/1.1"
|
||||
self.send_response(200, 'OK')
|
||||
self.send_header('Content-type', 'application/typescript')
|
||||
self.end_headers()
|
||||
self.wfile.write(
|
||||
bytes("import './xTypeScriptTypesRedirected.d.ts';"))
|
||||
return
|
||||
|
||||
if "xTypeScriptTypesRedirected.d.ts" in self.path:
|
||||
self.protocol_version = "HTTP/1.1"
|
||||
self.send_response(200, 'OK')
|
||||
self.send_header('Content-type', 'application/typescript')
|
||||
self.end_headers()
|
||||
self.wfile.write(bytes("export const foo: 'foo';"))
|
||||
return
|
||||
|
||||
if "xTypeScriptTypes.d.ts" in self.path:
|
||||
self.protocol_version = "HTTP/1.1"
|
||||
self.send_response(200, 'OK')
|
||||
|
|
|
@ -61,7 +61,8 @@ def eslint():
|
|||
"eslint")
|
||||
# Find all *directories* in the main repo that contain .ts/.js files.
|
||||
source_files = get_sources(root_path, [
|
||||
"*.js", "*.ts", ":!:std/**/testdata/*", ":!:std/**/node_modules/*",
|
||||
"*.js", "*.ts", ":!:cli/tests/swc_syntax_error.ts",
|
||||
":!:std/**/testdata/*", ":!:std/**/node_modules/*",
|
||||
":!:cli/compilers/wasm_wrap.js", ":!:cli/tests/error_syntax.js"
|
||||
])
|
||||
if source_files:
|
||||
|
|
Loading…
Add table
Reference in a new issue