0
0
Fork 0
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:
Ryan Dahl 2020-05-23 09:33:53 -04:00
commit f73a47d21c
62 changed files with 992 additions and 283 deletions

View file

@ -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
View file

@ -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",

View file

@ -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

View file

@ -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"

View file

@ -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/",
)
}

View file

@ -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[];

View file

@ -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();

View file

@ -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.");
* }

View file

@ -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}.`
);

View file

@ -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

View file

@ -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,

View file

@ -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)]

View file

@ -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,

View 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";

View 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";

View file

@ -0,0 +1 @@
error: Modules loaded over https:// are not allowed to import modules over http://

View file

@ -0,0 +1 @@
error: Modules loaded over https:// are not allowed to import modules over http://

View file

@ -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"

View file

@ -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"

View file

@ -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.

View file

@ -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
View file

@ -0,0 +1,5 @@
console.log("hello");
setInterval(() => {
console.log("hello from interval");
}, 1000);

View file

@ -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()

View file

@ -0,0 +1,3 @@
for await (const req of s) {
let something:
}

View file

@ -0,0 +1 @@
error: Unexpected token Some(RBrace) at [WILDCARD]syntax_error.ts:3:0

View 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());

View file

@ -0,0 +1,2 @@
Compile [WILDCARD]
SomeClass { someField: "asdf" }

View file

@ -0,0 +1,5 @@
/* eslint-disable */
type Foo = import("./ts_type_imports_foo.ts").Foo;
const foo: Foo = new Map<string, string>();

View 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

View file

@ -0,0 +1 @@
export type Foo = Map<string, number>;

View file

@ -0,0 +1,5 @@
{
"compilerOptions": {
"experimentalDecorators": true
}
}

View file

@ -0,0 +1 @@
import "http://localhost:4545/type_directives_redirect.js";

View 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

View 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);
});

View file

@ -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";

View file

@ -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> {

View file

@ -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",

View file

@ -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"]

View file

@ -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"

View file

@ -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
```

View file

@ -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

View file

@ -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.

View file

@ -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/

View file

@ -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"
```

View file

@ -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

View file

@ -1,2 +0,0 @@
export * from "./colors.ts";
export * from "./sprintf.ts";

View file

@ -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));
}

View file

@ -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
View 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
View 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);
}
});

View file

@ -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> = {

View file

@ -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 {

View file

@ -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);

View file

@ -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;

View file

@ -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";

View file

@ -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> {

View file

@ -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;

View file

@ -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 ||

View file

@ -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";

View file

@ -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"],

View file

@ -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')

View file

@ -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: