Skip to content

Commit eba58b7

Browse files
kevinkassimory
authored andcommitted
Guess extensions on extension not provided (#859)
Fixes #857
1 parent fc1c54d commit eba58b7

File tree

9 files changed

+134
-28
lines changed

9 files changed

+134
-28
lines changed

src/deno_dir.rs

Lines changed: 76 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,41 @@ impl DenoDir {
133133
self: &DenoDir,
134134
module_name: &str,
135135
filename: &str,
136-
) -> DenoResult<String> {
137-
if is_remote(module_name) {
138-
self.fetch_remote_source(module_name, filename)
139-
} else if module_name.starts_with(ASSET_PREFIX) {
136+
) -> DenoResult<CodeFetchOutput> {
137+
if module_name.starts_with(ASSET_PREFIX) {
140138
panic!("Asset resolution should be done in JS, not Rust.");
141-
} else {
142-
assert_eq!(
143-
module_name, filename,
144-
"if a module isn't remote, it should have the same filename"
145-
);
146-
let src = fs::read_to_string(Path::new(filename))?;
147-
Ok(src)
148139
}
140+
let is_module_remote = is_remote(module_name);
141+
let use_extension = |ext| {
142+
let module_name = format!("{}{}", module_name, ext);
143+
let filename = format!("{}{}", filename, ext);
144+
let source_code = if is_module_remote {
145+
self.fetch_remote_source(&module_name, &filename)?
146+
} else {
147+
assert_eq!(
148+
module_name, filename,
149+
"if a module isn't remote, it should have the same filename"
150+
);
151+
fs::read_to_string(Path::new(&filename))?
152+
};
153+
return Ok(CodeFetchOutput {
154+
module_name: module_name.to_string(),
155+
filename: filename.to_string(),
156+
source_code,
157+
maybe_output_code: None,
158+
});
159+
};
160+
let default_attempt = use_extension("");
161+
if default_attempt.is_ok() {
162+
return default_attempt;
163+
}
164+
debug!("Trying {}.ts...", module_name);
165+
let ts_attempt = use_extension(".ts");
166+
if ts_attempt.is_ok() {
167+
return ts_attempt;
168+
}
169+
debug!("Trying {}.js...", module_name);
170+
use_extension(".js")
149171
}
150172

151173
pub fn code_fetch(
@@ -161,16 +183,7 @@ impl DenoDir {
161183
let (module_name, filename) =
162184
self.resolve_module(module_specifier, containing_file)?;
163185

164-
let result = self
165-
.get_source_code(module_name.as_str(), filename.as_str())
166-
.and_then(|source_code| {
167-
Ok(CodeFetchOutput {
168-
module_name,
169-
filename,
170-
source_code,
171-
maybe_output_code: None,
172-
})
173-
});
186+
let result = self.get_source_code(module_name.as_str(), filename.as_str());
174187
let out = match result {
175188
Err(err) => {
176189
if err.kind() == ErrorKind::NotFound {
@@ -420,6 +433,48 @@ fn test_code_fetch() {
420433
//println!("code_fetch_output {:?}", code_fetch_output);
421434
}
422435

436+
#[test]
437+
fn test_code_fetch_no_ext() {
438+
let (_temp_dir, deno_dir) = test_setup();
439+
440+
let cwd = std::env::current_dir().unwrap();
441+
let cwd_string = String::from(cwd.to_str().unwrap()) + "/";
442+
443+
// Assuming cwd is the deno repo root.
444+
let module_specifier = "./js/main";
445+
let containing_file = cwd_string.as_str();
446+
let r = deno_dir.code_fetch(module_specifier, containing_file);
447+
assert!(r.is_ok());
448+
449+
// Test .ts extension
450+
// Assuming cwd is the deno repo root.
451+
let module_specifier = "./js/main";
452+
let containing_file = cwd_string.as_str();
453+
let r = deno_dir.code_fetch(module_specifier, containing_file);
454+
assert!(r.is_ok());
455+
let code_fetch_output = r.unwrap();
456+
// could only test .ends_with to avoid include local abs path
457+
assert!(code_fetch_output.module_name.ends_with("/js/main.ts"));
458+
assert!(code_fetch_output.filename.ends_with("/js/main.ts"));
459+
assert!(code_fetch_output.source_code.len() > 10);
460+
461+
// Test .js extension
462+
// Assuming cwd is the deno repo root.
463+
let module_specifier = "./js/mock_builtin";
464+
let containing_file = cwd_string.as_str();
465+
let r = deno_dir.code_fetch(module_specifier, containing_file);
466+
assert!(r.is_ok());
467+
let code_fetch_output = r.unwrap();
468+
// could only test .ends_with to avoid include local abs path
469+
assert!(
470+
code_fetch_output
471+
.module_name
472+
.ends_with("/js/mock_builtin.js")
473+
);
474+
assert!(code_fetch_output.filename.ends_with("/js/mock_builtin.js"));
475+
assert!(code_fetch_output.source_code.len() > 10);
476+
}
477+
423478
#[test]
424479
fn test_src_file_to_url_1() {
425480
let (_temp_dir, deno_dir) = test_setup();

src/http.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
22

3-
use errors::DenoResult;
3+
use errors;
4+
use errors::{DenoError, DenoResult};
45
use tokio_util;
56

6-
use futures::Future;
7-
use futures::Stream;
7+
use futures;
8+
use futures::future::Either;
9+
use futures::{Future, Stream};
810
use hyper;
911
use hyper::client::Client;
1012
use hyper::client::HttpConnector;
@@ -31,11 +33,25 @@ pub fn get_client() -> Client<Connector, hyper::Body> {
3133
pub fn fetch_sync_string(module_name: &str) -> DenoResult<String> {
3234
let url = module_name.parse::<Uri>().unwrap();
3335
let client = get_client();
34-
let future = client
36+
let fetch_future = client
3537
.get(url)
36-
.and_then(|response| response.into_body().concat2());
37-
let body = tokio_util::block_on(future)?;
38-
Ok(String::from_utf8(body.to_vec()).unwrap())
38+
.map_err(|err| DenoError::from(err))
39+
.and_then(|response| {
40+
if !response.status().is_success() {
41+
return Either::A(futures::future::err(errors::new(
42+
errors::ErrorKind::NotFound,
43+
"module not found".to_string(),
44+
)));
45+
}
46+
Either::B(
47+
response
48+
.into_body()
49+
.concat2()
50+
.map(|body| String::from_utf8(body.to_vec()).unwrap())
51+
.map_err(|err| DenoError::from(err)),
52+
)
53+
});
54+
tokio_util::block_on(fetch_future)
3955
}
4056

4157
/* TODO(ry) Re-enabled this test. Disabling to work around bug in #782.

tests/015_import_no_ext.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { isTSFile, printHello, phNoExt } from "./subdir/mod3";
2+
console.log(isTSFile);
3+
console.log(printHello);
4+
console.log(phNoExt);
5+
6+
import { isMod4 } from "./subdir/mod4";
7+
console.log(isMod4);
8+
9+
import { printHello as ph } from "http://localhost:4545/tests/subdir/mod2";
10+
console.log(ph);

tests/015_import_no_ext.ts.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Downloading http://localhost:4545/tests/subdir/mod2
2+
Downloading http://localhost:4545/tests/subdir/mod2.ts
3+
Downloading http://localhost:4545/tests/subdir/print_hello.ts
4+
true
5+
[Function: printHello]
6+
[Function: printHello]
7+
true
8+
[Function: printHello]

tests/error_006_import_ext_failure.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import "./non-existent";
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
NotFound: Cannot resolve module "./non-existent" from "[WILDCARD]deno/tests/error_006_import_ext_failure.ts"
2+
at maybeError (deno/js/errors.ts:[WILDCARD])
3+
at maybeThrowError (deno/js/errors.ts:[WILDCARD])
4+
at sendSync (deno/js/dispatch.ts:[WILDCARD])
5+
at Object.codeFetch (deno/js/os.ts:[WILDCARD])
6+
at DenoCompiler.resolveModule (deno/js/compiler.ts:[WILDCARD])
7+
at DenoCompiler._resolveModuleName (deno/js/compiler.ts:[WILDCARD])
8+
at moduleNames.map.name (deno/js/compiler.ts:[WILDCARD])
9+
at Array.map (<anonymous>)
10+
at DenoCompiler.resolveModuleNames (deno/js/compiler.ts:[WILDCARD])
11+
at Object.compilerHost.resolveModuleNames (deno/third_party/node_modules/typescript/lib/typescript.js:[WILDCARD])

tests/subdir/mod3.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const isTSFile = false;

tests/subdir/mod3.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const isTSFile = true;
2+
export { printHello } from "./print_hello.ts";
3+
export { printHello as phNoExt } from "./print_hello";

tests/subdir/mod4.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const isMod4 = true;

0 commit comments

Comments
 (0)