Compare commits
3 commits
156b6d6691
...
8d7dd789ed
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d7dd789ed | |||
| 16e6f1304c | |||
| 0c8367d29f |
9 changed files with 185 additions and 7 deletions
|
|
@ -27125,7 +27125,7 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,
|
|||
return i;
|
||||
}
|
||||
|
||||
static JSExportEntry *find_export_entry(JSContext *ctx, JSModuleDef *m,
|
||||
static JSExportEntry *find_export_entry(JSContext *ctx, const JSModuleDef *m,
|
||||
JSAtom export_name)
|
||||
{
|
||||
JSExportEntry *me;
|
||||
|
|
@ -27241,6 +27241,37 @@ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
|
|||
return -1;
|
||||
}
|
||||
|
||||
JSValueConst JS_GetModuleExport(JSContext *ctx, const JSModuleDef *m, const char *export_name) {
|
||||
JSExportEntry *me;
|
||||
JSAtom name;
|
||||
name = JS_NewAtom(ctx, export_name);
|
||||
if (name == JS_ATOM_NULL)
|
||||
goto fail;
|
||||
me = find_export_entry(ctx, m, name);
|
||||
JS_FreeAtom(ctx, name);
|
||||
if (!me)
|
||||
goto fail;
|
||||
return JS_DupValue(ctx, me->u.local.var_ref->value);
|
||||
fail:
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
int JS_CountModuleExport(JSContext *ctx, const JSModuleDef *m) {
|
||||
return m->export_entries_count;
|
||||
}
|
||||
|
||||
JSAtom JS_GetModuleExportName(JSContext *ctx, const JSModuleDef *m, int idx) {
|
||||
if (idx >= m->export_entries_count || idx < 0)
|
||||
return JS_ATOM_NULL;
|
||||
return JS_DupAtom(ctx, m->export_entries[idx].export_name);
|
||||
}
|
||||
|
||||
JSValueConst JS_GetModuleExportValue(JSContext *ctx, const JSModuleDef *m, int idx) {
|
||||
if (idx >= m->export_entries_count || idx < 0)
|
||||
return JS_UNDEFINED;
|
||||
return JS_DupValue(ctx, m->export_entries[idx].u.local.var_ref->value);
|
||||
}
|
||||
|
||||
void JS_SetModuleLoaderFunc(JSRuntime *rt,
|
||||
JSModuleNormalizeFunc *module_normalize,
|
||||
JSModuleLoaderFunc *module_loader, void *opaque)
|
||||
|
|
|
|||
|
|
@ -1038,6 +1038,11 @@ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
|
|||
JSValue val);
|
||||
int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
|
||||
const JSCFunctionListEntry *tab, int len);
|
||||
/* can only be called after the module is initialized */
|
||||
JSValueConst JS_GetModuleExport(JSContext *ctx, const JSModuleDef *m, const char *export_name);
|
||||
int JS_CountModuleExport(JSContext *ctx, const JSModuleDef *m);
|
||||
JSAtom JS_GetModuleExportName(JSContext *ctx, const JSModuleDef *m, int idx);
|
||||
JSValueConst JS_GetModuleExportValue(JSContext *ctx, const JSModuleDef *m, int idx);
|
||||
|
||||
#undef js_unlikely
|
||||
#undef js_force_inline
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@ extern "C" {
|
|||
magic: ::std::os::raw::c_int,
|
||||
) -> JSValue;
|
||||
fn JS_MakeException_real() -> JSValue;
|
||||
|
||||
fn JS_MakeNull_real() -> JSValue;
|
||||
fn JS_MakeUndefined_real() -> JSValue;
|
||||
fn JS_ValueGetPtr_real(v: JSValue) -> *mut ::std::os::raw::c_void;
|
||||
}
|
||||
|
||||
pub unsafe fn JS_ValueGetTag(v: JSValue) -> i32 {
|
||||
|
|
@ -217,3 +219,15 @@ pub unsafe fn JS_NewCFunctionMagic(
|
|||
pub unsafe fn JS_MakeException() -> JSValue {
|
||||
JS_MakeException_real()
|
||||
}
|
||||
|
||||
pub unsafe fn JS_MakeNull() -> JSValue {
|
||||
JS_MakeNull_real()
|
||||
}
|
||||
|
||||
pub unsafe fn JS_MakeUndefined() -> JSValue {
|
||||
JS_MakeUndefined_real()
|
||||
}
|
||||
|
||||
pub unsafe fn JS_ValueGetPtr(v: JSValue) -> *mut ::std::os::raw::c_void {
|
||||
JS_ValueGetPtr_real(v)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,3 +128,15 @@ JSValue JS_NewCFunctionMagic_real(JSContext *ctx, JSCFunctionMagic *func, const
|
|||
JSValue JS_MakeException_real() {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
JSValue JS_MakeNull_real() {
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue JS_MakeUndefined_real() {
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
void *JS_ValueGetPtr_real(JSValue val) {
|
||||
return JS_VALUE_GET_PTR(val);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,14 @@ impl ContextRef {
|
|||
unsafe { sys::JS_EnableBignumExt(self.ctx, if enable { 1 } else { 0 }) }
|
||||
}
|
||||
|
||||
pub fn load_module(&self, input: &str, filename: &str) -> Result<Value> {
|
||||
let val = self.eval(input, filename, EvalType::Module, EvalFlags::COMPILE_ONLY)?;
|
||||
assert!(val.is_module());
|
||||
val.eval_function(self)?;
|
||||
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
/// Evaluate the specified JavaScript code.
|
||||
pub fn eval(
|
||||
&self,
|
||||
|
|
@ -482,4 +490,23 @@ mod tests {
|
|||
.unwrap();
|
||||
assert_eq!(String::from("UNSAFE"), result.to_string(&ctx).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn modules_with_exports() {
|
||||
let ctx = Context::new(Runtime::new());
|
||||
let module = ctx
|
||||
.load_module("const foo = 123; export { foo };", "main.js")
|
||||
.expect("Could not load!");
|
||||
assert_eq!(module.value_type(), ValueType::Module);
|
||||
|
||||
let foo = module
|
||||
.get_module_export(&ctx, "foo")
|
||||
.expect("Could not get export");
|
||||
assert_eq!(String::from("123"), foo.to_string(&ctx).unwrap());
|
||||
|
||||
let bar = module
|
||||
.get_module_export(&ctx, "bar")
|
||||
.expect("Could not get export");
|
||||
assert!(bar.is_undefined());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{AtomRef, ContextRef, Error, Result, Runtime, RustFunction};
|
||||
use oden_js_sys as sys;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fmt;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
|
|
@ -309,6 +309,37 @@ impl ValueRef {
|
|||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn get_module_export(&self, ctx: &ContextRef, export: &str) -> Result<Value> {
|
||||
if self.value_type() != ValueType::Module {
|
||||
return Err(Error::InvalidType {
|
||||
expected: ValueType::Bool,
|
||||
found: self.value_type(),
|
||||
});
|
||||
}
|
||||
|
||||
let c_value = match CString::new(export) {
|
||||
Ok(cs) => Ok(cs),
|
||||
Err(_) => Err(Error::UnexpectedNul),
|
||||
}?;
|
||||
|
||||
unsafe {
|
||||
let module = sys::JS_ValueGetPtr(self.val) as *mut sys::JSModuleDef;
|
||||
ctx.check_exception(sys::JS_GetModuleExport(ctx.ctx, module, c_value.into_raw()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call(&self, ctx: &ContextRef) -> Result<Value> {
|
||||
unsafe {
|
||||
ctx.check_exception(sys::JS_Call(
|
||||
ctx.ctx,
|
||||
self.val,
|
||||
sys::JS_MakeUndefined(),
|
||||
0,
|
||||
std::ptr::null_mut(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> fmt::Debug for ValueRef {
|
||||
|
|
@ -338,6 +369,20 @@ impl Value {
|
|||
rt: Runtime::from_raw(unsafe { sys::JS_GetRuntime(ctx.ctx) }),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn null(ctx: &ContextRef) -> Self {
|
||||
Value {
|
||||
value: ValueRef::from_raw(unsafe { sys::JS_MakeNull() }),
|
||||
rt: Runtime::from_raw(unsafe { sys::JS_GetRuntime(ctx.ctx) }),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn undefined(ctx: &ContextRef) -> Self {
|
||||
Value {
|
||||
value: ValueRef::from_raw(unsafe { sys::JS_MakeUndefined() }),
|
||||
rt: Runtime::from_raw(unsafe { sys::JS_GetRuntime(ctx.ctx) }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Value {
|
||||
|
|
|
|||
|
|
@ -356,6 +356,8 @@ pub async fn run() {
|
|||
let mut state = State::new(window).await;
|
||||
|
||||
let context = script::ScriptContext::new();
|
||||
context.init();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
control_flow.set_poll();
|
||||
|
||||
|
|
|
|||
9
src/main.js
Normal file
9
src/main.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
function init() {
|
||||
// console.log("Hello world!");
|
||||
}
|
||||
|
||||
function update() {}
|
||||
|
||||
function draw() {}
|
||||
|
||||
export { init, update, draw }
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
use oden_js as js;
|
||||
|
||||
pub struct ScriptContext {
|
||||
_context: js::Context,
|
||||
context: js::Context,
|
||||
init: js::Value,
|
||||
update: js::Value,
|
||||
draw: js::Value,
|
||||
}
|
||||
|
||||
impl ScriptContext {
|
||||
|
|
@ -13,10 +16,40 @@ impl ScriptContext {
|
|||
context.add_intrinsic_bigdecimal();
|
||||
context.add_intrinsic_operators();
|
||||
|
||||
ScriptContext { _context: context }
|
||||
let js = include_str!("main.js");
|
||||
let module = context
|
||||
.load_module(js, "main.js")
|
||||
.expect("Unable to load main");
|
||||
|
||||
let init = module
|
||||
.get_module_export(&context, "init")
|
||||
.expect("Unable to fetch init");
|
||||
let update = module
|
||||
.get_module_export(&context, "update")
|
||||
.expect("Unable to fetch update");
|
||||
let draw = module
|
||||
.get_module_export(&context, "draw")
|
||||
.expect("Unable to fetch draw");
|
||||
|
||||
ScriptContext {
|
||||
context,
|
||||
init,
|
||||
update,
|
||||
draw,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&self) {}
|
||||
pub fn init(&self) {
|
||||
self.init.call(&self.context).expect("Exception in init");
|
||||
}
|
||||
|
||||
pub fn render(&self) {}
|
||||
pub fn update(&self) {
|
||||
self.update
|
||||
.call(&self.context)
|
||||
.expect("Exception in update");
|
||||
}
|
||||
|
||||
pub fn render(&self) {
|
||||
self.draw.call(&self.context).expect("Exception in draw");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue