mirror of
https://github.com/denoland/deno.git
synced 2025-01-10 16:11:13 -05:00
feat: support crate imports in deno_typescript (#3814)
Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
This commit is contained in:
parent
2cd3994902
commit
4f8a5c0239
6 changed files with 85 additions and 26 deletions
21
cli/build.rs
21
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);
|
||||
|
|
|
@ -45,3 +45,5 @@ pub fn v8_version() -> &'static str {
|
|||
fn test_v8_version() {
|
||||
assert!(v8_version().len() > 3);
|
||||
}
|
||||
|
||||
crate_modules!();
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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
|
||||
});
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue