Merge pull request #2173 from aarroyoc/js-eval
Add js_eval/2 for wasm32
This commit is contained in:
@@ -51,7 +51,8 @@ use wasm_bindgen::prelude::*;
|
||||
#[wasm_bindgen]
|
||||
pub fn eval_code(s: &str) -> String {
|
||||
use machine::mock_wam::*;
|
||||
use web_sys::console;
|
||||
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let mut wam = Machine::with_test_streams();
|
||||
let bytes = wam.test_load_string(s);
|
||||
|
||||
29
src/lib/wasm.pl
Normal file
29
src/lib/wasm.pl
Normal file
@@ -0,0 +1,29 @@
|
||||
/** Predicates for the WebAssembly platform
|
||||
|
||||
This module contains predicates that are only available in
|
||||
the WASM (WebAssembly) version of Scryer Prolog.
|
||||
*/
|
||||
|
||||
:- module(wasm, [js_eval/2]).
|
||||
|
||||
:- use_module(library(error)).
|
||||
|
||||
%% js_eval(+JsCode, -Result).
|
||||
%
|
||||
% Executes a JavaScript snippet `JsCode` using the platform
|
||||
% `eval` function. `Result` takes the return value of that code.
|
||||
% Strings, booleans, numbers, null and undefined are directly mapped to Prolog.
|
||||
% Arrays, objects, bigints, symbols and functions are not mapped.
|
||||
% Instead, a `js_{type}` atom will be returned.
|
||||
%
|
||||
% Example (on a browser):
|
||||
%
|
||||
% ```
|
||||
% ?- js_eval("prompt('What is your name?')", Name).
|
||||
% % A prompt is showed, with a textbox.
|
||||
% Name = "Whatever was written on the textbox".
|
||||
% ```
|
||||
js_eval(JsCode, Result) :-
|
||||
must_be(chars, JsCode),
|
||||
can_be(chars, Result),
|
||||
'$js_eval'(JsCode, Result).
|
||||
@@ -4139,6 +4139,14 @@ impl Machine {
|
||||
try_or_throw!(self.machine_st, self.define_foreign_struct());
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallJsEval => {
|
||||
try_or_throw!(self.machine_st, self.js_eval());
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
&Instruction::ExecuteJsEval => {
|
||||
try_or_throw!(self.machine_st, self.js_eval());
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallCurrentTime => {
|
||||
self.current_time();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
|
||||
@@ -4882,6 +4882,70 @@ impl Machine {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[inline(always)]
|
||||
pub(crate) fn js_eval(&mut self) -> CallResult {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[inline(always)]
|
||||
pub(crate) fn js_eval(&mut self) -> CallResult {
|
||||
let code = self.deref_register(1);
|
||||
let result_reg = self.deref_register(2);
|
||||
if let Some(code) = self.machine_st.value_to_str_like(code) {
|
||||
let result = match js_sys::eval(&code.as_str()) {
|
||||
Ok(result) => self.unify_js_value(result, result_reg),
|
||||
Err(result) => self.unify_js_value(result, result_reg),
|
||||
};
|
||||
return Ok(());
|
||||
}
|
||||
self.machine_st.fail = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn unify_js_value(&mut self, result: wasm_bindgen::JsValue, result_reg: HeapCellValue) {
|
||||
match result.as_bool() {
|
||||
Some(result) => match result {
|
||||
true => self.machine_st.unify_atom(atom!("true"), result_reg),
|
||||
false => self.machine_st.unify_atom(atom!("false"), result_reg),
|
||||
},
|
||||
None => match result.as_f64() {
|
||||
Some(result) => {
|
||||
let n = float_alloc!(result, self.machine_st.arena);
|
||||
self.machine_st.unify_f64(n, result_reg);
|
||||
}
|
||||
None => match result.as_string() {
|
||||
Some(result) => {
|
||||
let result = AtomTable::build_with(&self.machine_st.atom_tbl, &result);
|
||||
self.machine_st.unify_complete_string(result, result_reg);
|
||||
}
|
||||
None => {
|
||||
if result.is_null() {
|
||||
self.machine_st.unify_atom(atom!("null"), result_reg);
|
||||
} else if result.is_undefined() {
|
||||
self.machine_st.unify_atom(atom!("undefined"), result_reg);
|
||||
} else if result.is_symbol() {
|
||||
self.machine_st.unify_atom(atom!("js_symbol"), result_reg);
|
||||
} else if result.is_object() {
|
||||
self.machine_st.unify_atom(atom!("js_object"), result_reg);
|
||||
} else if result.is_array() {
|
||||
self.machine_st.unify_atom(atom!("js_array"), result_reg);
|
||||
} else if result.is_function() {
|
||||
self.machine_st.unify_atom(atom!("js_function"), result_reg);
|
||||
} else if result.is_bigint() {
|
||||
self.machine_st.unify_atom(atom!("js_bigint"), result_reg);
|
||||
} else {
|
||||
self.machine_st
|
||||
.unify_atom(atom!("js_unknown_type"), result_reg);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn current_time(&mut self) {
|
||||
let timestamp = self.systemtime_to_timestamp(SystemTime::now());
|
||||
|
||||
Reference in New Issue
Block a user