feat: 提取 oxide_builtins 独立 crate,泛型化 <H: VmHost>
This commit is contained in:
Generated
+19
@@ -1030,6 +1030,23 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxide_builtins"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"fast-float",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"oxide_kernel",
|
||||
"oxide_runtime_api",
|
||||
"oxide_types",
|
||||
"regex",
|
||||
"ryu",
|
||||
"serde_json",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxide_bytecode"
|
||||
version = "0.1.0"
|
||||
@@ -1107,6 +1124,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"oxide_kernel",
|
||||
"oxide_types",
|
||||
"ryu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1143,6 +1161,7 @@ dependencies = [
|
||||
"fast-float",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"oxide_builtins",
|
||||
"oxide_bytecode",
|
||||
"oxide_compiler",
|
||||
"oxide_kernel",
|
||||
|
||||
@@ -9,6 +9,7 @@ members = [
|
||||
"crates/oxide_vm",
|
||||
"crates/oxide_kernel",
|
||||
"crates/oxide_runtime_api",
|
||||
"crates/oxide_builtins",
|
||||
"crates/oxide_api",
|
||||
"crates/oxide_cli",
|
||||
"crates/oxide_test262",
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "oxide_builtins"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
rust-version.workspace = true
|
||||
description = "OxideJS - Generic builtin JS functions parameterized over VmHost"
|
||||
|
||||
[dependencies]
|
||||
oxide_runtime_api = { path = "../oxide_runtime_api" }
|
||||
oxide_types = { path = "../oxide_types" }
|
||||
oxide_kernel = { path = "../oxide_kernel" }
|
||||
fast-float.workspace = true
|
||||
ryu.workspace = true
|
||||
memchr.workspace = true
|
||||
regex.workspace = true
|
||||
serde_json.workspace = true
|
||||
chrono.workspace = true
|
||||
unicode-normalization.workspace = true
|
||||
indexmap.workspace = true
|
||||
@@ -2,9 +2,7 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::{JsObject, MAX_DENSE_PROPS};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
macro_rules! array_ptr {
|
||||
($vm:expr, $args:expr) => {{
|
||||
@@ -23,11 +21,11 @@ macro_rules! array_ptr_len {
|
||||
}};
|
||||
}
|
||||
|
||||
fn array_type_error(vm: &mut Vm, msg: &str) -> JsValue {
|
||||
crate::builtins::error::create_type_error(vm, msg)
|
||||
fn array_type_error<H: VmHost>(vm: &mut H, msg: &str) -> JsValue {
|
||||
crate::error::create_type_error(vm, msg)
|
||||
}
|
||||
|
||||
fn get_this_array_ref(vm: &mut Vm, val: JsValue) -> Result<*mut JsObject, JsValue> {
|
||||
fn get_this_array_ref<H: VmHost>(vm: &mut H, val: JsValue) -> Result<*mut JsObject, JsValue> {
|
||||
if !val.is_object() {
|
||||
return Err(array_type_error(vm, "Array method called on incompatible receiver"));
|
||||
}
|
||||
@@ -42,7 +40,7 @@ fn get_this_array_ref(vm: &mut Vm, val: JsValue) -> Result<*mut JsObject, JsValu
|
||||
Ok(ptr)
|
||||
}
|
||||
|
||||
fn require_callback(vm: &mut Vm, callback_val: JsValue) -> Result<JsValue, JsValue> {
|
||||
fn require_callback<H: VmHost>(vm: &mut H, callback_val: JsValue) -> Result<JsValue, JsValue> {
|
||||
if !callback_val.is_object() {
|
||||
return Err(array_type_error(vm, "callback is not a function"));
|
||||
}
|
||||
@@ -53,7 +51,7 @@ fn require_callback(vm: &mut Vm, callback_val: JsValue) -> Result<JsValue, JsVal
|
||||
Ok(callback_val)
|
||||
}
|
||||
|
||||
fn create_new_array(vm: &mut Vm, n: usize) -> *mut JsObject {
|
||||
fn create_new_array<H: VmHost>(vm: &mut H, n: usize) -> *mut JsObject {
|
||||
let proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
vm.alloc_object(JsObject::new_array(
|
||||
EMPTY_SHAPE_ID,
|
||||
@@ -63,25 +61,27 @@ fn create_new_array(vm: &mut Vm, n: usize) -> *mut JsObject {
|
||||
))
|
||||
}
|
||||
|
||||
fn array_length_arg(vm: &mut Vm, value: JsValue) -> Result<usize, JsValue> {
|
||||
let n = coercion::to_number(value);
|
||||
fn array_length_arg<H: VmHost>(vm: &mut H, value: JsValue) -> Result<usize, JsValue> {
|
||||
let n = oxide_runtime_api::to_number(value);
|
||||
if !n.is_finite() || n < 0.0 || n.fract() != 0.0 || n > MAX_DENSE_PROPS as f64 {
|
||||
return Err(crate::builtins::error::create_range_error(vm, "Invalid array length"));
|
||||
return Err(crate::error::create_range_error(vm, "Invalid array length"));
|
||||
}
|
||||
Ok(n as usize)
|
||||
}
|
||||
|
||||
fn invoke_native_callback(vm: &mut Vm, callback_val: JsValue, this_val: JsValue, cb_args: &[JsValue]) -> NativeResult {
|
||||
fn invoke_native_callback<H: VmHost>(
|
||||
vm: &mut H, callback_val: JsValue, this_val: JsValue, cb_args: &[JsValue],
|
||||
) -> NativeResult {
|
||||
if !callback_val.is_object() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "callback is not a function"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "callback is not a function"));
|
||||
}
|
||||
let cb_ptr = callback_val.as_js_object_ptr();
|
||||
if cb_ptr.is_null() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "callback is not a function"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "callback is not a function"));
|
||||
}
|
||||
let cb = unsafe { &*cb_ptr };
|
||||
if !cb.is_function() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "callback is not a function"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "callback is not a function"));
|
||||
}
|
||||
match vm.call_function_sync(callback_val, this_val, cb_args) {
|
||||
Ok(value) => NativeResult::Ok(value),
|
||||
@@ -89,31 +89,31 @@ fn invoke_native_callback(vm: &mut Vm, callback_val: JsValue, this_val: JsValue,
|
||||
}
|
||||
}
|
||||
|
||||
fn callback_error_from_text(vm: &mut Vm, err: &str) -> JsValue {
|
||||
fn callback_error_from_text<H: VmHost>(vm: &mut H, err: &str) -> JsValue {
|
||||
let err = err.strip_prefix("uncaught ").unwrap_or(err);
|
||||
if let Some(msg) = err.strip_prefix("TypeError: ") {
|
||||
return crate::builtins::error::create_type_error(vm, msg);
|
||||
return crate::error::create_type_error(vm, msg);
|
||||
}
|
||||
if let Some(msg) = err.strip_prefix("ReferenceError: ") {
|
||||
return crate::builtins::error::create_reference_error(vm, msg);
|
||||
return crate::error::create_reference_error(vm, msg);
|
||||
}
|
||||
if let Some(msg) = err.strip_prefix("RangeError: ") {
|
||||
return crate::builtins::error::create_range_error(vm, msg);
|
||||
return crate::error::create_range_error(vm, msg);
|
||||
}
|
||||
if let Some(msg) = err.strip_prefix("SyntaxError: ") {
|
||||
return crate::builtins::error::create_syntax_error(vm, msg);
|
||||
return crate::error::create_syntax_error(vm, msg);
|
||||
}
|
||||
if let Some(msg) = err.strip_prefix("Error: ") {
|
||||
return crate::builtins::error::create_error(vm, msg);
|
||||
return crate::error::create_error(vm, msg);
|
||||
}
|
||||
crate::builtins::error::create_error(vm, err)
|
||||
crate::error::create_error(vm, err)
|
||||
}
|
||||
|
||||
fn unexpected_tail_call_error(vm: &mut Vm) -> NativeResult {
|
||||
NativeResult::Err(crate::builtins::error::create_type_error(vm, "unexpected tail call in array callback"))
|
||||
fn unexpected_tail_call_error<H: VmHost>(vm: &mut H) -> NativeResult {
|
||||
NativeResult::Err(crate::error::create_type_error(vm, "unexpected tail call in array callback"))
|
||||
}
|
||||
|
||||
pub fn array_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let proto_val = JsValue::from_js_object(proto);
|
||||
|
||||
@@ -142,7 +142,7 @@ pub fn array_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(arr))
|
||||
}
|
||||
|
||||
pub fn array_is_array(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_is_array<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
@@ -157,7 +157,7 @@ pub fn array_is_array(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(unsafe { &*ptr }.is_array()))
|
||||
}
|
||||
|
||||
pub fn array_push(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_push<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let mut len = unsafe { &*arr_ptr }.prop_count();
|
||||
for &arg_reg in args.iter().skip(1) {
|
||||
@@ -169,7 +169,7 @@ pub fn array_push(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::int(len as i32))
|
||||
}
|
||||
|
||||
pub fn array_pop(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_pop<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &mut *arr_ptr };
|
||||
let len = arr.prop_count();
|
||||
@@ -181,17 +181,17 @@ pub fn array_pop(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(last)
|
||||
}
|
||||
|
||||
pub fn array_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &*arr_ptr };
|
||||
let n = arr.prop_count() as usize;
|
||||
let start = if args.len() > 1 {
|
||||
(coercion::to_number(vm.reg(args[1])) as i32) as usize
|
||||
(oxide_runtime_api::to_number(vm.reg(args[1])) as i32) as usize
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let end = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2])) as i32) as usize
|
||||
(oxide_runtime_api::to_number(vm.reg(args[2])) as i32) as usize
|
||||
} else {
|
||||
n
|
||||
};
|
||||
@@ -209,13 +209,13 @@ pub fn array_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(new_arr))
|
||||
}
|
||||
|
||||
pub fn array_splice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_splice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &mut *arr_ptr };
|
||||
let n = arr.prop_count() as usize;
|
||||
|
||||
let start = if args.len() > 1 {
|
||||
let v = coercion::to_number(vm.reg(args[1]));
|
||||
let v = oxide_runtime_api::to_number(vm.reg(args[1]));
|
||||
let s = v as i32;
|
||||
if s < 0 {
|
||||
(n as i32 + s).max(0) as usize
|
||||
@@ -227,7 +227,7 @@ pub fn array_splice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
};
|
||||
|
||||
let delete_count = if args.len() > 2 {
|
||||
let v = coercion::to_number(vm.reg(args[2]));
|
||||
let v = oxide_runtime_api::to_number(vm.reg(args[2]));
|
||||
(v as usize).min(n - start)
|
||||
} else {
|
||||
n - start
|
||||
@@ -271,7 +271,7 @@ pub fn array_splice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(removed_arr))
|
||||
}
|
||||
|
||||
pub fn array_concat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_concat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &*arr_ptr };
|
||||
let n = arr.prop_count() as usize;
|
||||
@@ -306,12 +306,12 @@ pub fn array_concat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(new_arr))
|
||||
}
|
||||
|
||||
pub fn array_join(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_join<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &*arr_ptr };
|
||||
let n = arr.prop_count() as usize;
|
||||
let sep = if args.len() > 1 {
|
||||
coercion::to_string(vm.reg(args[1]))
|
||||
oxide_runtime_api::to_string(vm.reg(args[1]))
|
||||
} else {
|
||||
",".to_string()
|
||||
};
|
||||
@@ -321,7 +321,7 @@ pub fn array_join(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
if v.is_undefined() || v.is_null() {
|
||||
String::new()
|
||||
} else {
|
||||
coercion::to_string(v)
|
||||
oxide_runtime_api::to_string(v)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
@@ -330,7 +330,7 @@ pub fn array_join(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(result_val)
|
||||
}
|
||||
|
||||
pub fn array_index_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &*arr_ptr };
|
||||
let n = arr.prop_count() as usize;
|
||||
@@ -339,14 +339,14 @@ pub fn array_index_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
let target = vm.reg(args[1]);
|
||||
for i in 0..n {
|
||||
if coercion::strict_equality(arr.get_prop_at(i), target) {
|
||||
if oxide_runtime_api::strict_equality(arr.get_prop_at(i), target) {
|
||||
return NativeResult::Ok(JsValue::int(i as i32));
|
||||
}
|
||||
}
|
||||
NativeResult::Ok(JsValue::int(-1))
|
||||
}
|
||||
|
||||
pub fn array_includes(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_includes<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &*arr_ptr };
|
||||
let n = arr.prop_count() as usize;
|
||||
@@ -363,14 +363,14 @@ pub fn array_includes(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Ok(JsValue::bool(true));
|
||||
}
|
||||
}
|
||||
if coercion::strict_equality(elem, target) {
|
||||
if oxide_runtime_api::strict_equality(elem, target) {
|
||||
return NativeResult::Ok(JsValue::bool(true));
|
||||
}
|
||||
}
|
||||
NativeResult::Ok(JsValue::bool(false))
|
||||
}
|
||||
|
||||
pub fn array_reverse(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_reverse<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &mut *arr_ptr };
|
||||
let n = arr.prop_count() as usize;
|
||||
@@ -386,21 +386,21 @@ pub fn array_reverse(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.reg(args[0]))
|
||||
}
|
||||
|
||||
pub fn array_flat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_flat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &*arr_ptr };
|
||||
let n = arr.prop_count() as usize;
|
||||
let depth = if args.len() > 1 {
|
||||
let n = coercion::to_number(vm.reg(args[1]));
|
||||
let n = oxide_runtime_api::to_number(vm.reg(args[1]));
|
||||
if !n.is_finite() {
|
||||
vm.kernel_core.config.max_call_depth
|
||||
vm.kernel_core().config.max_call_depth
|
||||
} else {
|
||||
(n as i32).max(1) as usize
|
||||
}
|
||||
} else {
|
||||
1
|
||||
}
|
||||
.min(vm.kernel_core.config.max_call_depth);
|
||||
.min(vm.kernel_core().config.max_call_depth);
|
||||
|
||||
fn flatten(items: &[JsValue], remaining_depth: usize, seen: &mut Vec<*mut JsObject>) -> Vec<JsValue> {
|
||||
let mut out = Vec::new();
|
||||
@@ -442,7 +442,7 @@ pub fn array_flat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(new_arr))
|
||||
}
|
||||
|
||||
pub fn array_for_each(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_for_each<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||
@@ -463,7 +463,7 @@ pub fn array_for_each(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn array_map(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||
@@ -490,7 +490,7 @@ pub fn array_map(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(new_arr))
|
||||
}
|
||||
|
||||
pub fn array_filter(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_filter<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||
@@ -505,7 +505,7 @@ pub fn array_filter(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let elem = unsafe { (*arr_ptr).get_prop_at(i) };
|
||||
match invoke_native_callback(vm, callback_val, this_val, &[elem, JsValue::int(i as i32), vm.reg(args[0])]) {
|
||||
NativeResult::Ok(result_val) => {
|
||||
if coercion::to_boolean(result_val) {
|
||||
if oxide_runtime_api::to_boolean(result_val) {
|
||||
kept.push(elem);
|
||||
}
|
||||
}
|
||||
@@ -523,7 +523,7 @@ pub fn array_filter(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(new_arr))
|
||||
}
|
||||
|
||||
pub fn array_reduce(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_reduce<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if n == 0 && args.len() < 3 {
|
||||
return NativeResult::Err(array_type_error(vm, "Reduce of empty array with no initial value"));
|
||||
@@ -562,7 +562,7 @@ pub fn array_reduce(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(accumulator)
|
||||
}
|
||||
|
||||
pub fn array_find(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_find<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||
@@ -576,7 +576,7 @@ pub fn array_find(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let elem = unsafe { (*arr_ptr).get_prop_at(i) };
|
||||
match invoke_native_callback(vm, callback_val, this_val, &[elem, JsValue::int(i as i32), vm.reg(args[0])]) {
|
||||
NativeResult::Ok(result_val) => {
|
||||
if coercion::to_boolean(result_val) {
|
||||
if oxide_runtime_api::to_boolean(result_val) {
|
||||
return NativeResult::Ok(elem);
|
||||
}
|
||||
}
|
||||
@@ -587,7 +587,7 @@ pub fn array_find(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn array_some(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_some<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||
@@ -601,7 +601,7 @@ pub fn array_some(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let elem = unsafe { (*arr_ptr).get_prop_at(i) };
|
||||
match invoke_native_callback(vm, callback_val, this_val, &[elem, JsValue::int(i as i32), vm.reg(args[0])]) {
|
||||
NativeResult::Ok(result_val) => {
|
||||
if coercion::to_boolean(result_val) {
|
||||
if oxide_runtime_api::to_boolean(result_val) {
|
||||
return NativeResult::Ok(JsValue::bool(true));
|
||||
}
|
||||
}
|
||||
@@ -612,7 +612,7 @@ pub fn array_some(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(false))
|
||||
}
|
||||
|
||||
pub fn array_every(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_every<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||
@@ -626,7 +626,7 @@ pub fn array_every(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let elem = unsafe { (*arr_ptr).get_prop_at(i) };
|
||||
match invoke_native_callback(vm, callback_val, this_val, &[elem, JsValue::int(i as i32), vm.reg(args[0])]) {
|
||||
NativeResult::Ok(result_val) => {
|
||||
if !coercion::to_boolean(result_val) {
|
||||
if !oxide_runtime_api::to_boolean(result_val) {
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
}
|
||||
@@ -637,7 +637,7 @@ pub fn array_every(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(true))
|
||||
}
|
||||
|
||||
pub fn array_flat_map(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_flat_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||
@@ -681,7 +681,7 @@ pub fn array_flat_map(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(new_arr))
|
||||
}
|
||||
|
||||
pub fn array_shift(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_shift<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &mut *arr_ptr };
|
||||
let len = arr.prop_count();
|
||||
@@ -697,7 +697,7 @@ pub fn array_shift(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(first)
|
||||
}
|
||||
|
||||
pub fn array_unshift(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_unshift<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &mut *arr_ptr };
|
||||
let len = arr.prop_count();
|
||||
@@ -714,18 +714,18 @@ pub fn array_unshift(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::int(new_len as i32))
|
||||
}
|
||||
|
||||
pub fn array_fill(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_fill<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &mut *arr_ptr };
|
||||
let len = arr.prop_count() as usize;
|
||||
let value = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let start = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2])) as i32).max(0) as usize
|
||||
(oxide_runtime_api::to_number(vm.reg(args[2])) as i32).max(0) as usize
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let end = if args.len() > 3 {
|
||||
let e = coercion::to_number(vm.reg(args[3])) as i32;
|
||||
let e = oxide_runtime_api::to_number(vm.reg(args[3])) as i32;
|
||||
(e as usize).min(len)
|
||||
} else {
|
||||
len
|
||||
@@ -736,7 +736,7 @@ pub fn array_fill(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.reg(args[0]))
|
||||
}
|
||||
|
||||
pub fn array_copy_within(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_copy_within<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &mut *arr_ptr };
|
||||
let len = arr.prop_count() as usize;
|
||||
@@ -744,17 +744,17 @@ pub fn array_copy_within(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Ok(vm.reg(args[0]));
|
||||
}
|
||||
let target = if args.len() > 1 {
|
||||
(coercion::to_number(vm.reg(args[1])) as i32) as usize
|
||||
(oxide_runtime_api::to_number(vm.reg(args[1])) as i32) as usize
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let start = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2])) as i32) as usize
|
||||
(oxide_runtime_api::to_number(vm.reg(args[2])) as i32) as usize
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let end = if args.len() > 3 {
|
||||
(coercion::to_number(vm.reg(args[3])) as i32 as usize).min(len)
|
||||
(oxide_runtime_api::to_number(vm.reg(args[3])) as i32 as usize).min(len)
|
||||
} else {
|
||||
len
|
||||
};
|
||||
@@ -770,11 +770,15 @@ pub fn array_copy_within(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.reg(args[0]))
|
||||
}
|
||||
|
||||
pub fn array_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &*arr_ptr };
|
||||
let len = arr.prop_count() as i32;
|
||||
let mut index = if args.len() > 1 { coercion::to_number(vm.reg(args[1])) as i32 } else { 0 };
|
||||
let mut index = if args.len() > 1 {
|
||||
oxide_runtime_api::to_number(vm.reg(args[1])) as i32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
if index < 0 {
|
||||
index += len;
|
||||
}
|
||||
@@ -784,20 +788,20 @@ pub fn array_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(arr.get_prop_at(index))
|
||||
}
|
||||
|
||||
pub fn array_last_index_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_last_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let arr = unsafe { &*arr_ptr };
|
||||
let len = arr.prop_count() as i32;
|
||||
let search = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
for i in (0..len).rev() {
|
||||
if coercion::strict_equality(arr.get_prop_at(i), search) {
|
||||
if oxide_runtime_api::strict_equality(arr.get_prop_at(i), search) {
|
||||
return NativeResult::Ok(JsValue::int(i));
|
||||
}
|
||||
}
|
||||
NativeResult::Ok(JsValue::int(-1))
|
||||
}
|
||||
|
||||
pub fn array_find_index(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_find_index<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||
@@ -811,7 +815,7 @@ pub fn array_find_index(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let elem = unsafe { (*arr_ptr).get_prop_at(i) };
|
||||
match invoke_native_callback(vm, callback_val, this_val, &[elem, JsValue::int(i as i32), vm.reg(args[0])]) {
|
||||
NativeResult::Ok(r) => {
|
||||
if coercion::to_boolean(r) {
|
||||
if oxide_runtime_api::to_boolean(r) {
|
||||
return NativeResult::Ok(JsValue::int(i as i32));
|
||||
}
|
||||
}
|
||||
@@ -822,7 +826,7 @@ pub fn array_find_index(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::int(-1))
|
||||
}
|
||||
|
||||
pub fn array_find_last(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_find_last<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = {
|
||||
let (arr_ptr, len) = array_ptr_len!(vm, args);
|
||||
(arr_ptr, len as i32)
|
||||
@@ -839,7 +843,7 @@ pub fn array_find_last(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let elem = unsafe { (*arr_ptr).get_prop_at(i) };
|
||||
match invoke_native_callback(vm, callback_val, this_val, &[elem, JsValue::int(i), vm.reg(args[0])]) {
|
||||
NativeResult::Ok(r) => {
|
||||
if coercion::to_boolean(r) {
|
||||
if oxide_runtime_api::to_boolean(r) {
|
||||
return NativeResult::Ok(elem);
|
||||
}
|
||||
}
|
||||
@@ -850,7 +854,7 @@ pub fn array_find_last(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn array_reduce_right(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_reduce_right<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||
@@ -883,7 +887,7 @@ pub fn array_reduce_right(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(acc)
|
||||
}
|
||||
|
||||
pub fn array_sort(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_sort<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_ptr = array_ptr!(vm, args);
|
||||
let len = unsafe { (*arr_ptr).prop_count() as usize };
|
||||
let mut vals: Vec<JsValue> = (0..len).map(|i| unsafe { (*arr_ptr).get_prop_at(i) }).collect();
|
||||
@@ -908,7 +912,7 @@ pub fn array_sort(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
if let Some(callback) = comparator {
|
||||
match invoke_native_callback(vm, callback, JsValue::undefined(), &[*a, *b]) {
|
||||
NativeResult::Ok(result) => {
|
||||
let n = coercion::to_number(result);
|
||||
let n = oxide_runtime_api::to_number(result);
|
||||
if n.is_nan() || n == 0.0 {
|
||||
std::cmp::Ordering::Equal
|
||||
} else if n < 0.0 {
|
||||
@@ -922,14 +926,13 @@ pub fn array_sort(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
std::cmp::Ordering::Equal
|
||||
}
|
||||
NativeResult::TailCall { .. } => {
|
||||
sort_error =
|
||||
Some(crate::builtins::error::create_type_error(vm, "unexpected tail call in array callback"));
|
||||
sort_error = Some(crate::error::create_type_error(vm, "unexpected tail call in array callback"));
|
||||
std::cmp::Ordering::Equal
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let sa = coercion::to_string(*a);
|
||||
let sb = coercion::to_string(*b);
|
||||
let sa = oxide_runtime_api::to_string(*a);
|
||||
let sb = oxide_runtime_api::to_string(*b);
|
||||
sa.cmp(&sb)
|
||||
}
|
||||
});
|
||||
@@ -943,9 +946,9 @@ pub fn array_sort(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.reg(args[0]))
|
||||
}
|
||||
|
||||
pub fn array_values(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_values<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(args[0]);
|
||||
match crate::builtins::iterator::make_iterator_for_value(vm, this_val) {
|
||||
match crate::iterator::make_iterator_for_value(vm, this_val) {
|
||||
Ok(iterator) => NativeResult::Ok(iterator),
|
||||
Err(err) => NativeResult::Err(err),
|
||||
}
|
||||
+23
-31
@@ -2,9 +2,7 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
pub(crate) const MAX_ARRAY_BUFFER_LENGTH: usize = 1 << 30;
|
||||
|
||||
@@ -17,23 +15,23 @@ macro_rules! native_try {
|
||||
};
|
||||
}
|
||||
|
||||
fn type_error(vm: &mut Vm, msg: &str) -> NativeResult {
|
||||
NativeResult::Err(crate::builtins::error::create_type_error(vm, msg))
|
||||
fn type_error<H: VmHost>(vm: &mut H, msg: &str) -> NativeResult {
|
||||
NativeResult::Err(crate::error::create_type_error(vm, msg))
|
||||
}
|
||||
|
||||
fn to_index(vm: &mut Vm, value: JsValue) -> Result<usize, JsValue> {
|
||||
let n = coercion::to_number(value);
|
||||
fn to_index<H: VmHost>(vm: &mut H, value: JsValue) -> Result<usize, JsValue> {
|
||||
let n = oxide_runtime_api::to_number(value);
|
||||
if n.is_nan() {
|
||||
return Ok(0);
|
||||
}
|
||||
if !n.is_finite() || n < 0.0 || n > MAX_ARRAY_BUFFER_LENGTH as f64 {
|
||||
return Err(crate::builtins::error::create_range_error(vm, "invalid ArrayBuffer length"));
|
||||
return Err(crate::error::create_range_error(vm, "invalid ArrayBuffer length"));
|
||||
}
|
||||
Ok(n.trunc() as usize)
|
||||
}
|
||||
|
||||
fn normalize_index(_vm: &mut Vm, value: JsValue, len: usize) -> usize {
|
||||
let n = coercion::to_number(value);
|
||||
fn normalize_index<H: VmHost>(_vm: &mut H, value: JsValue, len: usize) -> usize {
|
||||
let n = oxide_runtime_api::to_number(value);
|
||||
if n.is_nan() {
|
||||
return 0;
|
||||
}
|
||||
@@ -45,12 +43,12 @@ fn normalize_index(_vm: &mut Vm, value: JsValue, len: usize) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_named_prop(vm: &mut Vm, obj: &mut JsObject, name: &str, value: JsValue, attributes: PropAttributes) {
|
||||
fn set_named_prop<H: VmHost>(vm: &mut H, obj: &mut JsObject, name: &str, value: JsValue, attributes: PropAttributes) {
|
||||
let si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let _ = vm.define_data_property(obj, si, value, attributes);
|
||||
}
|
||||
|
||||
pub(crate) fn new_array_buffer(vm: &mut Vm, data: Vec<u8>) -> *mut JsObject {
|
||||
pub(crate) fn new_array_buffer<H: VmHost>(vm: &mut H, data: Vec<u8>) -> *mut JsObject {
|
||||
let proto = vm.session().builtin_world().array_buffer_proto.as_ptr() as *mut JsObject;
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto));
|
||||
obj.type_tag = JsObject::OBJ_TYPE_ARRAY_BUFFER;
|
||||
@@ -76,7 +74,7 @@ fn array_buffer_vec_ptr(obj: &JsObject) -> Option<*mut Vec<u8>> {
|
||||
obj.native_fn().map(|ptr| ptr.as_ptr() as *mut Vec<u8>)
|
||||
}
|
||||
|
||||
pub(crate) fn clone_array_buffer_native(old_obj: &JsObject, new_obj: &mut JsObject) {
|
||||
pub fn clone_array_buffer_native(old_obj: &JsObject, new_obj: &mut JsObject) {
|
||||
let Some(ptr) = array_buffer_vec_ptr(old_obj) else {
|
||||
return;
|
||||
};
|
||||
@@ -88,7 +86,7 @@ pub(crate) fn clone_array_buffer_native(old_obj: &JsObject, new_obj: &mut JsObje
|
||||
new_obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(cloned_ptr as *const ()) }));
|
||||
}
|
||||
|
||||
pub(crate) fn drop_array_buffer_native(obj: &mut JsObject) -> u64 {
|
||||
pub fn drop_array_buffer_native(obj: &mut JsObject) -> u64 {
|
||||
let Some(data_ptr) = array_buffer_vec_ptr(obj) else {
|
||||
return 0;
|
||||
};
|
||||
@@ -102,35 +100,29 @@ pub(crate) fn drop_array_buffer_native(obj: &mut JsObject) -> u64 {
|
||||
bytes as u64
|
||||
}
|
||||
|
||||
pub(crate) fn array_buffer_data_ptr(vm: &mut Vm, this_val: JsValue) -> Result<*mut Vec<u8>, JsValue> {
|
||||
pub(crate) fn array_buffer_data_ptr<H: VmHost>(vm: &mut H, this_val: JsValue) -> Result<*mut Vec<u8>, JsValue> {
|
||||
if !this_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"ArrayBuffer method called on incompatible receiver",
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, "ArrayBuffer method called on incompatible receiver"));
|
||||
}
|
||||
let obj_ptr = this_val.as_js_object_ptr();
|
||||
if obj_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "ArrayBuffer internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "ArrayBuffer internal state invalid"));
|
||||
}
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
if !obj.is_array_buffer_obj() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"ArrayBuffer method called on incompatible receiver",
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, "ArrayBuffer method called on incompatible receiver"));
|
||||
}
|
||||
let Some(data_ptr) = obj.native_fn() else {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "ArrayBuffer internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "ArrayBuffer internal state invalid"));
|
||||
};
|
||||
let data_ptr = data_ptr.as_ptr() as *mut Vec<u8>;
|
||||
if data_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "ArrayBuffer internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "ArrayBuffer internal state invalid"));
|
||||
}
|
||||
Ok(data_ptr)
|
||||
}
|
||||
|
||||
pub fn array_buffer_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_buffer_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let length = if args.len() > 1 {
|
||||
match to_index(vm, vm.reg(args[1])) {
|
||||
Ok(length) => length,
|
||||
@@ -142,13 +134,13 @@ pub fn array_buffer_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(new_array_buffer(vm, vec![0; length])))
|
||||
}
|
||||
|
||||
pub fn array_buffer_byte_length(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_buffer_byte_length<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let data_ptr = native_try!(array_buffer_data_ptr(vm, this_val));
|
||||
NativeResult::Ok(JsValue::int(unsafe { (*data_ptr).len() } as i32))
|
||||
}
|
||||
|
||||
pub fn array_buffer_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_buffer_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let data_ptr = native_try!(array_buffer_data_ptr(vm, this_val));
|
||||
let data = unsafe { &*data_ptr };
|
||||
@@ -159,7 +151,7 @@ pub fn array_buffer_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(new_array_buffer(vm, data[start..end].to_vec())))
|
||||
}
|
||||
|
||||
pub fn array_buffer_is_view(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_buffer_is_view<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
if !value.is_object() {
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
@@ -172,7 +164,7 @@ pub fn array_buffer_is_view(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(obj.is_data_view_obj() || obj.is_typed_array_obj()))
|
||||
}
|
||||
|
||||
pub fn array_buffer_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn array_buffer_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if array_buffer_data_ptr(vm, this_val).is_err() {
|
||||
return type_error(vm, "ArrayBuffer.prototype.toString called on incompatible receiver");
|
||||
@@ -1,10 +1,9 @@
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
pub fn boolean_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn boolean_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let bool_val = if args.len() > 1 {
|
||||
let arg = vm.reg(args[1]);
|
||||
@@ -51,20 +50,20 @@ pub fn boolean_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(this_val)
|
||||
}
|
||||
|
||||
pub fn boolean_prototype_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn boolean_prototype_value_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if this_val.is_bool() {
|
||||
return NativeResult::Ok(this_val);
|
||||
}
|
||||
if !this_val.is_object() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Boolean.prototype.valueOf called on non-Boolean object",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
if !obj.is_boolean_obj() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Boolean.prototype.valueOf called on non-Boolean object",
|
||||
));
|
||||
@@ -73,7 +72,7 @@ pub fn boolean_prototype_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(val)
|
||||
}
|
||||
|
||||
pub fn boolean_prototype_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn boolean_prototype_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if this_val.is_bool() {
|
||||
return if this_val.as_bool() {
|
||||
@@ -83,14 +82,14 @@ pub fn boolean_prototype_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
};
|
||||
}
|
||||
if !this_val.is_object() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Boolean.prototype.toString called on non-Boolean object",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
if !obj.is_boolean_obj() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Boolean.prototype.toString called on non-Boolean object",
|
||||
));
|
||||
+69
-70
@@ -2,10 +2,9 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::builtins::array_buffer::array_buffer_data_ptr;
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use crate::array_buffer::array_buffer_data_ptr;
|
||||
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct DataViewData {
|
||||
@@ -23,69 +22,69 @@ macro_rules! native_try {
|
||||
};
|
||||
}
|
||||
|
||||
fn to_index(vm: &mut Vm, value: JsValue, msg: &str) -> Result<usize, JsValue> {
|
||||
let n = coercion::to_number(value);
|
||||
fn to_index<H: VmHost>(vm: &mut H, value: JsValue, msg: &str) -> Result<usize, JsValue> {
|
||||
let n = oxide_runtime_api::to_number(value);
|
||||
if n.is_nan() {
|
||||
return Ok(0);
|
||||
}
|
||||
if !n.is_finite() || n < 0.0 {
|
||||
return Err(crate::builtins::error::create_range_error(vm, msg));
|
||||
return Err(crate::error::create_range_error(vm, msg));
|
||||
}
|
||||
Ok(n.trunc() as usize)
|
||||
}
|
||||
|
||||
fn is_little_endian(vm: &mut Vm, args: &[u8], idx: usize) -> bool {
|
||||
args.get(idx).map(|reg| coercion::to_boolean(vm.reg(*reg))).unwrap_or(false)
|
||||
fn is_little_endian<H: VmHost>(vm: &mut H, args: &[u8], idx: usize) -> bool {
|
||||
args.get(idx)
|
||||
.map(|reg| oxide_runtime_api::to_boolean(vm.reg(*reg)))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn numeric_arg(vm: &mut Vm, args: &[u8], idx: usize) -> f64 {
|
||||
args.get(idx).map(|reg| coercion::to_number(vm.reg(*reg))).unwrap_or(0.0)
|
||||
fn numeric_arg<H: VmHost>(vm: &mut H, args: &[u8], idx: usize) -> f64 {
|
||||
args.get(idx)
|
||||
.map(|reg| oxide_runtime_api::to_number(vm.reg(*reg)))
|
||||
.unwrap_or(0.0)
|
||||
}
|
||||
|
||||
fn set_named_prop(vm: &mut Vm, obj: &mut JsObject, name: &str, value: JsValue, attributes: PropAttributes) {
|
||||
fn set_named_prop<H: VmHost>(vm: &mut H, obj: &mut JsObject, name: &str, value: JsValue, attributes: PropAttributes) {
|
||||
let si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let _ = vm.define_data_property(obj, si, value, attributes);
|
||||
}
|
||||
|
||||
fn get_data_view_data(vm: &mut Vm, this_val: JsValue) -> Result<DataViewData, JsValue> {
|
||||
fn get_data_view_data<H: VmHost>(vm: &mut H, this_val: JsValue) -> Result<DataViewData, JsValue> {
|
||||
if !this_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"DataView method called on incompatible receiver",
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, "DataView method called on incompatible receiver"));
|
||||
}
|
||||
let obj_ptr = this_val.as_js_object_ptr();
|
||||
if obj_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "DataView internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "DataView internal state invalid"));
|
||||
}
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
if !obj.is_data_view_obj() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"DataView method called on incompatible receiver",
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, "DataView method called on incompatible receiver"));
|
||||
}
|
||||
let Some(data_ptr) = obj.native_fn() else {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "DataView internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "DataView internal state invalid"));
|
||||
};
|
||||
let data_ptr = data_ptr.as_ptr() as *const DataViewData;
|
||||
if data_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "DataView internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "DataView internal state invalid"));
|
||||
}
|
||||
Ok(unsafe { *data_ptr })
|
||||
}
|
||||
|
||||
fn checked_absolute_offset(vm: &mut Vm, view: DataViewData, offset: usize, width: usize) -> Result<usize, JsValue> {
|
||||
fn checked_absolute_offset<H: VmHost>(
|
||||
vm: &mut H, view: DataViewData, offset: usize, width: usize,
|
||||
) -> Result<usize, JsValue> {
|
||||
let Some(end) = offset.checked_add(width) else {
|
||||
return Err(crate::builtins::error::create_range_error(vm, "DataView offset out of bounds"));
|
||||
return Err(crate::error::create_range_error(vm, "DataView offset out of bounds"));
|
||||
};
|
||||
if end > view.byte_length {
|
||||
return Err(crate::builtins::error::create_range_error(vm, "DataView offset out of bounds"));
|
||||
return Err(crate::error::create_range_error(vm, "DataView offset out of bounds"));
|
||||
}
|
||||
Ok(view.byte_offset + offset)
|
||||
}
|
||||
|
||||
fn read_bytes<const N: usize>(vm: &mut Vm, args: &[u8]) -> Result<[u8; N], JsValue> {
|
||||
fn read_bytes<const N: usize, H: VmHost>(vm: &mut H, args: &[u8]) -> Result<[u8; N], JsValue> {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let view = get_data_view_data(vm, this_val)?;
|
||||
let offset = if args.len() > 1 {
|
||||
@@ -97,14 +96,14 @@ fn read_bytes<const N: usize>(vm: &mut Vm, args: &[u8]) -> Result<[u8; N], JsVal
|
||||
let buffer_ptr = array_buffer_data_ptr(vm, view.buffer)?;
|
||||
let buffer = unsafe { &*buffer_ptr };
|
||||
if abs + N > buffer.len() {
|
||||
return Err(crate::builtins::error::create_range_error(vm, "DataView offset out of bounds"));
|
||||
return Err(crate::error::create_range_error(vm, "DataView offset out of bounds"));
|
||||
}
|
||||
let mut out = [0u8; N];
|
||||
out.copy_from_slice(&buffer[abs..abs + N]);
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn write_bytes<const N: usize>(vm: &mut Vm, args: &[u8], bytes: [u8; N]) -> Result<(), JsValue> {
|
||||
fn write_bytes<const N: usize, H: VmHost>(vm: &mut H, args: &[u8], bytes: [u8; N]) -> Result<(), JsValue> {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let view = get_data_view_data(vm, this_val)?;
|
||||
let offset = if args.len() > 1 {
|
||||
@@ -116,15 +115,15 @@ fn write_bytes<const N: usize>(vm: &mut Vm, args: &[u8], bytes: [u8; N]) -> Resu
|
||||
let buffer_ptr = array_buffer_data_ptr(vm, view.buffer)?;
|
||||
let buffer = unsafe { &mut *buffer_ptr };
|
||||
if abs + N > buffer.len() {
|
||||
return Err(crate::builtins::error::create_range_error(vm, "DataView offset out of bounds"));
|
||||
return Err(crate::error::create_range_error(vm, "DataView offset out of bounds"));
|
||||
}
|
||||
buffer[abs..abs + N].copy_from_slice(&bytes);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn data_view_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "DataView requires an ArrayBuffer"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "DataView requires an ArrayBuffer"));
|
||||
}
|
||||
let buffer = vm.reg(args[1]);
|
||||
let buffer_ptr = native_try!(array_buffer_data_ptr(vm, buffer));
|
||||
@@ -135,7 +134,7 @@ pub fn data_view_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
0
|
||||
};
|
||||
if byte_offset > buffer_len {
|
||||
return NativeResult::Err(crate::builtins::error::create_range_error(vm, "DataView byteOffset out of bounds"));
|
||||
return NativeResult::Err(crate::error::create_range_error(vm, "DataView byteOffset out of bounds"));
|
||||
}
|
||||
let default_len = buffer_len - byte_offset;
|
||||
let byte_length = if args.len() > 3 {
|
||||
@@ -144,7 +143,7 @@ pub fn data_view_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
default_len
|
||||
};
|
||||
if byte_offset + byte_length > buffer_len {
|
||||
return NativeResult::Err(crate::builtins::error::create_range_error(vm, "DataView byteLength out of bounds"));
|
||||
return NativeResult::Err(crate::error::create_range_error(vm, "DataView byteLength out of bounds"));
|
||||
}
|
||||
|
||||
let proto = vm.session().builtin_world().data_view_proto.as_ptr() as *mut JsObject;
|
||||
@@ -183,7 +182,7 @@ fn data_view_data_ptr(obj: &JsObject) -> Option<*mut DataViewData> {
|
||||
obj.native_fn().map(|ptr| ptr.as_ptr() as *mut DataViewData)
|
||||
}
|
||||
|
||||
pub(crate) fn data_view_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
pub fn data_view_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
let Some(ptr) = data_view_data_ptr(obj) else {
|
||||
return Vec::new();
|
||||
};
|
||||
@@ -198,7 +197,7 @@ pub(crate) fn data_view_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clone_data_view_native_with_rewrite<F>(old_obj: &JsObject, new_obj: &mut JsObject, mut rewrite: F)
|
||||
pub fn clone_data_view_native_with_rewrite<F>(old_obj: &JsObject, new_obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
@@ -214,7 +213,7 @@ where
|
||||
new_obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(cloned as *const ()) }));
|
||||
}
|
||||
|
||||
pub(crate) fn rewrite_data_view_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
pub fn rewrite_data_view_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
@@ -229,7 +228,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn drop_data_view_native(obj: &mut JsObject) -> u64 {
|
||||
pub fn drop_data_view_native(obj: &mut JsObject) -> u64 {
|
||||
let Some(ptr) = data_view_data_ptr(obj) else {
|
||||
return 0;
|
||||
};
|
||||
@@ -241,18 +240,18 @@ pub(crate) fn drop_data_view_native(obj: &mut JsObject) -> u64 {
|
||||
std::mem::size_of::<DataViewData>() as u64
|
||||
}
|
||||
|
||||
pub fn data_view_get_int8(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<1>(vm, args));
|
||||
pub fn data_view_get_int8<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<1, H>(vm, args));
|
||||
NativeResult::Ok(JsValue::int(i8::from_ne_bytes(bytes) as i32))
|
||||
}
|
||||
|
||||
pub fn data_view_get_uint8(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<1>(vm, args));
|
||||
pub fn data_view_get_uint8<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<1, H>(vm, args));
|
||||
NativeResult::Ok(JsValue::int(bytes[0] as i32))
|
||||
}
|
||||
|
||||
pub fn data_view_get_int16(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<2>(vm, args));
|
||||
pub fn data_view_get_int16<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<2, H>(vm, args));
|
||||
let n = if is_little_endian(vm, args, 2) {
|
||||
i16::from_le_bytes(bytes)
|
||||
} else {
|
||||
@@ -261,8 +260,8 @@ pub fn data_view_get_int16(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::int(n as i32))
|
||||
}
|
||||
|
||||
pub fn data_view_get_uint16(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<2>(vm, args));
|
||||
pub fn data_view_get_uint16<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<2, H>(vm, args));
|
||||
let n = if is_little_endian(vm, args, 2) {
|
||||
u16::from_le_bytes(bytes)
|
||||
} else {
|
||||
@@ -271,8 +270,8 @@ pub fn data_view_get_uint16(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::int(n as i32))
|
||||
}
|
||||
|
||||
pub fn data_view_get_int32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<4>(vm, args));
|
||||
pub fn data_view_get_int32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<4, H>(vm, args));
|
||||
let n = if is_little_endian(vm, args, 2) {
|
||||
i32::from_le_bytes(bytes)
|
||||
} else {
|
||||
@@ -281,8 +280,8 @@ pub fn data_view_get_int32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::int(n))
|
||||
}
|
||||
|
||||
pub fn data_view_get_uint32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<4>(vm, args));
|
||||
pub fn data_view_get_uint32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<4, H>(vm, args));
|
||||
let n = if is_little_endian(vm, args, 2) {
|
||||
u32::from_le_bytes(bytes)
|
||||
} else {
|
||||
@@ -291,8 +290,8 @@ pub fn data_view_get_uint32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(n as f64))
|
||||
}
|
||||
|
||||
pub fn data_view_get_float32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<4>(vm, args));
|
||||
pub fn data_view_get_float32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<4, H>(vm, args));
|
||||
let n = if is_little_endian(vm, args, 2) {
|
||||
f32::from_le_bytes(bytes)
|
||||
} else {
|
||||
@@ -301,8 +300,8 @@ pub fn data_view_get_float32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(n as f64))
|
||||
}
|
||||
|
||||
pub fn data_view_get_float64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<8>(vm, args));
|
||||
pub fn data_view_get_float64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<8, H>(vm, args));
|
||||
let n = if is_little_endian(vm, args, 2) {
|
||||
f64::from_le_bytes(bytes)
|
||||
} else {
|
||||
@@ -311,8 +310,8 @@ pub fn data_view_get_float64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(n))
|
||||
}
|
||||
|
||||
pub fn data_view_get_big_int64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<8>(vm, args));
|
||||
pub fn data_view_get_big_int64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<8, H>(vm, args));
|
||||
let n = if is_little_endian(vm, args, 2) {
|
||||
i64::from_le_bytes(bytes)
|
||||
} else {
|
||||
@@ -321,8 +320,8 @@ pub fn data_view_get_big_int64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(n as f64))
|
||||
}
|
||||
|
||||
pub fn data_view_get_big_uint64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<8>(vm, args));
|
||||
pub fn data_view_get_big_uint64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let bytes = native_try!(read_bytes::<8, H>(vm, args));
|
||||
let n = if is_little_endian(vm, args, 2) {
|
||||
u64::from_le_bytes(bytes)
|
||||
} else {
|
||||
@@ -331,19 +330,19 @@ pub fn data_view_get_big_uint64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(n as f64))
|
||||
}
|
||||
|
||||
pub fn data_view_set_int8(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_int8<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2) as i32 as u8 as i8;
|
||||
native_try!(write_bytes(vm, args, value.to_ne_bytes()));
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_set_uint8(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_uint8<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2) as i32 as u8;
|
||||
native_try!(write_bytes(vm, args, [value]));
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_set_int16(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_int16<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2) as i32 as u16 as i16;
|
||||
let bytes = if is_little_endian(vm, args, 3) {
|
||||
value.to_le_bytes()
|
||||
@@ -354,7 +353,7 @@ pub fn data_view_set_int16(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_set_uint16(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_uint16<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2) as i32 as u16;
|
||||
let bytes = if is_little_endian(vm, args, 3) {
|
||||
value.to_le_bytes()
|
||||
@@ -365,7 +364,7 @@ pub fn data_view_set_uint16(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_set_int32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_int32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2) as i32;
|
||||
let bytes = if is_little_endian(vm, args, 3) {
|
||||
value.to_le_bytes()
|
||||
@@ -376,7 +375,7 @@ pub fn data_view_set_int32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_set_uint32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_uint32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2) as u32;
|
||||
let bytes = if is_little_endian(vm, args, 3) {
|
||||
value.to_le_bytes()
|
||||
@@ -387,7 +386,7 @@ pub fn data_view_set_uint32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_set_float32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_float32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2) as f32;
|
||||
let bytes = if is_little_endian(vm, args, 3) {
|
||||
value.to_le_bytes()
|
||||
@@ -398,7 +397,7 @@ pub fn data_view_set_float32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_set_float64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_float64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2);
|
||||
let bytes = if is_little_endian(vm, args, 3) {
|
||||
value.to_le_bytes()
|
||||
@@ -409,7 +408,7 @@ pub fn data_view_set_float64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_set_big_int64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_big_int64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2) as i64;
|
||||
let bytes = if is_little_endian(vm, args, 3) {
|
||||
value.to_le_bytes()
|
||||
@@ -420,7 +419,7 @@ pub fn data_view_set_big_int64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_set_big_uint64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_set_big_uint64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let value = numeric_arg(vm, args, 2) as u64;
|
||||
let bytes = if is_little_endian(vm, args, 3) {
|
||||
value.to_le_bytes()
|
||||
@@ -431,7 +430,7 @@ pub fn data_view_set_big_uint64(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn data_view_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn data_view_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
native_try!(get_data_view_data(vm, this_val));
|
||||
NativeResult::Ok(vm.new_string("[object DataView]"))
|
||||
@@ -4,9 +4,7 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
fn get_timestamp(obj: &JsObject) -> f64 {
|
||||
let v = obj.get_prop_at(0);
|
||||
@@ -21,9 +19,9 @@ fn set_timestamp(obj: &mut JsObject, ms: f64) {
|
||||
obj.set_prop_at(0, JsValue::float(ms));
|
||||
}
|
||||
|
||||
fn ensure_date(vm: &mut Vm, obj: &JsObject) -> Result<(), JsValue> {
|
||||
fn ensure_date<H: VmHost>(vm: &mut H, obj: &JsObject) -> Result<(), JsValue> {
|
||||
if !obj.is_date_obj() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
return Err(crate::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -37,28 +35,28 @@ macro_rules! native_try {
|
||||
};
|
||||
}
|
||||
|
||||
fn date_this_mut(vm: &mut Vm, args: &[u8]) -> Result<*mut JsObject, JsValue> {
|
||||
fn date_this_mut<H: VmHost>(vm: &mut H, args: &[u8]) -> Result<*mut JsObject, JsValue> {
|
||||
let raw = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !raw.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
return Err(crate::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
}
|
||||
let obj_ptr = raw.as_js_object_ptr();
|
||||
if obj_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
return Err(crate::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
}
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
ensure_date(vm, obj)?;
|
||||
Ok(obj_ptr)
|
||||
}
|
||||
|
||||
fn date_this(vm: &mut Vm, args: &[u8]) -> Result<*const JsObject, JsValue> {
|
||||
fn date_this<H: VmHost>(vm: &mut H, args: &[u8]) -> Result<*const JsObject, JsValue> {
|
||||
let raw = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !raw.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
return Err(crate::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
}
|
||||
let obj_ptr = raw.as_js_object_ptr();
|
||||
if obj_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
return Err(crate::error::create_type_error(vm, "called on incompatible receiver"));
|
||||
}
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
ensure_date(vm, obj)?;
|
||||
@@ -79,7 +77,7 @@ fn naive_from_ms(ms: f64) -> Option<NaiveDateTime> {
|
||||
dt_from_ms(ms).map(|dt| dt.naive_utc())
|
||||
}
|
||||
|
||||
pub fn date_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let is_ctor_call = this_val.is_object() && {
|
||||
let ptr = this_val.as_js_object_ptr();
|
||||
@@ -104,13 +102,33 @@ pub fn date_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let timestamp = if args.len() < 2 {
|
||||
Utc::now().timestamp_millis() as f64
|
||||
} else if args.len() > 2 {
|
||||
let y = coercion::to_number(vm.reg(args[1])) as i32;
|
||||
let m = coercion::to_number(vm.reg(args[2])) as u32;
|
||||
let d = if args.len() > 3 { coercion::to_number(vm.reg(args[3])) as u32 } else { 1 };
|
||||
let h = if args.len() > 4 { coercion::to_number(vm.reg(args[4])) as u32 } else { 0 };
|
||||
let min = if args.len() > 5 { coercion::to_number(vm.reg(args[5])) as u32 } else { 0 };
|
||||
let sec = if args.len() > 6 { coercion::to_number(vm.reg(args[6])) as u32 } else { 0 };
|
||||
let ms = if args.len() > 7 { coercion::to_number(vm.reg(args[7])) as u32 } else { 0 };
|
||||
let y = oxide_runtime_api::to_number(vm.reg(args[1])) as i32;
|
||||
let m = oxide_runtime_api::to_number(vm.reg(args[2])) as u32;
|
||||
let d = if args.len() > 3 {
|
||||
oxide_runtime_api::to_number(vm.reg(args[3])) as u32
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let h = if args.len() > 4 {
|
||||
oxide_runtime_api::to_number(vm.reg(args[4])) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let min = if args.len() > 5 {
|
||||
oxide_runtime_api::to_number(vm.reg(args[5])) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let sec = if args.len() > 6 {
|
||||
oxide_runtime_api::to_number(vm.reg(args[6])) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let ms = if args.len() > 7 {
|
||||
oxide_runtime_api::to_number(vm.reg(args[7])) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
NaiveDate::from_ymd_opt(y, m + 1, d)
|
||||
.and_then(|nd| {
|
||||
nd.and_hms_milli_opt(h, min, sec, ms)
|
||||
@@ -182,11 +200,11 @@ pub fn date_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(ptr))
|
||||
}
|
||||
|
||||
pub fn date_now(_vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
pub fn date_now<H: VmHost>(_vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(Utc::now().timestamp_millis() as f64))
|
||||
}
|
||||
|
||||
pub fn date_parse(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_parse<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
@@ -214,13 +232,13 @@ pub fn date_parse(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(ts))
|
||||
}
|
||||
|
||||
pub fn date_utc(_vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
pub fn date_utc<H: VmHost>(_vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(f64::NAN))
|
||||
}
|
||||
|
||||
macro_rules! make_getter {
|
||||
($name:ident, $f:expr, $df:expr) => {
|
||||
pub fn $name(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn $name<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj = unsafe { &*native_try!(date_this(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -236,7 +254,7 @@ macro_rules! make_getter {
|
||||
|
||||
macro_rules! make_utc_getter {
|
||||
($name:ident, $f:expr, $df:expr) => {
|
||||
pub fn $name(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn $name<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj = unsafe { &*native_try!(date_this(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -277,7 +295,7 @@ make_utc_getter!(
|
||||
f64::NAN
|
||||
);
|
||||
|
||||
pub fn date_get_timezone_offset(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_get_timezone_offset<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let _obj = unsafe { &*native_try!(date_this(vm, args)) };
|
||||
let offset_min = local_offset_minutes();
|
||||
NativeResult::Ok(JsValue::float(offset_min as f64))
|
||||
@@ -287,24 +305,28 @@ fn local_offset_minutes() -> i32 {
|
||||
chrono::Local::now().offset().local_minus_utc() / 60
|
||||
}
|
||||
|
||||
fn get_opt_arg(vm: &Vm, args: &[u8], idx: usize, default: u32) -> u32 {
|
||||
fn get_opt_arg<H: VmHost>(vm: &H, args: &[u8], idx: usize, default: u32) -> u32 {
|
||||
if args.len() > idx {
|
||||
coercion::to_number(vm.reg(args[idx])) as u32
|
||||
oxide_runtime_api::to_number(vm.reg(args[idx])) as u32
|
||||
} else {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
pub fn date_set_time(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_set_time<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) };
|
||||
let val = if args.len() > 1 { coercion::to_number(vm.reg(args[1])) } else { f64::NAN };
|
||||
let val = if args.len() > 1 {
|
||||
oxide_runtime_api::to_number(vm.reg(args[1]))
|
||||
} else {
|
||||
f64::NAN
|
||||
};
|
||||
set_timestamp(obj, val);
|
||||
NativeResult::Ok(JsValue::float(val))
|
||||
}
|
||||
|
||||
pub fn date_set_full_year(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_set_full_year<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let v = coercion::to_number(val);
|
||||
let v = oxide_runtime_api::to_number(val);
|
||||
let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -325,9 +347,9 @@ pub fn date_set_full_year(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
set_timestamp(obj, ts);
|
||||
NativeResult::Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_month(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_set_month<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let v = coercion::to_number(val);
|
||||
let v = oxide_runtime_api::to_number(val);
|
||||
let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -343,9 +365,9 @@ pub fn date_set_month(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
set_timestamp(obj, ts);
|
||||
NativeResult::Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_date(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_set_date<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let v = coercion::to_number(val);
|
||||
let v = oxide_runtime_api::to_number(val);
|
||||
let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -360,9 +382,9 @@ pub fn date_set_date(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
set_timestamp(obj, ts);
|
||||
NativeResult::Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_hours(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_set_hours<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let v = coercion::to_number(val);
|
||||
let v = oxide_runtime_api::to_number(val);
|
||||
let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -385,9 +407,9 @@ pub fn date_set_hours(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
set_timestamp(obj, ts);
|
||||
NativeResult::Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_minutes(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_set_minutes<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let v = coercion::to_number(val);
|
||||
let v = oxide_runtime_api::to_number(val);
|
||||
let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -408,9 +430,9 @@ pub fn date_set_minutes(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
set_timestamp(obj, ts);
|
||||
NativeResult::Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_seconds(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_set_seconds<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let v = coercion::to_number(val);
|
||||
let v = oxide_runtime_api::to_number(val);
|
||||
let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -429,9 +451,9 @@ pub fn date_set_seconds(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
set_timestamp(obj, ts);
|
||||
NativeResult::Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_milliseconds(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_set_milliseconds<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let v = coercion::to_number(val);
|
||||
let v = oxide_runtime_api::to_number(val);
|
||||
let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -447,7 +469,7 @@ pub fn date_set_milliseconds(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(ts))
|
||||
}
|
||||
|
||||
fn date_to_string_inner(vm: &mut Vm, args: &[u8], format_str: &str, invalid: &str) -> NativeResult {
|
||||
fn date_to_string_inner<H: VmHost>(vm: &mut H, args: &[u8], format_str: &str, invalid: &str) -> NativeResult {
|
||||
let obj = unsafe { &*native_try!(date_this(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -460,11 +482,11 @@ fn date_to_string_inner(vm: &mut Vm, args: &[u8], format_str: &str, invalid: &st
|
||||
NativeResult::Ok(vm.new_string(&s))
|
||||
}
|
||||
|
||||
pub fn date_to_iso_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_to_iso_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%Y-%m-%dT%H:%M:%S%.3fZ", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_to_json(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_to_json<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj = unsafe { &*native_try!(date_this(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
@@ -477,23 +499,23 @@ pub fn date_to_json(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&s))
|
||||
}
|
||||
|
||||
pub fn date_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%a %b %d %Y %H:%M:%S %Z %z", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_to_date_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_to_date_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%a %b %d %Y", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_to_time_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_to_time_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%H:%M:%S %Z", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_to_utc_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_to_utc_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%a, %d %b %Y %H:%M:%S GMT", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn date_value_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj = unsafe { &*native_try!(date_this(vm, args)) };
|
||||
let ms = get_timestamp(obj);
|
||||
NativeResult::Ok(JsValue::float(ms))
|
||||
@@ -0,0 +1,154 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_runtime_api::{to_string, NativeResult, VmHost};
|
||||
use oxide_types::mem::P;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
fn create_error_object<H: VmHost>(host: &mut H, error_proto_ptr: *mut JsObject, name: &str, message: &str) -> JsValue {
|
||||
let obj = host
|
||||
.epoch()
|
||||
.alloc(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(error_proto_ptr)));
|
||||
|
||||
let sf = Arc::clone(host.kernel_core().perm_interner());
|
||||
let sh = Arc::clone(host.kernel_core().shape_forge());
|
||||
|
||||
let si_message = sf.intern("message").0;
|
||||
let sh_message = sh.make_shape(EMPTY_SHAPE_ID, si_message);
|
||||
let msg_val = host.new_string(message);
|
||||
unsafe {
|
||||
(*obj).set_shape_id(sh_message);
|
||||
(*obj).push_prop(msg_val);
|
||||
}
|
||||
|
||||
let si_name = sf.intern("name").0;
|
||||
let sh_name = sh.make_shape(sh_message, si_name);
|
||||
let name_val = host.new_string(name);
|
||||
unsafe {
|
||||
(*obj).set_shape_id(sh_name);
|
||||
(*obj).push_prop(name_val);
|
||||
}
|
||||
|
||||
JsValue::from_js_object(obj)
|
||||
}
|
||||
|
||||
pub fn create_kind_error<H: VmHost>(host: &mut H, kind: &str, msg: &str) -> JsValue {
|
||||
let proto_ptr = match kind {
|
||||
"TypeError" => P::as_ptr(&host.session().builtin_world().type_error_proto) as *mut JsObject,
|
||||
"RangeError" => P::as_ptr(&host.session().builtin_world().range_error_proto) as *mut JsObject,
|
||||
"ReferenceError" => P::as_ptr(&host.session().builtin_world().reference_error_proto) as *mut JsObject,
|
||||
"SyntaxError" => P::as_ptr(&host.session().builtin_world().syntax_error_proto) as *mut JsObject,
|
||||
"URIError" => P::as_ptr(&host.session().builtin_world().uri_error_proto) as *mut JsObject,
|
||||
"EvalError" => P::as_ptr(&host.session().builtin_world().eval_error_proto) as *mut JsObject,
|
||||
_ => P::as_ptr(&host.session().builtin_world().error_proto) as *mut JsObject,
|
||||
};
|
||||
create_error_object(host, proto_ptr, kind, msg)
|
||||
}
|
||||
|
||||
pub fn create_type_error<H: VmHost>(host: &mut H, msg: &str) -> JsValue {
|
||||
create_kind_error(host, "TypeError", msg)
|
||||
}
|
||||
|
||||
pub fn create_error<H: VmHost>(host: &mut H, msg: &str) -> JsValue {
|
||||
create_kind_error(host, "Error", msg)
|
||||
}
|
||||
|
||||
pub fn create_reference_error<H: VmHost>(host: &mut H, msg: &str) -> JsValue {
|
||||
create_kind_error(host, "ReferenceError", msg)
|
||||
}
|
||||
|
||||
pub fn create_range_error<H: VmHost>(host: &mut H, msg: &str) -> JsValue {
|
||||
create_kind_error(host, "RangeError", msg)
|
||||
}
|
||||
|
||||
pub fn create_syntax_error<H: VmHost>(host: &mut H, msg: &str) -> JsValue {
|
||||
create_kind_error(host, "SyntaxError", msg)
|
||||
}
|
||||
|
||||
pub fn create_uri_error<H: VmHost>(host: &mut H, msg: &str) -> JsValue {
|
||||
create_kind_error(host, "URIError", msg)
|
||||
}
|
||||
|
||||
fn get_msg<H: VmHost>(host: &mut H, args: &[u8]) -> String {
|
||||
if args.len() > 1 {
|
||||
to_string(host.reg(args[1]))
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_constructor<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(host, args);
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(host, proto_ptr, "Error", &msg))
|
||||
}
|
||||
|
||||
pub fn type_error_constructor<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(host, args);
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().type_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(host, proto_ptr, "TypeError", &msg))
|
||||
}
|
||||
|
||||
pub fn reference_error_constructor<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(host, args);
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().reference_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(host, proto_ptr, "ReferenceError", &msg))
|
||||
}
|
||||
|
||||
pub fn range_error_constructor<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(host, args);
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().range_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(host, proto_ptr, "RangeError", &msg))
|
||||
}
|
||||
|
||||
pub fn syntax_error_constructor<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(host, args);
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().syntax_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(host, proto_ptr, "SyntaxError", &msg))
|
||||
}
|
||||
|
||||
pub fn uri_error_constructor<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(host, args);
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().uri_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(host, proto_ptr, "URIError", &msg))
|
||||
}
|
||||
|
||||
pub fn eval_error_constructor<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(host, args);
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().eval_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(host, proto_ptr, "EvalError", &msg))
|
||||
}
|
||||
|
||||
pub fn error_to_string<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = host.reg(args[0]);
|
||||
let (name, msg) = if this_val.is_object() {
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let name_val = obj
|
||||
.hash_props_vec()
|
||||
.and_then(|v| v.first())
|
||||
.copied()
|
||||
.unwrap_or(JsValue::undefined());
|
||||
let msg_val = obj
|
||||
.hash_props_vec()
|
||||
.and_then(|v| v.get(1))
|
||||
.copied()
|
||||
.unwrap_or(JsValue::undefined());
|
||||
(
|
||||
host.lookup_str(name_val).unwrap_or_else(|| "Error".to_string()),
|
||||
host.lookup_str(msg_val).unwrap_or_default(),
|
||||
)
|
||||
} else {
|
||||
("Error".to_string(), String::new())
|
||||
};
|
||||
let result = oxide_runtime_api::format_error_message(&name, &msg);
|
||||
NativeResult::Ok(host.new_string(&result))
|
||||
}
|
||||
|
||||
pub fn error_stack_getter<H: VmHost>(host: &mut H, _args: &[u8]) -> NativeResult {
|
||||
let names = host.call_stack_function_names();
|
||||
let mut lines: Vec<String> = names.iter().rev().map(|n| format!(" at {} (native)", n)).collect();
|
||||
lines.push(" at <anonymous> (native)".to_string());
|
||||
let result = lines.join("\n");
|
||||
NativeResult::Ok(host.new_string(&result))
|
||||
}
|
||||
@@ -2,10 +2,9 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::{JsObject, NativeFnPtr};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
fn invoke_target(vm: &mut Vm, target_val: JsValue, this_val: JsValue, arg_regs: &[u8]) -> NativeResult {
|
||||
fn invoke_target<H: VmHost>(vm: &mut H, target_val: JsValue, this_val: JsValue, arg_regs: &[u8]) -> NativeResult {
|
||||
let args: Vec<JsValue> = arg_regs.iter().map(|&r| vm.reg(r)).collect();
|
||||
NativeResult::TailCall {
|
||||
callee: target_val,
|
||||
@@ -14,7 +13,7 @@ fn invoke_target(vm: &mut Vm, target_val: JsValue, this_val: JsValue, arg_regs:
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_dispatcher(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
fn bind_dispatcher<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let wrapper_val = vm.reg(254);
|
||||
let wrapper = unsafe { &*wrapper_val.as_js_object_ptr() };
|
||||
let bound_target = wrapper
|
||||
@@ -31,7 +30,7 @@ fn bind_dispatcher(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
invoke_target(vm, bound_target, bound_this, &arg_regs)
|
||||
}
|
||||
|
||||
pub fn function_call(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn function_call<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.is_empty() {
|
||||
return NativeResult::Err(JsValue::undefined());
|
||||
}
|
||||
@@ -41,7 +40,7 @@ pub fn function_call(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
invoke_target(vm, target_val, this_val, &arg_regs)
|
||||
}
|
||||
|
||||
pub fn function_apply(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn function_apply<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.is_empty() {
|
||||
return NativeResult::Err(JsValue::undefined());
|
||||
}
|
||||
@@ -81,7 +80,7 @@ pub fn function_apply(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
invoke_target(vm, target_val, this_val, &arg_regs)
|
||||
}
|
||||
|
||||
pub fn function_bind(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn function_bind<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.is_empty() {
|
||||
return NativeResult::Err(JsValue::undefined());
|
||||
}
|
||||
@@ -95,7 +94,7 @@ pub fn function_bind(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
unsafe {
|
||||
(*wrapper).set_function(true);
|
||||
// SAFETY: bind_dispatcher is a NativeFn fn-item; valid to store as NativeFnPtr.
|
||||
(*wrapper).set_native_fn(Some(NativeFnPtr::from_raw(bind_dispatcher as *const ())));
|
||||
(*wrapper).set_native_fn(Some(NativeFnPtr::from_raw(bind_dispatcher::<H> as *const ())));
|
||||
(*wrapper).set_native_arg_count(0);
|
||||
(*wrapper).ensure_hash_props().push(target_val);
|
||||
(*wrapper).ensure_hash_props().push(bound_this);
|
||||
@@ -104,10 +103,10 @@ pub fn function_bind(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(wrapper))
|
||||
}
|
||||
|
||||
pub fn function_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn function_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !this_val.is_object() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Function.prototype.toString called on non-function",
|
||||
));
|
||||
@@ -115,7 +114,7 @@ pub fn function_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
|
||||
let func = unsafe { &*this_val.as_js_object_ptr() };
|
||||
if !func.is_function() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Function.prototype.toString called on non-function",
|
||||
));
|
||||
@@ -127,8 +126,8 @@ pub fn function_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
.and_then(|v| vm.lookup_str(v))
|
||||
.unwrap_or_else(|| {
|
||||
let sub_idx = func.sub_module_index();
|
||||
if sub_idx > 0 && (sub_idx as usize) <= vm.sub_modules.len() {
|
||||
vm.sub_modules[sub_idx as usize - 1].function_name.clone().unwrap_or_default()
|
||||
if sub_idx > 0 {
|
||||
vm.sub_module_function_name((sub_idx - 1) as u16)
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
use oxide_runtime_api::VmHost;
|
||||
mod annex_b;
|
||||
mod uri;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
|
||||
pub use annex_b::{js_escape, js_unescape};
|
||||
pub use uri::{decode_uri, decode_uri_component, encode_uri, encode_uri_component};
|
||||
|
||||
fn string_arg(vm: &mut Vm, args: &[u8]) -> String {
|
||||
fn string_arg<H: VmHost>(vm: &mut H, args: &[u8]) -> String {
|
||||
if args.len() > 1 {
|
||||
coercion::to_string(vm.reg(args[1]))
|
||||
oxide_runtime_api::to_string(vm.reg(args[1]))
|
||||
} else {
|
||||
"undefined".to_string()
|
||||
}
|
||||
+3
-4
@@ -1,5 +1,4 @@
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
const ESCAPE_SAFE: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_+-./";
|
||||
|
||||
@@ -85,12 +84,12 @@ fn unescape_string(input: &str) -> String {
|
||||
out
|
||||
}
|
||||
|
||||
pub fn js_escape(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn js_escape<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let input = super::string_arg(vm, args);
|
||||
NativeResult::Ok(vm.new_string(&escape_string(&input)))
|
||||
}
|
||||
|
||||
pub fn js_unescape(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn js_unescape<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let input = super::string_arg(vm, args);
|
||||
NativeResult::Ok(vm.new_string(&unescape_string(&input)))
|
||||
}
|
||||
+7
-8
@@ -1,5 +1,4 @@
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
const URI_UNESCAPED: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.!~*'()";
|
||||
const URI_RESERVED: &str = ";/?:@&=+$,#";
|
||||
@@ -82,21 +81,21 @@ fn decode_uri_string(input: &str, preserve_reserved: bool) -> Result<String, ()>
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn uri_error(vm: &mut Vm) -> NativeResult {
|
||||
NativeResult::Err(crate::builtins::error::create_uri_error(vm, URI_ERROR_MESSAGE))
|
||||
fn uri_error<H: VmHost>(vm: &mut H) -> NativeResult {
|
||||
NativeResult::Err(crate::error::create_uri_error(vm, URI_ERROR_MESSAGE))
|
||||
}
|
||||
|
||||
pub fn encode_uri(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn encode_uri<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let input = super::string_arg(vm, args);
|
||||
NativeResult::Ok(vm.new_string(&encode_uri_string(&input, URI_SAFE)))
|
||||
}
|
||||
|
||||
pub fn encode_uri_component(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn encode_uri_component<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let input = super::string_arg(vm, args);
|
||||
NativeResult::Ok(vm.new_string(&encode_uri_string(&input, URI_UNESCAPED)))
|
||||
}
|
||||
|
||||
pub fn decode_uri(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn decode_uri<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let input = super::string_arg(vm, args);
|
||||
match decode_uri_string(&input, true) {
|
||||
Ok(decoded) => NativeResult::Ok(vm.new_string(&decoded)),
|
||||
@@ -104,7 +103,7 @@ pub fn decode_uri(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_uri_component(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn decode_uri_component<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let input = super::string_arg(vm, args);
|
||||
match decode_uri_string(&input, false) {
|
||||
Ok(decoded) => NativeResult::Ok(vm.new_string(&decoded)),
|
||||
@@ -2,18 +2,16 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
const INNER_PROP: &str = "__inner__";
|
||||
const INDEX_PROP: &str = "__index__";
|
||||
|
||||
pub fn iterator_constructor(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
NativeResult::Err(crate::builtins::error::create_type_error(vm, "Iterator is not a constructor"))
|
||||
pub fn iterator_constructor<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
NativeResult::Err(crate::error::create_type_error(vm, "Iterator is not a constructor"))
|
||||
}
|
||||
|
||||
pub fn iterator_from(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn iterator_from<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let iterable = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
match make_iterator_for_value(vm, iterable) {
|
||||
Ok(iterator) => NativeResult::Ok(iterator),
|
||||
@@ -21,7 +19,7 @@ pub fn iterator_from(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn make_iterator_for_value(vm: &mut Vm, value: JsValue) -> Result<JsValue, JsValue> {
|
||||
pub fn make_iterator_for_value<H: VmHost>(vm: &mut H, value: JsValue) -> Result<JsValue, JsValue> {
|
||||
let inner = get_iterator(vm, value)?;
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let wrapper = vm
|
||||
@@ -35,19 +33,16 @@ pub(crate) fn make_iterator_for_value(vm: &mut Vm, value: JsValue) -> Result<JsV
|
||||
vm.set_or_create_prop_value(wrapper_obj, inner_si, inner);
|
||||
vm.set_or_create_prop_value(wrapper_obj, index_si, JsValue::int(0));
|
||||
|
||||
let next_fn = make_native_function(vm, "next", iterator_wrapper_next as *const (), 0);
|
||||
let next_fn = make_native_function(vm, "next", iterator_wrapper_next::<H> as *const (), 0);
|
||||
vm.set_or_create_prop_value(wrapper_obj, next_si, next_fn);
|
||||
|
||||
Ok(JsValue::from_js_object(wrapper))
|
||||
}
|
||||
|
||||
pub fn iterator_wrapper_next(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn iterator_wrapper_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !this_val.is_object() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Iterator wrapper next called on non-object",
|
||||
));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Iterator wrapper next called on non-object"));
|
||||
}
|
||||
|
||||
let wrapper = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
@@ -55,12 +50,7 @@ pub fn iterator_wrapper_next(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let index_si = vm.kernel_core().perm_interner().intern(INDEX_PROP).0;
|
||||
let inner = match vm.ordinary_get(wrapper, inner_si, this_val) {
|
||||
Ok(inner) if !inner.is_undefined() => inner,
|
||||
_ => {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Iterator wrapper has no inner iterator",
|
||||
))
|
||||
}
|
||||
_ => return NativeResult::Err(crate::error::create_type_error(vm, "Iterator wrapper has no inner iterator")),
|
||||
};
|
||||
|
||||
if let Some(result) = next_array_like(vm, wrapper, inner, index_si) {
|
||||
@@ -72,18 +62,18 @@ pub fn iterator_wrapper_next(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let next_si = vm.kernel_core().perm_interner().intern("next").0;
|
||||
let next = match vm.ordinary_get(inner_obj, next_si, inner) {
|
||||
Ok(next) => next,
|
||||
Err(err) => return NativeResult::Err(crate::builtins::error::create_type_error(vm, &err)),
|
||||
Err(err) => return NativeResult::Err(crate::error::create_type_error(vm, &err)),
|
||||
};
|
||||
return match vm.call_function_sync(next, inner, &[]) {
|
||||
Ok(result) => NativeResult::Ok(result),
|
||||
Err(err) => NativeResult::Err(crate::builtins::error::create_type_error(vm, &err)),
|
||||
Err(err) => NativeResult::Err(crate::error::create_type_error(vm, &err)),
|
||||
};
|
||||
}
|
||||
|
||||
NativeResult::Err(crate::builtins::error::create_type_error(vm, "value is not iterable"))
|
||||
NativeResult::Err(crate::error::create_type_error(vm, "value is not iterable"))
|
||||
}
|
||||
|
||||
fn get_iterator(vm: &mut Vm, value: JsValue) -> Result<JsValue, JsValue> {
|
||||
fn get_iterator<H: VmHost>(vm: &mut H, value: JsValue) -> Result<JsValue, JsValue> {
|
||||
if value.is_string() || is_array_value(value) {
|
||||
return Ok(value);
|
||||
}
|
||||
@@ -98,10 +88,10 @@ fn get_iterator(vm: &mut Vm, value: JsValue) -> Result<JsValue, JsValue> {
|
||||
}
|
||||
}
|
||||
|
||||
Err(crate::builtins::error::create_type_error(vm, "value is not iterable"))
|
||||
Err(crate::error::create_type_error(vm, "value is not iterable"))
|
||||
}
|
||||
|
||||
fn next_array_like(vm: &mut Vm, wrapper: &mut JsObject, inner: JsValue, index_si: u32) -> Option<JsValue> {
|
||||
fn next_array_like<H: VmHost>(vm: &mut H, wrapper: &mut JsObject, inner: JsValue, index_si: u32) -> Option<JsValue> {
|
||||
if is_array_value(inner) {
|
||||
let index = current_index(vm, wrapper, index_si);
|
||||
let arr = unsafe { &*inner.as_js_object_ptr() };
|
||||
@@ -115,7 +105,7 @@ fn next_array_like(vm: &mut Vm, wrapper: &mut JsObject, inner: JsValue, index_si
|
||||
|
||||
if inner.is_string() {
|
||||
let index = current_index(vm, wrapper, index_si);
|
||||
let source = coercion::to_string(inner);
|
||||
let source = oxide_runtime_api::to_string(inner);
|
||||
let mut chars = source.chars();
|
||||
if let Some(ch) = chars.nth(index) {
|
||||
vm.set_or_create_prop_value(wrapper, index_si, JsValue::int((index + 1) as i32));
|
||||
@@ -128,7 +118,7 @@ fn next_array_like(vm: &mut Vm, wrapper: &mut JsObject, inner: JsValue, index_si
|
||||
None
|
||||
}
|
||||
|
||||
fn current_index(vm: &mut Vm, wrapper: &JsObject, index_si: u32) -> usize {
|
||||
fn current_index<H: VmHost>(vm: &mut H, wrapper: &JsObject, index_si: u32) -> usize {
|
||||
match vm.ordinary_get(wrapper, index_si, JsValue::undefined()) {
|
||||
Ok(value) if value.is_int() => value.as_int().max(0) as usize,
|
||||
Ok(value) if value.is_double() => value.as_double().max(0.0) as usize,
|
||||
@@ -136,7 +126,7 @@ fn current_index(vm: &mut Vm, wrapper: &JsObject, index_si: u32) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_iter_result(vm: &mut Vm, value: JsValue, done: bool) -> JsValue {
|
||||
fn make_iter_result<H: VmHost>(vm: &mut H, value: JsValue, done: bool) -> JsValue {
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let obj = vm
|
||||
.epoch()
|
||||
@@ -149,7 +139,7 @@ fn make_iter_result(vm: &mut Vm, value: JsValue, done: bool) -> JsValue {
|
||||
JsValue::from_js_object(obj)
|
||||
}
|
||||
|
||||
fn make_native_function(vm: &mut Vm, name: &str, native_fn: *const (), arg_count: u8) -> JsValue {
|
||||
fn make_native_function<H: VmHost>(vm: &mut H, name: &str, native_fn: *const (), arg_count: u8) -> JsValue {
|
||||
let function_proto = vm.session().builtin_world().function_proto.as_ptr() as *mut JsObject;
|
||||
let mut func = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(function_proto));
|
||||
func.set_function(true);
|
||||
@@ -5,20 +5,17 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::builtins::object::walk_own_keys;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use crate::object::walk_own_keys;
|
||||
|
||||
pub fn json_parse(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
pub fn json_parse<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(crate::builtins::error::create_syntax_error(vm, "JSON.parse requires 1 argument"));
|
||||
return NativeResult::Err(crate::error::create_syntax_error(vm, "JSON.parse requires 1 argument"));
|
||||
}
|
||||
let val = vm.reg(args[1]);
|
||||
if !val.is_string() {
|
||||
return NativeResult::Err(crate::builtins::error::create_syntax_error(
|
||||
vm,
|
||||
"JSON.parse: argument is not a string",
|
||||
));
|
||||
return NativeResult::Err(crate::error::create_syntax_error(vm, "JSON.parse: argument is not a string"));
|
||||
}
|
||||
let text = {
|
||||
// SAFETY: val is a string value.
|
||||
@@ -27,13 +24,13 @@ pub fn json_parse(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
|
||||
let parsed: serde_json::Value = match serde_json::from_str(&text) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return NativeResult::Err(crate::builtins::error::create_syntax_error(vm, &format!("{}", e))),
|
||||
Err(e) => return NativeResult::Err(crate::error::create_syntax_error(vm, &format!("{}", e))),
|
||||
};
|
||||
|
||||
NativeResult::Ok(value_to_jsvalue(vm, &parsed))
|
||||
}
|
||||
|
||||
fn value_to_jsvalue(vm: &mut Vm, val: &serde_json::Value) -> JsValue {
|
||||
fn value_to_jsvalue<H: VmHost>(vm: &mut H, val: &serde_json::Value) -> JsValue {
|
||||
match val {
|
||||
serde_json::Value::Null => JsValue::null(),
|
||||
serde_json::Value::Bool(b) => JsValue::bool(*b),
|
||||
@@ -78,7 +75,7 @@ fn value_to_jsvalue(vm: &mut Vm, val: &serde_json::Value) -> JsValue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn json_stringify(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn json_stringify<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
@@ -89,12 +86,14 @@ pub fn json_stringify(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let mut visited = HashSet::new();
|
||||
let mut output = String::new();
|
||||
if jsvalue_to_json(vm, value, &mut visited, &mut output).is_err() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "cyclic object value"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "cyclic object value"));
|
||||
};
|
||||
NativeResult::Ok(vm.new_string(&output))
|
||||
}
|
||||
|
||||
fn jsvalue_to_json(vm: &Vm, val: JsValue, visited: &mut HashSet<*const u8>, out: &mut String) -> Result<(), ()> {
|
||||
fn jsvalue_to_json<H: VmHost>(
|
||||
vm: &H, val: JsValue, visited: &mut HashSet<*const u8>, out: &mut String,
|
||||
) -> Result<(), ()> {
|
||||
if val.is_null() {
|
||||
out.push_str("null");
|
||||
} else if val.is_undefined() {
|
||||
@@ -163,7 +162,9 @@ fn stringify_string(s: &str, out: &mut String) {
|
||||
out.push('"');
|
||||
}
|
||||
|
||||
fn stringify_object(vm: &Vm, obj: &JsObject, visited: &mut HashSet<*const u8>, out: &mut String) -> Result<(), ()> {
|
||||
fn stringify_object<H: VmHost>(
|
||||
vm: &H, obj: &JsObject, visited: &mut HashSet<*const u8>, out: &mut String,
|
||||
) -> Result<(), ()> {
|
||||
out.push('{');
|
||||
let keys = walk_own_keys(vm, obj);
|
||||
let mut first = true;
|
||||
@@ -193,7 +194,9 @@ fn stringify_object(vm: &Vm, obj: &JsObject, visited: &mut HashSet<*const u8>, o
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stringify_array(vm: &Vm, obj: &JsObject, visited: &mut HashSet<*const u8>, out: &mut String) -> Result<(), ()> {
|
||||
fn stringify_array<H: VmHost>(
|
||||
vm: &H, obj: &JsObject, visited: &mut HashSet<*const u8>, out: &mut String,
|
||||
) -> Result<(), ()> {
|
||||
out.push('[');
|
||||
let len = obj.prop_vec_len();
|
||||
for i in 0..len {
|
||||
@@ -2,9 +2,9 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::builtins::set::SetKey;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use crate::set::SetKey;
|
||||
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
macro_rules! native_try {
|
||||
($expr:expr) => {
|
||||
@@ -27,20 +27,20 @@ type MapInner = indexmap::IndexMap<SetKey, JsValue>;
|
||||
/// is created in `new_map_inner()` and is never freed until the process exits (intentional
|
||||
/// leak — lifetime is tied to the epoch). Only one live `*mut` alias exists at a time
|
||||
/// per Map object because native calls are single-threaded.
|
||||
fn get_map_inner(vm: &mut Vm, this_val: JsValue) -> Result<*mut MapInner, JsValue> {
|
||||
fn get_map_inner<H: VmHost>(vm: &mut H, this_val: JsValue) -> Result<*mut MapInner, JsValue> {
|
||||
if !this_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "called on non-Map object"));
|
||||
return Err(crate::error::create_type_error(vm, "called on non-Map object"));
|
||||
}
|
||||
let map_ptr = this_val.as_js_object_ptr();
|
||||
if map_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "Map internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "Map internal state invalid"));
|
||||
}
|
||||
// SAFETY: map_ptr is a non-null, aligned pointer to a JsObject bump-allocated in the
|
||||
// current Epoch. It remains valid for the duration of this call (epoch is not reset
|
||||
// during native execution).
|
||||
let map_obj = unsafe { &*map_ptr };
|
||||
if !map_obj.is_map() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
return Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Map.prototype method called on incompatible receiver",
|
||||
));
|
||||
@@ -50,7 +50,7 @@ fn get_map_inner(vm: &mut Vm, this_val: JsValue) -> Result<*mut MapInner, JsValu
|
||||
// Alignment: IndexMap requires at most 8-byte alignment; the global allocator satisfies this.
|
||||
let inner_ptr = map_obj.native_data() as *mut MapInner;
|
||||
if inner_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "Map internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "Map internal state invalid"));
|
||||
}
|
||||
Ok(inner_ptr)
|
||||
}
|
||||
@@ -59,7 +59,7 @@ fn new_map_inner() -> *mut MapInner {
|
||||
Box::into_raw(Box::new(MapInner::new()))
|
||||
}
|
||||
|
||||
fn alloc_map(vm: &mut Vm) -> *mut JsObject {
|
||||
fn alloc_map<H: VmHost>(vm: &mut H) -> *mut JsObject {
|
||||
let map_proto = vm.session().builtin_world().map_proto.as_ptr() as *mut JsObject;
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(map_proto));
|
||||
obj.set_map(true);
|
||||
@@ -68,7 +68,7 @@ fn alloc_map(vm: &mut Vm) -> *mut JsObject {
|
||||
vm.alloc_object(obj)
|
||||
}
|
||||
|
||||
pub(crate) fn map_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
pub fn map_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
if !obj.is_map() {
|
||||
return Vec::new();
|
||||
}
|
||||
@@ -80,12 +80,12 @@ pub(crate) fn map_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
(*inner)
|
||||
.iter()
|
||||
.flat_map(|(key, value)| [key.0, *value])
|
||||
.filter(|value| value.is_object())
|
||||
.filter(|value: &JsValue| value.is_object())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clone_map_native_with_rewrite<F>(src: &JsObject, dst: &mut JsObject, mut rewrite: F)
|
||||
pub fn clone_map_native_with_rewrite<F>(src: &JsObject, dst: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
@@ -108,7 +108,7 @@ where
|
||||
dst.set_native_data(Box::into_raw(Box::new(cloned)) as *mut u8);
|
||||
}
|
||||
|
||||
pub(crate) fn rewrite_map_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
pub fn rewrite_map_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
@@ -130,7 +130,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn drop_map_native(obj: &mut JsObject) -> u64 {
|
||||
pub fn drop_map_native(obj: &mut JsObject) -> u64 {
|
||||
if !obj.is_map() {
|
||||
return 0;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ pub(crate) fn drop_map_native(obj: &mut JsObject) -> u64 {
|
||||
return 0;
|
||||
}
|
||||
unsafe {
|
||||
let boxed = Box::from_raw(inner);
|
||||
let boxed: Box<MapInner> = Box::from_raw(inner);
|
||||
let bytes = std::mem::size_of::<MapInner>() + boxed.capacity() * std::mem::size_of::<(SetKey, JsValue)>();
|
||||
drop(boxed);
|
||||
obj.set_native_data(std::ptr::null_mut());
|
||||
@@ -147,12 +147,12 @@ pub(crate) fn drop_map_native(obj: &mut JsObject) -> u64 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_constructor(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
pub fn map_constructor<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
let map_obj = alloc_map(vm);
|
||||
NativeResult::Ok(JsValue::from_js_object(map_obj))
|
||||
}
|
||||
|
||||
pub fn map_set(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn map_set<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_map_inner(vm, this_val));
|
||||
let key = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
@@ -163,7 +163,7 @@ pub fn map_set(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(this_val)
|
||||
}
|
||||
|
||||
pub fn map_get(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn map_get<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_map_inner(vm, this_val));
|
||||
let key = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
@@ -171,7 +171,7 @@ pub fn map_get(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(found.unwrap_or(JsValue::undefined()))
|
||||
}
|
||||
|
||||
pub fn map_has(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn map_has<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_map_inner(vm, this_val));
|
||||
let key = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
@@ -179,7 +179,7 @@ pub fn map_has(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(found))
|
||||
}
|
||||
|
||||
pub fn map_delete(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn map_delete<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_map_inner(vm, this_val));
|
||||
let key = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
@@ -187,7 +187,7 @@ pub fn map_delete(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(removed.is_some()))
|
||||
}
|
||||
|
||||
pub fn map_clear(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn map_clear<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_map_inner(vm, this_val));
|
||||
unsafe {
|
||||
@@ -196,7 +196,7 @@ pub fn map_clear(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn map_size(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn map_size<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_map_inner(vm, this_val));
|
||||
NativeResult::Ok(JsValue::float(unsafe { (*inner).len() } as f64))
|
||||
@@ -1,14 +1,12 @@
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
fn num(vm: &Vm, reg: u8) -> f64 {
|
||||
coercion::to_number(vm.reg(reg))
|
||||
fn num<H: VmHost>(vm: &H, reg: u8) -> f64 {
|
||||
oxide_runtime_api::to_number(vm.reg(reg))
|
||||
}
|
||||
|
||||
fn arg1(vm: &Vm, args: &[u8]) -> f64 {
|
||||
fn arg1<H: VmHost>(vm: &H, args: &[u8]) -> f64 {
|
||||
if args.len() < 2 {
|
||||
f64::NAN
|
||||
} else {
|
||||
@@ -16,14 +14,14 @@ fn arg1(vm: &Vm, args: &[u8]) -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
fn arg2(vm: &Vm, args: &[u8]) -> (f64, f64) {
|
||||
fn arg2<H: VmHost>(vm: &H, args: &[u8]) -> (f64, f64) {
|
||||
(
|
||||
if args.len() > 1 { num(vm, args[1]) } else { f64::NAN },
|
||||
if args.len() > 2 { num(vm, args[2]) } else { f64::NAN },
|
||||
)
|
||||
}
|
||||
|
||||
pub fn math_abs(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_abs<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
@@ -37,7 +35,7 @@ pub fn math_abs(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
|
||||
macro_rules! math_unary {
|
||||
($name:ident, $op:ident) => {
|
||||
pub fn $name(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn $name<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(arg1(vm, args).$op()))
|
||||
}
|
||||
};
|
||||
@@ -67,18 +65,18 @@ math_unary!(math_tan, tan);
|
||||
math_unary!(math_tanh, tanh);
|
||||
math_unary!(math_trunc, trunc);
|
||||
|
||||
pub fn math_atan2(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_atan2<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (a, b) = arg2(vm, args);
|
||||
NativeResult::Ok(JsValue::float(a.atan2(b)))
|
||||
}
|
||||
|
||||
pub fn math_round(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_round<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let x = arg1(vm, args);
|
||||
let r = if x < 0.0 { (x - 0.5).ceil() } else { (x + 0.5).floor() };
|
||||
NativeResult::Ok(JsValue::float(r))
|
||||
}
|
||||
|
||||
pub fn math_sign(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_sign<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let x = arg1(vm, args);
|
||||
if x.is_nan() {
|
||||
NativeResult::Ok(JsValue::float(f64::NAN))
|
||||
@@ -91,31 +89,31 @@ pub fn math_sign(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn math_clz32(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_clz32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let n = arg1(vm, args) as u32;
|
||||
NativeResult::Ok(JsValue::int(n.leading_zeros() as i32))
|
||||
}
|
||||
|
||||
pub fn math_fround(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_fround<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(arg1(vm, args) as f32 as f64))
|
||||
}
|
||||
|
||||
pub fn math_hypot(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_hypot<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (a, b) = arg2(vm, args);
|
||||
NativeResult::Ok(JsValue::float(a.hypot(b)))
|
||||
}
|
||||
|
||||
pub fn math_imul(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_imul<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (a, b) = arg2(vm, args);
|
||||
NativeResult::Ok(JsValue::int((a as i32).wrapping_mul(b as i32)))
|
||||
}
|
||||
|
||||
pub fn math_pow(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_pow<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (a, b) = arg2(vm, args);
|
||||
NativeResult::Ok(JsValue::float(a.powf(b)))
|
||||
}
|
||||
|
||||
pub fn math_max(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_max<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::float(f64::NEG_INFINITY));
|
||||
}
|
||||
@@ -132,7 +130,7 @@ pub fn math_max(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(m))
|
||||
}
|
||||
|
||||
pub fn math_min(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn math_min<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::float(f64::INFINITY));
|
||||
}
|
||||
@@ -149,7 +147,7 @@ pub fn math_min(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(m))
|
||||
}
|
||||
|
||||
pub fn math_random(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
pub fn math_random<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
vm.step_rng();
|
||||
NativeResult::Ok(JsValue::float(vm.math_rng_value()))
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
pub fn number_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let n = if args.len() > 1 { coercion::to_number(vm.reg(args[1])) } else { 0.0 };
|
||||
pub fn number_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let n = if args.len() > 1 { oxide_runtime_api::to_number(vm.reg(args[1])) } else { 0.0 };
|
||||
let number_proto = vm.session().builtin_world().number_proto.as_ptr() as *mut oxide_types::object::JsObject;
|
||||
let is_ctor = if let Some(this_reg) = args.first().copied() {
|
||||
let this_val = vm.reg(this_reg);
|
||||
@@ -44,7 +42,7 @@ pub fn number_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn number_is_nan(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn number_is_nan<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
@@ -56,7 +54,7 @@ pub fn number_is_nan(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn number_is_finite(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn number_is_finite<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
@@ -67,15 +65,15 @@ pub fn number_is_finite(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
if val.is_double() {
|
||||
return NativeResult::Ok(JsValue::bool(val.as_double().is_finite()));
|
||||
}
|
||||
let n = coercion::to_number(val);
|
||||
let n = oxide_runtime_api::to_number(val);
|
||||
NativeResult::Ok(JsValue::bool(n.is_finite()))
|
||||
}
|
||||
|
||||
pub fn number_parse_int(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn number_parse_int<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let s = coercion::to_string(vm.reg(args[1]));
|
||||
let s = oxide_runtime_api::to_string(vm.reg(args[1]));
|
||||
let s = s.trim();
|
||||
|
||||
if s.is_empty() {
|
||||
@@ -83,7 +81,7 @@ pub fn number_parse_int(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
|
||||
let radix = if args.len() > 2 {
|
||||
let r = coercion::to_number(vm.reg(args[2])) as i32;
|
||||
let r = oxide_runtime_api::to_number(vm.reg(args[2])) as i32;
|
||||
if r == 0 {
|
||||
10
|
||||
} else {
|
||||
@@ -112,11 +110,11 @@ pub fn number_parse_int(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::float(f64::NAN))
|
||||
}
|
||||
|
||||
pub fn number_parse_float(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn number_parse_float<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let s = coercion::to_string(vm.reg(args[1]));
|
||||
let s = oxide_runtime_api::to_string(vm.reg(args[1]));
|
||||
let s = s.trim();
|
||||
|
||||
if s.is_empty() {
|
||||
@@ -129,10 +127,10 @@ pub fn number_parse_float(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn number_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let n = coercion::to_number(vm.reg(args[0]));
|
||||
pub fn number_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let n = oxide_runtime_api::to_number(vm.reg(args[0]));
|
||||
let radix = if args.len() > 1 {
|
||||
let r = coercion::to_number(vm.reg(args[1])) as u32;
|
||||
let r = oxide_runtime_api::to_number(vm.reg(args[1])) as u32;
|
||||
r.clamp(2, 36)
|
||||
} else {
|
||||
10u32
|
||||
@@ -180,10 +178,10 @@ pub fn number_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn number_to_fixed(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let n = coercion::to_number(vm.reg(args[0]));
|
||||
pub fn number_to_fixed<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let n = oxide_runtime_api::to_number(vm.reg(args[0]));
|
||||
let digits = if args.len() > 1 {
|
||||
coercion::to_number(vm.reg(args[1])) as usize
|
||||
oxide_runtime_api::to_number(vm.reg(args[1])) as usize
|
||||
} else {
|
||||
0usize
|
||||
}
|
||||
@@ -193,23 +191,23 @@ pub fn number_to_fixed(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&formatted))
|
||||
}
|
||||
|
||||
pub fn number_is_integer(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn number_is_integer<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = vm.reg(if args.len() > 1 { args[1] } else { args[0] });
|
||||
let n = coercion::to_number(val);
|
||||
let n = oxide_runtime_api::to_number(val);
|
||||
NativeResult::Ok(JsValue::bool(n.trunc() == n && n.is_finite()))
|
||||
}
|
||||
|
||||
pub fn number_is_safe_integer(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn number_is_safe_integer<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = vm.reg(if args.len() > 1 { args[1] } else { args[0] });
|
||||
let n = coercion::to_number(val);
|
||||
let n = oxide_runtime_api::to_number(val);
|
||||
let safe = n.trunc() == n && n.is_finite() && n >= -9007199254740991i64 as f64 && n <= 9007199254740991i64 as f64;
|
||||
NativeResult::Ok(JsValue::bool(safe))
|
||||
}
|
||||
|
||||
pub fn number_to_exponential(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let n = coercion::to_number(vm.reg(args[0]));
|
||||
pub fn number_to_exponential<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let n = oxide_runtime_api::to_number(vm.reg(args[0]));
|
||||
let digits = if args.len() > 1 {
|
||||
coercion::to_number(vm.reg(args[1])) as usize
|
||||
oxide_runtime_api::to_number(vm.reg(args[1])) as usize
|
||||
} else {
|
||||
0usize
|
||||
}
|
||||
@@ -224,10 +222,10 @@ pub fn number_to_exponential(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&formatted))
|
||||
}
|
||||
|
||||
pub fn number_to_precision(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let n = coercion::to_number(vm.reg(args[0]));
|
||||
pub fn number_to_precision<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let n = oxide_runtime_api::to_number(vm.reg(args[0]));
|
||||
let precision = if args.len() > 1 {
|
||||
coercion::to_number(vm.reg(args[1])) as usize
|
||||
oxide_runtime_api::to_number(vm.reg(args[1])) as usize
|
||||
} else {
|
||||
0usize
|
||||
}
|
||||
@@ -242,7 +240,7 @@ pub fn number_to_precision(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&formatted))
|
||||
}
|
||||
|
||||
pub fn number_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn number_value_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(args[0]);
|
||||
if this_val.is_int() || this_val.is_double() {
|
||||
return NativeResult::Ok(this_val);
|
||||
@@ -256,7 +254,7 @@ pub fn number_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
}
|
||||
NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Number.prototype.valueOf called on incompatible receiver",
|
||||
))
|
||||
@@ -4,11 +4,9 @@ use oxide_types::object::{JsObject, PropAttributes};
|
||||
use oxide_types::private_key::is_private_name_key;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
pub(crate) fn walk_own_keys(vm: &Vm, obj: &JsObject) -> Vec<(u32, u32)> {
|
||||
pub(crate) fn walk_own_keys<H: VmHost>(vm: &H, obj: &JsObject) -> Vec<(u32, u32)> {
|
||||
let mut keys: Vec<(u32, u32)> = Vec::new();
|
||||
let shape_id = obj.shape_id();
|
||||
let mut pos: u32 = 0;
|
||||
@@ -38,12 +36,12 @@ pub(crate) fn walk_own_keys(vm: &Vm, obj: &JsObject) -> Vec<(u32, u32)> {
|
||||
keys
|
||||
}
|
||||
|
||||
pub fn object_constructor(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
pub fn object_constructor<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
NativeResult::Ok(JsValue::from_js_object(obj))
|
||||
}
|
||||
|
||||
pub fn object_keys(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_keys<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(JsValue::undefined());
|
||||
}
|
||||
@@ -86,7 +84,7 @@ pub fn object_keys(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(arr))
|
||||
}
|
||||
|
||||
pub fn object_create(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_create<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
@@ -98,14 +96,14 @@ pub fn object_create(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(obj))
|
||||
}
|
||||
|
||||
pub fn object_assign(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_assign<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "Object.assign requires a target"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Object.assign requires a target"));
|
||||
}
|
||||
let target_val = vm.reg(args[1]);
|
||||
let target_val = match coercion::to_object(target_val, vm) {
|
||||
let target_val = match oxide_runtime_api::to_object(target_val, vm) {
|
||||
Ok(val) => val,
|
||||
Err(msg) => return NativeResult::Err(crate::builtins::error::create_type_error(vm, &msg)),
|
||||
Err(msg) => return NativeResult::Err(crate::error::create_type_error(vm, &msg)),
|
||||
};
|
||||
let target_ptr = target_val.as_js_object_ptr();
|
||||
if target_ptr.is_null() {
|
||||
@@ -133,13 +131,13 @@ pub fn object_assign(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(target_val)
|
||||
}
|
||||
|
||||
pub fn object_is(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_is<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let lhs = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let rhs = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||
NativeResult::Ok(JsValue::bool(coercion::same_value(lhs, rhs)))
|
||||
NativeResult::Ok(JsValue::bool(oxide_runtime_api::same_value(lhs, rhs)))
|
||||
}
|
||||
|
||||
pub fn object_define_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_define_property<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 4 {
|
||||
return NativeResult::Err(JsValue::undefined());
|
||||
}
|
||||
@@ -159,7 +157,7 @@ pub fn object_define_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
if desc_ptr.is_null() {
|
||||
return NativeResult::Err(JsValue::undefined());
|
||||
}
|
||||
let prop_name_str = coercion::to_string(vm.reg(args[2]));
|
||||
let prop_name_str = oxide_runtime_api::to_string(vm.reg(args[2]));
|
||||
let si = vm.kernel_core().perm_interner().intern(&prop_name_str).0;
|
||||
|
||||
let value_si = vm.kernel_core().perm_interner().intern("value").0;
|
||||
@@ -174,13 +172,17 @@ pub fn object_define_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let get_field = own_field(vm, desc, get_si);
|
||||
let set_field = own_field(vm, desc, set_si);
|
||||
let writable_field = own_field(vm, desc, writable_si);
|
||||
let enumerable = own_field(vm, desc, enumerable_si).map(coercion::to_boolean).unwrap_or(false);
|
||||
let configurable = own_field(vm, desc, configurable_si).map(coercion::to_boolean).unwrap_or(false);
|
||||
let enumerable = own_field(vm, desc, enumerable_si)
|
||||
.map(oxide_runtime_api::to_boolean)
|
||||
.unwrap_or(false);
|
||||
let configurable = own_field(vm, desc, configurable_si)
|
||||
.map(oxide_runtime_api::to_boolean)
|
||||
.unwrap_or(false);
|
||||
|
||||
let has_data = value_field.is_some() || writable_field.is_some();
|
||||
let has_accessor = get_field.is_some() || set_field.is_some();
|
||||
if has_data && has_accessor {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Invalid property descriptor: cannot mix data and accessor fields",
|
||||
));
|
||||
@@ -191,7 +193,7 @@ pub fn object_define_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let get = get_field.unwrap_or(JsValue::undefined());
|
||||
let set = set_field.unwrap_or(JsValue::undefined());
|
||||
if (!get.is_undefined() && !is_callable(get)) || (!set.is_undefined() && !is_callable(set)) {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"accessor descriptor get/set must be callable or undefined",
|
||||
));
|
||||
@@ -200,22 +202,22 @@ pub fn object_define_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
.define_accessor_property(obj, si, get, set, PropAttributes::new(false, enumerable, configurable))
|
||||
.is_err()
|
||||
{
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "Cannot define property"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Cannot define property"));
|
||||
}
|
||||
} else {
|
||||
let value = value_field.unwrap_or(JsValue::undefined());
|
||||
let writable = writable_field.map(coercion::to_boolean).unwrap_or(false);
|
||||
let writable = writable_field.map(oxide_runtime_api::to_boolean).unwrap_or(false);
|
||||
if vm
|
||||
.define_data_property(obj, si, value, PropAttributes::new(writable, enumerable, configurable))
|
||||
.is_err()
|
||||
{
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "Cannot define property"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Cannot define property"));
|
||||
}
|
||||
}
|
||||
NativeResult::Ok(obj_val)
|
||||
}
|
||||
|
||||
pub fn object_get_own_property_descriptor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_get_own_property_descriptor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 3 {
|
||||
return NativeResult::Err(JsValue::undefined());
|
||||
}
|
||||
@@ -227,7 +229,7 @@ pub fn object_get_own_property_descriptor(vm: &mut Vm, args: &[u8]) -> NativeRes
|
||||
if obj_ptr.is_null() {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
let prop_name_str = coercion::to_string(vm.reg(args[2]));
|
||||
let prop_name_str = oxide_runtime_api::to_string(vm.reg(args[2]));
|
||||
let si = vm.kernel_core().perm_interner().intern(&prop_name_str).0;
|
||||
|
||||
let (found_value, found_meta, found) = {
|
||||
@@ -277,7 +279,7 @@ pub fn object_get_own_property_descriptor(vm: &mut Vm, args: &[u8]) -> NativeRes
|
||||
NativeResult::Ok(JsValue::from_js_object(desc))
|
||||
}
|
||||
|
||||
fn own_field(vm: &Vm, obj: &JsObject, prop_si: u32) -> Option<JsValue> {
|
||||
fn own_field<H: VmHost>(vm: &H, obj: &JsObject, prop_si: u32) -> Option<JsValue> {
|
||||
vm.kernel_core()
|
||||
.shape_forge()
|
||||
.lookup_position(obj.shape_id(), prop_si)
|
||||
@@ -300,26 +302,17 @@ fn push_desc_prop(obj: &mut JsObject, shape_forge: &ShapeForge, prop_si: u32, va
|
||||
obj.push_prop(val);
|
||||
}
|
||||
|
||||
fn require_obj_arg(vm: &mut Vm, args: &[u8], fn_name: &str) -> Result<*mut JsObject, JsValue> {
|
||||
fn require_obj_arg<H: VmHost>(vm: &mut H, args: &[u8], fn_name: &str) -> Result<*mut JsObject, JsValue> {
|
||||
if args.len() < 2 {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
&format!("Object.{fn_name} called on non-object"),
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, &format!("Object.{fn_name} called on non-object")));
|
||||
}
|
||||
let val = vm.reg(args[1]);
|
||||
if !val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
&format!("Object.{fn_name} called on non-object"),
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, &format!("Object.{fn_name} called on non-object")));
|
||||
}
|
||||
let ptr = val.as_js_object_ptr();
|
||||
if ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
&format!("Object.{fn_name} called on non-object"),
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, &format!("Object.{fn_name} called on non-object")));
|
||||
}
|
||||
Ok(ptr)
|
||||
}
|
||||
@@ -333,7 +326,7 @@ macro_rules! native_try {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn object_freeze(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_freeze<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
@@ -344,7 +337,7 @@ pub fn object_freeze(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(val)
|
||||
}
|
||||
|
||||
pub fn object_seal(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_seal<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
@@ -355,7 +348,7 @@ pub fn object_seal(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(val)
|
||||
}
|
||||
|
||||
pub fn object_prevent_extensions(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_prevent_extensions<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
@@ -366,7 +359,7 @@ pub fn object_prevent_extensions(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(val)
|
||||
}
|
||||
|
||||
pub fn object_is_frozen(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_is_frozen<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::bool(true));
|
||||
}
|
||||
@@ -377,7 +370,7 @@ pub fn object_is_frozen(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(false))
|
||||
}
|
||||
|
||||
pub fn object_is_sealed(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_is_sealed<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::bool(true));
|
||||
}
|
||||
@@ -388,12 +381,12 @@ pub fn object_is_sealed(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(false))
|
||||
}
|
||||
|
||||
pub fn object_is_extensible(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_is_extensible<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
native_try!(require_obj_arg(vm, args, "isExtensible"));
|
||||
NativeResult::Ok(JsValue::bool(true))
|
||||
}
|
||||
|
||||
pub fn object_get_own_property_names(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_get_own_property_names<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj_ptr = native_try!(require_obj_arg(vm, args, "getOwnPropertyNames"));
|
||||
|
||||
let key_names: Vec<String> = {
|
||||
@@ -424,7 +417,7 @@ pub fn object_get_own_property_names(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(arr))
|
||||
}
|
||||
|
||||
pub fn object_define_properties(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_define_properties<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 3 {
|
||||
return NativeResult::Ok(vm.reg(args[1]));
|
||||
}
|
||||
@@ -436,7 +429,7 @@ pub fn object_define_properties(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.reg(args[1]))
|
||||
}
|
||||
|
||||
pub fn object_from_entries(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_from_entries<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::null());
|
||||
}
|
||||
@@ -451,12 +444,12 @@ pub fn object_from_entries(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(obj_ptr))
|
||||
}
|
||||
|
||||
pub fn object_get_prototype_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_get_prototype_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj_ptr = native_try!(require_obj_arg(vm, args, "getPrototypeOf"));
|
||||
NativeResult::Ok(unsafe { (*obj_ptr).proto() })
|
||||
}
|
||||
|
||||
pub fn object_has_own(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_has_own<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 3 {
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
@@ -466,13 +459,13 @@ pub fn object_has_own(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(vm.get_own_property_slot(obj, key_si).is_some()))
|
||||
}
|
||||
|
||||
pub fn object_proto_has_own_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_proto_has_own_property<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
let this_val = vm.reg(args[0]);
|
||||
if !this_val.is_object() || this_val.as_js_object_ptr().is_null() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Object.prototype.hasOwnProperty called on non-object",
|
||||
));
|
||||
@@ -482,13 +475,13 @@ pub fn object_proto_has_own_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(vm.get_own_property_slot(obj, key_si).is_some()))
|
||||
}
|
||||
|
||||
pub fn object_proto_property_is_enumerable(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_proto_property_is_enumerable<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
let this_val = vm.reg(args[0]);
|
||||
if !this_val.is_object() || this_val.as_js_object_ptr().is_null() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Object.prototype.propertyIsEnumerable called on non-object",
|
||||
));
|
||||
@@ -505,7 +498,7 @@ pub fn object_proto_property_is_enumerable(vm: &mut Vm, args: &[u8]) -> NativeRe
|
||||
NativeResult::Ok(JsValue::bool(enumerable))
|
||||
}
|
||||
|
||||
pub fn object_entries(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_entries<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj_ptr = native_try!(require_obj_arg(vm, args, "entries"));
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
let keys = walk_own_keys(vm, obj);
|
||||
@@ -540,7 +533,7 @@ pub fn object_entries(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(arr))
|
||||
}
|
||||
|
||||
pub fn object_values(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn object_values<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let obj_ptr = native_try!(require_obj_arg(vm, args, "values"));
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
let keys = walk_own_keys(vm, obj);
|
||||
@@ -2,12 +2,11 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::{JsObject, PropAttributes, PropMetaEntry};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::builtins::object::walk_own_keys;
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use crate::object::walk_own_keys;
|
||||
|
||||
pub fn reflect_apply(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
pub fn reflect_apply<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target = arg(vm, args, 1);
|
||||
let this_arg = arg(vm, args, 2);
|
||||
let arg_list = arg(vm, args, 3);
|
||||
@@ -23,11 +22,11 @@ pub fn reflect_apply(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reflect_construct(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_construct<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
type_error(vm, "Reflect.construct not yet supported")
|
||||
}
|
||||
|
||||
pub fn reflect_define_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_define_property<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.defineProperty target is not an object");
|
||||
@@ -50,8 +49,12 @@ pub fn reflect_define_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let get_field = own_field(vm, desc, get_si);
|
||||
let set_field = own_field(vm, desc, set_si);
|
||||
let writable_field = own_field(vm, desc, writable_si);
|
||||
let enumerable = own_field(vm, desc, enumerable_si).map(coercion::to_boolean).unwrap_or(false);
|
||||
let configurable = own_field(vm, desc, configurable_si).map(coercion::to_boolean).unwrap_or(false);
|
||||
let enumerable = own_field(vm, desc, enumerable_si)
|
||||
.map(oxide_runtime_api::to_boolean)
|
||||
.unwrap_or(false);
|
||||
let configurable = own_field(vm, desc, configurable_si)
|
||||
.map(oxide_runtime_api::to_boolean)
|
||||
.unwrap_or(false);
|
||||
|
||||
let has_data = value_field.is_some() || writable_field.is_some();
|
||||
let has_accessor = get_field.is_some() || set_field.is_some();
|
||||
@@ -69,13 +72,13 @@ pub fn reflect_define_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
vm.define_accessor_property(target, key_si, get, set, PropAttributes::new(false, enumerable, configurable))
|
||||
} else {
|
||||
let value = value_field.unwrap_or(JsValue::undefined());
|
||||
let writable = writable_field.map(coercion::to_boolean).unwrap_or(false);
|
||||
let writable = writable_field.map(oxide_runtime_api::to_boolean).unwrap_or(false);
|
||||
vm.define_data_property(target, key_si, value, PropAttributes::new(writable, enumerable, configurable))
|
||||
};
|
||||
NativeResult::Ok(JsValue::bool(result.is_ok()))
|
||||
}
|
||||
|
||||
pub fn reflect_delete_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_delete_property<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.deleteProperty target is not an object");
|
||||
@@ -85,7 +88,7 @@ pub fn reflect_delete_property(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(delete_own_property(vm, target, key_si)))
|
||||
}
|
||||
|
||||
pub fn reflect_get(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_get<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.get target is not an object");
|
||||
@@ -98,15 +101,15 @@ pub fn reflect_get(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reflect_get_own_property_descriptor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_get_own_property_descriptor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(_) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.getOwnPropertyDescriptor target is not an object");
|
||||
};
|
||||
crate::builtins::object::object_get_own_property_descriptor(vm, args)
|
||||
crate::object::object_get_own_property_descriptor(vm, args)
|
||||
}
|
||||
|
||||
pub fn reflect_get_prototype_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_get_prototype_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.getPrototypeOf target is not an object");
|
||||
@@ -114,7 +117,7 @@ pub fn reflect_get_prototype_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(unsafe { &*target_ptr }.proto())
|
||||
}
|
||||
|
||||
pub fn reflect_has(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_has<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.has target is not an object");
|
||||
@@ -123,7 +126,7 @@ pub fn reflect_has(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(vm.resolve_property(unsafe { &*target_ptr }, key_si).is_some()))
|
||||
}
|
||||
|
||||
pub fn reflect_is_extensible(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_is_extensible<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.isExtensible target is not an object");
|
||||
@@ -131,7 +134,7 @@ pub fn reflect_is_extensible(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(unsafe { &*target_ptr }.is_extensible()))
|
||||
}
|
||||
|
||||
pub fn reflect_own_keys(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_own_keys<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.ownKeys target is not an object");
|
||||
@@ -144,7 +147,7 @@ pub fn reflect_own_keys(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(make_string_array(vm, &key_names))
|
||||
}
|
||||
|
||||
pub fn reflect_prevent_extensions(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_prevent_extensions<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.preventExtensions target is not an object");
|
||||
@@ -153,7 +156,7 @@ pub fn reflect_prevent_extensions(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(true))
|
||||
}
|
||||
|
||||
pub fn reflect_set(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_set<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.set target is not an object");
|
||||
@@ -168,7 +171,7 @@ pub fn reflect_set(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(vm.ordinary_set(target, key_si, value, receiver).is_ok()))
|
||||
}
|
||||
|
||||
pub fn reflect_set_prototype_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn reflect_set_prototype_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.setPrototypeOf target is not an object");
|
||||
@@ -180,7 +183,7 @@ pub fn reflect_set_prototype_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(unsafe { &mut *target_ptr }.set_proto(proto).is_ok()))
|
||||
}
|
||||
|
||||
fn arg(vm: &Vm, args: &[u8], idx: usize) -> JsValue {
|
||||
fn arg<H: VmHost>(vm: &H, args: &[u8], idx: usize) -> JsValue {
|
||||
args.get(idx).map(|reg| vm.reg(*reg)).unwrap_or_else(JsValue::undefined)
|
||||
}
|
||||
|
||||
@@ -196,8 +199,8 @@ fn is_callable(value: JsValue) -> bool {
|
||||
object_ptr(value).is_some_and(|ptr| unsafe { &*ptr }.is_function())
|
||||
}
|
||||
|
||||
fn type_error(vm: &mut Vm, message: &str) -> NativeResult {
|
||||
NativeResult::Err(crate::builtins::error::create_type_error(vm, message))
|
||||
fn type_error<H: VmHost>(vm: &mut H, message: &str) -> NativeResult {
|
||||
NativeResult::Err(crate::error::create_type_error(vm, message))
|
||||
}
|
||||
|
||||
fn array_like_elements(value: JsValue) -> Option<Vec<JsValue>> {
|
||||
@@ -206,14 +209,14 @@ fn array_like_elements(value: JsValue) -> Option<Vec<JsValue>> {
|
||||
Some((0..obj.prop_count() as usize).map(|idx| obj.get_prop_at(idx)).collect())
|
||||
}
|
||||
|
||||
fn own_field(vm: &Vm, obj: &JsObject, prop_si: u32) -> Option<JsValue> {
|
||||
fn own_field<H: VmHost>(vm: &H, obj: &JsObject, prop_si: u32) -> Option<JsValue> {
|
||||
vm.kernel_core()
|
||||
.shape_forge()
|
||||
.lookup_position(obj.shape_id(), prop_si)
|
||||
.and_then(|pos| (obj.prop_vec_len() > pos as usize).then(|| obj.get_prop_at(pos)))
|
||||
}
|
||||
|
||||
fn make_string_array(vm: &mut Vm, parts: &[String]) -> JsValue {
|
||||
fn make_string_array<H: VmHost>(vm: &mut H, parts: &[String]) -> JsValue {
|
||||
let proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let arr = vm.alloc_object(JsObject::new_array(
|
||||
EMPTY_SHAPE_ID,
|
||||
@@ -229,7 +232,7 @@ fn make_string_array(vm: &mut Vm, parts: &[String]) -> JsValue {
|
||||
JsValue::from_js_object(arr)
|
||||
}
|
||||
|
||||
fn delete_own_property(vm: &mut Vm, obj: &mut JsObject, key_si: u32) -> bool {
|
||||
fn delete_own_property<H: VmHost>(vm: &mut H, obj: &mut JsObject, key_si: u32) -> bool {
|
||||
let keys = walk_own_keys(vm, obj);
|
||||
let Some((_, delete_pos)) = keys.iter().find(|(si, _)| *si == key_si).copied() else {
|
||||
return true;
|
||||
@@ -2,27 +2,19 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::{JsObject, NativeFnPtr};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
fn get_regexp_ptr(vm: &mut Vm, args: &[u8]) -> Result<*mut JsObject, JsValue> {
|
||||
fn get_regexp_ptr<H: VmHost>(vm: &mut H, args: &[u8]) -> Result<*mut JsObject, JsValue> {
|
||||
let this_val = vm.reg(args[0]);
|
||||
if !this_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"RegExp.prototype method called on non-object",
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, "RegExp.prototype method called on non-object"));
|
||||
}
|
||||
let ptr = this_val.as_js_object_ptr();
|
||||
if ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "null object"));
|
||||
return Err(crate::error::create_type_error(vm, "null object"));
|
||||
}
|
||||
if !unsafe { &*ptr }.is_regexp_obj() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"RegExp.prototype method called on non-RegExp object",
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, "RegExp.prototype method called on non-RegExp object"));
|
||||
}
|
||||
Ok(ptr)
|
||||
}
|
||||
@@ -42,7 +34,7 @@ fn parse_flags(flags: &str) -> (bool, bool, bool) {
|
||||
(global, ignore_case, multi_line)
|
||||
}
|
||||
|
||||
fn set_prop(obj: &mut JsObject, name: &str, val: JsValue, vm: &Vm) {
|
||||
fn set_prop<H: VmHost>(obj: &mut JsObject, name: &str, val: JsValue, vm: &H) {
|
||||
let si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let shape_id = vm.kernel_core().shape_forge().make_shape(obj.shape_id(), si);
|
||||
obj.set_shape_id(shape_id);
|
||||
@@ -67,15 +59,15 @@ fn set_prop_at(obj: *mut JsObject, idx: usize, val: JsValue) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn regexp_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn regexp_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let (pattern, flags) = if args.len() < 2 {
|
||||
(String::new(), String::new())
|
||||
} else if args.len() < 3 {
|
||||
let pat = coercion::to_string(vm.reg(args[1]));
|
||||
let pat = oxide_runtime_api::to_string(vm.reg(args[1]));
|
||||
(pat, String::new())
|
||||
} else {
|
||||
let pat = coercion::to_string(vm.reg(args[1]));
|
||||
let fl = coercion::to_string(vm.reg(args[2]));
|
||||
let pat = oxide_runtime_api::to_string(vm.reg(args[1]));
|
||||
let fl = oxide_runtime_api::to_string(vm.reg(args[2]));
|
||||
(pat, fl)
|
||||
};
|
||||
|
||||
@@ -101,7 +93,7 @@ pub fn regexp_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(re_ptr as *const ()) }));
|
||||
}
|
||||
Err(e) => {
|
||||
return NativeResult::Err(crate::builtins::error::create_syntax_error(
|
||||
return NativeResult::Err(crate::error::create_syntax_error(
|
||||
vm,
|
||||
&format!("Invalid regular expression: {e}"),
|
||||
));
|
||||
@@ -123,7 +115,7 @@ pub fn regexp_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(obj_ptr))
|
||||
}
|
||||
|
||||
pub(crate) fn drop_regexp_native(obj: &mut JsObject) -> u64 {
|
||||
pub fn drop_regexp_native(obj: &mut JsObject) -> u64 {
|
||||
if !obj.is_regexp_obj() {
|
||||
return 0;
|
||||
}
|
||||
@@ -139,7 +131,7 @@ pub(crate) fn drop_regexp_native(obj: &mut JsObject) -> u64 {
|
||||
std::mem::size_of::<regex::Regex>() as u64
|
||||
}
|
||||
|
||||
pub fn regexp_test(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn regexp_test<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let re_ptr = match get_regexp_ptr(vm, args) {
|
||||
Ok(ptr) => ptr,
|
||||
Err(err) => return NativeResult::Err(err),
|
||||
@@ -148,15 +140,15 @@ pub fn regexp_test(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
|
||||
let fn_ptr = match re.native_fn() {
|
||||
None => {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "invalid RegExp"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "invalid RegExp"));
|
||||
}
|
||||
Some(p) => p,
|
||||
};
|
||||
|
||||
// SAFETY: fn_ptr holds a Box<regex::Regex> pointer stored by regexp_constructor.
|
||||
let regex = unsafe { &*(fn_ptr.as_ptr() as *const regex::Regex) };
|
||||
let haystack = coercion::to_string(vm.reg(if args.len() > 1 { args[1] } else { args[0] }));
|
||||
let last_index = coercion::to_number(get_prop(re, 0)) as usize;
|
||||
let haystack = oxide_runtime_api::to_string(vm.reg(if args.len() > 1 { args[1] } else { args[0] }));
|
||||
let last_index = oxide_runtime_api::to_number(get_prop(re, 0)) as usize;
|
||||
let is_global = get_prop(re, 3).as_bool();
|
||||
|
||||
if is_global {
|
||||
@@ -167,7 +159,7 @@ pub fn regexp_test(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn regexp_exec(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn regexp_exec<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let re_ptr = match get_regexp_ptr(vm, args) {
|
||||
Ok(ptr) => ptr,
|
||||
Err(err) => return NativeResult::Err(err),
|
||||
@@ -177,7 +169,7 @@ pub fn regexp_exec(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let re = unsafe { &*re_ptr };
|
||||
match re.native_fn() {
|
||||
None => {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "invalid RegExp"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "invalid RegExp"));
|
||||
}
|
||||
Some(p) => p,
|
||||
}
|
||||
@@ -185,11 +177,11 @@ pub fn regexp_exec(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
|
||||
// SAFETY: fn_ptr holds a Box<regex::Regex> pointer stored by regexp_constructor.
|
||||
let regex = unsafe { &*(fn_ptr.as_ptr() as *const regex::Regex) };
|
||||
let haystack = coercion::to_string(vm.reg(if args.len() > 1 { args[1] } else { args[0] }));
|
||||
let haystack = oxide_runtime_api::to_string(vm.reg(if args.len() > 1 { args[1] } else { args[0] }));
|
||||
|
||||
let (last_index, is_global) = {
|
||||
let re = unsafe { &*re_ptr };
|
||||
let li = coercion::to_number(get_prop(re, 0)) as usize;
|
||||
let li = oxide_runtime_api::to_number(get_prop(re, 0)) as usize;
|
||||
let g = get_prop(re, 3).as_bool();
|
||||
(li, g)
|
||||
};
|
||||
@@ -241,7 +233,7 @@ pub fn regexp_exec(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn regexp_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn regexp_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let re_ptr = match get_regexp_ptr(vm, args) {
|
||||
Ok(ptr) => ptr,
|
||||
Err(err) => return NativeResult::Err(err),
|
||||
@@ -4,8 +4,7 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
macro_rules! native_try {
|
||||
($expr:expr) => {
|
||||
@@ -68,29 +67,26 @@ type SetInner = indexmap::IndexSet<SetKey>;
|
||||
/// native builtin is executing. The `Box<IndexSet>` is allocated in `new_set_inner()`
|
||||
/// and is never freed during the Set's lifetime. Only one live `*mut` alias exists per
|
||||
/// Set object at a time because native calls are single-threaded.
|
||||
fn get_set_inner(vm: &mut Vm, this_val: JsValue) -> Result<*mut SetInner, JsValue> {
|
||||
fn get_set_inner<H: VmHost>(vm: &mut H, this_val: JsValue) -> Result<*mut SetInner, JsValue> {
|
||||
if !this_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "called on non-Set object"));
|
||||
return Err(crate::error::create_type_error(vm, "called on non-Set object"));
|
||||
}
|
||||
let set_ptr = this_val.as_js_object_ptr();
|
||||
if set_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "Set internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "Set internal state invalid"));
|
||||
}
|
||||
// SAFETY: set_ptr is a non-null, aligned pointer to a JsObject bump-allocated in the
|
||||
// current Epoch. Remains valid for the duration of this call.
|
||||
let set_obj = unsafe { &*set_ptr };
|
||||
if !set_obj.is_set() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Set.prototype.add called on incompatible receiver",
|
||||
));
|
||||
return Err(crate::error::create_type_error(vm, "Set.prototype.add called on incompatible receiver"));
|
||||
}
|
||||
// SAFETY: native_data holds the raw pointer written by `alloc_set`.
|
||||
// The pointer is a valid, heap-allocated `Box<IndexSet<SetKey>>`.
|
||||
// Alignment: IndexSet requires at most 8-byte alignment; the global allocator satisfies this.
|
||||
let inner_ptr = set_obj.native_data() as *mut SetInner;
|
||||
if inner_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(vm, "Set internal state invalid"));
|
||||
return Err(crate::error::create_type_error(vm, "Set internal state invalid"));
|
||||
}
|
||||
Ok(inner_ptr)
|
||||
}
|
||||
@@ -99,7 +95,7 @@ fn new_set_inner() -> *mut SetInner {
|
||||
Box::into_raw(Box::new(SetInner::new()))
|
||||
}
|
||||
|
||||
fn alloc_set(vm: &mut Vm) -> *mut JsObject {
|
||||
fn alloc_set<H: VmHost>(vm: &mut H) -> *mut JsObject {
|
||||
let set_proto = vm.session().builtin_world().set_proto.as_ptr() as *mut JsObject;
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(set_proto));
|
||||
obj.set_set(true);
|
||||
@@ -108,7 +104,7 @@ fn alloc_set(vm: &mut Vm) -> *mut JsObject {
|
||||
vm.alloc_object(obj)
|
||||
}
|
||||
|
||||
pub(crate) fn set_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
pub fn set_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
if !obj.is_set() {
|
||||
return Vec::new();
|
||||
}
|
||||
@@ -116,10 +112,16 @@ pub(crate) fn set_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
if inner.is_null() {
|
||||
return Vec::new();
|
||||
}
|
||||
unsafe { (*inner).iter().map(|key| key.0).filter(|value| value.is_object()).collect() }
|
||||
unsafe {
|
||||
(*inner)
|
||||
.iter()
|
||||
.map(|key| key.0)
|
||||
.filter(|value: &JsValue| value.is_object())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clone_set_native_with_rewrite<F>(src: &JsObject, dst: &mut JsObject, mut rewrite: F)
|
||||
pub fn clone_set_native_with_rewrite<F>(src: &JsObject, dst: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
@@ -141,7 +143,7 @@ where
|
||||
dst.set_native_data(Box::into_raw(Box::new(cloned)) as *mut u8);
|
||||
}
|
||||
|
||||
pub(crate) fn rewrite_set_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
pub fn rewrite_set_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
@@ -162,7 +164,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn drop_set_native(obj: &mut JsObject) -> u64 {
|
||||
pub fn drop_set_native(obj: &mut JsObject) -> u64 {
|
||||
if !obj.is_set() {
|
||||
return 0;
|
||||
}
|
||||
@@ -171,7 +173,7 @@ pub(crate) fn drop_set_native(obj: &mut JsObject) -> u64 {
|
||||
return 0;
|
||||
}
|
||||
unsafe {
|
||||
let boxed = Box::from_raw(inner);
|
||||
let boxed: Box<SetInner> = Box::from_raw(inner);
|
||||
let bytes = std::mem::size_of::<SetInner>() + boxed.capacity() * std::mem::size_of::<SetKey>();
|
||||
drop(boxed);
|
||||
obj.set_native_data(std::ptr::null_mut());
|
||||
@@ -179,12 +181,12 @@ pub(crate) fn drop_set_native(obj: &mut JsObject) -> u64 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_constructor(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
pub fn set_constructor<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
let set_obj = alloc_set(vm);
|
||||
NativeResult::Ok(JsValue::from_js_object(set_obj))
|
||||
}
|
||||
|
||||
pub fn set_add(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn set_add<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_set_inner(vm, this_val));
|
||||
let val = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
@@ -194,7 +196,7 @@ pub fn set_add(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(this_val)
|
||||
}
|
||||
|
||||
pub fn set_has(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn set_has<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_set_inner(vm, this_val));
|
||||
let val = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
@@ -202,7 +204,7 @@ pub fn set_has(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(found))
|
||||
}
|
||||
|
||||
pub fn set_delete(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn set_delete<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_set_inner(vm, this_val));
|
||||
let val = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
@@ -210,7 +212,7 @@ pub fn set_delete(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::bool(removed))
|
||||
}
|
||||
|
||||
pub fn set_clear(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn set_clear<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_set_inner(vm, this_val));
|
||||
unsafe {
|
||||
@@ -219,7 +221,7 @@ pub fn set_clear(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn set_size(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn set_size<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = native_try!(get_set_inner(vm, this_val));
|
||||
NativeResult::Ok(JsValue::float(unsafe { (*inner).len() } as f64))
|
||||
@@ -2,19 +2,17 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use memchr::memchr;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
fn this_string(vm: &Vm, args: &[u8]) -> String {
|
||||
coercion::to_string(vm.reg(args[0]))
|
||||
fn this_string<H: VmHost>(vm: &H, args: &[u8]) -> String {
|
||||
oxide_runtime_api::to_string(vm.reg(args[0]))
|
||||
}
|
||||
|
||||
pub fn string_from_char_code(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_from_char_code<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let mut out = String::new();
|
||||
for &arg_reg in args.iter().skip(1) {
|
||||
let code = coercion::to_uint32(vm.reg(arg_reg)) & 0xFFFF;
|
||||
let code = oxide_runtime_api::to_uint32(vm.reg(arg_reg)) & 0xFFFF;
|
||||
if let Some(ch) = char::from_u32(code) {
|
||||
out.push(ch);
|
||||
} else {
|
||||
@@ -24,7 +22,7 @@ pub fn string_from_char_code(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&out))
|
||||
}
|
||||
|
||||
pub fn string_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_value_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(args[0]);
|
||||
if this_val.is_string() {
|
||||
return NativeResult::Ok(this_val);
|
||||
@@ -38,15 +36,15 @@ pub fn string_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
}
|
||||
NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"String.prototype.valueOf called on non-String object",
|
||||
))
|
||||
}
|
||||
|
||||
pub fn string_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = if args.len() > 1 {
|
||||
coercion::to_string(vm.reg(args[1]))
|
||||
oxide_runtime_api::to_string(vm.reg(args[1]))
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
@@ -76,7 +74,7 @@ pub fn string_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(this_val)
|
||||
}
|
||||
|
||||
pub fn string_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(args[0]);
|
||||
if this_val.is_string() {
|
||||
return NativeResult::Ok(this_val);
|
||||
@@ -90,13 +88,13 @@ pub fn string_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
}
|
||||
NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"String.prototype.toString called on non-String object",
|
||||
))
|
||||
}
|
||||
|
||||
fn make_string_array(vm: &mut Vm, parts: &[String]) -> JsValue {
|
||||
fn make_string_array<H: VmHost>(vm: &mut H, parts: &[String]) -> JsValue {
|
||||
let proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let n = parts.len();
|
||||
let arr =
|
||||
@@ -112,8 +110,8 @@ fn make_string_array(vm: &mut Vm, parts: &[String]) -> JsValue {
|
||||
JsValue::from_js_object(arr)
|
||||
}
|
||||
|
||||
fn as_string(_vm: &Vm, val: JsValue) -> String {
|
||||
coercion::to_string(val)
|
||||
fn as_string<H: VmHost>(_vm: &H, val: JsValue) -> String {
|
||||
oxide_runtime_api::to_string(val)
|
||||
}
|
||||
|
||||
fn char_len(s: &str) -> usize {
|
||||
@@ -137,7 +135,7 @@ fn take_chars(s: &str, count: usize) -> String {
|
||||
s.chars().take(count).collect()
|
||||
}
|
||||
|
||||
fn is_regexp_obj(val: JsValue, vm: &Vm) -> bool {
|
||||
fn is_regexp_obj<H: VmHost>(val: JsValue, vm: &H) -> bool {
|
||||
if !val.is_object() {
|
||||
return false;
|
||||
}
|
||||
@@ -158,7 +156,7 @@ fn is_regexp_obj(val: JsValue, vm: &Vm) -> bool {
|
||||
std::ptr::eq(proto_ptr, rp)
|
||||
}
|
||||
|
||||
pub fn string_index_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s);
|
||||
if args.len() < 2 {
|
||||
@@ -166,7 +164,7 @@ pub fn string_index_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
let search = as_string(vm, vm.reg(args[1]));
|
||||
let pos = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2])) as usize).min(n)
|
||||
(oxide_runtime_api::to_number(vm.reg(args[2])) as usize).min(n)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
@@ -189,7 +187,7 @@ pub fn string_index_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::int(-1))
|
||||
}
|
||||
|
||||
pub fn string_includes(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_includes<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s);
|
||||
if args.len() < 2 {
|
||||
@@ -197,7 +195,7 @@ pub fn string_includes(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
let search = as_string(vm, vm.reg(args[1]));
|
||||
let pos = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2])) as usize).min(n)
|
||||
(oxide_runtime_api::to_number(vm.reg(args[2])) as usize).min(n)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
@@ -214,7 +212,7 @@ pub fn string_includes(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string_char_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_char_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
if s.is_empty() {
|
||||
@@ -222,7 +220,7 @@ pub fn string_char_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
return NativeResult::Ok(vm.new_string(&take_chars(&s, 1)));
|
||||
}
|
||||
let idx = coercion::to_number(vm.reg(args[1])) as i32;
|
||||
let idx = oxide_runtime_api::to_number(vm.reg(args[1])) as i32;
|
||||
if idx < 0 || idx as usize >= char_len(&s) {
|
||||
return NativeResult::Ok(vm.new_string(""));
|
||||
}
|
||||
@@ -230,7 +228,7 @@ pub fn string_char_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&ch))
|
||||
}
|
||||
|
||||
pub fn string_char_code_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_char_code_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
if s.is_empty() {
|
||||
@@ -238,26 +236,26 @@ pub fn string_char_code_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
return NativeResult::Ok(JsValue::int(s.chars().next().unwrap() as i32));
|
||||
}
|
||||
let idx = coercion::to_number(vm.reg(args[1])) as i32;
|
||||
let idx = oxide_runtime_api::to_number(vm.reg(args[1])) as i32;
|
||||
if idx < 0 || idx as usize >= char_len(&s) {
|
||||
return NativeResult::Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
NativeResult::Ok(JsValue::int(s.chars().nth(idx as usize).unwrap() as i32))
|
||||
}
|
||||
|
||||
pub fn string_concat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_concat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let mut result = this_string(vm, args);
|
||||
for &arg_reg in args.iter().skip(1) {
|
||||
result.push_str(&coercion::to_string(vm.reg(arg_reg)));
|
||||
result.push_str(&oxide_runtime_api::to_string(vm.reg(arg_reg)));
|
||||
}
|
||||
NativeResult::Ok(vm.new_string(&result))
|
||||
}
|
||||
|
||||
pub fn string_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s) as i32;
|
||||
let start = if args.len() > 1 {
|
||||
let v = coercion::to_number(vm.reg(args[1])) as i32;
|
||||
let v = oxide_runtime_api::to_number(vm.reg(args[1])) as i32;
|
||||
if v < 0 {
|
||||
(n + v).max(0)
|
||||
} else {
|
||||
@@ -267,7 +265,7 @@ pub fn string_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
0
|
||||
};
|
||||
let end = if args.len() > 2 {
|
||||
let v = coercion::to_number(vm.reg(args[2])) as i32;
|
||||
let v = oxide_runtime_api::to_number(vm.reg(args[2])) as i32;
|
||||
if v < 0 {
|
||||
(n + v).max(0)
|
||||
} else {
|
||||
@@ -282,16 +280,16 @@ pub fn string_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(result))
|
||||
}
|
||||
|
||||
pub fn string_substring(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_substring<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s) as i32;
|
||||
let mut start = if args.len() > 1 {
|
||||
(coercion::to_number(vm.reg(args[1])) as i32).max(0).min(n)
|
||||
(oxide_runtime_api::to_number(vm.reg(args[1])) as i32).max(0).min(n)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let mut end = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2])) as i32).max(0).min(n)
|
||||
(oxide_runtime_api::to_number(vm.reg(args[2])) as i32).max(0).min(n)
|
||||
} else {
|
||||
n
|
||||
};
|
||||
@@ -302,41 +300,41 @@ pub fn string_substring(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(result))
|
||||
}
|
||||
|
||||
pub fn string_to_upper_case(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_to_upper_case<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
NativeResult::Ok(vm.new_string(&s.to_uppercase()))
|
||||
}
|
||||
|
||||
pub fn string_to_lower_case(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_to_lower_case<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
NativeResult::Ok(vm.new_string(&s.to_lowercase()))
|
||||
}
|
||||
|
||||
pub fn string_trim(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_trim<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
NativeResult::Ok(vm.new_string(s.trim()))
|
||||
}
|
||||
|
||||
pub fn string_repeat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_repeat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = if args.len() > 1 {
|
||||
(coercion::to_number(vm.reg(args[1])) as usize).min(10000)
|
||||
(oxide_runtime_api::to_number(vm.reg(args[1])) as usize).min(10000)
|
||||
} else {
|
||||
1
|
||||
};
|
||||
NativeResult::Ok(vm.new_string(&s.repeat(n)))
|
||||
}
|
||||
|
||||
pub fn string_pad_start(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_pad_start<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let s_len = char_len(&s);
|
||||
let target = if args.len() > 1 {
|
||||
coercion::to_number(vm.reg(args[1])) as usize
|
||||
oxide_runtime_api::to_number(vm.reg(args[1])) as usize
|
||||
} else {
|
||||
s_len
|
||||
};
|
||||
if target > 10000 {
|
||||
return NativeResult::Err(crate::builtins::error::create_range_error(vm, "Invalid string length"));
|
||||
return NativeResult::Err(crate::error::create_range_error(vm, "Invalid string length"));
|
||||
}
|
||||
let pad = if args.len() > 2 { as_string(vm, vm.reg(args[2])) } else { " ".to_string() };
|
||||
if s_len >= target || pad.is_empty() {
|
||||
@@ -350,16 +348,16 @@ pub fn string_pad_start(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&out))
|
||||
}
|
||||
|
||||
pub fn string_pad_end(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_pad_end<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let s_len = char_len(&s);
|
||||
let target = if args.len() > 1 {
|
||||
coercion::to_number(vm.reg(args[1])) as usize
|
||||
oxide_runtime_api::to_number(vm.reg(args[1])) as usize
|
||||
} else {
|
||||
s_len
|
||||
};
|
||||
if target > 10000 {
|
||||
return NativeResult::Err(crate::builtins::error::create_range_error(vm, "Invalid string length"));
|
||||
return NativeResult::Err(crate::error::create_range_error(vm, "Invalid string length"));
|
||||
}
|
||||
let pad = if args.len() > 2 { as_string(vm, vm.reg(args[2])) } else { " ".to_string() };
|
||||
if s_len >= target || pad.is_empty() {
|
||||
@@ -373,7 +371,7 @@ pub fn string_pad_end(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&out))
|
||||
}
|
||||
|
||||
pub fn string_starts_with(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_starts_with<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s);
|
||||
if args.len() < 2 {
|
||||
@@ -381,14 +379,14 @@ pub fn string_starts_with(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
let search = as_string(vm, vm.reg(args[1]));
|
||||
let pos = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2])) as usize).min(n)
|
||||
(oxide_runtime_api::to_number(vm.reg(args[2])) as usize).min(n)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
NativeResult::Ok(JsValue::bool(s[byte_index_at_char(&s, pos)..].starts_with(&search)))
|
||||
}
|
||||
|
||||
pub fn string_ends_with(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_ends_with<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s);
|
||||
if args.len() < 2 {
|
||||
@@ -396,14 +394,14 @@ pub fn string_ends_with(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
let search = as_string(vm, vm.reg(args[1]));
|
||||
let end_pos = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2])) as usize).min(n)
|
||||
(oxide_runtime_api::to_number(vm.reg(args[2])) as usize).min(n)
|
||||
} else {
|
||||
n
|
||||
};
|
||||
NativeResult::Ok(JsValue::bool(s[..byte_index_at_char(&s, end_pos)].ends_with(&search)))
|
||||
}
|
||||
|
||||
pub fn string_split(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_split<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
let parts = vec![s.clone()];
|
||||
@@ -411,7 +409,7 @@ pub fn string_split(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
let sep_val = vm.reg(args[1]);
|
||||
let limit = if args.len() > 2 {
|
||||
coercion::to_number(vm.reg(args[2])) as usize
|
||||
oxide_runtime_api::to_number(vm.reg(args[2])) as usize
|
||||
} else {
|
||||
usize::MAX
|
||||
};
|
||||
@@ -442,7 +440,7 @@ pub fn string_split(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(make_string_array(vm, &parts))
|
||||
}
|
||||
|
||||
pub fn string_replace(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_replace<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(vm.new_string(&s));
|
||||
@@ -468,7 +466,7 @@ pub fn string_replace(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&result))
|
||||
}
|
||||
|
||||
pub fn string_match_fn(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_match_fn<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
@@ -495,7 +493,7 @@ pub fn string_match_fn(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn string_search(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_search<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(JsValue::int(-1));
|
||||
@@ -524,19 +522,23 @@ pub fn string_search(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::int(-1))
|
||||
}
|
||||
|
||||
pub fn string_trim_start(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_trim_start<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
NativeResult::Ok(vm.new_string(s.trim_start()))
|
||||
}
|
||||
|
||||
pub fn string_trim_end(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_trim_end<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
NativeResult::Ok(vm.new_string(s.trim_end()))
|
||||
}
|
||||
|
||||
pub fn string_code_point_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_code_point_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let pos = if args.len() > 1 { coercion::to_number(vm.reg(args[1])) as usize } else { 0 };
|
||||
let pos = if args.len() > 1 {
|
||||
oxide_runtime_api::to_number(vm.reg(args[1])) as usize
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let chars: Vec<char> = s.chars().collect();
|
||||
if pos >= chars.len() {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
@@ -552,7 +554,7 @@ pub fn string_code_point_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::int(c as i32))
|
||||
}
|
||||
|
||||
pub fn string_normalize(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_normalize<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
use unicode_normalization::UnicodeNormalization;
|
||||
let s = this_string(vm, args);
|
||||
let form = if args.len() > 1 { as_string(vm, vm.reg(args[1])) } else { "NFC".to_string() };
|
||||
@@ -565,7 +567,7 @@ pub fn string_normalize(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(vm.new_string(&result))
|
||||
}
|
||||
|
||||
pub fn string_match_all(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_match_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(JsValue::undefined());
|
||||
@@ -586,7 +588,7 @@ pub fn string_match_all(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn string_replace_all(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn string_replace_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Ok(vm.new_string(&s));
|
||||
@@ -0,0 +1,31 @@
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
fn stub_error<H: VmHost>(vm: &mut H, name: &str) -> NativeResult {
|
||||
NativeResult::Err(crate::error::create_type_error(vm, &format!("{name} is not implemented")))
|
||||
}
|
||||
|
||||
// Architecturally deferred — these features are excluded from the supported language subset by design.
|
||||
pub fn proxy_stub<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "Proxy")
|
||||
}
|
||||
pub fn bigint_stub<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "BigInt")
|
||||
}
|
||||
pub fn weakmap_stub<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "WeakMap")
|
||||
}
|
||||
pub fn weakset_stub<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "WeakSet")
|
||||
}
|
||||
pub fn weakref_stub<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "WeakRef")
|
||||
}
|
||||
pub fn finalization_registry_stub<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "FinalizationRegistry")
|
||||
}
|
||||
pub fn shared_array_buffer_stub<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "SharedArrayBuffer")
|
||||
}
|
||||
pub fn atomics_stub<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "Atomics")
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
pub fn symbol_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn symbol_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if this_val.is_object() {
|
||||
let ptr = this_val.as_js_object_ptr();
|
||||
@@ -17,10 +15,7 @@ pub fn symbol_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
if !proto_ptr.is_null() {
|
||||
let sp = vm.session().builtin_world().symbol_proto.as_ptr() as *mut JsObject;
|
||||
if std::ptr::eq(proto_ptr, sp) {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Symbol is not a constructor",
|
||||
));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Symbol is not a constructor"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,54 +23,51 @@ pub fn symbol_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
|
||||
let description = if args.len() > 1 {
|
||||
coercion::to_string(vm.reg(args[1]))
|
||||
oxide_runtime_api::to_string(vm.reg(args[1]))
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let idx = vm.symbols.intern(description);
|
||||
let idx = vm.symbol_intern(description);
|
||||
NativeResult::Ok(JsValue::symbol(idx))
|
||||
}
|
||||
|
||||
pub fn symbol_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn symbol_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(args[0]);
|
||||
if !this_val.is_symbol() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Symbol.prototype.toString requires a Symbol",
|
||||
));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Symbol.prototype.toString requires a Symbol"));
|
||||
}
|
||||
|
||||
let idx = this_val.as_symbol_index();
|
||||
let desc = vm.symbols.description(idx).unwrap_or("").to_string();
|
||||
let desc = vm.symbol_description(idx).unwrap_or("").to_string();
|
||||
let result = format!("Symbol({})", desc);
|
||||
NativeResult::Ok(vm.new_string(&result))
|
||||
}
|
||||
|
||||
pub fn symbol_for(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn symbol_for<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let key = if args.len() > 1 {
|
||||
coercion::to_string(vm.reg(args[1]))
|
||||
oxide_runtime_api::to_string(vm.reg(args[1]))
|
||||
} else {
|
||||
"undefined".to_string()
|
||||
};
|
||||
|
||||
if let Some(idx) = vm.symbols.lookup_global(&key) {
|
||||
if let Some(idx) = vm.symbol_lookup_global(&key) {
|
||||
return NativeResult::Ok(JsValue::symbol(idx));
|
||||
}
|
||||
|
||||
let idx = vm.symbols.intern(key.clone());
|
||||
vm.symbols.register_global(key, idx);
|
||||
let idx = vm.symbol_intern(key.clone());
|
||||
vm.symbol_register_global(key, idx);
|
||||
NativeResult::Ok(JsValue::symbol(idx))
|
||||
}
|
||||
|
||||
pub fn symbol_key_for(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn symbol_key_for<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let sym = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
if !sym.is_symbol() {
|
||||
return NativeResult::Err(crate::builtins::error::create_type_error(vm, "is not a symbol"));
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "is not a symbol"));
|
||||
}
|
||||
|
||||
let idx = sym.as_symbol_index();
|
||||
match vm.symbols.key_for_id(idx) {
|
||||
match vm.symbol_key_for_id(idx) {
|
||||
Some(key) => NativeResult::Ok(vm.new_string(&key)),
|
||||
None => NativeResult::Ok(JsValue::undefined()),
|
||||
}
|
||||
+31
-32
@@ -2,10 +2,9 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes, TypedArrayKind};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::builtins::array_buffer::{array_buffer_data_ptr, new_array_buffer, MAX_ARRAY_BUFFER_LENGTH};
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use crate::array_buffer::{array_buffer_data_ptr, new_array_buffer, MAX_ARRAY_BUFFER_LENGTH};
|
||||
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct TypedArrayData {
|
||||
@@ -24,16 +23,16 @@ macro_rules! native_try {
|
||||
};
|
||||
}
|
||||
|
||||
fn type_error(vm: &mut Vm, msg: &str) -> JsValue {
|
||||
crate::builtins::error::create_type_error(vm, msg)
|
||||
fn type_error<H: VmHost>(vm: &mut H, msg: &str) -> JsValue {
|
||||
crate::error::create_type_error(vm, msg)
|
||||
}
|
||||
|
||||
fn range_error(vm: &mut Vm, msg: &str) -> JsValue {
|
||||
crate::builtins::error::create_range_error(vm, msg)
|
||||
fn range_error<H: VmHost>(vm: &mut H, msg: &str) -> JsValue {
|
||||
crate::error::create_range_error(vm, msg)
|
||||
}
|
||||
|
||||
fn to_index(vm: &mut Vm, value: JsValue, msg: &str) -> Result<usize, JsValue> {
|
||||
let n = coercion::to_number(value);
|
||||
fn to_index<H: VmHost>(vm: &mut H, value: JsValue, msg: &str) -> Result<usize, JsValue> {
|
||||
let n = oxide_runtime_api::to_number(value);
|
||||
if n.is_nan() {
|
||||
return Ok(0);
|
||||
}
|
||||
@@ -43,8 +42,8 @@ fn to_index(vm: &mut Vm, value: JsValue, msg: &str) -> Result<usize, JsValue> {
|
||||
Ok(n.trunc() as usize)
|
||||
}
|
||||
|
||||
fn normalize_index(_vm: &mut Vm, value: JsValue, len: usize) -> usize {
|
||||
let n = coercion::to_number(value);
|
||||
fn normalize_index<H: VmHost>(_vm: &mut H, value: JsValue, len: usize) -> usize {
|
||||
let n = oxide_runtime_api::to_number(value);
|
||||
if n.is_nan() {
|
||||
return 0;
|
||||
}
|
||||
@@ -56,12 +55,12 @@ fn normalize_index(_vm: &mut Vm, value: JsValue, len: usize) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_named_prop(vm: &mut Vm, obj: &mut JsObject, name: &str, value: JsValue, attributes: PropAttributes) {
|
||||
fn set_named_prop<H: VmHost>(vm: &mut H, obj: &mut JsObject, name: &str, value: JsValue, attributes: PropAttributes) {
|
||||
let si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let _ = vm.define_data_property(obj, si, value, attributes);
|
||||
}
|
||||
|
||||
fn typed_array_proto_ptr(vm: &mut Vm, kind: TypedArrayKind) -> *mut JsObject {
|
||||
fn typed_array_proto_ptr<H: VmHost>(vm: &mut H, kind: TypedArrayKind) -> *mut JsObject {
|
||||
let world = vm.session().builtin_world();
|
||||
match kind {
|
||||
TypedArrayKind::Int8 => world.int8array_proto.as_ptr() as *mut JsObject,
|
||||
@@ -78,8 +77,8 @@ fn typed_array_proto_ptr(vm: &mut Vm, kind: TypedArrayKind) -> *mut JsObject {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_typed_array(
|
||||
vm: &mut Vm, kind: TypedArrayKind, buffer: JsValue, byte_offset: usize, length: usize,
|
||||
fn create_typed_array<H: VmHost>(
|
||||
vm: &mut H, kind: TypedArrayKind, buffer: JsValue, byte_offset: usize, length: usize,
|
||||
) -> *mut JsObject {
|
||||
let proto = typed_array_proto_ptr(vm, kind);
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto));
|
||||
@@ -127,7 +126,7 @@ fn typed_array_data_ptr(obj: &JsObject) -> Option<*mut TypedArrayData> {
|
||||
obj.native_fn().map(|ptr| ptr.as_ptr() as *mut TypedArrayData)
|
||||
}
|
||||
|
||||
pub(crate) fn typed_array_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
pub fn typed_array_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
let Some(ptr) = typed_array_data_ptr(obj) else {
|
||||
return Vec::new();
|
||||
};
|
||||
@@ -142,7 +141,7 @@ pub(crate) fn typed_array_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clone_typed_array_native_with_rewrite<F>(old_obj: &JsObject, new_obj: &mut JsObject, mut rewrite: F)
|
||||
pub fn clone_typed_array_native_with_rewrite<F>(old_obj: &JsObject, new_obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
@@ -158,7 +157,7 @@ where
|
||||
new_obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(cloned as *const ()) }));
|
||||
}
|
||||
|
||||
pub(crate) fn rewrite_typed_array_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
pub fn rewrite_typed_array_native<F>(obj: &mut JsObject, mut rewrite: F)
|
||||
where
|
||||
F: FnMut(JsValue) -> JsValue,
|
||||
{
|
||||
@@ -173,7 +172,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn drop_typed_array_native(obj: &mut JsObject) -> u64 {
|
||||
pub fn drop_typed_array_native(obj: &mut JsObject) -> u64 {
|
||||
let Some(ptr) = typed_array_data_ptr(obj) else {
|
||||
return 0;
|
||||
};
|
||||
@@ -185,7 +184,7 @@ pub(crate) fn drop_typed_array_native(obj: &mut JsObject) -> u64 {
|
||||
std::mem::size_of::<TypedArrayData>() as u64
|
||||
}
|
||||
|
||||
pub(crate) fn get_typed_array_data(vm: &mut Vm, this_val: JsValue) -> Result<TypedArrayData, JsValue> {
|
||||
pub(crate) fn get_typed_array_data<H: VmHost>(vm: &mut H, this_val: JsValue) -> Result<TypedArrayData, JsValue> {
|
||||
if !this_val.is_object() {
|
||||
return Err(type_error(vm, "TypedArray method called on incompatible receiver"));
|
||||
}
|
||||
@@ -236,8 +235,8 @@ fn read_element(kind: TypedArrayKind, bytes: &[u8], offset: usize) -> JsValue {
|
||||
}
|
||||
}
|
||||
|
||||
fn numeric_value(_vm: &mut Vm, value: JsValue) -> f64 {
|
||||
coercion::to_number(value)
|
||||
fn numeric_value<H: VmHost>(_vm: &mut H, value: JsValue) -> f64 {
|
||||
oxide_runtime_api::to_number(value)
|
||||
}
|
||||
|
||||
fn write_element(kind: TypedArrayKind, bytes: &mut [u8], offset: usize, value: f64) {
|
||||
@@ -256,7 +255,7 @@ fn write_element(kind: TypedArrayKind, bytes: &mut [u8], offset: usize, value: f
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_array_like(vm: &mut Vm, value: JsValue) -> Result<Vec<JsValue>, JsValue> {
|
||||
fn collect_array_like<H: VmHost>(vm: &mut H, value: JsValue) -> Result<Vec<JsValue>, JsValue> {
|
||||
if !value.is_object() {
|
||||
return Err(type_error(vm, "TypedArray source must be array-like"));
|
||||
}
|
||||
@@ -280,7 +279,7 @@ fn collect_array_like(vm: &mut Vm, value: JsValue) -> Result<Vec<JsValue>, JsVal
|
||||
Err(type_error(vm, "TypedArray source must be Array, ArrayBuffer, or TypedArray"))
|
||||
}
|
||||
|
||||
fn typed_array_new(vm: &mut Vm, args: &[u8], kind: TypedArrayKind) -> NativeResult {
|
||||
fn typed_array_new<H: VmHost>(vm: &mut H, args: &[u8], kind: TypedArrayKind) -> NativeResult {
|
||||
let first = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::int(0) };
|
||||
let bpe = kind.bytes_per_element();
|
||||
|
||||
@@ -342,7 +341,7 @@ fn typed_array_new(vm: &mut Vm, args: &[u8], kind: TypedArrayKind) -> NativeResu
|
||||
|
||||
macro_rules! typed_array_ctor {
|
||||
($name:ident, $kind:ident) => {
|
||||
pub fn $name(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn $name<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
typed_array_new(vm, args, TypedArrayKind::$kind)
|
||||
}
|
||||
};
|
||||
@@ -360,7 +359,7 @@ typed_array_ctor!(float64array_constructor, Float64);
|
||||
typed_array_ctor!(bigint64array_constructor, BigInt64);
|
||||
typed_array_ctor!(biguint64array_constructor, BigUint64);
|
||||
|
||||
pub fn typed_array_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn typed_array_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let view = native_try!(get_typed_array_data(vm, this_val));
|
||||
let raw_index = if args.len() > 1 {
|
||||
@@ -377,7 +376,7 @@ pub fn typed_array_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(read_element(view.kind, buffer, absolute_byte_offset(view, idx as usize)))
|
||||
}
|
||||
|
||||
pub fn typed_array_fill(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn typed_array_fill<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let view = native_try!(get_typed_array_data(vm, this_val));
|
||||
let value = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
@@ -400,7 +399,7 @@ pub fn typed_array_fill(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(this_val)
|
||||
}
|
||||
|
||||
pub fn typed_array_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn typed_array_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let view = native_try!(get_typed_array_data(vm, this_val));
|
||||
let start = if args.len() > 1 {
|
||||
@@ -425,7 +424,7 @@ pub fn typed_array_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(create_typed_array(vm, view.kind, buffer, 0, count)))
|
||||
}
|
||||
|
||||
pub fn typed_array_subarray(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn typed_array_subarray<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let view = native_try!(get_typed_array_data(vm, this_val));
|
||||
let start = if args.len() > 1 {
|
||||
@@ -449,7 +448,7 @@ pub fn typed_array_subarray(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn typed_array_set(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn typed_array_set<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let view = native_try!(get_typed_array_data(vm, this_val));
|
||||
if args.len() < 2 {
|
||||
@@ -474,7 +473,7 @@ pub fn typed_array_set(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn typed_array_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
pub fn typed_array_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
native_try!(get_typed_array_data(vm, this_val));
|
||||
NativeResult::Ok(vm.new_string("[object TypedArray]"))
|
||||
@@ -9,3 +9,4 @@ description = "OxideJS - VmHost trait: the abstract Vm interface builtins are wr
|
||||
[dependencies]
|
||||
oxide_types = { path = "../oxide_types" }
|
||||
oxide_kernel = { path = "../oxide_kernel" }
|
||||
ryu.workspace = true
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_kernel::kernel::{KernelCore, KernelSession};
|
||||
use oxide_types::mem::Epoch;
|
||||
use oxide_types::mem::{Epoch, P};
|
||||
use oxide_types::object::{JsObject, PropAttributes};
|
||||
use oxide_types::shape::EMPTY_SHAPE_ID;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
/// Return value of every builtin native function.
|
||||
@@ -105,4 +106,345 @@ pub trait VmHost {
|
||||
fn checked_object_ptr(&mut self, val: JsValue, error_msg: &str) -> Result<Option<*mut JsObject>, String>;
|
||||
fn raise_type_error(&mut self, msg: &str) -> Result<(), String>;
|
||||
fn error_message_text(&self, kind: &str, msg: &str) -> String;
|
||||
fn call_stack_function_names(&self) -> Vec<String>;
|
||||
fn promote_if_needed_for_write_ptr(&mut self, target_ptr: *mut JsObject, value: JsValue) -> JsValue;
|
||||
fn step_rng(&mut self);
|
||||
fn math_rng_value(&self) -> f64;
|
||||
fn sub_module_function_name(&self, sub_idx: u16) -> String;
|
||||
fn symbol_intern(&mut self, desc: String) -> u32;
|
||||
fn symbol_description(&self, idx: u32) -> Option<&str>;
|
||||
fn symbol_lookup_global(&self, key: &str) -> Option<u32>;
|
||||
fn symbol_register_global(&mut self, key: String, idx: u32);
|
||||
fn symbol_key_for_id(&self, idx: u32) -> Option<String>;
|
||||
}
|
||||
|
||||
pub fn format_error_message(kind: &str, msg: &str) -> String {
|
||||
if msg.is_empty() || msg == kind || msg.starts_with(&format!("{kind}:")) {
|
||||
msg.to_string()
|
||||
} else {
|
||||
format!("{kind}: {msg}")
|
||||
}
|
||||
}
|
||||
|
||||
/// Borrow a string value's content.
|
||||
///
|
||||
/// # Safety
|
||||
/// `val` must be a string `JsValue` whose `JsString` pointer is alive.
|
||||
#[inline]
|
||||
pub unsafe fn string_data(val: JsValue) -> &'static str {
|
||||
(*val.as_string_ptr()).as_str()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn string_value_eq(a: JsValue, b: JsValue) -> bool {
|
||||
if a.as_string_ptr() == b.as_string_ptr() {
|
||||
return true;
|
||||
}
|
||||
let sa = unsafe { &*a.as_string_ptr() };
|
||||
let sb = unsafe { &*b.as_string_ptr() };
|
||||
sa.hash == sb.hash && sa.data == sb.data
|
||||
}
|
||||
|
||||
pub fn to_number(val: JsValue) -> f64 {
|
||||
if val.is_int() {
|
||||
return val.as_int() as f64;
|
||||
}
|
||||
if val.is_double() {
|
||||
return val.as_double();
|
||||
}
|
||||
if val.is_bool() {
|
||||
return if val.as_bool() { 1.0 } else { 0.0 };
|
||||
}
|
||||
if val.is_null() {
|
||||
return 0.0;
|
||||
}
|
||||
if val.is_undefined() {
|
||||
return f64::NAN;
|
||||
}
|
||||
if val.is_string() {
|
||||
let s = unsafe { string_data(val) };
|
||||
return s.parse::<f64>().unwrap_or(f64::NAN);
|
||||
}
|
||||
if val.is_object() {
|
||||
return f64::NAN;
|
||||
}
|
||||
f64::NAN
|
||||
}
|
||||
|
||||
pub fn to_uint32(val: JsValue) -> u32 {
|
||||
let n = to_number(val);
|
||||
if n == 0.0 || !n.is_finite() {
|
||||
return 0;
|
||||
}
|
||||
n.trunc().rem_euclid(4_294_967_296.0) as u32
|
||||
}
|
||||
|
||||
pub fn to_int32(val: JsValue) -> i32 {
|
||||
let int = to_uint32(val);
|
||||
if int > i32::MAX as u32 {
|
||||
(int as i64 - 4_294_967_296i64) as i32
|
||||
} else {
|
||||
int as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(val: JsValue) -> String {
|
||||
if val.is_int() {
|
||||
return val.as_int().to_string();
|
||||
}
|
||||
if val.is_double() {
|
||||
let d = val.as_double();
|
||||
if d.is_nan() {
|
||||
return "NaN".to_string();
|
||||
}
|
||||
if d.is_infinite() {
|
||||
return if d.is_sign_positive() {
|
||||
"Infinity".to_string()
|
||||
} else {
|
||||
"-Infinity".to_string()
|
||||
};
|
||||
}
|
||||
if d.is_finite() && d.fract() == 0.0 {
|
||||
return (d as i64).to_string();
|
||||
}
|
||||
let mut buf = ryu::Buffer::new();
|
||||
return buf.format(d).to_string();
|
||||
}
|
||||
if val.is_bool() {
|
||||
return val.as_bool().to_string();
|
||||
}
|
||||
if val.is_null() {
|
||||
return "null".to_string();
|
||||
}
|
||||
if val.is_undefined() {
|
||||
return "undefined".to_string();
|
||||
}
|
||||
if val.is_string() {
|
||||
return unsafe { string_data(val) }.to_string();
|
||||
}
|
||||
if val.is_object() {
|
||||
return "[object]".to_string();
|
||||
}
|
||||
String::new()
|
||||
}
|
||||
|
||||
pub fn to_boolean(val: JsValue) -> bool {
|
||||
if val.is_undefined() || val.is_null() {
|
||||
return false;
|
||||
}
|
||||
if val.is_bool() {
|
||||
return val.as_bool();
|
||||
}
|
||||
if val.is_int() {
|
||||
return val.as_int() != 0;
|
||||
}
|
||||
if val.is_double() {
|
||||
let d = val.as_double();
|
||||
return !(d == 0.0 || d == -0.0 || d.is_nan());
|
||||
}
|
||||
if val.is_string() {
|
||||
return !unsafe { (*val.as_string_ptr()).is_empty() };
|
||||
}
|
||||
if val.is_object() {
|
||||
return true;
|
||||
}
|
||||
if val.is_symbol() {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn abstract_eq(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_null() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_string() && rhs.is_string() {
|
||||
return string_value_eq(lhs, rhs);
|
||||
}
|
||||
if lhs.is_int() && rhs.is_int() {
|
||||
return lhs.as_int() == rhs.as_int();
|
||||
}
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
return strict_double_eq(lhs.as_double(), rhs.as_double());
|
||||
}
|
||||
if lhs.is_bool() && rhs.is_bool() {
|
||||
return lhs.as_bool() == rhs.as_bool();
|
||||
}
|
||||
if lhs.is_null() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if (lhs.is_int() || lhs.is_double()) && (rhs.is_int() || rhs.is_double()) {
|
||||
return strict_double_eq(to_number(lhs), to_number(rhs));
|
||||
}
|
||||
if (lhs.is_int() || lhs.is_double()) && rhs.is_bool() {
|
||||
return to_number(lhs) == to_number(rhs);
|
||||
}
|
||||
if lhs.is_bool() && (rhs.is_int() || rhs.is_double()) {
|
||||
return to_number(lhs) == to_number(rhs);
|
||||
}
|
||||
if lhs.is_bool() || rhs.is_bool() {
|
||||
return to_number(lhs) == to_number(rhs);
|
||||
}
|
||||
if lhs.is_null() || rhs.is_null() {
|
||||
return false;
|
||||
}
|
||||
if lhs.is_object() || rhs.is_object() {
|
||||
return lhs.is_object() && rhs.is_object() && lhs.as_ptr() == rhs.as_ptr();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn strict_eq(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_int() && rhs.is_int() {
|
||||
return lhs.as_int() == rhs.as_int();
|
||||
}
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
return strict_double_eq(lhs.as_double(), rhs.as_double());
|
||||
}
|
||||
if lhs.is_bool() && rhs.is_bool() {
|
||||
return lhs.as_bool() == rhs.as_bool();
|
||||
}
|
||||
if lhs.is_null() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_string() && rhs.is_string() {
|
||||
return string_value_eq(lhs, rhs);
|
||||
}
|
||||
if lhs.is_object() && rhs.is_object() {
|
||||
return lhs.as_ptr() == rhs.as_ptr();
|
||||
}
|
||||
if lhs.is_symbol() && rhs.is_symbol() {
|
||||
return lhs.as_symbol_index() == rhs.as_symbol_index();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn strict_double_eq(a: f64, b: f64) -> bool {
|
||||
if a.is_nan() || b.is_nan() {
|
||||
return false;
|
||||
}
|
||||
a == b
|
||||
}
|
||||
|
||||
pub fn relational_compare(lhs: JsValue, rhs: JsValue) -> Option<bool> {
|
||||
if lhs.is_string() && rhs.is_string() {
|
||||
let ls = unsafe { string_data(lhs) };
|
||||
let rs = unsafe { string_data(rhs) };
|
||||
return Some(ls < rs);
|
||||
}
|
||||
let l = to_number(lhs);
|
||||
let r = to_number(rhs);
|
||||
if l.is_nan() || r.is_nan() {
|
||||
return None;
|
||||
}
|
||||
l.partial_cmp(&r).map(|o| o.is_lt())
|
||||
}
|
||||
|
||||
pub fn string_concat(lhs: &str, rhs: &str) -> String {
|
||||
let mut s = String::with_capacity(lhs.len() + rhs.len());
|
||||
s.push_str(lhs);
|
||||
s.push_str(rhs);
|
||||
s
|
||||
}
|
||||
|
||||
fn to_f64(val: JsValue) -> f64 {
|
||||
if val.is_int() {
|
||||
val.as_int() as f64
|
||||
} else if val.is_double() {
|
||||
val.as_double()
|
||||
} else {
|
||||
f64::NAN
|
||||
}
|
||||
}
|
||||
|
||||
pub fn same_value(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
let a = lhs.as_double();
|
||||
let b = rhs.as_double();
|
||||
if a.is_nan() && b.is_nan() {
|
||||
return true;
|
||||
}
|
||||
if a == 0.0 && b == 0.0 {
|
||||
let a_neg = a.is_sign_negative();
|
||||
let b_neg = b.is_sign_negative();
|
||||
return a_neg == b_neg;
|
||||
}
|
||||
return a == b;
|
||||
}
|
||||
if lhs.is_int() && rhs.is_int() {
|
||||
return lhs.as_int() == rhs.as_int();
|
||||
}
|
||||
if (lhs.is_int() || lhs.is_double()) && (rhs.is_int() || rhs.is_double()) {
|
||||
let a = to_f64(lhs);
|
||||
let b = to_f64(rhs);
|
||||
if a.is_nan() && b.is_nan() {
|
||||
return true;
|
||||
}
|
||||
if a == 0.0 && b == 0.0 {
|
||||
return a.is_sign_negative() == b.is_sign_negative();
|
||||
}
|
||||
return a == b;
|
||||
}
|
||||
if lhs.is_bool() && rhs.is_bool() {
|
||||
return lhs.as_bool() == rhs.as_bool();
|
||||
}
|
||||
if lhs.is_null() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_string() && rhs.is_string() {
|
||||
return string_value_eq(lhs, rhs);
|
||||
}
|
||||
if lhs.is_object() && rhs.is_object() {
|
||||
return lhs.as_ptr() == rhs.as_ptr();
|
||||
}
|
||||
if lhs.is_symbol() && rhs.is_symbol() {
|
||||
return lhs.as_symbol_index() == rhs.as_symbol_index();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn strict_equality(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
return strict_double_eq(lhs.as_double(), rhs.as_double());
|
||||
}
|
||||
same_value(lhs, rhs)
|
||||
}
|
||||
|
||||
pub fn to_object<H: VmHost>(val: JsValue, host: &mut H) -> Result<JsValue, String> {
|
||||
if val.is_object() {
|
||||
return Ok(val);
|
||||
}
|
||||
if val.is_null() || val.is_undefined() {
|
||||
return Err(host.error_message_text("TypeError", "Cannot convert null or undefined to object"));
|
||||
}
|
||||
let world = host.session().builtin_world();
|
||||
let (proto_ptr, type_tag) = if val.is_string() {
|
||||
(P::as_ptr(&world.string_proto) as *mut JsObject, JsObject::OBJ_TYPE_STRING_OBJ)
|
||||
} else if val.is_int() || val.is_double() {
|
||||
(P::as_ptr(&world.number_proto) as *mut JsObject, JsObject::OBJ_TYPE_NUMBER_OBJ)
|
||||
} else if val.is_bool() {
|
||||
(P::as_ptr(&world.boolean_proto) as *mut JsObject, JsObject::OBJ_TYPE_BOOLEAN_OBJ)
|
||||
} else {
|
||||
(P::as_ptr(&world.object_proto) as *mut JsObject, JsObject::OBJ_TYPE_PLAIN)
|
||||
};
|
||||
let proto_val = JsValue::from_js_object(proto_ptr);
|
||||
let obj = host.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
|
||||
let obj_val = JsValue::from_js_object(obj);
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
obj_ref.type_tag = type_tag;
|
||||
obj_ref.ensure_hash_props().push(val);
|
||||
obj_ref.set_prop_count(1);
|
||||
Ok(obj_val)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ description = "OxideJS - Register-based VM with epoch arena memory"
|
||||
oxide_bytecode = { path = "../oxide_bytecode" }
|
||||
oxide_kernel = { path = "../oxide_kernel" }
|
||||
oxide_runtime_api = { path = "../oxide_runtime_api" }
|
||||
oxide_builtins = { path = "../oxide_builtins" }
|
||||
oxide_types = { path = "../oxide_types" }
|
||||
bumpalo.workspace = true
|
||||
fast-float.workspace = true
|
||||
|
||||
@@ -8,36 +8,36 @@ use crate::bind_constructor;
|
||||
|
||||
pub fn bind_array(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
|
||||
let _array_methods = ArrayMethods {
|
||||
is_array: crate::builtins::array::array_is_array as *const (),
|
||||
push: crate::builtins::array::array_push as *const (),
|
||||
pop: crate::builtins::array::array_pop as *const (),
|
||||
slice: crate::builtins::array::array_slice as *const (),
|
||||
splice: crate::builtins::array::array_splice as *const (),
|
||||
concat: crate::builtins::array::array_concat as *const (),
|
||||
join: crate::builtins::array::array_join as *const (),
|
||||
index_of: crate::builtins::array::array_index_of as *const (),
|
||||
includes: crate::builtins::array::array_includes as *const (),
|
||||
reverse: crate::builtins::array::array_reverse as *const (),
|
||||
for_each: crate::builtins::array::array_for_each as *const (),
|
||||
map: crate::builtins::array::array_map as *const (),
|
||||
filter: crate::builtins::array::array_filter as *const (),
|
||||
reduce: crate::builtins::array::array_reduce as *const (),
|
||||
find: crate::builtins::array::array_find as *const (),
|
||||
some: crate::builtins::array::array_some as *const (),
|
||||
every: crate::builtins::array::array_every as *const (),
|
||||
flat: crate::builtins::array::array_flat as *const (),
|
||||
flat_map: crate::builtins::array::array_flat_map as *const (),
|
||||
shift: crate::builtins::array::array_shift as *const (),
|
||||
unshift: crate::builtins::array::array_unshift as *const (),
|
||||
fill: crate::builtins::array::array_fill as *const (),
|
||||
copy_within: crate::builtins::array::array_copy_within as *const (),
|
||||
at: crate::builtins::array::array_at as *const (),
|
||||
last_index_of: crate::builtins::array::array_last_index_of as *const (),
|
||||
find_index: crate::builtins::array::array_find_index as *const (),
|
||||
find_last: crate::builtins::array::array_find_last as *const (),
|
||||
reduce_right: crate::builtins::array::array_reduce_right as *const (),
|
||||
sort: crate::builtins::array::array_sort as *const (),
|
||||
values: crate::builtins::array::array_values as *const (),
|
||||
is_array: oxide_builtins::array::array_is_array::<crate::vm::Vm> as *const (),
|
||||
push: oxide_builtins::array::array_push::<crate::vm::Vm> as *const (),
|
||||
pop: oxide_builtins::array::array_pop::<crate::vm::Vm> as *const (),
|
||||
slice: oxide_builtins::array::array_slice::<crate::vm::Vm> as *const (),
|
||||
splice: oxide_builtins::array::array_splice::<crate::vm::Vm> as *const (),
|
||||
concat: oxide_builtins::array::array_concat::<crate::vm::Vm> as *const (),
|
||||
join: oxide_builtins::array::array_join::<crate::vm::Vm> as *const (),
|
||||
index_of: oxide_builtins::array::array_index_of::<crate::vm::Vm> as *const (),
|
||||
includes: oxide_builtins::array::array_includes::<crate::vm::Vm> as *const (),
|
||||
reverse: oxide_builtins::array::array_reverse::<crate::vm::Vm> as *const (),
|
||||
for_each: oxide_builtins::array::array_for_each::<crate::vm::Vm> as *const (),
|
||||
map: oxide_builtins::array::array_map::<crate::vm::Vm> as *const (),
|
||||
filter: oxide_builtins::array::array_filter::<crate::vm::Vm> as *const (),
|
||||
reduce: oxide_builtins::array::array_reduce::<crate::vm::Vm> as *const (),
|
||||
find: oxide_builtins::array::array_find::<crate::vm::Vm> as *const (),
|
||||
some: oxide_builtins::array::array_some::<crate::vm::Vm> as *const (),
|
||||
every: oxide_builtins::array::array_every::<crate::vm::Vm> as *const (),
|
||||
flat: oxide_builtins::array::array_flat::<crate::vm::Vm> as *const (),
|
||||
flat_map: oxide_builtins::array::array_flat_map::<crate::vm::Vm> as *const (),
|
||||
shift: oxide_builtins::array::array_shift::<crate::vm::Vm> as *const (),
|
||||
unshift: oxide_builtins::array::array_unshift::<crate::vm::Vm> as *const (),
|
||||
fill: oxide_builtins::array::array_fill::<crate::vm::Vm> as *const (),
|
||||
copy_within: oxide_builtins::array::array_copy_within::<crate::vm::Vm> as *const (),
|
||||
at: oxide_builtins::array::array_at::<crate::vm::Vm> as *const (),
|
||||
last_index_of: oxide_builtins::array::array_last_index_of::<crate::vm::Vm> as *const (),
|
||||
find_index: oxide_builtins::array::array_find_index::<crate::vm::Vm> as *const (),
|
||||
find_last: oxide_builtins::array::array_find_last::<crate::vm::Vm> as *const (),
|
||||
reduce_right: oxide_builtins::array::array_reduce_right::<crate::vm::Vm> as *const (),
|
||||
sort: oxide_builtins::array::array_sort::<crate::vm::Vm> as *const (),
|
||||
values: oxide_builtins::array::array_values::<crate::vm::Vm> as *const (),
|
||||
};
|
||||
|
||||
session.builtin_world().bind_array_methods(
|
||||
@@ -47,5 +47,5 @@ pub fn bind_array(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
);
|
||||
|
||||
let ctor_ptr = session.builtin_world().array_constructor.as_ptr() as *mut JsObject;
|
||||
bind_constructor!(core, global, "Array", ctor_ptr, crate::builtins::array::array_constructor, 1, hash: true);
|
||||
bind_constructor!(core, global, "Array", ctor_ptr, oxide_builtins::array::array_constructor::<crate::vm::Vm>, 1, hash: true);
|
||||
}
|
||||
|
||||
@@ -11,13 +11,21 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
|
||||
let proto_ptr = session.builtin_world().array_buffer_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
|
||||
configure_native_constructor(ctor, crate::builtins::array_buffer::array_buffer_constructor as *const (), 1);
|
||||
configure_native_constructor(
|
||||
ctor,
|
||||
oxide_builtins::array_buffer::array_buffer_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
ctor,
|
||||
core,
|
||||
&[("isView", crate::builtins::array_buffer::array_buffer_is_view as *const (), 1)],
|
||||
&[(
|
||||
"isView",
|
||||
oxide_builtins::array_buffer::array_buffer_is_view::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
)],
|
||||
);
|
||||
|
||||
apply_binding_table(
|
||||
@@ -25,9 +33,17 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
|
||||
proto,
|
||||
core,
|
||||
&[
|
||||
("byteLength", crate::builtins::array_buffer::array_buffer_byte_length as *const (), 0),
|
||||
("slice", crate::builtins::array_buffer::array_buffer_slice as *const (), 2),
|
||||
("toString", crate::builtins::array_buffer::array_buffer_to_string as *const (), 0),
|
||||
(
|
||||
"byteLength",
|
||||
oxide_builtins::array_buffer::array_buffer_byte_length::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
("slice", oxide_builtins::array_buffer::array_buffer_slice::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"toString",
|
||||
oxide_builtins::array_buffer::array_buffer_to_string::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -36,7 +52,7 @@ pub fn bind_array_buffer(core: &Arc<KernelCore>, session: &KernelSession, global
|
||||
global,
|
||||
"ArrayBuffer",
|
||||
ctor_ptr,
|
||||
crate::builtins::array_buffer::array_buffer_constructor,
|
||||
oxide_builtins::array_buffer::array_buffer_constructor::<crate::vm::Vm>,
|
||||
1,
|
||||
hash: true
|
||||
);
|
||||
|
||||
@@ -11,17 +11,25 @@ pub fn bind_boolean(core: &Arc<KernelCore>, session: &KernelSession, global: &mu
|
||||
let proto_ptr = session.builtin_world().boolean_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
|
||||
configure_native_constructor(ctor, crate::builtins::boolean::boolean_constructor as *const (), 1);
|
||||
configure_native_constructor(ctor, oxide_builtins::boolean::boolean_constructor::<crate::vm::Vm> as *const (), 1);
|
||||
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
proto,
|
||||
core,
|
||||
&[
|
||||
("valueOf", crate::builtins::boolean::boolean_prototype_value_of as *const (), 0),
|
||||
("toString", crate::builtins::boolean::boolean_prototype_to_string as *const (), 0),
|
||||
(
|
||||
"valueOf",
|
||||
oxide_builtins::boolean::boolean_prototype_value_of::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
(
|
||||
"toString",
|
||||
oxide_builtins::boolean::boolean_prototype_to_string::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
bind_constructor!(core, global, "Boolean", ctor_ptr, crate::builtins::boolean::boolean_constructor, 1, hash: true);
|
||||
bind_constructor!(core, global, "Boolean", ctor_ptr, oxide_builtins::boolean::boolean_constructor::<crate::vm::Vm>, 1, hash: true);
|
||||
}
|
||||
|
||||
@@ -11,36 +11,116 @@ pub fn bind_data_view(core: &Arc<KernelCore>, session: &KernelSession, global: &
|
||||
let proto_ptr = session.builtin_world().data_view_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
|
||||
configure_native_constructor(ctor, crate::builtins::data_view::data_view_constructor as *const (), 3);
|
||||
configure_native_constructor(
|
||||
ctor,
|
||||
oxide_builtins::data_view::data_view_constructor::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
);
|
||||
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
proto,
|
||||
core,
|
||||
&[
|
||||
("getInt8", crate::builtins::data_view::data_view_get_int8 as *const (), 1),
|
||||
("getUint8", crate::builtins::data_view::data_view_get_uint8 as *const (), 1),
|
||||
("getInt16", crate::builtins::data_view::data_view_get_int16 as *const (), 2),
|
||||
("getUint16", crate::builtins::data_view::data_view_get_uint16 as *const (), 2),
|
||||
("getInt32", crate::builtins::data_view::data_view_get_int32 as *const (), 2),
|
||||
("getUint32", crate::builtins::data_view::data_view_get_uint32 as *const (), 2),
|
||||
("getFloat32", crate::builtins::data_view::data_view_get_float32 as *const (), 2),
|
||||
("getFloat64", crate::builtins::data_view::data_view_get_float64 as *const (), 2),
|
||||
("getBigInt64", crate::builtins::data_view::data_view_get_big_int64 as *const (), 2),
|
||||
("getBigUint64", crate::builtins::data_view::data_view_get_big_uint64 as *const (), 2),
|
||||
("setInt8", crate::builtins::data_view::data_view_set_int8 as *const (), 2),
|
||||
("setUint8", crate::builtins::data_view::data_view_set_uint8 as *const (), 2),
|
||||
("setInt16", crate::builtins::data_view::data_view_set_int16 as *const (), 3),
|
||||
("setUint16", crate::builtins::data_view::data_view_set_uint16 as *const (), 3),
|
||||
("setInt32", crate::builtins::data_view::data_view_set_int32 as *const (), 3),
|
||||
("setUint32", crate::builtins::data_view::data_view_set_uint32 as *const (), 3),
|
||||
("setFloat32", crate::builtins::data_view::data_view_set_float32 as *const (), 3),
|
||||
("setFloat64", crate::builtins::data_view::data_view_set_float64 as *const (), 3),
|
||||
("setBigInt64", crate::builtins::data_view::data_view_set_big_int64 as *const (), 3),
|
||||
("setBigUint64", crate::builtins::data_view::data_view_set_big_uint64 as *const (), 3),
|
||||
("toString", crate::builtins::data_view::data_view_to_string as *const (), 0),
|
||||
("getInt8", oxide_builtins::data_view::data_view_get_int8::<crate::vm::Vm> as *const (), 1),
|
||||
(
|
||||
"getUint8",
|
||||
oxide_builtins::data_view::data_view_get_uint8::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
(
|
||||
"getInt16",
|
||||
oxide_builtins::data_view::data_view_get_int16::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"getUint16",
|
||||
oxide_builtins::data_view::data_view_get_uint16::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"getInt32",
|
||||
oxide_builtins::data_view::data_view_get_int32::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"getUint32",
|
||||
oxide_builtins::data_view::data_view_get_uint32::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"getFloat32",
|
||||
oxide_builtins::data_view::data_view_get_float32::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"getFloat64",
|
||||
oxide_builtins::data_view::data_view_get_float64::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"getBigInt64",
|
||||
oxide_builtins::data_view::data_view_get_big_int64::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"getBigUint64",
|
||||
oxide_builtins::data_view::data_view_get_big_uint64::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
("setInt8", oxide_builtins::data_view::data_view_set_int8::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"setUint8",
|
||||
oxide_builtins::data_view::data_view_set_uint8::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"setInt16",
|
||||
oxide_builtins::data_view::data_view_set_int16::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"setUint16",
|
||||
oxide_builtins::data_view::data_view_set_uint16::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"setInt32",
|
||||
oxide_builtins::data_view::data_view_set_int32::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"setUint32",
|
||||
oxide_builtins::data_view::data_view_set_uint32::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"setFloat32",
|
||||
oxide_builtins::data_view::data_view_set_float32::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"setFloat64",
|
||||
oxide_builtins::data_view::data_view_set_float64::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"setBigInt64",
|
||||
oxide_builtins::data_view::data_view_set_big_int64::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"setBigUint64",
|
||||
oxide_builtins::data_view::data_view_set_big_uint64::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"toString",
|
||||
oxide_builtins::data_view::data_view_to_string::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
bind_constructor!(core, global, "DataView", ctor_ptr, crate::builtins::data_view::data_view_constructor, 3, hash: true);
|
||||
bind_constructor!(core, global, "DataView", ctor_ptr, oxide_builtins::data_view::data_view_constructor::<crate::vm::Vm>, 3, hash: true);
|
||||
}
|
||||
|
||||
@@ -11,16 +11,16 @@ pub fn bind_date(core: &Arc<KernelCore>, session: &KernelSession, global: &mut J
|
||||
let proto_ptr = session.builtin_world().date_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
|
||||
configure_native_constructor(ctor, crate::builtins::date::date_constructor as *const (), 7);
|
||||
configure_native_constructor(ctor, oxide_builtins::date::date_constructor::<crate::vm::Vm> as *const (), 7);
|
||||
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
ctor,
|
||||
core,
|
||||
&[
|
||||
("now", crate::builtins::date::date_now as *const (), 0),
|
||||
("parse", crate::builtins::date::date_parse as *const (), 1),
|
||||
("UTC", crate::builtins::date::date_utc as *const (), 7),
|
||||
("now", oxide_builtins::date::date_now::<crate::vm::Vm> as *const (), 0),
|
||||
("parse", oxide_builtins::date::date_parse::<crate::vm::Vm> as *const (), 1),
|
||||
("UTC", oxide_builtins::date::date_utc::<crate::vm::Vm> as *const (), 7),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -29,39 +29,67 @@ pub fn bind_date(core: &Arc<KernelCore>, session: &KernelSession, global: &mut J
|
||||
proto,
|
||||
core,
|
||||
&[
|
||||
("getTime", crate::builtins::date::date_get_time as *const (), 0),
|
||||
("getFullYear", crate::builtins::date::date_get_full_year as *const (), 0),
|
||||
("getMonth", crate::builtins::date::date_get_month as *const (), 0),
|
||||
("getDate", crate::builtins::date::date_get_date as *const (), 0),
|
||||
("getDay", crate::builtins::date::date_get_day as *const (), 0),
|
||||
("getHours", crate::builtins::date::date_get_hours as *const (), 0),
|
||||
("getMinutes", crate::builtins::date::date_get_minutes as *const (), 0),
|
||||
("getSeconds", crate::builtins::date::date_get_seconds as *const (), 0),
|
||||
("getMilliseconds", crate::builtins::date::date_get_milliseconds as *const (), 0),
|
||||
("getUTCFullYear", crate::builtins::date::date_get_utc_full_year as *const (), 0),
|
||||
("getUTCMonth", crate::builtins::date::date_get_utc_month as *const (), 0),
|
||||
("getUTCDate", crate::builtins::date::date_get_utc_date as *const (), 0),
|
||||
("getUTCDay", crate::builtins::date::date_get_utc_day as *const (), 0),
|
||||
("getUTCHours", crate::builtins::date::date_get_utc_hours as *const (), 0),
|
||||
("getUTCMinutes", crate::builtins::date::date_get_utc_minutes as *const (), 0),
|
||||
("getUTCSeconds", crate::builtins::date::date_get_utc_seconds as *const (), 0),
|
||||
("getUTCMilliseconds", crate::builtins::date::date_get_utc_milliseconds as *const (), 0),
|
||||
("getTimezoneOffset", crate::builtins::date::date_get_timezone_offset as *const (), 0),
|
||||
("setTime", crate::builtins::date::date_set_time as *const (), 1),
|
||||
("setFullYear", crate::builtins::date::date_set_full_year as *const (), 3),
|
||||
("setMonth", crate::builtins::date::date_set_month as *const (), 2),
|
||||
("setDate", crate::builtins::date::date_set_date as *const (), 1),
|
||||
("setHours", crate::builtins::date::date_set_hours as *const (), 4),
|
||||
("setMinutes", crate::builtins::date::date_set_minutes as *const (), 3),
|
||||
("setSeconds", crate::builtins::date::date_set_seconds as *const (), 2),
|
||||
("setMilliseconds", crate::builtins::date::date_set_milliseconds as *const (), 1),
|
||||
("toISOString", crate::builtins::date::date_to_iso_string as *const (), 0),
|
||||
("toJSON", crate::builtins::date::date_to_json as *const (), 1),
|
||||
("toString", crate::builtins::date::date_to_string as *const (), 0),
|
||||
("toDateString", crate::builtins::date::date_to_date_string as *const (), 0),
|
||||
("toTimeString", crate::builtins::date::date_to_time_string as *const (), 0),
|
||||
("toUTCString", crate::builtins::date::date_to_utc_string as *const (), 0),
|
||||
("valueOf", crate::builtins::date::date_value_of as *const (), 0),
|
||||
("getTime", oxide_builtins::date::date_get_time::<crate::vm::Vm> as *const (), 0),
|
||||
("getFullYear", oxide_builtins::date::date_get_full_year::<crate::vm::Vm> as *const (), 0),
|
||||
("getMonth", oxide_builtins::date::date_get_month::<crate::vm::Vm> as *const (), 0),
|
||||
("getDate", oxide_builtins::date::date_get_date::<crate::vm::Vm> as *const (), 0),
|
||||
("getDay", oxide_builtins::date::date_get_day::<crate::vm::Vm> as *const (), 0),
|
||||
("getHours", oxide_builtins::date::date_get_hours::<crate::vm::Vm> as *const (), 0),
|
||||
("getMinutes", oxide_builtins::date::date_get_minutes::<crate::vm::Vm> as *const (), 0),
|
||||
("getSeconds", oxide_builtins::date::date_get_seconds::<crate::vm::Vm> as *const (), 0),
|
||||
(
|
||||
"getMilliseconds",
|
||||
oxide_builtins::date::date_get_milliseconds::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
(
|
||||
"getUTCFullYear",
|
||||
oxide_builtins::date::date_get_utc_full_year::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
("getUTCMonth", oxide_builtins::date::date_get_utc_month::<crate::vm::Vm> as *const (), 0),
|
||||
("getUTCDate", oxide_builtins::date::date_get_utc_date::<crate::vm::Vm> as *const (), 0),
|
||||
("getUTCDay", oxide_builtins::date::date_get_utc_day::<crate::vm::Vm> as *const (), 0),
|
||||
("getUTCHours", oxide_builtins::date::date_get_utc_hours::<crate::vm::Vm> as *const (), 0),
|
||||
(
|
||||
"getUTCMinutes",
|
||||
oxide_builtins::date::date_get_utc_minutes::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
(
|
||||
"getUTCSeconds",
|
||||
oxide_builtins::date::date_get_utc_seconds::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
(
|
||||
"getUTCMilliseconds",
|
||||
oxide_builtins::date::date_get_utc_milliseconds::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
(
|
||||
"getTimezoneOffset",
|
||||
oxide_builtins::date::date_get_timezone_offset::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
("setTime", oxide_builtins::date::date_set_time::<crate::vm::Vm> as *const (), 1),
|
||||
("setFullYear", oxide_builtins::date::date_set_full_year::<crate::vm::Vm> as *const (), 3),
|
||||
("setMonth", oxide_builtins::date::date_set_month::<crate::vm::Vm> as *const (), 2),
|
||||
("setDate", oxide_builtins::date::date_set_date::<crate::vm::Vm> as *const (), 1),
|
||||
("setHours", oxide_builtins::date::date_set_hours::<crate::vm::Vm> as *const (), 4),
|
||||
("setMinutes", oxide_builtins::date::date_set_minutes::<crate::vm::Vm> as *const (), 3),
|
||||
("setSeconds", oxide_builtins::date::date_set_seconds::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"setMilliseconds",
|
||||
oxide_builtins::date::date_set_milliseconds::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
("toISOString", oxide_builtins::date::date_to_iso_string::<crate::vm::Vm> as *const (), 0),
|
||||
("toJSON", oxide_builtins::date::date_to_json::<crate::vm::Vm> as *const (), 1),
|
||||
("toString", oxide_builtins::date::date_to_string::<crate::vm::Vm> as *const (), 0),
|
||||
("toDateString", oxide_builtins::date::date_to_date_string::<crate::vm::Vm> as *const (), 0),
|
||||
("toTimeString", oxide_builtins::date::date_to_time_string::<crate::vm::Vm> as *const (), 0),
|
||||
("toUTCString", oxide_builtins::date::date_to_utc_string::<crate::vm::Vm> as *const (), 0),
|
||||
("valueOf", oxide_builtins::date::date_value_of::<crate::vm::Vm> as *const (), 0),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -45,15 +45,15 @@ fn bind_error_subtype_constructor(
|
||||
|
||||
pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
|
||||
let error_methods = ErrorMethods {
|
||||
error: crate::builtins::error::error_constructor as *const (),
|
||||
type_error: crate::builtins::error::type_error_constructor as *const (),
|
||||
reference_error: crate::builtins::error::reference_error_constructor as *const (),
|
||||
range_error: crate::builtins::error::range_error_constructor as *const (),
|
||||
syntax_error: crate::builtins::error::syntax_error_constructor as *const (),
|
||||
uri_error: crate::builtins::error::uri_error_constructor as *const (),
|
||||
eval_error: crate::builtins::error::eval_error_constructor as *const (),
|
||||
to_string: crate::builtins::error::error_to_string as *const (),
|
||||
stack: crate::builtins::error::error_stack_getter as *const (),
|
||||
error: oxide_builtins::error::error_constructor::<crate::vm::Vm> as *const (),
|
||||
type_error: oxide_builtins::error::type_error_constructor::<crate::vm::Vm> as *const (),
|
||||
reference_error: oxide_builtins::error::reference_error_constructor::<crate::vm::Vm> as *const (),
|
||||
range_error: oxide_builtins::error::range_error_constructor::<crate::vm::Vm> as *const (),
|
||||
syntax_error: oxide_builtins::error::syntax_error_constructor::<crate::vm::Vm> as *const (),
|
||||
uri_error: oxide_builtins::error::uri_error_constructor::<crate::vm::Vm> as *const (),
|
||||
eval_error: oxide_builtins::error::eval_error_constructor::<crate::vm::Vm> as *const (),
|
||||
to_string: oxide_builtins::error::error_to_string::<crate::vm::Vm> as *const (),
|
||||
stack: oxide_builtins::error::error_stack_getter::<crate::vm::Vm> as *const (),
|
||||
};
|
||||
session.builtin_world().bind_error_methods(
|
||||
&error_methods,
|
||||
@@ -74,7 +74,7 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
global,
|
||||
"TypeError",
|
||||
session.builtin_world().type_error_proto.as_ptr() as *mut JsObject,
|
||||
crate::builtins::error::type_error_constructor as *const (),
|
||||
oxide_builtins::error::type_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_constructor(
|
||||
core,
|
||||
@@ -82,7 +82,7 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
global,
|
||||
"ReferenceError",
|
||||
session.builtin_world().reference_error_proto.as_ptr() as *mut JsObject,
|
||||
crate::builtins::error::reference_error_constructor as *const (),
|
||||
oxide_builtins::error::reference_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_constructor(
|
||||
core,
|
||||
@@ -90,7 +90,7 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
global,
|
||||
"RangeError",
|
||||
session.builtin_world().range_error_proto.as_ptr() as *mut JsObject,
|
||||
crate::builtins::error::range_error_constructor as *const (),
|
||||
oxide_builtins::error::range_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_constructor(
|
||||
core,
|
||||
@@ -98,7 +98,7 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
global,
|
||||
"SyntaxError",
|
||||
session.builtin_world().syntax_error_proto.as_ptr() as *mut JsObject,
|
||||
crate::builtins::error::syntax_error_constructor as *const (),
|
||||
oxide_builtins::error::syntax_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_constructor(
|
||||
core,
|
||||
@@ -106,7 +106,7 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
global,
|
||||
"URIError",
|
||||
session.builtin_world().uri_error_proto.as_ptr() as *mut JsObject,
|
||||
crate::builtins::error::uri_error_constructor as *const (),
|
||||
oxide_builtins::error::uri_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_constructor(
|
||||
core,
|
||||
@@ -114,7 +114,7 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
global,
|
||||
"EvalError",
|
||||
session.builtin_world().eval_error_proto.as_ptr() as *mut JsObject,
|
||||
crate::builtins::error::eval_error_constructor as *const (),
|
||||
oxide_builtins::error::eval_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
|
||||
{
|
||||
@@ -122,7 +122,7 @@ pub fn bind_error(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
let err_ctor = unsafe { &mut *err_ctor_ptr };
|
||||
// SAFETY: error_constructor is a NativeFn fn-item.
|
||||
err_ctor.set_native_fn(Some(unsafe {
|
||||
NativeFnPtr::from_raw(crate::builtins::error::error_constructor as *const ())
|
||||
NativeFnPtr::from_raw(oxide_builtins::error::error_constructor::<crate::vm::Vm> as *const ())
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ use super::bind_global_value;
|
||||
|
||||
pub fn bind_function(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
|
||||
let function_methods = FunctionMethods {
|
||||
call: crate::builtins::function::function_call as *const (),
|
||||
apply: crate::builtins::function::function_apply as *const (),
|
||||
bind: crate::builtins::function::function_bind as *const (),
|
||||
to_string: crate::builtins::function::function_to_string as *const (),
|
||||
call: oxide_builtins::function::function_call::<crate::vm::Vm> as *const (),
|
||||
apply: oxide_builtins::function::function_apply::<crate::vm::Vm> as *const (),
|
||||
bind: oxide_builtins::function::function_bind::<crate::vm::Vm> as *const (),
|
||||
to_string: oxide_builtins::function::function_to_string::<crate::vm::Vm> as *const (),
|
||||
};
|
||||
session.builtin_world().bind_function_methods(
|
||||
&function_methods,
|
||||
|
||||
@@ -11,12 +11,20 @@ pub fn bind_global(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
global,
|
||||
core,
|
||||
&[
|
||||
("escape", crate::builtins::global::js_escape as *const (), 1),
|
||||
("unescape", crate::builtins::global::js_unescape as *const (), 1),
|
||||
("encodeURI", crate::builtins::global::encode_uri as *const (), 1),
|
||||
("decodeURI", crate::builtins::global::decode_uri as *const (), 1),
|
||||
("encodeURIComponent", crate::builtins::global::encode_uri_component as *const (), 1),
|
||||
("decodeURIComponent", crate::builtins::global::decode_uri_component as *const (), 1),
|
||||
("escape", oxide_builtins::global::js_escape::<crate::vm::Vm> as *const (), 1),
|
||||
("unescape", oxide_builtins::global::js_unescape::<crate::vm::Vm> as *const (), 1),
|
||||
("encodeURI", oxide_builtins::global::encode_uri::<crate::vm::Vm> as *const (), 1),
|
||||
("decodeURI", oxide_builtins::global::decode_uri::<crate::vm::Vm> as *const (), 1),
|
||||
(
|
||||
"encodeURIComponent",
|
||||
oxide_builtins::global::encode_uri_component::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
(
|
||||
"decodeURIComponent",
|
||||
oxide_builtins::global::decode_uri_component::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,13 +11,17 @@ pub fn bind_iterator(core: &Arc<KernelCore>, session: &KernelSession, global: &m
|
||||
let function_proto = session.builtin_world().function_proto.as_ptr() as *mut JsObject;
|
||||
let mut iterator = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(function_proto)));
|
||||
iterator.set_function(true);
|
||||
configure_native_constructor(&mut iterator, crate::builtins::iterator::iterator_constructor as *const (), 0);
|
||||
configure_native_constructor(
|
||||
&mut iterator,
|
||||
oxide_builtins::iterator::iterator_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
);
|
||||
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
&mut iterator,
|
||||
core,
|
||||
&[("from", crate::builtins::iterator::iterator_from as *const (), 1)],
|
||||
&[("from", oxide_builtins::iterator::iterator_from::<crate::vm::Vm> as *const (), 1)],
|
||||
);
|
||||
|
||||
bind_global_value(core, global, "Iterator", JsValue::from_js_object(Box::into_raw(iterator)));
|
||||
|
||||
@@ -14,8 +14,8 @@ pub fn bind_json(core: &Arc<KernelCore>, session: &KernelSession, global: &mut J
|
||||
json,
|
||||
core,
|
||||
&[
|
||||
("parse", crate::builtins::json::json_parse as *const (), 1),
|
||||
("stringify", crate::builtins::json::json_stringify as *const (), 1),
|
||||
("parse", oxide_builtins::json::json_parse::<crate::vm::Vm> as *const (), 1),
|
||||
("stringify", oxide_builtins::json::json_stringify::<crate::vm::Vm> as *const (), 1),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ pub fn bind_map(core: &Arc<KernelCore>, session: &KernelSession, global: &mut Js
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
let proto_ptr = session.builtin_world().map_proto.as_ptr() as *mut JsObject;
|
||||
|
||||
configure_native_constructor(ctor, crate::builtins::map::map_constructor as *const (), 1);
|
||||
configure_native_constructor(ctor, oxide_builtins::map::map_constructor::<crate::vm::Vm> as *const (), 1);
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
|
||||
apply_binding_table(
|
||||
@@ -18,14 +18,14 @@ pub fn bind_map(core: &Arc<KernelCore>, session: &KernelSession, global: &mut Js
|
||||
proto,
|
||||
core,
|
||||
&[
|
||||
("set", crate::builtins::map::map_set as *const (), 2),
|
||||
("get", crate::builtins::map::map_get as *const (), 1),
|
||||
("has", crate::builtins::map::map_has as *const (), 1),
|
||||
("delete", crate::builtins::map::map_delete as *const (), 1),
|
||||
("clear", crate::builtins::map::map_clear as *const (), 0),
|
||||
("size", crate::builtins::map::map_size as *const (), 0),
|
||||
("set", oxide_builtins::map::map_set::<crate::vm::Vm> as *const (), 2),
|
||||
("get", oxide_builtins::map::map_get::<crate::vm::Vm> as *const (), 1),
|
||||
("has", oxide_builtins::map::map_has::<crate::vm::Vm> as *const (), 1),
|
||||
("delete", oxide_builtins::map::map_delete::<crate::vm::Vm> as *const (), 1),
|
||||
("clear", oxide_builtins::map::map_clear::<crate::vm::Vm> as *const (), 0),
|
||||
("size", oxide_builtins::map::map_size::<crate::vm::Vm> as *const (), 0),
|
||||
],
|
||||
);
|
||||
|
||||
bind_constructor!(core, global, "Map", ctor_ptr, crate::builtins::map::map_constructor, 1, hash: true);
|
||||
bind_constructor!(core, global, "Map", ctor_ptr, oxide_builtins::map::map_constructor::<crate::vm::Vm>, 1, hash: true);
|
||||
}
|
||||
|
||||
@@ -18,41 +18,41 @@ pub fn bind_math(core: &Arc<KernelCore>, session: &KernelSession, global: &mut J
|
||||
math,
|
||||
sf,
|
||||
sh,
|
||||
("abs", crate::builtins::math::math_abs, 1),
|
||||
("acos", crate::builtins::math::math_acos, 1),
|
||||
("asin", crate::builtins::math::math_asin, 1),
|
||||
("atan", crate::builtins::math::math_atan, 1),
|
||||
("atan2", crate::builtins::math::math_atan2, 2),
|
||||
("cbrt", crate::builtins::math::math_cbrt, 1),
|
||||
("ceil", crate::builtins::math::math_ceil, 1),
|
||||
("cos", crate::builtins::math::math_cos, 1),
|
||||
("cosh", crate::builtins::math::math_cosh, 1),
|
||||
("exp", crate::builtins::math::math_exp, 1),
|
||||
("floor", crate::builtins::math::math_floor, 1),
|
||||
("hypot", crate::builtins::math::math_hypot, 2),
|
||||
("imul", crate::builtins::math::math_imul, 2),
|
||||
("log", crate::builtins::math::math_log, 1),
|
||||
("log10", crate::builtins::math::math_log10, 1),
|
||||
("log2", crate::builtins::math::math_log2, 1),
|
||||
("max", crate::builtins::math::math_max, 2),
|
||||
("min", crate::builtins::math::math_min, 2),
|
||||
("pow", crate::builtins::math::math_pow, 2),
|
||||
("random", crate::builtins::math::math_random, 0),
|
||||
("round", crate::builtins::math::math_round, 1),
|
||||
("sign", crate::builtins::math::math_sign, 1),
|
||||
("sin", crate::builtins::math::math_sin, 1),
|
||||
("sinh", crate::builtins::math::math_sinh, 1),
|
||||
("sqrt", crate::builtins::math::math_sqrt, 1),
|
||||
("tan", crate::builtins::math::math_tan, 1),
|
||||
("tanh", crate::builtins::math::math_tanh, 1),
|
||||
("trunc", crate::builtins::math::math_trunc, 1),
|
||||
("acosh", crate::builtins::math::math_acosh, 1),
|
||||
("asinh", crate::builtins::math::math_asinh, 1),
|
||||
("atanh", crate::builtins::math::math_atanh, 1),
|
||||
("clz32", crate::builtins::math::math_clz32, 1),
|
||||
("expm1", crate::builtins::math::math_expm1, 1),
|
||||
("fround", crate::builtins::math::math_fround, 1),
|
||||
("log1p", crate::builtins::math::math_log1p, 1),
|
||||
("abs", oxide_builtins::math::math_abs::<crate::vm::Vm>, 1),
|
||||
("acos", oxide_builtins::math::math_acos::<crate::vm::Vm>, 1),
|
||||
("asin", oxide_builtins::math::math_asin::<crate::vm::Vm>, 1),
|
||||
("atan", oxide_builtins::math::math_atan::<crate::vm::Vm>, 1),
|
||||
("atan2", oxide_builtins::math::math_atan2::<crate::vm::Vm>, 2),
|
||||
("cbrt", oxide_builtins::math::math_cbrt::<crate::vm::Vm>, 1),
|
||||
("ceil", oxide_builtins::math::math_ceil::<crate::vm::Vm>, 1),
|
||||
("cos", oxide_builtins::math::math_cos::<crate::vm::Vm>, 1),
|
||||
("cosh", oxide_builtins::math::math_cosh::<crate::vm::Vm>, 1),
|
||||
("exp", oxide_builtins::math::math_exp::<crate::vm::Vm>, 1),
|
||||
("floor", oxide_builtins::math::math_floor::<crate::vm::Vm>, 1),
|
||||
("hypot", oxide_builtins::math::math_hypot::<crate::vm::Vm>, 2),
|
||||
("imul", oxide_builtins::math::math_imul::<crate::vm::Vm>, 2),
|
||||
("log", oxide_builtins::math::math_log::<crate::vm::Vm>, 1),
|
||||
("log10", oxide_builtins::math::math_log10::<crate::vm::Vm>, 1),
|
||||
("log2", oxide_builtins::math::math_log2::<crate::vm::Vm>, 1),
|
||||
("max", oxide_builtins::math::math_max::<crate::vm::Vm>, 2),
|
||||
("min", oxide_builtins::math::math_min::<crate::vm::Vm>, 2),
|
||||
("pow", oxide_builtins::math::math_pow::<crate::vm::Vm>, 2),
|
||||
("random", oxide_builtins::math::math_random::<crate::vm::Vm>, 0),
|
||||
("round", oxide_builtins::math::math_round::<crate::vm::Vm>, 1),
|
||||
("sign", oxide_builtins::math::math_sign::<crate::vm::Vm>, 1),
|
||||
("sin", oxide_builtins::math::math_sin::<crate::vm::Vm>, 1),
|
||||
("sinh", oxide_builtins::math::math_sinh::<crate::vm::Vm>, 1),
|
||||
("sqrt", oxide_builtins::math::math_sqrt::<crate::vm::Vm>, 1),
|
||||
("tan", oxide_builtins::math::math_tan::<crate::vm::Vm>, 1),
|
||||
("tanh", oxide_builtins::math::math_tanh::<crate::vm::Vm>, 1),
|
||||
("trunc", oxide_builtins::math::math_trunc::<crate::vm::Vm>, 1),
|
||||
("acosh", oxide_builtins::math::math_acosh::<crate::vm::Vm>, 1),
|
||||
("asinh", oxide_builtins::math::math_asinh::<crate::vm::Vm>, 1),
|
||||
("atanh", oxide_builtins::math::math_atanh::<crate::vm::Vm>, 1),
|
||||
("clz32", oxide_builtins::math::math_clz32::<crate::vm::Vm>, 1),
|
||||
("expm1", oxide_builtins::math::math_expm1::<crate::vm::Vm>, 1),
|
||||
("fround", oxide_builtins::math::math_fround::<crate::vm::Vm>, 1),
|
||||
("log1p", oxide_builtins::math::math_log1p::<crate::vm::Vm>, 1),
|
||||
);
|
||||
|
||||
for (name, val) in [
|
||||
|
||||
@@ -12,17 +12,21 @@ pub fn bind_number(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
let proto_ptr = session.builtin_world().number_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
|
||||
configure_native_constructor(ctor, crate::builtins::number::number_constructor as *const (), 1);
|
||||
configure_native_constructor(ctor, oxide_builtins::number::number_constructor::<crate::vm::Vm> as *const (), 1);
|
||||
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
ctor,
|
||||
core,
|
||||
&[
|
||||
("isNaN", crate::builtins::number::number_is_nan as *const (), 1),
|
||||
("isFinite", crate::builtins::number::number_is_finite as *const (), 1),
|
||||
("isInteger", crate::builtins::number::number_is_integer as *const (), 1),
|
||||
("isSafeInteger", crate::builtins::number::number_is_safe_integer as *const (), 1),
|
||||
("isNaN", oxide_builtins::number::number_is_nan::<crate::vm::Vm> as *const (), 1),
|
||||
("isFinite", oxide_builtins::number::number_is_finite::<crate::vm::Vm> as *const (), 1),
|
||||
("isInteger", oxide_builtins::number::number_is_integer::<crate::vm::Vm> as *const (), 1),
|
||||
(
|
||||
"isSafeInteger",
|
||||
oxide_builtins::number::number_is_safe_integer::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -31,11 +35,19 @@ pub fn bind_number(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
proto,
|
||||
core,
|
||||
&[
|
||||
("toString", crate::builtins::number::number_to_string as *const (), 0),
|
||||
("toFixed", crate::builtins::number::number_to_fixed as *const (), 0),
|
||||
("toExponential", crate::builtins::number::number_to_exponential as *const (), 0),
|
||||
("toPrecision", crate::builtins::number::number_to_precision as *const (), 0),
|
||||
("valueOf", crate::builtins::number::number_value_of as *const (), 0),
|
||||
("toString", oxide_builtins::number::number_to_string::<crate::vm::Vm> as *const (), 0),
|
||||
("toFixed", oxide_builtins::number::number_to_fixed::<crate::vm::Vm> as *const (), 0),
|
||||
(
|
||||
"toExponential",
|
||||
oxide_builtins::number::number_to_exponential::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
(
|
||||
"toPrecision",
|
||||
oxide_builtins::number::number_to_precision::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
("valueOf", oxide_builtins::number::number_value_of::<crate::vm::Vm> as *const (), 0),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -55,15 +67,15 @@ pub fn bind_number(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
ctor.set_shape_id(next_shape);
|
||||
}
|
||||
|
||||
bind_constructor!(core, global, "Number", ctor_ptr, crate::builtins::number::number_constructor, 1, hash: true);
|
||||
bind_constructor!(core, global, "Number", ctor_ptr, oxide_builtins::number::number_constructor::<crate::vm::Vm>, 1, hash: true);
|
||||
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
global,
|
||||
core,
|
||||
&[
|
||||
("parseInt", crate::builtins::number::number_parse_int as *const (), 1),
|
||||
("parseFloat", crate::builtins::number::number_parse_float as *const (), 1),
|
||||
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 1),
|
||||
("parseFloat", oxide_builtins::number::number_parse_float::<crate::vm::Vm> as *const (), 1),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,32 +8,41 @@ use crate::bind_constructor;
|
||||
|
||||
pub fn bind_object(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
|
||||
let methods = ObjectMethods {
|
||||
keys: crate::builtins::object::object_keys as *const (),
|
||||
create: crate::builtins::object::object_create as *const (),
|
||||
assign: crate::builtins::object::object_assign as *const (),
|
||||
is: crate::builtins::object::object_is as *const (),
|
||||
define_property: crate::builtins::object::object_define_property as *const (),
|
||||
get_own_property_descriptor: crate::builtins::object::object_get_own_property_descriptor as *const (),
|
||||
freeze: crate::builtins::object::object_freeze as *const (),
|
||||
seal: crate::builtins::object::object_seal as *const (),
|
||||
prevent_extensions: crate::builtins::object::object_prevent_extensions as *const (),
|
||||
is_frozen: crate::builtins::object::object_is_frozen as *const (),
|
||||
is_sealed: crate::builtins::object::object_is_sealed as *const (),
|
||||
is_extensible: crate::builtins::object::object_is_extensible as *const (),
|
||||
get_own_property_names: crate::builtins::object::object_get_own_property_names as *const (),
|
||||
define_properties: crate::builtins::object::object_define_properties as *const (),
|
||||
from_entries: crate::builtins::object::object_from_entries as *const (),
|
||||
get_prototype_of: crate::builtins::object::object_get_prototype_of as *const (),
|
||||
has_own: crate::builtins::object::object_has_own as *const (),
|
||||
entries: crate::builtins::object::object_entries as *const (),
|
||||
values: crate::builtins::object::object_values as *const (),
|
||||
has_own_property: crate::builtins::object::object_proto_has_own_property as *const (),
|
||||
property_is_enumerable: crate::builtins::object::object_proto_property_is_enumerable as *const (),
|
||||
keys: oxide_builtins::object::object_keys::<crate::vm::Vm> as *const (),
|
||||
create: oxide_builtins::object::object_create::<crate::vm::Vm> as *const (),
|
||||
assign: oxide_builtins::object::object_assign::<crate::vm::Vm> as *const (),
|
||||
is: oxide_builtins::object::object_is::<crate::vm::Vm> as *const (),
|
||||
define_property: oxide_builtins::object::object_define_property::<crate::vm::Vm> as *const (),
|
||||
get_own_property_descriptor: oxide_builtins::object::object_get_own_property_descriptor::<crate::vm::Vm>
|
||||
as *const (),
|
||||
freeze: oxide_builtins::object::object_freeze::<crate::vm::Vm> as *const (),
|
||||
seal: oxide_builtins::object::object_seal::<crate::vm::Vm> as *const (),
|
||||
prevent_extensions: oxide_builtins::object::object_prevent_extensions::<crate::vm::Vm> as *const (),
|
||||
is_frozen: oxide_builtins::object::object_is_frozen::<crate::vm::Vm> as *const (),
|
||||
is_sealed: oxide_builtins::object::object_is_sealed::<crate::vm::Vm> as *const (),
|
||||
is_extensible: oxide_builtins::object::object_is_extensible::<crate::vm::Vm> as *const (),
|
||||
get_own_property_names: oxide_builtins::object::object_get_own_property_names::<crate::vm::Vm> as *const (),
|
||||
define_properties: oxide_builtins::object::object_define_properties::<crate::vm::Vm> as *const (),
|
||||
from_entries: oxide_builtins::object::object_from_entries::<crate::vm::Vm> as *const (),
|
||||
get_prototype_of: oxide_builtins::object::object_get_prototype_of::<crate::vm::Vm> as *const (),
|
||||
has_own: oxide_builtins::object::object_has_own::<crate::vm::Vm> as *const (),
|
||||
entries: oxide_builtins::object::object_entries::<crate::vm::Vm> as *const (),
|
||||
values: oxide_builtins::object::object_values::<crate::vm::Vm> as *const (),
|
||||
has_own_property: oxide_builtins::object::object_proto_has_own_property::<crate::vm::Vm> as *const (),
|
||||
property_is_enumerable: oxide_builtins::object::object_proto_property_is_enumerable::<crate::vm::Vm>
|
||||
as *const (),
|
||||
};
|
||||
session
|
||||
.builtin_world()
|
||||
.bind_object_methods(&methods, core.perm_interner().as_ref(), core.shape_forge().as_ref());
|
||||
|
||||
let ctor_ptr = session.builtin_world().object_constructor.as_ptr() as *mut JsObject;
|
||||
bind_constructor!(core, global, "Object", ctor_ptr, crate::builtins::object::object_constructor, 1);
|
||||
bind_constructor!(
|
||||
core,
|
||||
global,
|
||||
"Object",
|
||||
ctor_ptr,
|
||||
oxide_builtins::object::object_constructor::<crate::vm::Vm>,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,23 +17,47 @@ pub fn bind_reflect(core: &Arc<KernelCore>, session: &KernelSession, global: &mu
|
||||
&mut reflect,
|
||||
core,
|
||||
&[
|
||||
("apply", crate::builtins::reflect::reflect_apply as *const (), 3),
|
||||
("construct", crate::builtins::reflect::reflect_construct as *const (), 2),
|
||||
("defineProperty", crate::builtins::reflect::reflect_define_property as *const (), 3),
|
||||
("deleteProperty", crate::builtins::reflect::reflect_delete_property as *const (), 2),
|
||||
("get", crate::builtins::reflect::reflect_get as *const (), 2),
|
||||
("apply", oxide_builtins::reflect::reflect_apply::<crate::vm::Vm> as *const (), 3),
|
||||
("construct", oxide_builtins::reflect::reflect_construct::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"getOwnPropertyDescriptor",
|
||||
crate::builtins::reflect::reflect_get_own_property_descriptor as *const (),
|
||||
"defineProperty",
|
||||
oxide_builtins::reflect::reflect_define_property::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"deleteProperty",
|
||||
oxide_builtins::reflect::reflect_delete_property::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
("get", oxide_builtins::reflect::reflect_get::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"getOwnPropertyDescriptor",
|
||||
oxide_builtins::reflect::reflect_get_own_property_descriptor::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"getPrototypeOf",
|
||||
oxide_builtins::reflect::reflect_get_prototype_of::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
("has", oxide_builtins::reflect::reflect_has::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"isExtensible",
|
||||
oxide_builtins::reflect::reflect_is_extensible::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
("ownKeys", oxide_builtins::reflect::reflect_own_keys::<crate::vm::Vm> as *const (), 1),
|
||||
(
|
||||
"preventExtensions",
|
||||
oxide_builtins::reflect::reflect_prevent_extensions::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
("set", oxide_builtins::reflect::reflect_set::<crate::vm::Vm> as *const (), 3),
|
||||
(
|
||||
"setPrototypeOf",
|
||||
oxide_builtins::reflect::reflect_set_prototype_of::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
("getPrototypeOf", crate::builtins::reflect::reflect_get_prototype_of as *const (), 1),
|
||||
("has", crate::builtins::reflect::reflect_has as *const (), 2),
|
||||
("isExtensible", crate::builtins::reflect::reflect_is_extensible as *const (), 1),
|
||||
("ownKeys", crate::builtins::reflect::reflect_own_keys as *const (), 1),
|
||||
("preventExtensions", crate::builtins::reflect::reflect_prevent_extensions as *const (), 1),
|
||||
("set", crate::builtins::reflect::reflect_set as *const (), 3),
|
||||
("setPrototypeOf", crate::builtins::reflect::reflect_set_prototype_of as *const (), 2),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -12,18 +12,18 @@ pub fn bind_regexp(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
let proto_ptr = session.builtin_world().regexp_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
|
||||
configure_native_constructor(ctor, crate::builtins::regexp::regexp_constructor as *const (), 2);
|
||||
configure_native_constructor(ctor, oxide_builtins::regexp::regexp_constructor::<crate::vm::Vm> as *const (), 2);
|
||||
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
proto,
|
||||
core,
|
||||
&[
|
||||
("exec", crate::builtins::regexp::regexp_exec as *const (), 1),
|
||||
("test", crate::builtins::regexp::regexp_test as *const (), 1),
|
||||
("toString", crate::builtins::regexp::regexp_to_string as *const (), 0),
|
||||
("exec", oxide_builtins::regexp::regexp_exec::<crate::vm::Vm> as *const (), 1),
|
||||
("test", oxide_builtins::regexp::regexp_test::<crate::vm::Vm> as *const (), 1),
|
||||
("toString", oxide_builtins::regexp::regexp_to_string::<crate::vm::Vm> as *const (), 0),
|
||||
],
|
||||
);
|
||||
|
||||
bind_constructor!(core, global, "RegExp", ctor_ptr, crate::builtins::regexp::regexp_constructor, 2, hash: true);
|
||||
bind_constructor!(core, global, "RegExp", ctor_ptr, oxide_builtins::regexp::regexp_constructor::<crate::vm::Vm>, 2, hash: true);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ pub fn bind_set(core: &Arc<KernelCore>, session: &KernelSession, global: &mut Js
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
let proto_ptr = session.builtin_world().set_proto.as_ptr() as *mut JsObject;
|
||||
|
||||
configure_native_constructor(ctor, crate::builtins::set::set_constructor as *const (), 1);
|
||||
configure_native_constructor(ctor, oxide_builtins::set::set_constructor::<crate::vm::Vm> as *const (), 1);
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
|
||||
apply_binding_table(
|
||||
@@ -18,13 +18,13 @@ pub fn bind_set(core: &Arc<KernelCore>, session: &KernelSession, global: &mut Js
|
||||
proto,
|
||||
core,
|
||||
&[
|
||||
("add", crate::builtins::set::set_add as *const (), 1),
|
||||
("has", crate::builtins::set::set_has as *const (), 1),
|
||||
("delete", crate::builtins::set::set_delete as *const (), 1),
|
||||
("clear", crate::builtins::set::set_clear as *const (), 0),
|
||||
("size", crate::builtins::set::set_size as *const (), 0),
|
||||
("add", oxide_builtins::set::set_add::<crate::vm::Vm> as *const (), 1),
|
||||
("has", oxide_builtins::set::set_has::<crate::vm::Vm> as *const (), 1),
|
||||
("delete", oxide_builtins::set::set_delete::<crate::vm::Vm> as *const (), 1),
|
||||
("clear", oxide_builtins::set::set_clear::<crate::vm::Vm> as *const (), 0),
|
||||
("size", oxide_builtins::set::set_size::<crate::vm::Vm> as *const (), 0),
|
||||
],
|
||||
);
|
||||
|
||||
bind_constructor!(core, global, "Set", ctor_ptr, crate::builtins::set::set_constructor, 1, hash: true);
|
||||
bind_constructor!(core, global, "Set", ctor_ptr, oxide_builtins::set::set_constructor::<crate::vm::Vm>, 1, hash: true);
|
||||
}
|
||||
|
||||
@@ -8,33 +8,33 @@ use oxide_types::value::JsValue;
|
||||
|
||||
pub fn bind_string(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
|
||||
let string_methods = StringMethods {
|
||||
from_char_code: crate::builtins::string::string_from_char_code as *const (),
|
||||
index_of: crate::builtins::string::string_index_of as *const (),
|
||||
includes: crate::builtins::string::string_includes as *const (),
|
||||
char_at: crate::builtins::string::string_char_at as *const (),
|
||||
char_code_at: crate::builtins::string::string_char_code_at as *const (),
|
||||
concat: crate::builtins::string::string_concat as *const (),
|
||||
slice: crate::builtins::string::string_slice as *const (),
|
||||
substring: crate::builtins::string::string_substring as *const (),
|
||||
to_upper_case: crate::builtins::string::string_to_upper_case as *const (),
|
||||
to_lower_case: crate::builtins::string::string_to_lower_case as *const (),
|
||||
trim: crate::builtins::string::string_trim as *const (),
|
||||
repeat: crate::builtins::string::string_repeat as *const (),
|
||||
pad_start: crate::builtins::string::string_pad_start as *const (),
|
||||
pad_end: crate::builtins::string::string_pad_end as *const (),
|
||||
starts_with: crate::builtins::string::string_starts_with as *const (),
|
||||
ends_with: crate::builtins::string::string_ends_with as *const (),
|
||||
split: crate::builtins::string::string_split as *const (),
|
||||
replace: crate::builtins::string::string_replace as *const (),
|
||||
match_fn: crate::builtins::string::string_match_fn as *const (),
|
||||
search: crate::builtins::string::string_search as *const (),
|
||||
trim_start: crate::builtins::string::string_trim_start as *const (),
|
||||
trim_end: crate::builtins::string::string_trim_end as *const (),
|
||||
code_point_at: crate::builtins::string::string_code_point_at as *const (),
|
||||
normalize: crate::builtins::string::string_normalize as *const (),
|
||||
match_all: crate::builtins::string::string_match_all as *const (),
|
||||
replace_all: crate::builtins::string::string_replace_all as *const (),
|
||||
value_of: crate::builtins::string::string_value_of as *const (),
|
||||
from_char_code: oxide_builtins::string::string_from_char_code::<crate::vm::Vm> as *const (),
|
||||
index_of: oxide_builtins::string::string_index_of::<crate::vm::Vm> as *const (),
|
||||
includes: oxide_builtins::string::string_includes::<crate::vm::Vm> as *const (),
|
||||
char_at: oxide_builtins::string::string_char_at::<crate::vm::Vm> as *const (),
|
||||
char_code_at: oxide_builtins::string::string_char_code_at::<crate::vm::Vm> as *const (),
|
||||
concat: oxide_builtins::string::string_concat::<crate::vm::Vm> as *const (),
|
||||
slice: oxide_builtins::string::string_slice::<crate::vm::Vm> as *const (),
|
||||
substring: oxide_builtins::string::string_substring::<crate::vm::Vm> as *const (),
|
||||
to_upper_case: oxide_builtins::string::string_to_upper_case::<crate::vm::Vm> as *const (),
|
||||
to_lower_case: oxide_builtins::string::string_to_lower_case::<crate::vm::Vm> as *const (),
|
||||
trim: oxide_builtins::string::string_trim::<crate::vm::Vm> as *const (),
|
||||
repeat: oxide_builtins::string::string_repeat::<crate::vm::Vm> as *const (),
|
||||
pad_start: oxide_builtins::string::string_pad_start::<crate::vm::Vm> as *const (),
|
||||
pad_end: oxide_builtins::string::string_pad_end::<crate::vm::Vm> as *const (),
|
||||
starts_with: oxide_builtins::string::string_starts_with::<crate::vm::Vm> as *const (),
|
||||
ends_with: oxide_builtins::string::string_ends_with::<crate::vm::Vm> as *const (),
|
||||
split: oxide_builtins::string::string_split::<crate::vm::Vm> as *const (),
|
||||
replace: oxide_builtins::string::string_replace::<crate::vm::Vm> as *const (),
|
||||
match_fn: oxide_builtins::string::string_match_fn::<crate::vm::Vm> as *const (),
|
||||
search: oxide_builtins::string::string_search::<crate::vm::Vm> as *const (),
|
||||
trim_start: oxide_builtins::string::string_trim_start::<crate::vm::Vm> as *const (),
|
||||
trim_end: oxide_builtins::string::string_trim_end::<crate::vm::Vm> as *const (),
|
||||
code_point_at: oxide_builtins::string::string_code_point_at::<crate::vm::Vm> as *const (),
|
||||
normalize: oxide_builtins::string::string_normalize::<crate::vm::Vm> as *const (),
|
||||
match_all: oxide_builtins::string::string_match_all::<crate::vm::Vm> as *const (),
|
||||
replace_all: oxide_builtins::string::string_replace_all::<crate::vm::Vm> as *const (),
|
||||
value_of: oxide_builtins::string::string_value_of::<crate::vm::Vm> as *const (),
|
||||
};
|
||||
session.builtin_world().bind_string_methods(
|
||||
&string_methods,
|
||||
@@ -44,7 +44,7 @@ pub fn bind_string(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
|
||||
let ctor_ptr = session.builtin_world().string_constructor.as_ptr() as *mut JsObject;
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
configure_native_constructor(ctor, crate::builtins::string::string_constructor as *const (), 1);
|
||||
configure_native_constructor(ctor, oxide_builtins::string::string_constructor::<crate::vm::Vm> as *const (), 1);
|
||||
|
||||
let proto_ptr = session.builtin_world().string_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
@@ -52,7 +52,7 @@ pub fn bind_string(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
session.builtin_world(),
|
||||
proto,
|
||||
core,
|
||||
&[("toString", crate::builtins::string::string_to_string as *const (), 0)],
|
||||
&[("toString", oxide_builtins::string::string_to_string::<crate::vm::Vm> as *const (), 0)],
|
||||
);
|
||||
|
||||
let si_str = core.perm_interner().intern("String").0;
|
||||
|
||||
@@ -9,14 +9,22 @@ use oxide_types::value::JsValue;
|
||||
use crate::bindings::{bind_global_value, configure_native_constructor};
|
||||
|
||||
const STUBS: [(&str, *const (), u8); 8] = [
|
||||
("Proxy", crate::builtins::stubs::proxy_stub as *const (), 2),
|
||||
("BigInt", crate::builtins::stubs::bigint_stub as *const (), 1),
|
||||
("WeakMap", crate::builtins::stubs::weakmap_stub as *const (), 0),
|
||||
("WeakSet", crate::builtins::stubs::weakset_stub as *const (), 0),
|
||||
("WeakRef", crate::builtins::stubs::weakref_stub as *const (), 1),
|
||||
("FinalizationRegistry", crate::builtins::stubs::finalization_registry_stub as *const (), 1),
|
||||
("SharedArrayBuffer", crate::builtins::stubs::shared_array_buffer_stub as *const (), 1),
|
||||
("Atomics", crate::builtins::stubs::atomics_stub as *const (), 0),
|
||||
("Proxy", oxide_builtins::stubs::proxy_stub::<crate::vm::Vm> as *const (), 2),
|
||||
("BigInt", oxide_builtins::stubs::bigint_stub::<crate::vm::Vm> as *const (), 1),
|
||||
("WeakMap", oxide_builtins::stubs::weakmap_stub::<crate::vm::Vm> as *const (), 0),
|
||||
("WeakSet", oxide_builtins::stubs::weakset_stub::<crate::vm::Vm> as *const (), 0),
|
||||
("WeakRef", oxide_builtins::stubs::weakref_stub::<crate::vm::Vm> as *const (), 1),
|
||||
(
|
||||
"FinalizationRegistry",
|
||||
oxide_builtins::stubs::finalization_registry_stub::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
(
|
||||
"SharedArrayBuffer",
|
||||
oxide_builtins::stubs::shared_array_buffer_stub::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
("Atomics", oxide_builtins::stubs::atomics_stub::<crate::vm::Vm> as *const (), 0),
|
||||
];
|
||||
|
||||
pub fn bind_stubs(core: &Arc<KernelCore>, session: &mut KernelSession, global: &mut JsObject) {
|
||||
|
||||
@@ -13,15 +13,15 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
let proto_ptr = session.builtin_world().symbol_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
|
||||
configure_native_constructor(ctor, crate::builtins::symbol::symbol_constructor as *const (), 1);
|
||||
configure_native_constructor(ctor, oxide_builtins::symbol::symbol_constructor::<crate::vm::Vm> as *const (), 1);
|
||||
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
ctor,
|
||||
core,
|
||||
&[
|
||||
("for", crate::builtins::symbol::symbol_for as *const (), 1),
|
||||
("keyFor", crate::builtins::symbol::symbol_key_for as *const (), 1),
|
||||
("for", oxide_builtins::symbol::symbol_for::<crate::vm::Vm> as *const (), 1),
|
||||
("keyFor", oxide_builtins::symbol::symbol_key_for::<crate::vm::Vm> as *const (), 1),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -29,7 +29,7 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
session.builtin_world(),
|
||||
proto,
|
||||
core,
|
||||
&[("toString", crate::builtins::symbol::symbol_to_string as *const (), 0)],
|
||||
&[("toString", oxide_builtins::symbol::symbol_to_string::<crate::vm::Vm> as *const (), 0)],
|
||||
);
|
||||
|
||||
for (name, val) in [
|
||||
@@ -57,7 +57,7 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
|
||||
bind_well_known_symbol(core, ctor, name, val);
|
||||
}
|
||||
|
||||
bind_constructor!(core, global, "Symbol", ctor_ptr, crate::builtins::symbol::symbol_constructor, 1, hash: true);
|
||||
bind_constructor!(core, global, "Symbol", ctor_ptr, oxide_builtins::symbol::symbol_constructor::<crate::vm::Vm>, 1, hash: true);
|
||||
}
|
||||
|
||||
fn bind_well_known_symbol(core: &Arc<KernelCore>, ctor: &mut JsObject, name: &str, val: JsValue) {
|
||||
|
||||
@@ -8,7 +8,7 @@ use oxide_types::object::JsObject;
|
||||
macro_rules! bind_typed_array_constructor {
|
||||
($core:expr, $global:expr, $name:literal, $ctor_ptr:expr, $ctor_fn:path) => {{
|
||||
let ctor = unsafe { &mut *$ctor_ptr };
|
||||
configure_native_constructor(ctor, $ctor_fn as *const (), 1);
|
||||
configure_native_constructor(ctor, ($ctor_fn as fn(&mut $crate::vm::Vm, &[u8]) -> oxide_runtime_api::NativeResult) as *const (), 1);
|
||||
bind_constructor!($core, $global, $name, $ctor_ptr, $ctor_fn, 1, hash: true);
|
||||
}};
|
||||
}
|
||||
@@ -21,12 +21,20 @@ pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global:
|
||||
shared_proto,
|
||||
core,
|
||||
&[
|
||||
("at", crate::builtins::typed_array::typed_array_at as *const (), 1),
|
||||
("fill", crate::builtins::typed_array::typed_array_fill as *const (), 3),
|
||||
("set", crate::builtins::typed_array::typed_array_set as *const (), 2),
|
||||
("slice", crate::builtins::typed_array::typed_array_slice as *const (), 2),
|
||||
("subarray", crate::builtins::typed_array::typed_array_subarray as *const (), 2),
|
||||
("toString", crate::builtins::typed_array::typed_array_to_string as *const (), 0),
|
||||
("at", oxide_builtins::typed_array::typed_array_at::<crate::vm::Vm> as *const (), 1),
|
||||
("fill", oxide_builtins::typed_array::typed_array_fill::<crate::vm::Vm> as *const (), 3),
|
||||
("set", oxide_builtins::typed_array::typed_array_set::<crate::vm::Vm> as *const (), 2),
|
||||
("slice", oxide_builtins::typed_array::typed_array_slice::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"subarray",
|
||||
oxide_builtins::typed_array::typed_array_subarray::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"toString",
|
||||
oxide_builtins::typed_array::typed_array_to_string::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -35,76 +43,76 @@ pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global:
|
||||
global,
|
||||
"Int8Array",
|
||||
session.builtin_world().int8array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::int8array_constructor
|
||||
oxide_builtins::typed_array::int8array_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"Uint8Array",
|
||||
session.builtin_world().uint8array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::uint8array_constructor
|
||||
oxide_builtins::typed_array::uint8array_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"Uint8ClampedArray",
|
||||
session.builtin_world().uint8clampedarray_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::uint8clampedarray_constructor
|
||||
oxide_builtins::typed_array::uint8clampedarray_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"Int16Array",
|
||||
session.builtin_world().int16array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::int16array_constructor
|
||||
oxide_builtins::typed_array::int16array_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"Uint16Array",
|
||||
session.builtin_world().uint16array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::uint16array_constructor
|
||||
oxide_builtins::typed_array::uint16array_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"Int32Array",
|
||||
session.builtin_world().int32array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::int32array_constructor
|
||||
oxide_builtins::typed_array::int32array_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"Uint32Array",
|
||||
session.builtin_world().uint32array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::uint32array_constructor
|
||||
oxide_builtins::typed_array::uint32array_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"Float32Array",
|
||||
session.builtin_world().float32array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::float32array_constructor
|
||||
oxide_builtins::typed_array::float32array_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"Float64Array",
|
||||
session.builtin_world().float64array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::float64array_constructor
|
||||
oxide_builtins::typed_array::float64array_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"BigInt64Array",
|
||||
session.builtin_world().bigint64array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::bigint64array_constructor
|
||||
oxide_builtins::typed_array::bigint64array_constructor
|
||||
);
|
||||
bind_typed_array_constructor!(
|
||||
core,
|
||||
global,
|
||||
"BigUint64Array",
|
||||
session.builtin_world().biguint64array_constructor.as_ptr() as *mut JsObject,
|
||||
crate::builtins::typed_array::biguint64array_constructor
|
||||
oxide_builtins::typed_array::biguint64array_constructor
|
||||
);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,8 @@ macro_rules! bind_constructor {
|
||||
$global.push_prop(val);
|
||||
}
|
||||
let ctor = unsafe { &mut *$ctor_ptr };
|
||||
ctor.set_native_fn(Some(unsafe { oxide_types::object::NativeFnPtr::from_raw($ctor_fn as *const ()) }));
|
||||
let ptr: *const () = ($ctor_fn as fn(&mut $crate::vm::Vm, &[u8]) -> oxide_runtime_api::NativeResult) as *const ();
|
||||
ctor.set_native_fn(Some(unsafe { oxide_types::object::NativeFnPtr::from_raw(ptr) }));
|
||||
ctor.set_native_arg_count($nargs);
|
||||
}};
|
||||
}
|
||||
@@ -127,14 +128,22 @@ fn bind_global_functions(core: &Arc<KernelCore>, session: &KernelSession, global
|
||||
global,
|
||||
core,
|
||||
&[
|
||||
("parseInt", crate::builtins::number::number_parse_int as *const (), 1),
|
||||
("parseFloat", crate::builtins::number::number_parse_float as *const (), 1),
|
||||
("escape", crate::builtins::global::js_escape as *const (), 1),
|
||||
("unescape", crate::builtins::global::js_unescape as *const (), 1),
|
||||
("encodeURI", crate::builtins::global::encode_uri as *const (), 1),
|
||||
("decodeURI", crate::builtins::global::decode_uri as *const (), 1),
|
||||
("encodeURIComponent", crate::builtins::global::encode_uri_component as *const (), 1),
|
||||
("decodeURIComponent", crate::builtins::global::decode_uri_component as *const (), 1),
|
||||
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 1),
|
||||
("parseFloat", oxide_builtins::number::number_parse_float::<crate::vm::Vm> as *const (), 1),
|
||||
("escape", oxide_builtins::global::js_escape::<crate::vm::Vm> as *const (), 1),
|
||||
("unescape", oxide_builtins::global::js_unescape::<crate::vm::Vm> as *const (), 1),
|
||||
("encodeURI", oxide_builtins::global::encode_uri::<crate::vm::Vm> as *const (), 1),
|
||||
("decodeURI", oxide_builtins::global::decode_uri::<crate::vm::Vm> as *const (), 1),
|
||||
(
|
||||
"encodeURIComponent",
|
||||
oxide_builtins::global::encode_uri_component::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
(
|
||||
"decodeURIComponent",
|
||||
oxide_builtins::global::decode_uri_component::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -149,23 +158,47 @@ fn bind_reflect_global(core: &Arc<KernelCore>, session: &KernelSession, global:
|
||||
&mut reflect,
|
||||
core,
|
||||
&[
|
||||
("apply", crate::builtins::reflect::reflect_apply as *const (), 3),
|
||||
("construct", crate::builtins::reflect::reflect_construct as *const (), 2),
|
||||
("defineProperty", crate::builtins::reflect::reflect_define_property as *const (), 3),
|
||||
("deleteProperty", crate::builtins::reflect::reflect_delete_property as *const (), 2),
|
||||
("get", crate::builtins::reflect::reflect_get as *const (), 2),
|
||||
("apply", oxide_builtins::reflect::reflect_apply::<crate::vm::Vm> as *const (), 3),
|
||||
("construct", oxide_builtins::reflect::reflect_construct::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"getOwnPropertyDescriptor",
|
||||
crate::builtins::reflect::reflect_get_own_property_descriptor as *const (),
|
||||
"defineProperty",
|
||||
oxide_builtins::reflect::reflect_define_property::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
),
|
||||
(
|
||||
"deleteProperty",
|
||||
oxide_builtins::reflect::reflect_delete_property::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
("get", oxide_builtins::reflect::reflect_get::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"getOwnPropertyDescriptor",
|
||||
oxide_builtins::reflect::reflect_get_own_property_descriptor::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
(
|
||||
"getPrototypeOf",
|
||||
oxide_builtins::reflect::reflect_get_prototype_of::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
("has", oxide_builtins::reflect::reflect_has::<crate::vm::Vm> as *const (), 2),
|
||||
(
|
||||
"isExtensible",
|
||||
oxide_builtins::reflect::reflect_is_extensible::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
("ownKeys", oxide_builtins::reflect::reflect_own_keys::<crate::vm::Vm> as *const (), 1),
|
||||
(
|
||||
"preventExtensions",
|
||||
oxide_builtins::reflect::reflect_prevent_extensions::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
("set", oxide_builtins::reflect::reflect_set::<crate::vm::Vm> as *const (), 3),
|
||||
(
|
||||
"setPrototypeOf",
|
||||
oxide_builtins::reflect::reflect_set_prototype_of::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
),
|
||||
("getPrototypeOf", crate::builtins::reflect::reflect_get_prototype_of as *const (), 1),
|
||||
("has", crate::builtins::reflect::reflect_has as *const (), 2),
|
||||
("isExtensible", crate::builtins::reflect::reflect_is_extensible as *const (), 1),
|
||||
("ownKeys", crate::builtins::reflect::reflect_own_keys as *const (), 1),
|
||||
("preventExtensions", crate::builtins::reflect::reflect_prevent_extensions as *const (), 1),
|
||||
("set", crate::builtins::reflect::reflect_set as *const (), 3),
|
||||
("setPrototypeOf", crate::builtins::reflect::reflect_set_prototype_of as *const (), 2),
|
||||
],
|
||||
);
|
||||
bind_existing_global(core, global, "Reflect", JsValue::from_js_object(Box::into_raw(reflect)));
|
||||
@@ -175,26 +208,38 @@ fn bind_iterator_global(core: &Arc<KernelCore>, session: &KernelSession, global:
|
||||
let function_proto = session.builtin_world().function_proto.as_ptr() as *mut JsObject;
|
||||
let mut iterator = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(function_proto)));
|
||||
iterator.set_function(true);
|
||||
configure_native_constructor(&mut iterator, crate::builtins::iterator::iterator_constructor as *const (), 0);
|
||||
configure_native_constructor(
|
||||
&mut iterator,
|
||||
oxide_builtins::iterator::iterator_constructor::<crate::vm::Vm> as *const (),
|
||||
0,
|
||||
);
|
||||
apply_binding_table(
|
||||
session.builtin_world(),
|
||||
&mut iterator,
|
||||
core,
|
||||
&[("from", crate::builtins::iterator::iterator_from as *const (), 1)],
|
||||
&[("from", oxide_builtins::iterator::iterator_from::<crate::vm::Vm> as *const (), 1)],
|
||||
);
|
||||
bind_existing_global(core, global, "Iterator", JsValue::from_js_object(Box::into_raw(iterator)));
|
||||
}
|
||||
|
||||
fn bind_stub_globals(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
|
||||
for (index, (name, native_fn, arg_count)) in [
|
||||
("Proxy", crate::builtins::stubs::proxy_stub as *const (), 2),
|
||||
("BigInt", crate::builtins::stubs::bigint_stub as *const (), 1),
|
||||
("WeakMap", crate::builtins::stubs::weakmap_stub as *const (), 0),
|
||||
("WeakSet", crate::builtins::stubs::weakset_stub as *const (), 0),
|
||||
("WeakRef", crate::builtins::stubs::weakref_stub as *const (), 1),
|
||||
("FinalizationRegistry", crate::builtins::stubs::finalization_registry_stub as *const (), 1),
|
||||
("SharedArrayBuffer", crate::builtins::stubs::shared_array_buffer_stub as *const (), 1),
|
||||
("Atomics", crate::builtins::stubs::atomics_stub as *const (), 0),
|
||||
("Proxy", oxide_builtins::stubs::proxy_stub::<crate::vm::Vm> as *const (), 2),
|
||||
("BigInt", oxide_builtins::stubs::bigint_stub::<crate::vm::Vm> as *const (), 1),
|
||||
("WeakMap", oxide_builtins::stubs::weakmap_stub::<crate::vm::Vm> as *const (), 0),
|
||||
("WeakSet", oxide_builtins::stubs::weakset_stub::<crate::vm::Vm> as *const (), 0),
|
||||
("WeakRef", oxide_builtins::stubs::weakref_stub::<crate::vm::Vm> as *const (), 1),
|
||||
(
|
||||
"FinalizationRegistry",
|
||||
oxide_builtins::stubs::finalization_registry_stub::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
(
|
||||
"SharedArrayBuffer",
|
||||
oxide_builtins::stubs::shared_array_buffer_stub::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
),
|
||||
("Atomics", oxide_builtins::stubs::atomics_stub::<crate::vm::Vm> as *const (), 0),
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
@@ -209,26 +254,66 @@ fn bind_stub_globals(core: &Arc<KernelCore>, session: &KernelSession, global: &m
|
||||
pub fn bind_global_builtin_slots(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject) {
|
||||
let world = session.builtin_world();
|
||||
|
||||
configure_existing_ctor(&world.object_constructor, crate::builtins::object::object_constructor as *const (), 1);
|
||||
configure_existing_ctor(&world.array_constructor, crate::builtins::array::array_constructor as *const (), 1);
|
||||
configure_existing_ctor(
|
||||
&world.object_constructor,
|
||||
oxide_builtins::object::object_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.array_constructor,
|
||||
oxide_builtins::array::array_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.array_buffer_constructor,
|
||||
crate::builtins::array_buffer::array_buffer_constructor as *const (),
|
||||
oxide_builtins::array_buffer::array_buffer_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.data_view_constructor,
|
||||
crate::builtins::data_view::data_view_constructor as *const (),
|
||||
oxide_builtins::data_view::data_view_constructor::<crate::vm::Vm> as *const (),
|
||||
3,
|
||||
);
|
||||
configure_existing_ctor(&world.error_constructor, crate::builtins::error::error_constructor as *const (), 1);
|
||||
configure_existing_ctor(&world.number_constructor, crate::builtins::number::number_constructor as *const (), 1);
|
||||
configure_existing_ctor(&world.date_constructor, crate::builtins::date::date_constructor as *const (), 7);
|
||||
configure_existing_ctor(&world.set_constructor, crate::builtins::set::set_constructor as *const (), 1);
|
||||
configure_existing_ctor(&world.map_constructor, crate::builtins::map::map_constructor as *const (), 1);
|
||||
configure_existing_ctor(&world.boolean_constructor, crate::builtins::boolean::boolean_constructor as *const (), 1);
|
||||
configure_existing_ctor(&world.regexp_constructor, crate::builtins::regexp::regexp_constructor as *const (), 2);
|
||||
configure_existing_ctor(&world.symbol_constructor, crate::builtins::symbol::symbol_constructor as *const (), 1);
|
||||
configure_existing_ctor(
|
||||
&world.error_constructor,
|
||||
oxide_builtins::error::error_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.number_constructor,
|
||||
oxide_builtins::number::number_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.date_constructor,
|
||||
oxide_builtins::date::date_constructor::<crate::vm::Vm> as *const (),
|
||||
7,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.set_constructor,
|
||||
oxide_builtins::set::set_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.map_constructor,
|
||||
oxide_builtins::map::map_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.boolean_constructor,
|
||||
oxide_builtins::boolean::boolean_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.regexp_constructor,
|
||||
oxide_builtins::regexp::regexp_constructor::<crate::vm::Vm> as *const (),
|
||||
2,
|
||||
);
|
||||
configure_existing_ctor(
|
||||
&world.symbol_constructor,
|
||||
oxide_builtins::symbol::symbol_constructor::<crate::vm::Vm> as *const (),
|
||||
1,
|
||||
);
|
||||
|
||||
for (name, value) in [
|
||||
("Object", JsValue::from_js_object(world.object_constructor.as_ptr() as *mut JsObject)),
|
||||
@@ -258,57 +343,57 @@ pub fn bind_global_builtin_slots(core: &Arc<KernelCore>, session: &KernelSession
|
||||
(
|
||||
"Int8Array",
|
||||
&world.int8array_constructor,
|
||||
crate::builtins::typed_array::int8array_constructor as *const (),
|
||||
oxide_builtins::typed_array::int8array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"Uint8Array",
|
||||
&world.uint8array_constructor,
|
||||
crate::builtins::typed_array::uint8array_constructor as *const (),
|
||||
oxide_builtins::typed_array::uint8array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"Uint8ClampedArray",
|
||||
&world.uint8clampedarray_constructor,
|
||||
crate::builtins::typed_array::uint8clampedarray_constructor as *const (),
|
||||
oxide_builtins::typed_array::uint8clampedarray_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"Int16Array",
|
||||
&world.int16array_constructor,
|
||||
crate::builtins::typed_array::int16array_constructor as *const (),
|
||||
oxide_builtins::typed_array::int16array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"Uint16Array",
|
||||
&world.uint16array_constructor,
|
||||
crate::builtins::typed_array::uint16array_constructor as *const (),
|
||||
oxide_builtins::typed_array::uint16array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"Int32Array",
|
||||
&world.int32array_constructor,
|
||||
crate::builtins::typed_array::int32array_constructor as *const (),
|
||||
oxide_builtins::typed_array::int32array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"Uint32Array",
|
||||
&world.uint32array_constructor,
|
||||
crate::builtins::typed_array::uint32array_constructor as *const (),
|
||||
oxide_builtins::typed_array::uint32array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"Float32Array",
|
||||
&world.float32array_constructor,
|
||||
crate::builtins::typed_array::float32array_constructor as *const (),
|
||||
oxide_builtins::typed_array::float32array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"Float64Array",
|
||||
&world.float64array_constructor,
|
||||
crate::builtins::typed_array::float64array_constructor as *const (),
|
||||
oxide_builtins::typed_array::float64array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"BigInt64Array",
|
||||
&world.bigint64array_constructor,
|
||||
crate::builtins::typed_array::bigint64array_constructor as *const (),
|
||||
oxide_builtins::typed_array::bigint64array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
(
|
||||
"BigUint64Array",
|
||||
&world.biguint64array_constructor,
|
||||
crate::builtins::typed_array::biguint64array_constructor as *const (),
|
||||
oxide_builtins::typed_array::biguint64array_constructor::<crate::vm::Vm> as *const (),
|
||||
),
|
||||
] {
|
||||
configure_existing_ctor(ctor, native_fn, 1);
|
||||
@@ -321,7 +406,7 @@ pub fn bind_global_builtin_slots(core: &Arc<KernelCore>, session: &KernelSession
|
||||
global,
|
||||
"TypeError",
|
||||
&world.type_error_proto,
|
||||
crate::builtins::error::type_error_constructor as *const (),
|
||||
oxide_builtins::error::type_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_global(
|
||||
core,
|
||||
@@ -329,7 +414,7 @@ pub fn bind_global_builtin_slots(core: &Arc<KernelCore>, session: &KernelSession
|
||||
global,
|
||||
"ReferenceError",
|
||||
&world.reference_error_proto,
|
||||
crate::builtins::error::reference_error_constructor as *const (),
|
||||
oxide_builtins::error::reference_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_global(
|
||||
core,
|
||||
@@ -337,7 +422,7 @@ pub fn bind_global_builtin_slots(core: &Arc<KernelCore>, session: &KernelSession
|
||||
global,
|
||||
"RangeError",
|
||||
&world.range_error_proto,
|
||||
crate::builtins::error::range_error_constructor as *const (),
|
||||
oxide_builtins::error::range_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_global(
|
||||
core,
|
||||
@@ -345,7 +430,7 @@ pub fn bind_global_builtin_slots(core: &Arc<KernelCore>, session: &KernelSession
|
||||
global,
|
||||
"SyntaxError",
|
||||
&world.syntax_error_proto,
|
||||
crate::builtins::error::syntax_error_constructor as *const (),
|
||||
oxide_builtins::error::syntax_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_global(
|
||||
core,
|
||||
@@ -353,7 +438,7 @@ pub fn bind_global_builtin_slots(core: &Arc<KernelCore>, session: &KernelSession
|
||||
global,
|
||||
"URIError",
|
||||
&world.uri_error_proto,
|
||||
crate::builtins::error::uri_error_constructor as *const (),
|
||||
oxide_builtins::error::uri_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
bind_error_subtype_global(
|
||||
core,
|
||||
@@ -361,7 +446,7 @@ pub fn bind_global_builtin_slots(core: &Arc<KernelCore>, session: &KernelSession
|
||||
global,
|
||||
"EvalError",
|
||||
&world.eval_error_proto,
|
||||
crate::builtins::error::eval_error_constructor as *const (),
|
||||
oxide_builtins::error::eval_error_constructor::<crate::vm::Vm> as *const (),
|
||||
);
|
||||
|
||||
bind_reflect_global(core, session, global);
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::mem::P;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
|
||||
fn create_error_object(vm: &mut Vm, error_proto_ptr: *mut JsObject, name: &str, message: &str) -> JsValue {
|
||||
let obj = vm
|
||||
.epoch()
|
||||
.alloc(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(error_proto_ptr)));
|
||||
|
||||
let sf = Arc::clone(vm.kernel_core().perm_interner());
|
||||
let sh = Arc::clone(vm.kernel_core().shape_forge());
|
||||
|
||||
let si_message = sf.intern("message").0;
|
||||
let sh_message = sh.make_shape(EMPTY_SHAPE_ID, si_message);
|
||||
let msg_val = vm.new_string(message);
|
||||
unsafe {
|
||||
(*obj).set_shape_id(sh_message);
|
||||
(*obj).push_prop(msg_val);
|
||||
}
|
||||
|
||||
let si_name = sf.intern("name").0;
|
||||
let sh_name = sh.make_shape(sh_message, si_name);
|
||||
let name_val = vm.new_string(name);
|
||||
unsafe {
|
||||
(*obj).set_shape_id(sh_name);
|
||||
(*obj).push_prop(name_val);
|
||||
}
|
||||
|
||||
JsValue::from_js_object(obj)
|
||||
}
|
||||
|
||||
pub fn create_kind_error(vm: &mut Vm, kind: &str, msg: &str) -> JsValue {
|
||||
let proto_ptr = match kind {
|
||||
"TypeError" => P::as_ptr(&vm.session().builtin_world().type_error_proto) as *mut JsObject,
|
||||
"RangeError" => P::as_ptr(&vm.session().builtin_world().range_error_proto) as *mut JsObject,
|
||||
"ReferenceError" => P::as_ptr(&vm.session().builtin_world().reference_error_proto) as *mut JsObject,
|
||||
"SyntaxError" => P::as_ptr(&vm.session().builtin_world().syntax_error_proto) as *mut JsObject,
|
||||
"URIError" => P::as_ptr(&vm.session().builtin_world().uri_error_proto) as *mut JsObject,
|
||||
"EvalError" => P::as_ptr(&vm.session().builtin_world().eval_error_proto) as *mut JsObject,
|
||||
_ => P::as_ptr(&vm.session().builtin_world().error_proto) as *mut JsObject,
|
||||
};
|
||||
create_error_object(vm, proto_ptr, kind, msg)
|
||||
}
|
||||
|
||||
pub fn create_type_error(vm: &mut Vm, msg: &str) -> JsValue {
|
||||
create_kind_error(vm, "TypeError", msg)
|
||||
}
|
||||
|
||||
pub fn create_error(vm: &mut Vm, msg: &str) -> JsValue {
|
||||
create_kind_error(vm, "Error", msg)
|
||||
}
|
||||
|
||||
pub fn create_reference_error(vm: &mut Vm, msg: &str) -> JsValue {
|
||||
create_kind_error(vm, "ReferenceError", msg)
|
||||
}
|
||||
|
||||
pub fn create_range_error(vm: &mut Vm, msg: &str) -> JsValue {
|
||||
create_kind_error(vm, "RangeError", msg)
|
||||
}
|
||||
|
||||
pub fn create_syntax_error(vm: &mut Vm, msg: &str) -> JsValue {
|
||||
create_kind_error(vm, "SyntaxError", msg)
|
||||
}
|
||||
|
||||
pub fn create_uri_error(vm: &mut Vm, msg: &str) -> JsValue {
|
||||
create_kind_error(vm, "URIError", msg)
|
||||
}
|
||||
|
||||
fn get_msg(vm: &mut Vm, args: &[u8]) -> String {
|
||||
if args.len() > 1 {
|
||||
coercion::to_string(vm.reg(args[1]))
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(vm, args);
|
||||
let proto_ptr = P::as_ptr(&vm.session().builtin_world().error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(vm, proto_ptr, "Error", &msg))
|
||||
}
|
||||
|
||||
pub fn type_error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(vm, args);
|
||||
let proto_ptr = P::as_ptr(&vm.session().builtin_world().type_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(vm, proto_ptr, "TypeError", &msg))
|
||||
}
|
||||
|
||||
pub fn reference_error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(vm, args);
|
||||
let proto_ptr = P::as_ptr(&vm.session().builtin_world().reference_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(vm, proto_ptr, "ReferenceError", &msg))
|
||||
}
|
||||
|
||||
pub fn range_error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(vm, args);
|
||||
let proto_ptr = P::as_ptr(&vm.session().builtin_world().range_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(vm, proto_ptr, "RangeError", &msg))
|
||||
}
|
||||
|
||||
pub fn syntax_error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(vm, args);
|
||||
let proto_ptr = P::as_ptr(&vm.session().builtin_world().syntax_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(vm, proto_ptr, "SyntaxError", &msg))
|
||||
}
|
||||
|
||||
pub fn uri_error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(vm, args);
|
||||
let proto_ptr = P::as_ptr(&vm.session().builtin_world().uri_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(vm, proto_ptr, "URIError", &msg))
|
||||
}
|
||||
|
||||
pub fn eval_error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let msg = get_msg(vm, args);
|
||||
let proto_ptr = P::as_ptr(&vm.session().builtin_world().eval_error_proto) as *mut JsObject;
|
||||
NativeResult::Ok(create_error_object(vm, proto_ptr, "EvalError", &msg))
|
||||
}
|
||||
|
||||
pub fn error_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(args[0]);
|
||||
let (name, msg) = if this_val.is_object() {
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let name_val = obj
|
||||
.hash_props_vec()
|
||||
.and_then(|v| v.first())
|
||||
.copied()
|
||||
.unwrap_or(JsValue::undefined());
|
||||
let msg_val = obj
|
||||
.hash_props_vec()
|
||||
.and_then(|v| v.get(1))
|
||||
.copied()
|
||||
.unwrap_or(JsValue::undefined());
|
||||
(
|
||||
vm.lookup_str(name_val).unwrap_or_else(|| "Error".to_string()),
|
||||
vm.lookup_str(msg_val).unwrap_or_default(),
|
||||
)
|
||||
} else {
|
||||
("Error".to_string(), String::new())
|
||||
};
|
||||
let result = crate::vm::format_error_message(&name, &msg);
|
||||
NativeResult::Ok(vm.new_string(&result))
|
||||
}
|
||||
|
||||
pub fn error_stack_getter(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
let mut lines = vec![];
|
||||
for frame in vm.frames.iter().rev() {
|
||||
let func_name = vm
|
||||
.kernel_core()
|
||||
.perm_interner()
|
||||
.lookup(frame.function_name)
|
||||
.unwrap_or("<anonymous>");
|
||||
lines.push(format!(" at {} (native)", func_name));
|
||||
}
|
||||
lines.push(" at <anonymous> (native)".to_string());
|
||||
let result = lines.join("\n");
|
||||
NativeResult::Ok(vm.new_string(&result))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::error_stack_getter;
|
||||
use crate::vm::{CallFrame, FrameContinuation, Vm};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
#[test]
|
||||
fn error_stack_uses_call_frame_function_name() {
|
||||
let mut vm = Vm::new();
|
||||
let name_si = vm.kernel_core().perm_interner().intern("foo").0;
|
||||
vm.frames.push(CallFrame {
|
||||
return_addr: 0,
|
||||
function_name: name_si,
|
||||
caller_reg_limit: 1,
|
||||
saved_reg_offset: 0,
|
||||
saved_this: JsValue::undefined(),
|
||||
saved_new_target: JsValue::undefined(),
|
||||
callee: JsValue::undefined(),
|
||||
construct_result_reg: None,
|
||||
constructed_this: None,
|
||||
is_derived_constructor: false,
|
||||
continuation: FrameContinuation::None,
|
||||
});
|
||||
|
||||
let stack = error_stack_getter(&mut vm, &[0]).unwrap();
|
||||
let stack_str = vm.lookup_str(stack).unwrap_or_default();
|
||||
assert!(stack_str.contains("foo"), "expected function name in stack: {stack_str}");
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
|
||||
fn stub_error(vm: &mut Vm, name: &str) -> NativeResult {
|
||||
NativeResult::Err(crate::builtins::error::create_type_error(vm, &format!("{name} is not implemented")))
|
||||
}
|
||||
|
||||
// Architecturally deferred — these features are excluded from the supported language subset by design.
|
||||
pub fn proxy_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "Proxy")
|
||||
}
|
||||
pub fn bigint_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "BigInt")
|
||||
}
|
||||
pub fn weakmap_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "WeakMap")
|
||||
}
|
||||
pub fn weakset_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "WeakSet")
|
||||
}
|
||||
pub fn weakref_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "WeakRef")
|
||||
}
|
||||
pub fn finalization_registry_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "FinalizationRegistry")
|
||||
}
|
||||
pub fn shared_array_buffer_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "SharedArrayBuffer")
|
||||
}
|
||||
pub fn atomics_stub(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
stub_error(vm, "Atomics")
|
||||
}
|
||||
@@ -1,343 +0,0 @@
|
||||
use crate::vm::Vm;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::shape::EMPTY_SHAPE_ID;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
/// Borrow a string value's content. Caller must hold a valid string `JsValue`.
|
||||
///
|
||||
/// # Safety
|
||||
/// `val` must be a string `JsValue` whose `JsString` pointer is alive (session or
|
||||
/// permanent string) — the same contract as object-pointer derefs in the VM.
|
||||
#[inline]
|
||||
unsafe fn string_data(val: JsValue) -> &'static str {
|
||||
(*val.as_string_ptr()).as_str()
|
||||
}
|
||||
|
||||
/// Content equality of two string values: pointer identity → hash+len reject →
|
||||
/// byte compare. Replaces the old interner-index compare.
|
||||
#[inline]
|
||||
fn string_value_eq(a: JsValue, b: JsValue) -> bool {
|
||||
if a.as_string_ptr() == b.as_string_ptr() {
|
||||
return true;
|
||||
}
|
||||
// SAFETY: both are string JsValues; their JsString pointers are valid.
|
||||
let sa = unsafe { &*a.as_string_ptr() };
|
||||
let sb = unsafe { &*b.as_string_ptr() };
|
||||
sa.hash == sb.hash && sa.data == sb.data
|
||||
}
|
||||
|
||||
pub fn to_number(val: JsValue) -> f64 {
|
||||
if val.is_int() {
|
||||
return val.as_int() as f64;
|
||||
}
|
||||
if val.is_double() {
|
||||
return val.as_double();
|
||||
}
|
||||
if val.is_bool() {
|
||||
return if val.as_bool() { 1.0 } else { 0.0 };
|
||||
}
|
||||
if val.is_null() {
|
||||
return 0.0;
|
||||
}
|
||||
if val.is_undefined() {
|
||||
return f64::NAN;
|
||||
}
|
||||
if val.is_string() {
|
||||
// SAFETY: val is a string value.
|
||||
let s = unsafe { string_data(val) };
|
||||
return s.parse::<f64>().unwrap_or(f64::NAN);
|
||||
}
|
||||
if val.is_object() {
|
||||
return f64::NAN;
|
||||
}
|
||||
f64::NAN
|
||||
}
|
||||
|
||||
pub fn to_uint32(val: JsValue) -> u32 {
|
||||
let n = to_number(val);
|
||||
if n == 0.0 || !n.is_finite() {
|
||||
return 0;
|
||||
}
|
||||
n.trunc().rem_euclid(4_294_967_296.0) as u32
|
||||
}
|
||||
|
||||
pub fn to_int32(val: JsValue) -> i32 {
|
||||
let int = to_uint32(val);
|
||||
if int > i32::MAX as u32 {
|
||||
(int as i64 - 4_294_967_296i64) as i32
|
||||
} else {
|
||||
int as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(val: JsValue) -> String {
|
||||
if val.is_int() {
|
||||
return val.as_int().to_string();
|
||||
}
|
||||
if val.is_double() {
|
||||
let d = val.as_double();
|
||||
if d.is_nan() {
|
||||
return "NaN".to_string();
|
||||
}
|
||||
if d.is_infinite() {
|
||||
return if d.is_sign_positive() {
|
||||
"Infinity".to_string()
|
||||
} else {
|
||||
"-Infinity".to_string()
|
||||
};
|
||||
}
|
||||
if d.is_finite() && d.fract() == 0.0 {
|
||||
return (d as i64).to_string();
|
||||
}
|
||||
let mut buf = ryu::Buffer::new();
|
||||
return buf.format(d).to_string();
|
||||
}
|
||||
if val.is_bool() {
|
||||
return val.as_bool().to_string();
|
||||
}
|
||||
if val.is_null() {
|
||||
return "null".to_string();
|
||||
}
|
||||
if val.is_undefined() {
|
||||
return "undefined".to_string();
|
||||
}
|
||||
if val.is_string() {
|
||||
// SAFETY: val is a string value.
|
||||
return unsafe { string_data(val) }.to_string();
|
||||
}
|
||||
if val.is_object() {
|
||||
return "[object]".to_string();
|
||||
}
|
||||
String::new()
|
||||
}
|
||||
|
||||
pub fn to_boolean(val: JsValue) -> bool {
|
||||
if val.is_undefined() || val.is_null() {
|
||||
return false;
|
||||
}
|
||||
if val.is_bool() {
|
||||
return val.as_bool();
|
||||
}
|
||||
if val.is_int() {
|
||||
return val.as_int() != 0;
|
||||
}
|
||||
if val.is_double() {
|
||||
let d = val.as_double();
|
||||
return !(d == 0.0 || d == -0.0 || d.is_nan());
|
||||
}
|
||||
if val.is_string() {
|
||||
// SAFETY: val is a string value.
|
||||
return !unsafe { (*val.as_string_ptr()).is_empty() };
|
||||
}
|
||||
if val.is_object() {
|
||||
return true;
|
||||
}
|
||||
if val.is_symbol() {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn abstract_eq(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_null() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_string() && rhs.is_string() {
|
||||
return string_value_eq(lhs, rhs);
|
||||
}
|
||||
if lhs.is_int() && rhs.is_int() {
|
||||
return lhs.as_int() == rhs.as_int();
|
||||
}
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
return strict_double_eq(lhs.as_double(), rhs.as_double());
|
||||
}
|
||||
if lhs.is_bool() && rhs.is_bool() {
|
||||
return lhs.as_bool() == rhs.as_bool();
|
||||
}
|
||||
if lhs.is_null() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if (lhs.is_int() || lhs.is_double()) && (rhs.is_int() || rhs.is_double()) {
|
||||
return strict_double_eq(to_number(lhs), to_number(rhs));
|
||||
}
|
||||
if (lhs.is_int() || lhs.is_double()) && rhs.is_bool() {
|
||||
return to_number(lhs) == to_number(rhs);
|
||||
}
|
||||
if lhs.is_bool() && (rhs.is_int() || rhs.is_double()) {
|
||||
return to_number(lhs) == to_number(rhs);
|
||||
}
|
||||
if lhs.is_bool() || rhs.is_bool() {
|
||||
return to_number(lhs) == to_number(rhs);
|
||||
}
|
||||
if lhs.is_null() || rhs.is_null() {
|
||||
return false;
|
||||
}
|
||||
if lhs.is_object() || rhs.is_object() {
|
||||
return lhs.is_object() && rhs.is_object() && lhs.as_ptr() == rhs.as_ptr();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn strict_eq(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_int() && rhs.is_int() {
|
||||
return lhs.as_int() == rhs.as_int();
|
||||
}
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
return strict_double_eq(lhs.as_double(), rhs.as_double());
|
||||
}
|
||||
if lhs.is_bool() && rhs.is_bool() {
|
||||
return lhs.as_bool() == rhs.as_bool();
|
||||
}
|
||||
if lhs.is_null() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_string() && rhs.is_string() {
|
||||
return string_value_eq(lhs, rhs);
|
||||
}
|
||||
if lhs.is_object() && rhs.is_object() {
|
||||
return lhs.as_ptr() == rhs.as_ptr();
|
||||
}
|
||||
if lhs.is_symbol() && rhs.is_symbol() {
|
||||
return lhs.as_symbol_index() == rhs.as_symbol_index();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn strict_double_eq(a: f64, b: f64) -> bool {
|
||||
if a.is_nan() || b.is_nan() {
|
||||
return false;
|
||||
}
|
||||
a == b
|
||||
}
|
||||
|
||||
pub fn relational_compare(lhs: JsValue, rhs: JsValue) -> Option<bool> {
|
||||
if lhs.is_string() && rhs.is_string() {
|
||||
// SAFETY: both are string values.
|
||||
let ls = unsafe { string_data(lhs) };
|
||||
let rs = unsafe { string_data(rhs) };
|
||||
return Some(ls < rs);
|
||||
}
|
||||
let l = to_number(lhs);
|
||||
let r = to_number(rhs);
|
||||
if l.is_nan() || r.is_nan() {
|
||||
return None;
|
||||
}
|
||||
l.partial_cmp(&r).map(|o| o.is_lt())
|
||||
}
|
||||
|
||||
pub fn string_concat(lhs: &str, rhs: &str) -> String {
|
||||
let mut s = String::with_capacity(lhs.len() + rhs.len());
|
||||
s.push_str(lhs);
|
||||
s.push_str(rhs);
|
||||
s
|
||||
}
|
||||
|
||||
fn to_f64(val: JsValue) -> f64 {
|
||||
if val.is_int() {
|
||||
val.as_int() as f64
|
||||
} else if val.is_double() {
|
||||
val.as_double()
|
||||
} else {
|
||||
f64::NAN
|
||||
}
|
||||
}
|
||||
|
||||
pub fn same_value(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
let a = lhs.as_double();
|
||||
let b = rhs.as_double();
|
||||
if a.is_nan() && b.is_nan() {
|
||||
return true;
|
||||
}
|
||||
if a == 0.0 && b == 0.0 {
|
||||
let a_neg = a.is_sign_negative();
|
||||
let b_neg = b.is_sign_negative();
|
||||
return a_neg == b_neg;
|
||||
}
|
||||
return a == b;
|
||||
}
|
||||
if lhs.is_int() && rhs.is_int() {
|
||||
return lhs.as_int() == rhs.as_int();
|
||||
}
|
||||
if (lhs.is_int() || lhs.is_double()) && (rhs.is_int() || rhs.is_double()) {
|
||||
let a = to_f64(lhs);
|
||||
let b = to_f64(rhs);
|
||||
if a.is_nan() && b.is_nan() {
|
||||
return true;
|
||||
}
|
||||
if a == 0.0 && b == 0.0 {
|
||||
return a.is_sign_negative() == b.is_sign_negative();
|
||||
}
|
||||
return a == b;
|
||||
}
|
||||
if lhs.is_bool() && rhs.is_bool() {
|
||||
return lhs.as_bool() == rhs.as_bool();
|
||||
}
|
||||
if lhs.is_null() && rhs.is_null() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_undefined() && rhs.is_undefined() {
|
||||
return true;
|
||||
}
|
||||
if lhs.is_string() && rhs.is_string() {
|
||||
return string_value_eq(lhs, rhs);
|
||||
}
|
||||
if lhs.is_object() && rhs.is_object() {
|
||||
return lhs.as_ptr() == rhs.as_ptr();
|
||||
}
|
||||
if lhs.is_symbol() && rhs.is_symbol() {
|
||||
return lhs.as_symbol_index() == rhs.as_symbol_index();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn strict_equality(lhs: JsValue, rhs: JsValue) -> bool {
|
||||
if lhs.is_double() && rhs.is_double() {
|
||||
return strict_double_eq(lhs.as_double(), rhs.as_double());
|
||||
}
|
||||
same_value(lhs, rhs)
|
||||
}
|
||||
|
||||
pub fn to_object(val: JsValue, vm: &mut Vm) -> Result<JsValue, String> {
|
||||
if val.is_object() {
|
||||
return Ok(val);
|
||||
}
|
||||
if val.is_null() || val.is_undefined() {
|
||||
return Err(vm.error_message_text("TypeError", "Cannot convert null or undefined to object"));
|
||||
}
|
||||
let (proto_ptr, type_tag) = if val.is_string() {
|
||||
(
|
||||
vm.session().builtin_world().string_proto.as_ptr() as *mut JsObject,
|
||||
JsObject::OBJ_TYPE_STRING_OBJ,
|
||||
)
|
||||
} else if val.is_int() || val.is_double() {
|
||||
(
|
||||
vm.session().builtin_world().number_proto.as_ptr() as *mut JsObject,
|
||||
JsObject::OBJ_TYPE_NUMBER_OBJ,
|
||||
)
|
||||
} else if val.is_bool() {
|
||||
(
|
||||
vm.session().builtin_world().boolean_proto.as_ptr() as *mut JsObject,
|
||||
JsObject::OBJ_TYPE_BOOLEAN_OBJ,
|
||||
)
|
||||
} else {
|
||||
(&*vm.object_prototype as *const JsObject as *mut JsObject, JsObject::OBJ_TYPE_PLAIN)
|
||||
};
|
||||
let proto_val = JsValue::from_js_object(proto_ptr);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
|
||||
let obj_val = JsValue::from_js_object(obj);
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
obj_ref.type_tag = type_tag;
|
||||
obj_ref.ensure_hash_props().push(val);
|
||||
obj_ref.set_prop_count(1);
|
||||
Ok(obj_val)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api as coercion;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
impl Vm {
|
||||
|
||||
@@ -54,7 +54,7 @@ impl Vm {
|
||||
format!("{err_val}")
|
||||
};
|
||||
builtins_debug!("native_call err={}", msg);
|
||||
(crate::builtins::error::create_error(self, &msg), "Error")
|
||||
(oxide_builtins::error::create_error(self, &msg), "Error")
|
||||
};
|
||||
self.exception_value = Some(error);
|
||||
self.pending_error_kind = Some(kind);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api as coercion;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
impl Vm {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_bytecode::opcode::{self, Instr};
|
||||
use oxide_runtime_api as coercion;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
impl Vm {
|
||||
|
||||
@@ -2,8 +2,8 @@ use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_runtime_api as coercion;
|
||||
|
||||
impl Vm {
|
||||
pub(crate) fn dispatch_member_op(&mut self, op: OpCode, rd: usize, a: usize, b: usize) -> Result<(), String> {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#![doc = "OxideJS - Register-based VM with epoch arena memory"]
|
||||
|
||||
pub mod bindings;
|
||||
pub mod builtins;
|
||||
pub mod coercion;
|
||||
mod dispatch;
|
||||
mod ic_helper;
|
||||
pub mod native;
|
||||
|
||||
@@ -4,8 +4,8 @@ use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
use rustc_hash::FxBuildHasher;
|
||||
|
||||
use crate::builtins::{data_view, map, set, typed_array};
|
||||
use crate::vm::Vm;
|
||||
use oxide_builtins::{data_view, map, set, typed_array};
|
||||
|
||||
impl Vm {
|
||||
pub(crate) fn is_session_escape_root_ptr(&self, target_ptr: *mut JsObject) -> bool {
|
||||
|
||||
@@ -7,8 +7,8 @@ use oxide_types::object::{JsObject, JsString, PropMetaEntry};
|
||||
use oxide_types::value::JsValue;
|
||||
use rustc_hash::FxBuildHasher;
|
||||
|
||||
use crate::builtins::{array_buffer, data_view, map, regexp, set, typed_array};
|
||||
use crate::vm::Vm;
|
||||
use oxide_builtins::{array_buffer, data_view, map, regexp, set, typed_array};
|
||||
|
||||
pub struct SessionGc {
|
||||
pub total_collections: u64,
|
||||
@@ -502,8 +502,8 @@ mod tests {
|
||||
use oxide_types::object::JsObject;
|
||||
|
||||
use super::*;
|
||||
use crate::builtins::{array_buffer, data_view, map, set, typed_array};
|
||||
use crate::vm::{CallFrame, FrameContinuation};
|
||||
use oxide_builtins::{array_buffer, data_view, map, set, typed_array};
|
||||
use oxide_runtime_api::NativeResult;
|
||||
|
||||
fn plain_object(vm: &mut Vm) -> *mut JsObject {
|
||||
|
||||
+121
-3
@@ -7,15 +7,15 @@ use oxide_bytecode::opcode::{self, OpCode};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
pub use crate::bindings::init_kernel_builtins;
|
||||
use crate::coercion;
|
||||
use crate::native::NativeFn;
|
||||
use crate::session_gc::SessionGc;
|
||||
use crate::vm_state::{GcState, IterState, ProfilingState, SymbolState};
|
||||
use oxide_kernel::kernel::{KernelCore, KernelSession};
|
||||
use oxide_runtime_api as coercion;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_types::error::{JsError, JsErrorKind};
|
||||
use oxide_types::mem::{Epoch, P};
|
||||
use oxide_types::object::{JsObject, NativeFnPtr};
|
||||
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
pub(crate) const MAX_PROTO_CHAIN_DEPTH: usize = 1024;
|
||||
@@ -408,7 +408,7 @@ impl Vm {
|
||||
|
||||
pub(crate) fn raise_js_error(&mut self, err: JsError) -> Result<(), String> {
|
||||
let kind = js_error_kind_name(err.kind);
|
||||
let error = crate::builtins::error::create_kind_error(self, kind, &err.message);
|
||||
let error = oxide_builtins::error::create_kind_error(self, kind, &err.message);
|
||||
self.exception_value = Some(error);
|
||||
self.pending_error_kind = Some(kind);
|
||||
self.unwind()
|
||||
@@ -1457,3 +1457,121 @@ mod tests {
|
||||
assert_eq!(vm.reg(255), JsValue::int(13));
|
||||
}
|
||||
}
|
||||
|
||||
impl oxide_runtime_api::VmHost for Vm {
|
||||
fn reg(&self, idx: u8) -> JsValue {
|
||||
self.reg(idx)
|
||||
}
|
||||
fn set_reg(&mut self, idx: u8, val: JsValue) {
|
||||
self.set_reg(idx, val);
|
||||
}
|
||||
fn alloc_object(&mut self, obj: JsObject) -> *mut JsObject {
|
||||
self.alloc_object(obj)
|
||||
}
|
||||
fn new_string(&mut self, s: &str) -> JsValue {
|
||||
self.new_string(s)
|
||||
}
|
||||
fn kernel_core(&self) -> &Arc<KernelCore> {
|
||||
self.kernel_core()
|
||||
}
|
||||
fn session(&self) -> &KernelSession {
|
||||
self.session()
|
||||
}
|
||||
fn epoch(&self) -> &Epoch {
|
||||
self.epoch()
|
||||
}
|
||||
fn property_key_si(&mut self, val: JsValue) -> u32 {
|
||||
self.property_key_si(val)
|
||||
}
|
||||
fn resolve_property(&self, obj: &JsObject, prop_name_si: u32) -> Option<JsValue> {
|
||||
self.resolve_property(obj, prop_name_si)
|
||||
}
|
||||
fn get_own_property_slot(&self, obj: &JsObject, prop_name_si: u32) -> Option<u32> {
|
||||
self.get_own_property_slot(obj, prop_name_si)
|
||||
}
|
||||
fn ordinary_get(&mut self, obj: &JsObject, prop_name_si: u32, receiver: JsValue) -> Result<JsValue, String> {
|
||||
self.ordinary_get(obj, prop_name_si, receiver)
|
||||
}
|
||||
fn ordinary_set(
|
||||
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue,
|
||||
) -> Result<(), String> {
|
||||
self.ordinary_set(obj, prop_name_si, val, receiver)
|
||||
}
|
||||
fn define_data_property(
|
||||
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, attributes: PropAttributes,
|
||||
) -> Result<(), String> {
|
||||
self.define_data_property(obj, prop_name_si, val, attributes)
|
||||
}
|
||||
fn define_accessor_property(
|
||||
&mut self, obj: &mut JsObject, prop_name_si: u32, get: JsValue, set: JsValue, attributes: PropAttributes,
|
||||
) -> Result<(), String> {
|
||||
self.define_accessor_property(obj, prop_name_si, get, set, attributes)
|
||||
}
|
||||
fn set_or_create_prop_value(&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue) {
|
||||
self.set_or_create_prop_value(obj, prop_name_si, val)
|
||||
}
|
||||
fn lookup_str(&self, val: JsValue) -> Option<String> {
|
||||
self.lookup_str(val)
|
||||
}
|
||||
fn coerce_primitive_bounded(&mut self, value: JsValue, prefer_string: bool) -> Result<JsValue, String> {
|
||||
self.coerce_primitive_bounded(value, prefer_string)
|
||||
}
|
||||
fn coerce_number_bounded(&mut self, value: JsValue) -> Result<f64, String> {
|
||||
self.coerce_number_bounded(value)
|
||||
}
|
||||
fn call_function_sync(&mut self, callee: JsValue, receiver: JsValue, args: &[JsValue]) -> Result<JsValue, String> {
|
||||
self.call_function_sync(callee, receiver, args)
|
||||
}
|
||||
fn checked_object_ptr(&mut self, val: JsValue, error_msg: &str) -> Result<Option<*mut JsObject>, String> {
|
||||
self.checked_object_ptr(val, error_msg)
|
||||
}
|
||||
fn raise_type_error(&mut self, msg: &str) -> Result<(), String> {
|
||||
self.raise_type_error(msg)
|
||||
}
|
||||
fn error_message_text(&self, kind: &str, msg: &str) -> String {
|
||||
self.error_message_text(kind, msg)
|
||||
}
|
||||
fn call_stack_function_names(&self) -> Vec<String> {
|
||||
self.frames
|
||||
.iter()
|
||||
.rev()
|
||||
.map(|f| {
|
||||
self.kernel_core
|
||||
.perm_interner()
|
||||
.lookup(f.function_name)
|
||||
.unwrap_or("<anonymous>")
|
||||
.to_string()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
fn promote_if_needed_for_write_ptr(&mut self, target_ptr: *mut JsObject, value: JsValue) -> JsValue {
|
||||
self.promote_if_needed_for_write_ptr(target_ptr, value)
|
||||
}
|
||||
fn step_rng(&mut self) {
|
||||
self.step_rng()
|
||||
}
|
||||
fn math_rng_value(&self) -> f64 {
|
||||
self.math_rng_value()
|
||||
}
|
||||
fn sub_module_function_name(&self, sub_idx: u16) -> String {
|
||||
self.sub_modules
|
||||
.get(sub_idx as usize)
|
||||
.and_then(|m| m.function_name.clone())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
fn symbol_intern(&mut self, desc: String) -> u32 {
|
||||
self.symbols.intern(desc)
|
||||
}
|
||||
fn symbol_description(&self, idx: u32) -> Option<&str> {
|
||||
self.symbols.description(idx)
|
||||
}
|
||||
fn symbol_lookup_global(&self, key: &str) -> Option<u32> {
|
||||
self.symbols.lookup_global(key)
|
||||
}
|
||||
fn symbol_register_global(&mut self, key: String, idx: u32) {
|
||||
self.symbols.register_global(key, idx)
|
||||
}
|
||||
fn symbol_key_for_id(&self, idx: u32) -> Option<String> {
|
||||
self.symbols.key_for_id(idx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
|
||||
use crate::native::NativeFn;
|
||||
use crate::vm::{native_fn_ptr_to_fn, CallFrame, ForInIter, FrameContinuation, Vm, MAX_PROTO_CHAIN_DEPTH};
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_runtime_api::{to_boolean, NativeResult};
|
||||
use oxide_types::object::{JsObject, PropAttributes};
|
||||
use oxide_types::private_key::is_private_name_key;
|
||||
use oxide_types::value::JsValue;
|
||||
@@ -155,7 +155,7 @@ impl Vm {
|
||||
Ok(true)
|
||||
} else {
|
||||
let error =
|
||||
crate::builtins::error::create_error(self, "NEW_EXPRESSION: bytecode constructors not yet supported");
|
||||
oxide_builtins::error::create_error(self, "NEW_EXPRESSION: bytecode constructors not yet supported");
|
||||
self.exception_value = Some(error);
|
||||
self.pending_error_kind = Some(self.thrown_error_kind(error));
|
||||
self.unwind().map(|_| true)
|
||||
@@ -344,7 +344,7 @@ impl Vm {
|
||||
|
||||
pub(crate) fn dispatch_for_of_init(&mut self, a: usize) -> Result<(), String> {
|
||||
let iterable = self.regs[a];
|
||||
match crate::builtins::iterator::make_iterator_for_value(self, iterable) {
|
||||
match oxide_builtins::iterator::make_iterator_for_value(self, iterable) {
|
||||
Ok(iterator) => {
|
||||
self.iters.push_for_of(iterator);
|
||||
self.iters.clear_last_for_of_result();
|
||||
@@ -377,7 +377,7 @@ impl Vm {
|
||||
let result_obj = unsafe { &*result.as_js_object_ptr() };
|
||||
let done_si = self.kernel_core.perm_interner().intern("done").0;
|
||||
let done_val = self.ordinary_get(result_obj, done_si, result)?;
|
||||
let done = crate::coercion::to_boolean(done_val);
|
||||
let done = to_boolean(done_val);
|
||||
self.iters.set_last_for_of_result(result);
|
||||
self.regs[rd] = JsValue::bool(!done);
|
||||
Ok(())
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::coercion;
|
||||
use crate::vm::{FrameContinuation, Vm, MAX_PROTO_CHAIN_DEPTH};
|
||||
use oxide_runtime_api as coercion;
|
||||
use oxide_types::object::{JsObject, PropAttributes, PropMetaEntry};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use oxide_builtins::array::{array_constructor, array_push};
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::builtins::array::{array_constructor, array_push};
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
fn eval(source: &str) -> Result<(Vm, JsValue), String> {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use oxide_builtins::boolean::{boolean_constructor, boolean_prototype_to_string, boolean_prototype_value_of};
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::builtins::boolean::{boolean_constructor, boolean_prototype_to_string, boolean_prototype_value_of};
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use oxide_builtins::error;
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::builtins::error;
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
fn make_vm() -> Vm {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use oxide_builtins::map::{map_clear, map_constructor as new_map, map_delete, map_get, map_has, map_set, map_size};
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::builtins::map::{map_clear, map_constructor as new_map, map_delete, map_get, map_has, map_set, map_size};
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use oxide_builtins::set::{set_add, set_clear, set_constructor as new_set, set_delete, set_has, set_size};
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::builtins::set::{set_add, set_clear, set_constructor as new_set, set_delete, set_has, set_size};
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use oxide_compiler::compiler::Compiler;
|
||||
use oxide_parser::Allocator;
|
||||
use oxide_runtime_api as coercion;
|
||||
use oxide_types::value::JsValue;
|
||||
use oxide_vm::coercion;
|
||||
use oxide_vm::vm::Vm;
|
||||
|
||||
fn eval(source: &str) -> String {
|
||||
|
||||
Reference in New Issue
Block a user