2019-09-02 17:07:11 -04:00
|
|
|
use crate::TSState;
|
2020-01-05 11:56:18 -05:00
|
|
|
use deno_core::CoreOp;
|
|
|
|
use deno_core::ErrBox;
|
|
|
|
use deno_core::ModuleSpecifier;
|
|
|
|
use deno_core::Op;
|
2019-09-02 17:07:11 -04:00
|
|
|
use serde::Deserialize;
|
|
|
|
use serde_json::json;
|
|
|
|
use serde_json::Value;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct WrittenFile {
|
|
|
|
pub url: String,
|
|
|
|
pub module_name: String,
|
|
|
|
pub source_code: String,
|
|
|
|
}
|
|
|
|
|
2019-10-02 13:05:48 -04:00
|
|
|
type Dispatcher = fn(state: &mut TSState, args: Value) -> Result<Value, ErrBox>;
|
2019-09-02 17:07:11 -04:00
|
|
|
|
2019-10-02 13:05:48 -04:00
|
|
|
pub fn json_op(d: Dispatcher) -> impl Fn(&mut TSState, &[u8]) -> CoreOp {
|
|
|
|
move |state: &mut TSState, control: &[u8]| {
|
|
|
|
let result = serde_json::from_slice(control)
|
|
|
|
.map_err(ErrBox::from)
|
|
|
|
.and_then(move |args| d(state, args));
|
|
|
|
|
|
|
|
let response = match result {
|
|
|
|
Ok(v) => json!({ "ok": v }),
|
|
|
|
Err(err) => json!({ "err": err.to_string() }),
|
|
|
|
};
|
|
|
|
|
|
|
|
let x = serde_json::to_string(&response).unwrap();
|
|
|
|
let vec = x.into_bytes();
|
|
|
|
Op::Sync(vec.into_boxed_slice())
|
|
|
|
}
|
2019-09-02 17:07:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
struct ReadFile {
|
|
|
|
file_name: String,
|
|
|
|
language_version: Option<i32>,
|
|
|
|
should_create_new_source_file: bool,
|
|
|
|
}
|
|
|
|
|
2019-10-02 13:05:48 -04:00
|
|
|
pub fn read_file(_s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
|
2019-09-02 17:07:11 -04:00
|
|
|
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$/", "");
|
2020-01-12 08:53:32 -05:00
|
|
|
let source_code = crate::get_asset2(&asset)?;
|
2019-09-02 17:07:11 -04:00
|
|
|
(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)?,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
Ok(json!({
|
|
|
|
"moduleName": module_name,
|
|
|
|
"sourceCode": source_code,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
struct WriteFile {
|
|
|
|
file_name: String,
|
|
|
|
data: String,
|
|
|
|
module_name: String,
|
|
|
|
}
|
|
|
|
|
2019-10-02 13:05:48 -04:00
|
|
|
pub fn write_file(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
|
2019-09-02 17:07:11 -04:00
|
|
|
let v: WriteFile = serde_json::from_value(v)?;
|
|
|
|
let module_specifier = ModuleSpecifier::resolve_url_or_path(&v.file_name)?;
|
|
|
|
if s.bundle {
|
|
|
|
std::fs::write(&v.file_name, &v.data)?;
|
|
|
|
}
|
|
|
|
s.written_files.push(WrittenFile {
|
|
|
|
url: module_specifier.as_str().to_string(),
|
|
|
|
module_name: v.module_name,
|
|
|
|
source_code: v.data,
|
|
|
|
});
|
|
|
|
Ok(json!(true))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
struct ResolveModuleNames {
|
|
|
|
module_names: Vec<String>,
|
|
|
|
containing_file: String,
|
|
|
|
}
|
|
|
|
|
2019-10-02 13:05:48 -04:00
|
|
|
pub fn resolve_module_names(
|
|
|
|
_s: &mut TSState,
|
|
|
|
v: Value,
|
|
|
|
) -> Result<Value, ErrBox> {
|
2019-09-02 17:07:11 -04:00
|
|
|
let v: ResolveModuleNames = serde_json::from_value(v).unwrap();
|
|
|
|
let mut resolved = Vec::<String>::new();
|
|
|
|
let referrer = ModuleSpecifier::resolve_url_or_path(&v.containing_file)?;
|
|
|
|
for specifier in v.module_names {
|
2019-09-15 18:36:27 -04:00
|
|
|
if specifier.starts_with("$asset$/") {
|
|
|
|
resolved.push(specifier.clone());
|
|
|
|
} else {
|
|
|
|
let ms = ModuleSpecifier::resolve_import(&specifier, referrer.as_str())?;
|
|
|
|
resolved.push(ms.as_str().to_string());
|
|
|
|
}
|
2019-09-02 17:07:11 -04:00
|
|
|
}
|
|
|
|
Ok(json!(resolved))
|
|
|
|
}
|
|
|
|
|
2020-01-12 06:20:33 -05:00
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
struct FetchAssetArgs {
|
|
|
|
name: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fetch_asset(_s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
|
|
|
|
let args: FetchAssetArgs = serde_json::from_value(v)?;
|
|
|
|
if let Some(source_code) = crate::get_asset(&args.name) {
|
|
|
|
Ok(json!(source_code))
|
|
|
|
} else {
|
|
|
|
panic!("op_fetch_asset bad asset {}", args.name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-02 17:07:11 -04:00
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
struct Exit {
|
|
|
|
code: i32,
|
|
|
|
}
|
|
|
|
|
2019-10-02 13:05:48 -04:00
|
|
|
pub fn exit(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
|
2019-09-02 17:07:11 -04:00
|
|
|
let v: Exit = serde_json::from_value(v)?;
|
|
|
|
s.exit_code = v.code;
|
|
|
|
std::process::exit(v.code)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
pub struct EmitResult {
|
|
|
|
pub emit_skipped: bool,
|
|
|
|
pub diagnostics: Vec<String>,
|
|
|
|
pub emitted_files: Vec<String>,
|
|
|
|
}
|
|
|
|
|
2019-10-02 13:05:48 -04:00
|
|
|
pub fn set_emit_result(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
|
2019-09-02 17:07:11 -04:00
|
|
|
let v: EmitResult = serde_json::from_value(v)?;
|
|
|
|
s.emit_result = Some(v);
|
|
|
|
Ok(json!(true))
|
|
|
|
}
|