Skip to content

Commit

Permalink
Merge pull request #397 from Sharktheone/js/update-js-value-covnersion
Browse files Browse the repository at this point in the history
Uupdate js value covnersion
  • Loading branch information
Sharktheone authored Mar 3, 2024
2 parents 49489b2 + b93aaa0 commit fa958da
Show file tree
Hide file tree
Showing 16 changed files with 271 additions and 152 deletions.
26 changes: 10 additions & 16 deletions crates/gosub_webexecutor/src/js/array.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,24 @@
use crate::js::{JSRuntime, JSValue};
use crate::js::JSRuntime;
use gosub_shared::types::Result;

pub trait JSArray: Iterator {
type RT: JSRuntime;

fn get(
&self,
index: <Self::RT as JSRuntime>::ArrayIndex,
) -> Result<<Self::RT as JSRuntime>::Value>;
fn get(&self, index: usize) -> Result<<Self::RT as JSRuntime>::Value>;

fn set(
&self,
index: <Self::RT as JSRuntime>::ArrayIndex,
value: &<Self::RT as JSRuntime>::Value,
) -> Result<()>;
fn set(&self, index: usize, value: &<Self::RT as JSRuntime>::Value) -> Result<()>;

fn push(&self, value: <Self::RT as JSRuntime>::Value) -> Result<()>;

fn pop(&self) -> Result<<Self::RT as JSRuntime>::Value>;

fn remove<T: Into<<Self::RT as JSRuntime>::ArrayIndex>>(&self, index: T) -> Result<()>;
fn remove(&self, index: usize) -> Result<()>;

fn len(&self) -> <Self::RT as JSRuntime>::ArrayIndex;
fn len(&self) -> usize;

fn is_empty(&self) -> bool;

fn new(
ctx: <Self::RT as JSRuntime>::Context,
cap: <Self::RT as JSRuntime>::ArrayIndex,
) -> Result<Self>
fn new(ctx: <Self::RT as JSRuntime>::Context, cap: usize) -> Result<Self>
where
Self: Sized;

Expand All @@ -38,4 +28,8 @@ pub trait JSArray: Iterator {
) -> Result<Self>
where
Self: Sized;

fn as_value(&self) -> <Self::RT as JSRuntime>::Value;

fn as_vec(&self) -> Vec<<Self::RT as JSRuntime>::Value>;
}
2 changes: 1 addition & 1 deletion crates/gosub_webexecutor/src/js/compile.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use gosub_shared::types::Result;

use crate::js::{JSContext, JSRuntime, JSValue};
use crate::js::JSRuntime;

//compiled code will be stored with this trait for later execution (e.g HTML parsing not done yet)
pub trait JSCompiled {
Expand Down
2 changes: 1 addition & 1 deletion crates/gosub_webexecutor/src/js/context.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use gosub_shared::types::Result;

use crate::js::{JSArray, JSCompiled, JSFunction, JSObject, JSRuntime, JSValue};
use crate::js::JSRuntime;

//main trait for JS context (can be implemented for different JS engines like V8, SpiderMonkey, JSC, etc.)
pub trait JSContext: Clone {
Expand Down
4 changes: 1 addition & 3 deletions crates/gosub_webexecutor/src/js/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ use core::fmt::Display;

use gosub_shared::types::Result;

use crate::js::{JSContext, JSObject, JSRuntime, JSValue};

struct Function<T: JSFunction>(pub T);
use crate::js::JSRuntime;

//trait for JS functions (interop between JS and Rust)
pub trait JSFunction {
Expand Down
2 changes: 1 addition & 1 deletion crates/gosub_webexecutor/src/js/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::fmt::Display;

use gosub_shared::types::Result;

use crate::js::{JSContext, JSFunction, JSFunctionVariadic, JSRuntime, JSValue};
use crate::js::JSRuntime;

pub trait JSObject {
type RT: JSRuntime;
Expand Down
1 change: 0 additions & 1 deletion crates/gosub_webexecutor/src/js/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ pub trait JSRuntime {
type Function: JSFunction<RT = Self>;
type FunctionVariadic: JSFunctionVariadic<RT = Self>;
type Array: JSArray<RT = Self>;
type ArrayIndex;
type FunctionCallBack: JSFunctionCallBack<RT = Self>;
type FunctionCallBackVariadic: JSFunctionCallBackVariadic<RT = Self>;
type Args: Args<RT = Self>;
Expand Down
9 changes: 3 additions & 6 deletions crates/gosub_webexecutor/src/js/v8.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::any::Any;
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};

use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;
Expand All @@ -13,7 +12,7 @@ use gosub_shared::types::Result;
pub use object::*;
pub use value::*;

use crate::js::{JSArray, JSContext, JSFunction, JSObject, JSRuntime, JSValue, ValueConversion};
use crate::js::JSRuntime;

mod array;
mod compile;
Expand Down Expand Up @@ -106,7 +105,6 @@ impl<'a> JSRuntime for V8Engine<'a> {
type Function = V8Function<'a>;
type FunctionVariadic = V8FunctionVariadic<'a>;
type Array = V8Array<'a>;
type ArrayIndex = u32;
type FunctionCallBack = V8FunctionCallBack<'a>;
type FunctionCallBackVariadic = V8FunctionCallBackVariadic<'a>;
type Args = V8Args<'a>;
Expand All @@ -125,14 +123,13 @@ impl<'a> JSRuntime for V8Engine<'a> {

#[cfg(test)]
mod tests {
use anyhow;

use crate::js::v8::V8_INITIALIZED;
use crate::js::{JSContext, JSRuntime, JSValue};

#[test]
fn v8_engine_initialization() {
let mut engine = crate::js::v8::V8Engine::new();
let _engine = crate::js::v8::V8Engine::new();

assert!(V8_INITIALIZED.is_completed());
}
Expand Down
91 changes: 70 additions & 21 deletions crates/gosub_webexecutor/src/js/v8/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ impl<'a> Iterator for V8Array<'a> {
impl<'a> JSArray for V8Array<'a> {
type RT = V8Engine<'a>;

fn get(&self, index: u32) -> Result<<Self::RT as JSRuntime>::Value> {
let Some(value) = self.value.get_index(self.ctx.borrow_mut().scope(), index) else {
fn get(&self, index: usize) -> Result<<Self::RT as JSRuntime>::Value> {
let Some(value) = self
.value
.get_index(self.ctx.borrow_mut().scope(), index as u32)
else {
return Err(Error::JS(JSError::Generic(
"failed to get a value from an array".to_owned(),
))
Expand All @@ -49,10 +52,10 @@ impl<'a> JSArray for V8Array<'a> {
Ok(V8Value::from_value(self.ctx.clone(), value))
}

fn set(&self, index: u32, value: &V8Value) -> Result<()> {
fn set(&self, index: usize, value: &V8Value) -> Result<()> {
match self
.value
.set_index(self.ctx.borrow_mut().scope(), index, value.value)
.set_index(self.ctx.borrow_mut().scope(), index as u32, value.value)
{
Some(_) => Ok(()),
None => Err(Error::JS(JSError::Conversion(
Expand Down Expand Up @@ -100,10 +103,10 @@ impl<'a> JSArray for V8Array<'a> {
Ok(V8Value::from_value(self.ctx.clone(), value))
}

fn remove<T: Into<u32>>(&self, index: T) -> Result<()> {
fn remove(&self, index: usize) -> Result<()> {
if self
.value
.delete_index(self.ctx.borrow_mut().scope(), index.into())
.delete_index(self.ctx.borrow_mut().scope(), index as u32)
.is_none()
{
return Err(Error::JS(JSError::Generic(
Expand All @@ -115,15 +118,15 @@ impl<'a> JSArray for V8Array<'a> {
Ok(())
}

fn len(&self) -> u32 {
self.value.length()
fn len(&self) -> usize {
self.value.length() as usize
}

fn is_empty(&self) -> bool {
self.value.length() == 0
}

fn new(ctx: V8Context<'a>, cap: u32) -> Result<Self> {
fn new(ctx: V8Context<'a>, cap: usize) -> Result<Self> {
let value = Array::new(ctx.borrow_mut().scope(), cap as i32);

Ok(Self {
Expand All @@ -143,19 +146,32 @@ impl<'a> JSArray for V8Array<'a> {
next: 0,
})
}

fn as_value(&self) -> <Self::RT as JSRuntime>::Value {
V8Value::from_value(self.ctx.clone(), Local::from(self.value))
}

fn as_vec(&self) -> Vec<<Self::RT as JSRuntime>::Value> {
let mut vec = Vec::with_capacity(self.len());
for i in 0..self.len() {
vec.push(self.get(i).unwrap());
}
vec
}
}

#[cfg(test)]
mod tests {
use crate::js::v8::{V8Array, V8Engine};
use crate::js::v8::{V8Array, V8Engine, V8Value};
use crate::js::{
ArrayConversion, JSArray, JSContext, JSObject, JSRuntime, JSValue, ValueConversion,
ArrayConversion, IntoJSValue, IntoRustValue, JSArray, JSContext, JSObject, JSRuntime,
JSValue,
};

#[test]
fn set() {
let mut engine = V8Engine::new();
let mut context = engine.new_context().unwrap();
let context = engine.new_context().unwrap();

let array = V8Array::new(context.clone(), 2).unwrap();
array
Expand All @@ -171,7 +187,7 @@ mod tests {
#[test]
fn get() {
let mut engine = V8Engine::new();
let mut context = engine.new_context().unwrap();
let context = engine.new_context().unwrap();

let array = V8Array::new(context.clone(), 2).unwrap();

Expand All @@ -189,7 +205,7 @@ mod tests {
#[test]
fn push() {
let mut engine = V8Engine::new();
let mut context = engine.new_context().unwrap();
let context = engine.new_context().unwrap();

let array = V8Array::new(context.clone(), 2).unwrap();

Expand All @@ -206,7 +222,7 @@ mod tests {
#[test]
fn out_of_bounds() {
let mut engine = V8Engine::new();
let mut context = engine.new_context().unwrap();
let context = engine.new_context().unwrap();

let array = V8Array::new(context.clone(), 2).unwrap();

Expand All @@ -223,7 +239,7 @@ mod tests {
#[test]
fn pop() {
let mut engine = V8Engine::new();
let mut context = engine.new_context().unwrap();
let context = engine.new_context().unwrap();

let array = V8Array::new(context.clone(), 2).unwrap();

Expand All @@ -235,14 +251,14 @@ mod tests {
.unwrap();

assert_eq!(array.pop().unwrap().as_string().unwrap(), "Hello World!");
assert_eq!(array.get(0u32).unwrap().as_number().unwrap(), 1234.0);
assert!(array.get(1u32).unwrap().is_undefined());
assert_eq!(array.get(0).unwrap().as_number().unwrap(), 1234.0);
assert!(array.get(1).unwrap().is_undefined());
}

#[test]
fn dynamic_resize() {
let mut engine = V8Engine::new();
let mut context = engine.new_context().unwrap();
let context = engine.new_context().unwrap();

let array = V8Array::new(context.clone(), 2).unwrap();

Expand All @@ -265,7 +281,7 @@ mod tests {
#[test]
fn rust_to_js() {
let mut engine = V8Engine::new();
let mut context = engine.new_context().unwrap();
let context = engine.new_context().unwrap();

let array: V8Array = [42, 1337, 1234].to_js_array(context.clone()).unwrap();

Expand All @@ -275,6 +291,21 @@ mod tests {
assert_eq!(array.get(2).unwrap().as_number().unwrap(), 1234.0);
}

#[test]
fn rust_to_js_value() {
let mut engine = V8Engine::new();
let context = engine.new_context().unwrap();

let array: V8Value = [42, 1337, 1234].to_js_value(context.clone()).unwrap();

assert!(array.is_array());
let array = array.as_array().unwrap();
assert_eq!(array.len(), 3);
assert_eq!(array.get(0).unwrap().as_number().unwrap(), 42.0);
assert_eq!(array.get(1).unwrap().as_number().unwrap(), 1337.0);
assert_eq!(array.get(2).unwrap().as_number().unwrap(), 1234.0);
}

#[test]
fn rust_to_js_global() {
let mut engine = V8Engine::new();
Expand Down Expand Up @@ -384,7 +415,7 @@ mod tests {
#[test]
fn rust_vec_to_js() {
let mut engine = V8Engine::new();
let mut context = engine.new_context().unwrap();
let context = engine.new_context().unwrap();

#[allow(clippy::useless_vec)]
let vec = vec![42, 1337, 1234];
Expand All @@ -396,4 +427,22 @@ mod tests {
assert_eq!(array.get(1).unwrap().as_number().unwrap(), 1337.0);
assert_eq!(array.get(2).unwrap().as_number().unwrap(), 1234.0);
}

#[test]
fn js_vec_to_rust() {
let mut engine = V8Engine::new();
let mut context = engine.new_context().unwrap();

let array = context
.run(
r#"
[42, 1337, 1234]
"#,
)
.unwrap();

let vec: Vec<u32> = array.as_array().unwrap().to_rust_value().unwrap();

assert_eq!(vec, vec![42, 1337, 1234]);
}
}
10 changes: 4 additions & 6 deletions crates/gosub_webexecutor/src/js/v8/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ impl Copied {
}

pub(crate) enum HandleScopeType<'a> {
WithContext(HandleScope<'a>),
WithContextRef(&'a mut HandleScope<'a>),
WithoutContext(HandleScope<'a, ()>),
CallbackScope(CallbackScope<'a>),
Expand All @@ -57,7 +56,6 @@ impl<'a> HandleScopeType<'a> {

pub(crate) fn get(&mut self) -> &mut HandleScope<'a, ()> {
match self {
Self::WithContext(scope) => scope,
Self::WithoutContext(scope) => scope,
Self::CallbackScope(scope) => scope,
Self::WithContextRef(scope) => scope,
Expand Down Expand Up @@ -121,9 +119,9 @@ impl<'a> V8Ctx<'a> {
unsafe { self.context_scope.as_mut() }
}

pub(crate) fn handle_scope(&mut self) -> &'a mut HandleScope<'a, ()> {
unsafe { self.handle_scope.as_mut() }.get()
}
// pub(crate) fn handle_scope(&mut self) -> &'a mut HandleScope<'a, ()> {
// unsafe { self.handle_scope.as_mut() }.get()
// }

pub(crate) fn context(&mut self) -> &'a mut Local<'a, v8::Context> {
unsafe { self.ctx.as_mut() }
Expand Down Expand Up @@ -217,7 +215,7 @@ pub(crate) fn ctx_from_scope_isolate<'a>(
}

pub(crate) fn ctx_from_function_callback_info(
mut scope: CallbackScope,
scope: CallbackScope,
isolate: NonNull<OwnedIsolate>,
) -> std::result::Result<V8Context, (HandleScopeType, Error)> {
let ctx = scope.get_current_context();
Expand Down
Loading

0 comments on commit fa958da

Please sign in to comment.