Skip to content

Commit

Permalink
Finish the boxing and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hansl committed Dec 20, 2024
1 parent c64417d commit e357908
Show file tree
Hide file tree
Showing 11 changed files with 912 additions and 587 deletions.
1 change: 1 addition & 0 deletions core/engine/src/builtins/symbol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ impl Symbol {
fn this_symbol_value(value: &JsValue) -> JsResult<JsSymbol> {
value
.as_symbol()
.cloned()
.or_else(|| {
value
.as_object()
Expand Down
20 changes: 10 additions & 10 deletions core/engine/src/value/conversions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Conversions from JavaScript values into Rust values, and the other way around.
use super::{JsBigInt, JsObject, JsString, JsSymbol, JsValue, Profiler};
use crate::value::inner::InnerValue;
use crate::{js_string, string::JsStr};

use super::{InnerValue, JsBigInt, JsObject, JsString, JsSymbol, JsValue, Profiler};

mod either;
mod serde_json;
pub(super) mod try_from_js;
Expand All @@ -15,15 +15,15 @@ impl From<JsStr<'_>> for JsValue {
fn from(value: JsStr<'_>) -> Self {
let _timer = Profiler::global().start_event("From<JsStr<'_>>", "value");

Self::from_inner(InnerValue::String(value.into()))
Self::from_inner(InnerValue::string(value.into()))
}
}

impl From<JsString> for JsValue {
fn from(value: JsString) -> Self {
let _timer = Profiler::global().start_event("From<JsString>", "value");

Self::from_inner(InnerValue::String(value))
Self::from_inner(InnerValue::string(value))
}
}

Expand All @@ -45,7 +45,7 @@ impl From<JsSymbol> for JsValue {
fn from(value: JsSymbol) -> Self {
let _timer = Profiler::global().start_event("From<JsSymbol>", "value");

Self::from_inner(InnerValue::Symbol(value))
Self::from_inner(InnerValue::symbol(value))
}
}

Expand All @@ -63,7 +63,7 @@ impl From<f64> for JsValue {
fn from(value: f64) -> Self {
let _timer = Profiler::global().start_event("From<f64>", "value");

Self::from_inner(InnerValue::Float64(value))
Self::from_inner(InnerValue::float64(value))
}
}

Expand All @@ -79,7 +79,7 @@ macro_rules! impl_from_integer {
i32::try_from(value)
.map_or_else(
|_| Self::from(value as f64),
|value| Self::from_inner(InnerValue::Integer32(value)),
|value| Self::from_inner(InnerValue::integer32(value)),
)
}
}
Expand All @@ -94,7 +94,7 @@ impl From<JsBigInt> for JsValue {
fn from(value: JsBigInt) -> Self {
let _timer = Profiler::global().start_event("From<JsBigInt>", "value");

Self::from_inner(InnerValue::BigInt(value))
Self::from_inner(InnerValue::bigint(value))
}
}

Expand All @@ -103,7 +103,7 @@ impl From<bool> for JsValue {
fn from(value: bool) -> Self {
let _timer = Profiler::global().start_event("From<bool>", "value");

Self::from_inner(InnerValue::Boolean(value))
Self::from_inner(InnerValue::boolean(value))
}
}

Expand All @@ -112,7 +112,7 @@ impl From<JsObject> for JsValue {
fn from(object: JsObject) -> Self {
let _timer = Profiler::global().start_event("From<JsObject>", "value");

Self::from_inner(InnerValue::Object(object))
Self::from_inner(InnerValue::object(object))
}
}

Expand Down
24 changes: 12 additions & 12 deletions core/engine/src/value/conversions/serde_json.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! This module implements the conversions from and into [`serde_json::Value`].
use super::{InnerValue, JsValue};
use super::JsValue;
use crate::{
builtins::Array,
error::JsNativeError,
js_string,
object::JsObject,
property::{PropertyDescriptor, PropertyKey},
Context, JsResult,
Context, JsResult, JsVariant,
};
use serde_json::{Map, Value};

Expand Down Expand Up @@ -113,17 +113,17 @@ impl JsValue {
///
/// Panics if the `JsValue` is `Undefined`.
pub fn to_json(&self, context: &mut Context) -> JsResult<Value> {
match &self.inner {
InnerValue::Null => Ok(Value::Null),
InnerValue::Undefined => todo!("undefined to JSON"),
InnerValue::Boolean(b) => Ok(Value::from(*b)),
InnerValue::String(string) => Ok(string.to_std_string_escaped().into()),
InnerValue::Float64(rat) => Ok(Value::from(*rat)),
InnerValue::Integer32(int) => Ok(Value::from(*int)),
InnerValue::BigInt(_bigint) => Err(JsNativeError::typ()
match self.variant() {
JsVariant::Null => Ok(Value::Null),
JsVariant::Undefined => todo!("undefined to JSON"),
JsVariant::Boolean(b) => Ok(Value::from(b)),
JsVariant::String(string) => Ok(string.to_std_string_escaped().into()),
JsVariant::Float64(rat) => Ok(Value::from(rat)),
JsVariant::Integer32(int) => Ok(Value::from(int)),
JsVariant::BigInt(_bigint) => Err(JsNativeError::typ()
.with_message("cannot convert bigint to JSON")
.into()),
InnerValue::Object(obj) => {
JsVariant::Object(obj) => {
let value_by_prop_key = |property_key, context: &mut Context| {
obj.borrow()
.properties()
Expand Down Expand Up @@ -168,7 +168,7 @@ impl JsValue {
Ok(Value::Object(map))
}
}
InnerValue::Symbol(_sym) => Err(JsNativeError::typ()
JsVariant::Symbol(_sym) => Err(JsNativeError::typ()
.with_message("cannot convert Symbol to JSON")
.into()),
}
Expand Down
67 changes: 36 additions & 31 deletions core/engine/src/value/conversions/try_from_js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use num_bigint::BigInt;
use num_traits::AsPrimitive;

use crate::value::InnerValue;
use crate::{js_string, Context, JsBigInt, JsNativeError, JsObject, JsResult, JsString, JsValue};

mod collections;
Expand Down Expand Up @@ -62,11 +61,12 @@ impl TryFromJs for String {

impl TryFromJs for JsString {
fn try_from_js(value: &JsValue, _context: &mut Context) -> JsResult<Self> {
match &value.inner {
InnerValue::String(s) => Ok(s.clone()),
_ => Err(JsNativeError::typ()
.with_message("cannot convert value to a String")
.into()),
if let Some(s) = value.as_string() {
Ok(s.clone())
} else {
Err(JsNativeError::typ()
.with_message("cannot convert value to a JsString")
.into())
}
}
}
Expand All @@ -90,7 +90,7 @@ where
T: TryFromJs,
{
fn try_from_js(value: &JsValue, context: &mut Context) -> JsResult<Self> {
let InnerValue::Object(object) = &value.inner else {
let Some(object) = &value.as_object() else {
return Err(JsNativeError::typ()
.with_message("cannot convert value to a Vec")
.into());
Expand Down Expand Up @@ -119,33 +119,36 @@ where

impl TryFromJs for JsObject {
fn try_from_js(value: &JsValue, _context: &mut Context) -> JsResult<Self> {
match &value.inner {
InnerValue::Object(o) => Ok(o.clone()),
_ => Err(JsNativeError::typ()
if let Some(o) = value.as_object() {
Ok(o.clone())
} else {
Err(JsNativeError::typ()
.with_message("cannot convert value to a Object")
.into()),
.into())
}
}
}

impl TryFromJs for JsBigInt {
fn try_from_js(value: &JsValue, _context: &mut Context) -> JsResult<Self> {
match &value.inner {
InnerValue::BigInt(b) => Ok(b.clone()),
_ => Err(JsNativeError::typ()
if let Some(b) = value.as_bigint() {
Ok(b.clone())
} else {
Err(JsNativeError::typ()
.with_message("cannot convert value to a BigInt")
.into()),
.into())
}
}
}

impl TryFromJs for BigInt {
fn try_from_js(value: &JsValue, _context: &mut Context) -> JsResult<Self> {
match &value.inner {
InnerValue::BigInt(b) => Ok(b.as_inner().clone()),
_ => Err(JsNativeError::typ()
if let Some(b) = value.as_bigint() {
Ok(b.as_inner().clone())
} else {
Err(JsNativeError::typ()
.with_message("cannot convert value to a BigInt")
.into()),
.into())
}
}
}
Expand All @@ -158,12 +161,12 @@ impl TryFromJs for JsValue {

impl TryFromJs for f64 {
fn try_from_js(value: &JsValue, _context: &mut Context) -> JsResult<Self> {
match &value.inner {
InnerValue::Integer32(i) => Ok((*i).into()),
InnerValue::Float64(r) => Ok(*r),
_ => Err(JsNativeError::typ()
if let Some(f) = value.as_number() {
Ok(f)
} else {
Err(JsNativeError::typ()
.with_message("cannot convert value to a f64")
.into()),
.into())
}
}
}
Expand All @@ -184,23 +187,25 @@ macro_rules! impl_try_from_js_integer {
$(
impl TryFromJs for $type {
fn try_from_js(value: &JsValue, _context: &mut Context) -> JsResult<Self> {
match &value.inner {
InnerValue::Integer32(i) => (*i).try_into().map_err(|e| {
if let Some(i) = value.as_i32() {
i.try_into().map_err(|e| {
JsNativeError::typ()
.with_message(format!(
concat!("cannot convert value to a ", stringify!($type), ": {}"),
e)
)
.into()
}),
InnerValue::Float64(f) => from_f64(*f).ok_or_else(|| {
})
} else if let Some(f) = value.as_number() {
from_f64(f).ok_or_else(|| {
JsNativeError::typ()
.with_message(concat!("cannot convert value to a ", stringify!($type)))
.into()
}),
_ => Err(JsNativeError::typ()
})
} else {
Err(JsNativeError::typ()
.with_message(concat!("cannot convert value to a ", stringify!($type)))
.into()),
.into())
}
}
}
Expand Down
Loading

0 comments on commit e357908

Please sign in to comment.