summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Finch <andyfinch7@gmail.com>2020-02-01 03:02:23 -0800
committerGitHub <noreply@github.com>2020-02-01 12:02:23 +0100
commit4f8a5c0239cd633ea3fd15a27046da3edee2b2f2 (patch)
tree80467fdd1132a44dc7fce01d73261693ee6c7fb5
parent2cd3994902fb6a4d4d0603c839a78503d792b96a (diff)
feat: support crate imports in deno_typescript (#3814)
Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
-rw-r--r--cli/build.rs21
-rw-r--r--core/lib.rs2
-rw-r--r--core/modules.rs20
-rw-r--r--deno_typescript/compiler_main.js4
-rw-r--r--deno_typescript/lib.rs19
-rw-r--r--deno_typescript/ops.rs45
6 files changed, 85 insertions, 26 deletions
diff --git a/cli/build.rs b/cli/build.rs
index 7e073c8ff..e75b09d74 100644
--- a/cli/build.rs
+++ b/cli/build.rs
@@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+use deno_core::include_crate_modules;
use deno_core::CoreOp;
use deno_core::Isolate;
use deno_core::Op;
@@ -47,6 +48,8 @@ fn main() {
deno_typescript::ts_version()
);
+ let extern_crate_modules = include_crate_modules![deno_core];
+
// The generation of snapshots is slow and often unnecessary. Until we figure
// out how to speed it up, or avoid it when unnecessary, this env var provides
// an escape hatch for the impatient hacker in need of faster incremental
@@ -65,9 +68,12 @@ fn main() {
let bundle_path = o.join("CLI_SNAPSHOT.js");
let snapshot_path = o.join("CLI_SNAPSHOT.bin");
- let main_module_name =
- deno_typescript::compile_bundle(&bundle_path, root_names)
- .expect("Bundle compilation failed");
+ let main_module_name = deno_typescript::compile_bundle(
+ &bundle_path,
+ root_names,
+ Some(extern_crate_modules.clone()),
+ )
+ .expect("Bundle compilation failed");
assert!(bundle_path.exists());
let runtime_isolate = &mut Isolate::new(StartupData::None, true);
@@ -102,9 +108,12 @@ fn main() {
c.join("js/lib.deno.ns.d.ts"),
);
- let main_module_name =
- deno_typescript::compile_bundle(&bundle_path, root_names)
- .expect("Bundle compilation failed");
+ let main_module_name = deno_typescript::compile_bundle(
+ &bundle_path,
+ root_names,
+ Some(extern_crate_modules),
+ )
+ .expect("Bundle compilation failed");
assert!(bundle_path.exists());
let runtime_isolate = &mut Isolate::new(StartupData::None, true);
diff --git a/core/lib.rs b/core/lib.rs
index 91f91a1c9..2fcfa178b 100644
--- a/core/lib.rs
+++ b/core/lib.rs
@@ -45,3 +45,5 @@ pub fn v8_version() -> &'static str {
fn test_v8_version() {
assert!(v8_version().len() > 3);
}
+
+crate_modules!();
diff --git a/core/modules.rs b/core/modules.rs
index 21c2481dd..c02bd4cab 100644
--- a/core/modules.rs
+++ b/core/modules.rs
@@ -449,6 +449,26 @@ impl fmt::Display for Deps {
}
}
+#[macro_export]
+macro_rules! crate_modules {
+ () => {
+ pub const DENO_CRATE_PATH: &'static str = env!("CARGO_MANIFEST_DIR");
+ };
+}
+
+#[macro_export]
+macro_rules! include_crate_modules {
+ ( $( $x:ident ),* ) => {
+ {
+ let mut temp: HashMap<String, String> = HashMap::new();
+ $(
+ temp.insert(stringify!($x).to_string(), $x::DENO_CRATE_PATH.to_string());
+ )*
+ temp
+ }
+ };
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/deno_typescript/compiler_main.js b/deno_typescript/compiler_main.js
index 94b38e070..013d6e157 100644
--- a/deno_typescript/compiler_main.js
+++ b/deno_typescript/compiler_main.js
@@ -184,8 +184,8 @@ class Host {
fileName = moduleMap.get(fileName);
}
- const { sourceCode, moduleName } = dispatch("readFile", {
- fileName,
+ const { sourceCode, moduleName } = dispatch("loadModule", {
+ moduleUrl: fileName,
languageVersion,
shouldCreateNewSourceFile
});
diff --git a/deno_typescript/lib.rs b/deno_typescript/lib.rs
index 1bf6eb351..7977b7cfe 100644
--- a/deno_typescript/lib.rs
+++ b/deno_typescript/lib.rs
@@ -16,6 +16,7 @@ use deno_core::StartupData;
use deno_core::ZeroCopyBuf;
pub use ops::EmitResult;
use ops::WrittenFile;
+use std::collections::HashMap;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
@@ -32,6 +33,8 @@ pub fn ts_version() -> String {
pkg["version"].as_str().unwrap().to_string()
}
+type ExternCrateModules = HashMap<String, String>;
+
#[derive(Debug)]
pub struct TSState {
bundle: bool,
@@ -40,6 +43,7 @@ pub struct TSState {
/// A list of files emitted by typescript. WrittenFile is tuple of the form
/// (url, corresponding_module, source_code)
written_files: Vec<WrittenFile>,
+ extern_crate_modules: ExternCrateModules,
}
fn compiler_op<D>(
@@ -62,21 +66,27 @@ pub struct TSIsolate {
}
impl TSIsolate {
- fn new(bundle: bool) -> TSIsolate {
+ fn new(
+ bundle: bool,
+ maybe_extern_crate_modules: Option<ExternCrateModules>,
+ ) -> TSIsolate {
let mut isolate = Isolate::new(StartupData::None, false);
js_check(isolate.execute("assets/typescript.js", TYPESCRIPT_CODE));
js_check(isolate.execute("compiler_main.js", COMPILER_CODE));
+ let extern_crate_modules = maybe_extern_crate_modules.unwrap_or_default();
+
let state = Arc::new(Mutex::new(TSState {
bundle,
exit_code: 0,
emit_result: None,
written_files: Vec::new(),
+ extern_crate_modules,
}));
isolate.register_op(
- "readFile",
- compiler_op(state.clone(), ops::json_op(ops::read_file)),
+ "loadModule",
+ compiler_op(state.clone(), ops::json_op(ops::load_module)),
);
isolate
.register_op("exit", compiler_op(state.clone(), ops::json_op(ops::exit)));
@@ -125,8 +135,9 @@ impl TSIsolate {
pub fn compile_bundle(
bundle_filename: &Path,
root_names: Vec<PathBuf>,
+ extern_crate_modules: Option<ExternCrateModules>,
) -> Result<String, ErrBox> {
- let ts_isolate = TSIsolate::new(true);
+ let ts_isolate = TSIsolate::new(true, extern_crate_modules);
let config_json = serde_json::json!({
"compilerOptions": {
diff --git a/deno_typescript/ops.rs b/deno_typescript/ops.rs
index f76662620..f9b244397 100644
--- a/deno_typescript/ops.rs
+++ b/deno_typescript/ops.rs
@@ -35,16 +35,16 @@ pub fn json_op(d: Dispatcher) -> impl Fn(&mut TSState, &[u8]) -> CoreOp {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
-struct ReadFile {
- file_name: String,
+struct LoadModule {
+ module_url: String,
language_version: Option<i32>,
should_create_new_source_file: bool,
}
-pub fn read_file(_s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
- let v: ReadFile = serde_json::from_value(v)?;
- let (module_name, source_code) = if v.file_name.starts_with("$asset$/") {
- let asset = v.file_name.replace("$asset$/", "");
+pub fn load_module(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
+ let v: LoadModule = serde_json::from_value(v)?;
+ let (module_name, source_code) = if v.module_url.starts_with("$asset$/") {
+ let asset = v.module_url.replace("$asset$/", "");
let source_code = match crate::get_asset(&asset) {
Some(code) => code.to_string(),
@@ -58,14 +58,31 @@ pub fn read_file(_s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
(asset, source_code)
} else {
- assert!(!v.file_name.starts_with("$assets$"), "you meant $asset$");
- let module_specifier = ModuleSpecifier::resolve_url_or_path(&v.file_name)?;
- let path = module_specifier.as_url().to_file_path().unwrap();
- println!("cargo:rerun-if-changed={}", path.display());
- (
- module_specifier.as_str().to_string(),
- std::fs::read_to_string(&path)?,
- )
+ assert!(!v.module_url.starts_with("$assets$"), "you meant $asset$");
+ let module_specifier = ModuleSpecifier::resolve_url_or_path(&v.module_url)?;
+ let module_url = module_specifier.as_url();
+ match module_url.scheme() {
+ "file" => {
+ let path = module_url.to_file_path().unwrap();
+ println!("cargo:rerun-if-changed={}", path.display());
+ (
+ module_specifier.as_str().to_string(),
+ std::fs::read_to_string(&path)?,
+ )
+ }
+ "crate" => {
+ let crate_name = module_url.host_str().unwrap();
+ // TODO(afinch7) turn failures here into real error messages.
+ let path_prefix = s.extern_crate_modules.get(crate_name).unwrap();
+ let path =
+ std::path::Path::new(path_prefix).join(&module_url.path()[1..]);
+ (
+ module_specifier.as_str().to_string(),
+ std::fs::read_to_string(&path)?,
+ )
+ }
+ _ => unimplemented!(),
+ }
};
Ok(json!({
"moduleName": module_name,