feat: Variable args (#1667)

* feat: Variable args

* chore: Make the assert error message not wrong
This commit is contained in:
J M
2022-07-18 15:46:32 -06:00
committed by GitHub
parent 009f7ddf84
commit 635c3627c9
4 changed files with 81 additions and 8 deletions

View File

@@ -45,7 +45,10 @@ impl PathForVolumeId for Volumes {
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub struct JsProcedure {} pub struct JsProcedure {
#[serde(default)]
args: Vec<serde_json::Value>,
}
impl JsProcedure { impl JsProcedure {
pub fn validate(&self, _volumes: &Volumes) -> Result<(), color_eyre::eyre::Report> { pub fn validate(&self, _volumes: &Volumes) -> Result<(), color_eyre::eyre::Report> {
@@ -71,7 +74,7 @@ impl JsProcedure {
Box::new(volumes.clone()), Box::new(volumes.clone()),
) )
.await? .await?
.run_action(name, input); .run_action(name, input, self.args.clone());
let output: ErrorValue = match timeout { let output: ErrorValue = match timeout {
Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action) Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action)
.await .await
@@ -105,7 +108,7 @@ impl JsProcedure {
) )
.await? .await?
.read_only_effects() .read_only_effects()
.run_action(name, input); .run_action(name, input, self.args.clone());
let output: ErrorValue = match timeout { let output: ErrorValue = match timeout {
Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action) Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action)
.await .await
@@ -145,7 +148,7 @@ fn unwrap_known_error<O: for<'de> Deserialize<'de>>(
#[tokio::test] #[tokio::test]
async fn js_action_execute() { async fn js_action_execute() {
let js_action = JsProcedure {}; let js_action = JsProcedure { args: vec![] };
let path: PathBuf = "test/js_action_execute/" let path: PathBuf = "test/js_action_execute/"
.parse::<PathBuf>() .parse::<PathBuf>()
.unwrap() .unwrap()
@@ -200,7 +203,7 @@ async fn js_action_execute() {
#[tokio::test] #[tokio::test]
async fn js_action_execute_error() { async fn js_action_execute_error() {
let js_action = JsProcedure {}; let js_action = JsProcedure { args: vec![] };
let path: PathBuf = "test/js_action_execute/" let path: PathBuf = "test/js_action_execute/"
.parse::<PathBuf>() .parse::<PathBuf>()
.unwrap() .unwrap()
@@ -244,7 +247,52 @@ async fn js_action_execute_error() {
#[tokio::test] #[tokio::test]
async fn js_action_fetch() { async fn js_action_fetch() {
let js_action = JsProcedure {}; let js_action = JsProcedure { args: vec![] };
let path: PathBuf = "test/js_action_execute/"
.parse::<PathBuf>()
.unwrap()
.canonicalize()
.unwrap();
let package_id = "test-package".parse().unwrap();
let package_version: Version = "0.3.0.3".parse().unwrap();
let name = ProcedureName::Action("fetch".parse().unwrap());
let volumes: Volumes = serde_json::from_value(serde_json::json!({
"main": {
"type": "data"
},
"compat": {
"type": "assets"
},
"filebrowser" :{
"package-id": "filebrowser",
"path": "data",
"readonly": true,
"type": "pointer",
"volume-id": "main",
}
}))
.unwrap();
let input: Option<serde_json::Value> = None;
let timeout = Some(Duration::from_secs(10));
js_action
.execute::<serde_json::Value, serde_json::Value>(
&path,
&package_id,
&package_version,
name,
&volumes,
input,
timeout,
)
.await
.unwrap()
.unwrap();
}
#[tokio::test]
async fn js_action_var_arg() {
let js_action = JsProcedure {
args: vec![42.into()],
};
let path: PathBuf = "test/js_action_execute/" let path: PathBuf = "test/js_action_execute/"
.parse::<PathBuf>() .parse::<PathBuf>()
.unwrap() .unwrap()

View File

@@ -758,5 +758,18 @@ export const action = {
qr: false, qr: false,
} }
} }
},
async fetch(_effects, _input, testInput) {
assert(testInput == 42, "Input should be passed in");
return {
result: {
copyable: false,
message: "Done",
version: "0",
qr: false,
}
}
} }
} }

View File

@@ -68,6 +68,7 @@ const fetch = async (url, options = null) => {
const currentFunction = Deno.core.opSync("current_function"); const currentFunction = Deno.core.opSync("current_function");
const input = Deno.core.opSync("get_input"); const input = Deno.core.opSync("get_input");
const variable_args = Deno.core.opSync("get_variable_args");
const setState = (x) => Deno.core.opSync("set_value", x); const setState = (x) => Deno.core.opSync("set_value", x);
const effects = { const effects = {
writeFile, writeFile,
@@ -93,6 +94,6 @@ const runFunction = jsonPointerValue(mainModule, currentFunction);
error(`Expecting ${ currentFunction } to be a function`); error(`Expecting ${ currentFunction } to be a function`);
throw new Error(`Expecting ${ currentFunction } to be a function`); throw new Error(`Expecting ${ currentFunction } to be a function`);
} }
const answer = await runFunction(effects, input); const answer = await runFunction(effects, input, ...variable_args);
setState(answer); setState(answer);
})(); })();

View File

@@ -87,6 +87,7 @@ struct JsContext {
package_id: PackageId, package_id: PackageId,
volumes: Arc<dyn PathForVolumeId>, volumes: Arc<dyn PathForVolumeId>,
input: Value, input: Value,
variable_args: Vec<serde_json::Value>,
} }
#[derive(Clone, Default)] #[derive(Clone, Default)]
@@ -218,6 +219,7 @@ impl JsExecutionEnvironment {
self, self,
procedure_name: ProcedureName, procedure_name: ProcedureName,
input: Option<I>, input: Option<I>,
variable_args: Vec<serde_json::Value>,
) -> Result<O, (JsError, String)> { ) -> Result<O, (JsError, String)> {
let input = match serde_json::to_value(input) { let input = match serde_json::to_value(input) {
Ok(a) => a, Ok(a) => a,
@@ -231,7 +233,8 @@ impl JsExecutionEnvironment {
} }
}; };
let safer_handle: NonDetachingJoinHandle<_> = let safer_handle: NonDetachingJoinHandle<_> =
tokio::task::spawn_blocking(move || self.execute(procedure_name, input)).into(); tokio::task::spawn_blocking(move || self.execute(procedure_name, input, variable_args))
.into();
let output = safer_handle let output = safer_handle
.await .await
.map_err(|err| (JsError::Tokio, format!("Tokio gave us the error: {}", err)))??; .map_err(|err| (JsError::Tokio, format!("Tokio gave us the error: {}", err)))??;
@@ -266,6 +269,7 @@ impl JsExecutionEnvironment {
fns::log_debug::decl(), fns::log_debug::decl(),
fns::log_info::decl(), fns::log_info::decl(),
fns::get_input::decl(), fns::get_input::decl(),
fns::get_variable_args::decl(),
fns::set_value::decl(), fns::set_value::decl(),
fns::is_sandboxed::decl(), fns::is_sandboxed::decl(),
] ]
@@ -275,6 +279,7 @@ impl JsExecutionEnvironment {
&self, &self,
procedure_name: ProcedureName, procedure_name: ProcedureName,
input: Value, input: Value,
variable_args: Vec<serde_json::Value>,
) -> Result<Value, (JsError, String)> { ) -> Result<Value, (JsError, String)> {
let base_directory = self.base_directory.clone(); let base_directory = self.base_directory.clone();
let answer_state = AnswerState::default(); let answer_state = AnswerState::default();
@@ -287,6 +292,7 @@ impl JsExecutionEnvironment {
version: self.version.clone(), version: self.version.clone(),
sandboxed: self.sandboxed, sandboxed: self.sandboxed,
input, input,
variable_args,
}; };
let ext = Extension::builder() let ext = Extension::builder()
.ops(Self::declarations()) .ops(Self::declarations())
@@ -675,6 +681,11 @@ mod fns {
Ok(ctx.input.clone()) Ok(ctx.input.clone())
} }
#[op] #[op]
fn get_variable_args(state: &mut OpState) -> Result<Vec<Value>, AnyError> {
let ctx = state.borrow::<JsContext>();
Ok(ctx.variable_args.clone())
}
#[op]
fn set_value(state: &mut OpState, value: Value) -> Result<(), AnyError> { fn set_value(state: &mut OpState, value: Value) -> Result<(), AnyError> {
let mut answer = state.borrow::<AnswerState>().0.lock(); let mut answer = state.borrow::<AnswerState>().0.lock();
*answer = value; *answer = value;