idk. but added AGENTS.md
This commit is contained in:
@@ -4,6 +4,9 @@ use deno_core::OpState;
|
||||
use mize::{Mize, MizeError};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::CliPart;
|
||||
use crate::JsPart;
|
||||
|
||||
#[op2(fast)]
|
||||
fn op_mize_get_part(#[string] name: &str) {
|
||||
println!("js wants the part {}", name);
|
||||
@@ -22,6 +25,21 @@ fn op_mize_add_part(state: &mut OpState, #[string] key: &str) {
|
||||
println!("adding part {}", key);
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
fn op_cli_subcommand(state: &mut OpState, #[string] name: String) {
|
||||
let mut mize: Mize = state.borrow::<Mize>().clone();
|
||||
let mut cli = mize.get_part_native::<CliPart>("cli").unwrap();
|
||||
cli.subcommand(
|
||||
clap::Command::new(name.clone()),
|
||||
move |_sub_matches, mut mize| {
|
||||
let mut js = mize.get_part_native::<JsPart>("js").unwrap();
|
||||
js.eval("log(\"cli command being called\")".to_string())?;
|
||||
js.eval(format!("mize.vars.cli.subcommand({name})"))?;
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Create an extension with your custom ops
|
||||
extension!(
|
||||
my_extension,
|
||||
|
||||
11
packages/marts/js/glue_deno.ts
Normal file
11
packages/marts/js/glue_deno.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Mize } from "./stub_deno.ts";
|
||||
|
||||
function argsToMessage(...args) {
|
||||
return args.map((arg) => JSON.stringify(arg)).join(" ");
|
||||
}
|
||||
|
||||
globalThis.log = (...args) => {
|
||||
Deno.core.print(`[out]: ${argsToMessage(...args)}\n`, false);
|
||||
};
|
||||
|
||||
globalThis.mize = new Mize();
|
||||
@@ -1,6 +1,10 @@
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::url::Url;
|
||||
use deno_core::{extension, op2, JsRuntime, ModuleSpecifier, PollEventLoopOptions, RuntimeOptions};
|
||||
use deno_core::v8::OneByteConst;
|
||||
use deno_core::{
|
||||
ascii_str_include, extension, op2, JsRuntime, ModuleSpecifier, PollEventLoopOptions,
|
||||
RuntimeOptions,
|
||||
};
|
||||
use deno_core::{FastStaticString, FsModuleLoader};
|
||||
use mize::async_trait;
|
||||
use mize::instance::MizePartCreate;
|
||||
@@ -19,35 +23,36 @@ mod glue_deno;
|
||||
#[derive(Default)]
|
||||
pub struct JsPart {
|
||||
mize: Mize,
|
||||
closure_sender: Option<flume::Sender<Box<dyn FnOnce(&mut JsRuntime) -> MizeResult<()> + Send>>>,
|
||||
async_closure_sender: Option<flume::Sender<BoxClosure>>,
|
||||
sender: Option<flume::Sender<JsRuntimeThreadMessage>>,
|
||||
}
|
||||
|
||||
pub type BoxFuture<'a> = Pin<Box<dyn Future<Output = MizeResult<()>> + 'a>>;
|
||||
pub type BoxClosure = Box<dyn for<'a> FnOnce(&'a mut JsRuntime) -> BoxFuture<'a> + Send + 'static>;
|
||||
|
||||
impl MizePart for JsPart {
|
||||
fn init(&mut self, mize: &mut Mize) -> MizeResult<()> {
|
||||
println!("js part init");
|
||||
fn run(&mut self, mize: &mut Mize) -> MizeResult<()> {
|
||||
println!("js part run");
|
||||
self.sender
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send(JsRuntimeThreadMessage::DoRunPhase)
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn js(mize: &mut Mize) -> MizeResult<()> {
|
||||
let (closure_sender, closure_receiver) =
|
||||
flume::unbounded::<Box<dyn FnOnce(&mut JsRuntime) -> MizeResult<()> + Send>>();
|
||||
let (async_closure_sender, async_closure_receiver) = flume::unbounded::<BoxClosure>();
|
||||
let (sender, receiver) = flume::unbounded::<JsRuntimeThreadMessage>();
|
||||
let mize_clone = mize.clone();
|
||||
|
||||
// the thread which will run any js
|
||||
mize.spawn("js_runtime_thread", || {
|
||||
js_runtime_thread(mize_clone, closure_receiver, async_closure_receiver)
|
||||
mize.spawn_and_wait("js_runtime_thread", || {
|
||||
js_runtime_thread(mize_clone, receiver)
|
||||
})?;
|
||||
|
||||
mize.add_part(Box::new(JsPart {
|
||||
mize: mize.clone(),
|
||||
closure_sender: Some(closure_sender),
|
||||
async_closure_sender: Some(async_closure_sender),
|
||||
sender: Some(sender),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -57,169 +62,75 @@ pub fn part_from_file(
|
||||
code: FastStaticString,
|
||||
) -> MizeResult<()> {
|
||||
let mut js = mize.get_part_native::<JsPart>("js")?;
|
||||
js.with_runtime_async(move |runtime: &mut JsRuntime| {
|
||||
let module_spec = ModuleSpecifier::from_str(name).unwrap();
|
||||
return Box::pin(async move {
|
||||
runtime
|
||||
.load_side_es_module_from_code(&module_spec, code)
|
||||
.await;
|
||||
Ok(())
|
||||
});
|
||||
});
|
||||
js.execute_init_js(code)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl JsPart {
|
||||
/*
|
||||
pub fn part_from_js_file(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
path: &'static str,
|
||||
) -> Box<dyn MizePart + Send + Sync> {
|
||||
Box::new(PartFromJsFileAdapter {
|
||||
mize: self.mize.clone(),
|
||||
name,
|
||||
js_file: path,
|
||||
})
|
||||
}
|
||||
*/
|
||||
pub fn with_runtime<T: FnOnce(&mut JsRuntime) -> MizeResult<()> + Send + 'static>(
|
||||
&mut self,
|
||||
func: T,
|
||||
) {
|
||||
self.closure_sender
|
||||
.as_mut()
|
||||
pub fn execute_init_js(&mut self, code: FastStaticString) -> MizeResult<()> {
|
||||
self.sender
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send(Box::new(func))
|
||||
.send(JsRuntimeThreadMessage::RunInitJs(code))
|
||||
.unwrap();
|
||||
}
|
||||
pub fn with_runtime_async<F>(&mut self, func: F)
|
||||
where
|
||||
F: for<'a> FnOnce(&'a mut JsRuntime) -> BoxFuture<'a> + Send + 'static,
|
||||
{
|
||||
self.async_closure_sender
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.send(Box::new(func))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[mize_part]
|
||||
#[derive(Default)]
|
||||
struct PartFromJsFileAdapter {
|
||||
mize: Mize,
|
||||
name: &'static str,
|
||||
js_file: &'static str,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl MizePart for PartFromJsFileAdapter {
|
||||
fn deps(&self) -> &'static [&'static str] {
|
||||
&["js"]
|
||||
}
|
||||
fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
async fn async_init(&mut self, mize: &mut Mize) -> MizeResult<()> {
|
||||
let js = mize.get_part_native::<JsPart>("js")?;
|
||||
let path = self.js_file;
|
||||
let js_code = format!(
|
||||
r#"
|
||||
import {{ opts, deps, create }} from "{path}";
|
||||
|
||||
const isPromise = (value) => {{
|
||||
return !!value && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function';
|
||||
}};
|
||||
|
||||
// Call the async function
|
||||
let create_result = create(mize);
|
||||
if (isPromise(create_result)) {{
|
||||
create_result = await create_result;
|
||||
}}
|
||||
const result = {{
|
||||
opts: opts(mize),
|
||||
deps: deps(mize),
|
||||
create: create_result,
|
||||
}};
|
||||
|
||||
result;
|
||||
"#
|
||||
);
|
||||
|
||||
// Execute the script
|
||||
let result = js.runtime().execute_script("[main]", js_code)?;
|
||||
|
||||
// Resolve the promise and run event loop
|
||||
let resolved_value = js.runtime().resolve_value(result).await?;
|
||||
|
||||
// Run the event loop to completion
|
||||
js.runtime()
|
||||
.run_event_loop(PollEventLoopOptions::default())
|
||||
.await?;
|
||||
|
||||
println!("Execution of part {} completed successfully", self.name());
|
||||
Ok(())
|
||||
}
|
||||
async fn async_run(&mut self, mize: &mut Mize) -> MizeResult<()> {
|
||||
let js = mize.get_part_native::<JsPart>("js")?;
|
||||
let path = self.js_file;
|
||||
let js_code = format!(
|
||||
r#"
|
||||
import {{ run }} from "{path}";
|
||||
|
||||
const result = run()
|
||||
|
||||
result;
|
||||
"#
|
||||
);
|
||||
// Execute the script
|
||||
let result = js.runtime().execute_script("[main]", js_code)?;
|
||||
|
||||
// Resolve the promise and run event loop
|
||||
let resolved_value = js.runtime().resolve_value(result).await?;
|
||||
|
||||
// Run the event loop to completion
|
||||
js.runtime()
|
||||
.run_event_loop(PollEventLoopOptions::default())
|
||||
.await?;
|
||||
|
||||
println!("Running of part {} completed successfully", self.name());
|
||||
pub fn eval(&mut self, code: String) -> MizeResult<()> {
|
||||
self.sender
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send(JsRuntimeThreadMessage::RunJs(code))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
fn js_runtime_thread(
|
||||
mize: Mize,
|
||||
closure_receiver: flume::Receiver<Box<dyn FnOnce(&mut JsRuntime) -> MizeResult<()> + Send>>,
|
||||
async_closure_receiver: flume::Receiver<BoxClosure>,
|
||||
receiver: flume::Receiver<JsRuntimeThreadMessage>,
|
||||
) -> MizeResult<()> {
|
||||
let mut js_runtime = JsRuntime::new(RuntimeOptions {
|
||||
module_loader: Some(Rc::new(FsModuleLoader)),
|
||||
extensions: vec![glue_deno::my_extension::init(mize.clone())],
|
||||
//module_loader: Some(Rc::new(FsModuleLoader)),
|
||||
//extensions: vec![glue_deno::my_extension::init(mize.clone())],
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let poll_opts = PollEventLoopOptions::default();
|
||||
js_runtime
|
||||
.execute_script("[stub]", ascii_str_include!("../deno_dist/glue_deno.js"))
|
||||
.unwrap();
|
||||
|
||||
let tokio_runtime = Builder::new_current_thread().enable_all().build().unwrap();
|
||||
|
||||
let local = LocalSet::new();
|
||||
local.block_on(&tokio_runtime, async move {
|
||||
loop {
|
||||
// Drain queued closures quickly (no await here if possible)
|
||||
if let Ok(func) = closure_receiver.recv_async().await {
|
||||
if let Err(e) = func(&mut js_runtime) {
|
||||
mize.report_err(e);
|
||||
loop {
|
||||
println!("js thread waiting for smth");
|
||||
let msg = receiver.recv().unwrap();
|
||||
println!("js thread got smth");
|
||||
match msg {
|
||||
JsRuntimeThreadMessage::RunInitJs(js_code) => {
|
||||
if let Err(err) = js_runtime.execute_script("[init]", js_code) {
|
||||
println!("err: {}", err);
|
||||
}
|
||||
println!("done running js");
|
||||
}
|
||||
JsRuntimeThreadMessage::RunJs(js_code) => {
|
||||
if let Err(err) = js_runtime.execute_script("[idk]", js_code) {
|
||||
println!("err: {}", err);
|
||||
}
|
||||
println!("done running js");
|
||||
}
|
||||
JsRuntimeThreadMessage::DoRunPhase => {
|
||||
if let Err(err) = js_runtime.execute_script("[runPhase]", "mize.runPhase()") {
|
||||
println!("err: {}", err);
|
||||
}
|
||||
println!("done with runPhase");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Drive JS one tick
|
||||
let _ = futures::future::poll_fn(|cx| js_runtime.poll_event_loop(cx, poll_opts)).await;
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
enum JsRuntimeThreadMessage {
|
||||
//Closure(Box<dyn FnOnce(&mut JsRuntime) -> MizeResult<()> + Send>),
|
||||
//AsyncClosure(BoxClosure),
|
||||
RunInitJs(FastStaticString),
|
||||
RunJs(String),
|
||||
DoRunPhase,
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ export class Mize {
|
||||
async add_opts(opts: any): Promise<void> {}
|
||||
async add_part(part: any): Promise<void> {}
|
||||
async report_err(err: MizeError) {}
|
||||
runPhase() {
|
||||
Deno.core.print("runPhase in js \n");
|
||||
}
|
||||
}
|
||||
|
||||
type MizeError = string;
|
||||
|
||||
Reference in New Issue
Block a user