remove legacy Isolate.set_dispatch API (#3041)

* migrate deno_typescript crate to Isolate.register_op API
* remove dual-dispatch mechanism
* update Isolate tests to new dispatch mechanism
This commit is contained in:
Bartek Iwańczuk 2019-10-02 19:05:48 +02:00 committed by Ryan Dahl
parent 99eec73b4b
commit a569be861a
5 changed files with 144 additions and 148 deletions

View file

@ -13,6 +13,7 @@ const ASSETS = "$asset$";
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function main(configText, rootNames) {
ops = Deno.core.ops();
println(`>>> ts version ${ts.version}`);
println(`>>> rootNames ${rootNames}`);
@ -97,17 +98,11 @@ function encode(str) {
}
//
/** **Warning!** The op_id values below are shared between this code and the
* Rust side. Update with care!
/** **Warning!** Op ids must be acquired from Rust using `Deno.core.ops()`
* before dispatching any action.
* @type {Record<string, number>}
*/
const ops = {
readFile: 49,
exit: 50,
writeFile: 51,
resolveModuleNames: 52,
setEmitResult: 53
};
let ops;
/**
* @type {Map<string, string>}
@ -315,9 +310,15 @@ function configure(configurationText) {
* @param {Record<string,any>} obj
*/
function dispatch(opName, obj) {
const opId = ops[opName];
if (!opId) {
throw new Error(`Unknown op: ${opName}`);
}
const s = JSON.stringify(obj);
const msg = encode(s);
const resUi8 = Deno.core.dispatch(ops[opName], msg);
const resUi8 = Deno.core.dispatch(opId, msg);
const resStr = decodeAscii(resUi8);
const res = JSON.parse(resStr);
if (!res["ok"]) {

View file

@ -6,9 +6,11 @@ extern crate serde_json;
mod ops;
use deno::js_check;
pub use deno::v8_set_flags;
use deno::CoreOp;
use deno::ErrBox;
use deno::Isolate;
use deno::ModuleSpecifier;
use deno::PinnedBuf;
use deno::StartupData;
pub use ops::EmitResult;
use ops::WrittenFile;
@ -45,6 +47,20 @@ impl TSState {
}
}
fn compiler_op<D>(
ts_state: Arc<Mutex<TSState>>,
dispatcher: D,
) -> impl Fn(&[u8], Option<PinnedBuf>) -> CoreOp
where
D: Fn(&mut TSState, &[u8]) -> CoreOp,
{
move |control: &[u8], zero_copy_buf: Option<PinnedBuf>| -> CoreOp {
assert!(zero_copy_buf.is_none()); // zero_copy_buf unused in compiler.
let mut s = ts_state.lock().unwrap();
dispatcher(&mut s, control)
}
}
pub struct TSIsolate {
isolate: Isolate,
state: Arc<Mutex<TSState>>,
@ -62,12 +78,26 @@ impl TSIsolate {
emit_result: None,
written_files: Vec::new(),
}));
let state_ = state.clone();
isolate.set_dispatch(move |op_id, control_buf, zero_copy_buf| {
assert!(zero_copy_buf.is_none()); // zero_copy_buf unused in compiler.
let mut s = state_.lock().unwrap();
ops::dispatch_op(&mut s, op_id, control_buf)
});
isolate.register_op(
"readFile",
compiler_op(state.clone(), ops::json_op(ops::read_file)),
);
isolate
.register_op("exit", compiler_op(state.clone(), ops::json_op(ops::exit)));
isolate.register_op(
"writeFile",
compiler_op(state.clone(), ops::json_op(ops::write_file)),
);
isolate.register_op(
"resolveModuleNames",
compiler_op(state.clone(), ops::json_op(ops::resolve_module_names)),
);
isolate.register_op(
"setEmitResult",
compiler_op(state.clone(), ops::json_op(ops::set_emit_result)),
);
TSIsolate { isolate, state }
}

View file

@ -3,7 +3,6 @@ use deno::CoreOp;
use deno::ErrBox;
use deno::ModuleSpecifier;
use deno::Op;
use deno::OpId;
use serde::Deserialize;
use serde_json::json;
use serde_json::Value;
@ -15,33 +14,23 @@ pub struct WrittenFile {
pub source_code: String,
}
fn dispatch2(
s: &mut TSState,
op_id: OpId,
control_buf: &[u8],
) -> Result<Value, ErrBox> {
let v = serde_json::from_slice(control_buf)?;
// Warning! The op_id values below are shared between this code and
// compiler_main.js. Update with care!
match op_id {
49 => read_file(s, v),
50 => exit(s, v),
51 => write_file(s, v),
52 => resolve_module_names(s, v),
53 => set_emit_result(s, v),
_ => unreachable!(),
}
}
type Dispatcher = fn(state: &mut TSState, args: Value) -> Result<Value, ErrBox>;
pub fn dispatch_op(s: &mut TSState, op_id: OpId, control_buf: &[u8]) -> CoreOp {
let result = dispatch2(s, op_id, control_buf);
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())
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())
}
}
#[derive(Debug, Deserialize)]
@ -52,7 +41,7 @@ struct ReadFile {
should_create_new_source_file: bool,
}
fn read_file(_s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
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$/", "");
@ -82,7 +71,7 @@ struct WriteFile {
module_name: String,
}
fn write_file(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
pub fn write_file(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
let v: WriteFile = serde_json::from_value(v)?;
let module_specifier = ModuleSpecifier::resolve_url_or_path(&v.file_name)?;
if s.bundle {
@ -103,7 +92,10 @@ struct ResolveModuleNames {
containing_file: String,
}
fn resolve_module_names(_s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
pub fn resolve_module_names(
_s: &mut TSState,
v: Value,
) -> Result<Value, ErrBox> {
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)?;
@ -124,7 +116,7 @@ struct Exit {
code: i32,
}
fn exit(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
pub fn exit(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
let v: Exit = serde_json::from_value(v)?;
s.exit_code = v.code;
std::process::exit(v.code)
@ -138,7 +130,7 @@ pub struct EmitResult {
pub emitted_files: Vec<String>,
}
fn set_emit_result(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
pub fn set_emit_result(s: &mut TSState, v: Value) -> Result<Value, ErrBox> {
let v: EmitResult = serde_json::from_value(v)?;
s.emit_result = Some(v);
Ok(json!(true))