feat: 为 Array/String 原型方法添加入口和错误路径结构化日志,编译器添加阶段边界日志
This commit is contained in:
@@ -4,11 +4,17 @@ use oxide_types::value::JsValue;
|
|||||||
|
|
||||||
use oxide_runtime_api::{NativeResult, VmHost};
|
use oxide_runtime_api::{NativeResult, VmHost};
|
||||||
|
|
||||||
|
use crate::builtins_debug;
|
||||||
|
use crate::builtins_error;
|
||||||
|
|
||||||
macro_rules! array_ptr {
|
macro_rules! array_ptr {
|
||||||
($vm:expr, $args:expr) => {{
|
($vm:expr, $args:expr) => {{
|
||||||
match get_this_array_ref($vm, $vm.reg($args[0])) {
|
match get_this_array_ref($vm, $vm.reg($args[0])) {
|
||||||
Ok(ptr) => ptr,
|
Ok(ptr) => ptr,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array method: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@@ -158,6 +164,7 @@ pub fn array_is_array<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_push<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_push<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.push called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let mut len = unsafe { &*arr_ptr }.prop_count();
|
let mut len = unsafe { &*arr_ptr }.prop_count();
|
||||||
for &arg_reg in args.iter().skip(1) {
|
for &arg_reg in args.iter().skip(1) {
|
||||||
@@ -170,6 +177,7 @@ pub fn array_push<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_pop<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_pop<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.pop called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &mut *arr_ptr };
|
let arr = unsafe { &mut *arr_ptr };
|
||||||
let len = arr.prop_count();
|
let len = arr.prop_count();
|
||||||
@@ -182,6 +190,7 @@ pub fn array_pop<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.slice called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &*arr_ptr };
|
let arr = unsafe { &*arr_ptr };
|
||||||
let n = arr.prop_count() as usize;
|
let n = arr.prop_count() as usize;
|
||||||
@@ -210,6 +219,7 @@ pub fn array_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_splice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_splice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.splice called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &mut *arr_ptr };
|
let arr = unsafe { &mut *arr_ptr };
|
||||||
let n = arr.prop_count() as usize;
|
let n = arr.prop_count() as usize;
|
||||||
@@ -272,6 +282,7 @@ pub fn array_splice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_concat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_concat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.concat called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &*arr_ptr };
|
let arr = unsafe { &*arr_ptr };
|
||||||
let n = arr.prop_count() as usize;
|
let n = arr.prop_count() as usize;
|
||||||
@@ -307,6 +318,7 @@ pub fn array_concat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_join<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_join<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.join called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &*arr_ptr };
|
let arr = unsafe { &*arr_ptr };
|
||||||
let n = arr.prop_count() as usize;
|
let n = arr.prop_count() as usize;
|
||||||
@@ -331,6 +343,7 @@ pub fn array_join<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.indexOf called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &*arr_ptr };
|
let arr = unsafe { &*arr_ptr };
|
||||||
let n = arr.prop_count() as usize;
|
let n = arr.prop_count() as usize;
|
||||||
@@ -347,6 +360,7 @@ pub fn array_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_includes<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_includes<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.includes called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &*arr_ptr };
|
let arr = unsafe { &*arr_ptr };
|
||||||
let n = arr.prop_count() as usize;
|
let n = arr.prop_count() as usize;
|
||||||
@@ -371,6 +385,7 @@ pub fn array_includes<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_reverse<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_reverse<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.reverse called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &mut *arr_ptr };
|
let arr = unsafe { &mut *arr_ptr };
|
||||||
let n = arr.prop_count() as usize;
|
let n = arr.prop_count() as usize;
|
||||||
@@ -387,6 +402,7 @@ pub fn array_reverse<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_flat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_flat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.flat called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &*arr_ptr };
|
let arr = unsafe { &*arr_ptr };
|
||||||
let n = arr.prop_count() as usize;
|
let n = arr.prop_count() as usize;
|
||||||
@@ -443,34 +459,50 @@ pub fn array_flat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_for_each<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_for_each<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.forEach called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.forEach: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.forEach: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let elem = unsafe { (*arr_ptr).get_prop_at(i) };
|
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])]) {
|
match invoke_native_callback(vm, callback_val, this_val, &[elem, JsValue::int(i as i32), vm.reg(args[0])]) {
|
||||||
NativeResult::Ok(_) => {}
|
NativeResult::Ok(_) => {}
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.forEach: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.forEach: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Ok(JsValue::undefined())
|
NativeResult::Ok(JsValue::undefined())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.map called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.map: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.map: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
let new_arr = create_new_array(vm, n);
|
let new_arr = create_new_array(vm, n);
|
||||||
@@ -480,8 +512,14 @@ pub fn array_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
NativeResult::Ok(mapped) => unsafe {
|
NativeResult::Ok(mapped) => unsafe {
|
||||||
(*new_arr).set_prop_at(i, mapped);
|
(*new_arr).set_prop_at(i, mapped);
|
||||||
},
|
},
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.map: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.map: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -491,13 +529,18 @@ pub fn array_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_filter<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_filter<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.filter called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.filter: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.filter: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
let mut kept: Vec<JsValue> = Vec::new();
|
let mut kept: Vec<JsValue> = Vec::new();
|
||||||
@@ -509,8 +552,14 @@ pub fn array_filter<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
kept.push(elem);
|
kept.push(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.filter: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.filter: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let new_arr = create_new_array(vm, kept.len());
|
let new_arr = create_new_array(vm, kept.len());
|
||||||
@@ -524,16 +573,22 @@ pub fn array_filter<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_reduce<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_reduce<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.reduce called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if n == 0 && args.len() < 3 {
|
if n == 0 && args.len() < 3 {
|
||||||
|
builtins_error!("Array.prototype.reduce: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "Reduce of empty array with no initial value"));
|
return NativeResult::Err(array_type_error(vm, "Reduce of empty array with no initial value"));
|
||||||
}
|
}
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.reduce: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.reduce: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let has_initial = args.len() > 2;
|
let has_initial = args.len() > 2;
|
||||||
let mut accumulator;
|
let mut accumulator;
|
||||||
@@ -555,21 +610,32 @@ pub fn array_reduce<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
&[accumulator, elem, JsValue::int(i as i32), vm.reg(args[0])],
|
&[accumulator, elem, JsValue::int(i as i32), vm.reg(args[0])],
|
||||||
) {
|
) {
|
||||||
NativeResult::Ok(result) => accumulator = result,
|
NativeResult::Ok(result) => accumulator = result,
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.reduce: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.reduce: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Ok(accumulator)
|
NativeResult::Ok(accumulator)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_find<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_find<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.find called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.find: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.find: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
@@ -580,21 +646,32 @@ pub fn array_find<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
return NativeResult::Ok(elem);
|
return NativeResult::Ok(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.find: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.find: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Ok(JsValue::undefined())
|
NativeResult::Ok(JsValue::undefined())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_some<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_some<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.some called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.some: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.some: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
@@ -605,21 +682,32 @@ pub fn array_some<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
return NativeResult::Ok(JsValue::bool(true));
|
return NativeResult::Ok(JsValue::bool(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.some: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.some: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Ok(JsValue::bool(false))
|
NativeResult::Ok(JsValue::bool(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_every<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_every<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.every called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.every: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.every: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
@@ -630,21 +718,32 @@ pub fn array_every<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
return NativeResult::Ok(JsValue::bool(false));
|
return NativeResult::Ok(JsValue::bool(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.every: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.every: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Ok(JsValue::bool(true))
|
NativeResult::Ok(JsValue::bool(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_flat_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_flat_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.flatMap called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.flatMap: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.flatMap: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
let mut flat: Vec<JsValue> = Vec::new();
|
let mut flat: Vec<JsValue> = Vec::new();
|
||||||
@@ -667,8 +766,14 @@ pub fn array_flat_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
flat.push(result);
|
flat.push(result);
|
||||||
}
|
}
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.flatMap: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.flatMap: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let new_arr = create_new_array(vm, flat.len());
|
let new_arr = create_new_array(vm, flat.len());
|
||||||
@@ -682,6 +787,7 @@ pub fn array_flat_map<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_shift<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_shift<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.shift called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &mut *arr_ptr };
|
let arr = unsafe { &mut *arr_ptr };
|
||||||
let len = arr.prop_count();
|
let len = arr.prop_count();
|
||||||
@@ -698,6 +804,7 @@ pub fn array_shift<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_unshift<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_unshift<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.unshift called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &mut *arr_ptr };
|
let arr = unsafe { &mut *arr_ptr };
|
||||||
let len = arr.prop_count();
|
let len = arr.prop_count();
|
||||||
@@ -715,6 +822,7 @@ pub fn array_unshift<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_fill<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_fill<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.fill called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &mut *arr_ptr };
|
let arr = unsafe { &mut *arr_ptr };
|
||||||
let len = arr.prop_count() as usize;
|
let len = arr.prop_count() as usize;
|
||||||
@@ -737,6 +845,7 @@ pub fn array_fill<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_copy_within<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_copy_within<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.copyWithin called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &mut *arr_ptr };
|
let arr = unsafe { &mut *arr_ptr };
|
||||||
let len = arr.prop_count() as usize;
|
let len = arr.prop_count() as usize;
|
||||||
@@ -771,6 +880,7 @@ pub fn array_copy_within<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.at called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &*arr_ptr };
|
let arr = unsafe { &*arr_ptr };
|
||||||
let len = arr.prop_count() as i32;
|
let len = arr.prop_count() as i32;
|
||||||
@@ -789,6 +899,7 @@ pub fn array_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_last_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_last_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.lastIndexOf called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let arr = unsafe { &*arr_ptr };
|
let arr = unsafe { &*arr_ptr };
|
||||||
let len = arr.prop_count() as i32;
|
let len = arr.prop_count() as i32;
|
||||||
@@ -802,13 +913,18 @@ pub fn array_last_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_find_index<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_find_index<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.findIndex called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.findIndex: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.findIndex: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
@@ -819,24 +935,35 @@ pub fn array_find_index<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
return NativeResult::Ok(JsValue::int(i as i32));
|
return NativeResult::Ok(JsValue::int(i as i32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.findIndex: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.findIndex: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Ok(JsValue::int(-1))
|
NativeResult::Ok(JsValue::int(-1))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_find_last<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_find_last<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.findLast called with {} args", args.len());
|
||||||
let (arr_ptr, n) = {
|
let (arr_ptr, n) = {
|
||||||
let (arr_ptr, len) = array_ptr_len!(vm, args);
|
let (arr_ptr, len) = array_ptr_len!(vm, args);
|
||||||
(arr_ptr, len as i32)
|
(arr_ptr, len as i32)
|
||||||
};
|
};
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.findLast: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.findLast: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let this_val = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
for i in (0..n).rev() {
|
for i in (0..n).rev() {
|
||||||
@@ -847,26 +974,38 @@ pub fn array_find_last<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
return NativeResult::Ok(elem);
|
return NativeResult::Ok(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.findLast: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.findLast: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Ok(JsValue::undefined())
|
NativeResult::Ok(JsValue::undefined())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_reduce_right<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_reduce_right<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.reduceRight called with {} args", args.len());
|
||||||
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
let (arr_ptr, n) = array_ptr_len!(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("Array.prototype.reduceRight: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
return NativeResult::Err(array_type_error(vm, "callback is not a function"));
|
||||||
}
|
}
|
||||||
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
let callback_val = match require_callback(vm, vm.reg(args[1])) {
|
||||||
Ok(callback) => callback,
|
Ok(callback) => callback,
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.reduceRight: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let (mut acc, start_idx): (JsValue, i32) = if args.len() > 2 {
|
let (mut acc, start_idx): (JsValue, i32) = if args.len() > 2 {
|
||||||
(vm.reg(args[2]), n as i32 - 1)
|
(vm.reg(args[2]), n as i32 - 1)
|
||||||
} else {
|
} else {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
|
builtins_error!("Array.prototype.reduceRight: invalid receiver");
|
||||||
return NativeResult::Err(array_type_error(vm, "Reduce of empty array with no initial value"));
|
return NativeResult::Err(array_type_error(vm, "Reduce of empty array with no initial value"));
|
||||||
}
|
}
|
||||||
(unsafe { (*arr_ptr).get_prop_at(n - 1) }, n as i32 - 2)
|
(unsafe { (*arr_ptr).get_prop_at(n - 1) }, n as i32 - 2)
|
||||||
@@ -880,14 +1019,21 @@ pub fn array_reduce_right<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
&[acc, elem, JsValue::int(i), vm.reg(args[0])],
|
&[acc, elem, JsValue::int(i), vm.reg(args[0])],
|
||||||
) {
|
) {
|
||||||
NativeResult::Ok(r) => acc = r,
|
NativeResult::Ok(r) => acc = r,
|
||||||
NativeResult::Err(err) => return NativeResult::Err(err),
|
NativeResult::Err(err) => {
|
||||||
NativeResult::TailCall { .. } => return unexpected_tail_call_error(vm),
|
builtins_error!("Array.prototype.reduceRight: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
|
NativeResult::TailCall { .. } => {
|
||||||
|
builtins_error!("Array.prototype.reduceRight: invalid receiver");
|
||||||
|
return unexpected_tail_call_error(vm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeResult::Ok(acc)
|
NativeResult::Ok(acc)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_sort<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_sort<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.sort called with {} args", args.len());
|
||||||
let arr_ptr = array_ptr!(vm, args);
|
let arr_ptr = array_ptr!(vm, args);
|
||||||
let len = unsafe { (*arr_ptr).prop_count() as usize };
|
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();
|
let mut vals: Vec<JsValue> = (0..len).map(|i| unsafe { (*arr_ptr).get_prop_at(i) }).collect();
|
||||||
@@ -898,7 +1044,10 @@ pub fn array_sort<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
} else {
|
} else {
|
||||||
match require_callback(vm, candidate) {
|
match require_callback(vm, candidate) {
|
||||||
Ok(callback) => Some(callback),
|
Ok(callback) => Some(callback),
|
||||||
Err(err) => return NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.sort: invalid receiver");
|
||||||
|
return NativeResult::Err(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -937,6 +1086,7 @@ pub fn array_sort<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if let Some(err) = sort_error {
|
if let Some(err) = sort_error {
|
||||||
|
builtins_error!("Array.prototype.sort: invalid receiver");
|
||||||
return NativeResult::Err(err);
|
return NativeResult::Err(err);
|
||||||
}
|
}
|
||||||
let arr = unsafe { &mut *arr_ptr };
|
let arr = unsafe { &mut *arr_ptr };
|
||||||
@@ -947,9 +1097,13 @@ pub fn array_sort<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn array_values<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_values<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("Array.prototype.values called with {} args", args.len());
|
||||||
let this_val = vm.reg(args[0]);
|
let this_val = vm.reg(args[0]);
|
||||||
match crate::iterator::make_iterator_for_value(vm, this_val) {
|
match crate::iterator::make_iterator_for_value(vm, this_val) {
|
||||||
Ok(iterator) => NativeResult::Ok(iterator),
|
Ok(iterator) => NativeResult::Ok(iterator),
|
||||||
Err(err) => NativeResult::Err(err),
|
Err(err) => {
|
||||||
|
builtins_error!("Array.prototype.values: invalid receiver");
|
||||||
|
NativeResult::Err(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,15 @@ use oxide_types::value::JsValue;
|
|||||||
use memchr::memchr;
|
use memchr::memchr;
|
||||||
use oxide_runtime_api::{NativeResult, VmHost};
|
use oxide_runtime_api::{NativeResult, VmHost};
|
||||||
|
|
||||||
|
use crate::builtins_debug;
|
||||||
|
use crate::builtins_error;
|
||||||
|
|
||||||
fn this_string<H: VmHost>(vm: &H, args: &[u8]) -> String {
|
fn this_string<H: VmHost>(vm: &H, args: &[u8]) -> String {
|
||||||
oxide_runtime_api::to_string(vm.reg(args[0]))
|
oxide_runtime_api::to_string(vm.reg(args[0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_from_char_code<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_from_char_code<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.fromCharCode called with {} args", args.len());
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
for &arg_reg in args.iter().skip(1) {
|
for &arg_reg in args.iter().skip(1) {
|
||||||
let code = oxide_runtime_api::to_uint32(vm.reg(arg_reg)) & 0xFFFF;
|
let code = oxide_runtime_api::to_uint32(vm.reg(arg_reg)) & 0xFFFF;
|
||||||
@@ -23,6 +27,7 @@ pub fn string_from_char_code<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_value_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_value_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.valueOf called with {} args", args.len());
|
||||||
let this_val = vm.reg(args[0]);
|
let this_val = vm.reg(args[0]);
|
||||||
if this_val.is_string() {
|
if this_val.is_string() {
|
||||||
return NativeResult::Ok(this_val);
|
return NativeResult::Ok(this_val);
|
||||||
@@ -36,6 +41,7 @@ pub fn string_value_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
builtins_error!("String.prototype.valueOf: invalid receiver");
|
||||||
NativeResult::Err(crate::error::create_type_error(
|
NativeResult::Err(crate::error::create_type_error(
|
||||||
vm,
|
vm,
|
||||||
"String.prototype.valueOf called on non-String object",
|
"String.prototype.valueOf called on non-String object",
|
||||||
@@ -157,6 +163,7 @@ fn is_regexp_obj<H: VmHost>(val: JsValue, vm: &H) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.indexOf called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let n = char_len(&s);
|
let n = char_len(&s);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
@@ -188,6 +195,7 @@ pub fn string_index_of<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_includes<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_includes<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.includes called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let n = char_len(&s);
|
let n = char_len(&s);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
@@ -213,6 +221,7 @@ pub fn string_includes<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_char_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_char_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.charAt called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
@@ -229,6 +238,7 @@ pub fn string_char_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_char_code_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_char_code_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.charCodeAt called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
@@ -244,6 +254,7 @@ pub fn string_char_code_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_concat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_concat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.concat called with {} args", args.len());
|
||||||
let mut result = this_string(vm, args);
|
let mut result = this_string(vm, args);
|
||||||
for &arg_reg in args.iter().skip(1) {
|
for &arg_reg in args.iter().skip(1) {
|
||||||
result.push_str(&oxide_runtime_api::to_string(vm.reg(arg_reg)));
|
result.push_str(&oxide_runtime_api::to_string(vm.reg(arg_reg)));
|
||||||
@@ -252,6 +263,7 @@ pub fn string_concat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.slice called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let n = char_len(&s) as i32;
|
let n = char_len(&s) as i32;
|
||||||
let start = if args.len() > 1 {
|
let start = if args.len() > 1 {
|
||||||
@@ -281,6 +293,7 @@ pub fn string_slice<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_substring<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_substring<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.substring called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let n = char_len(&s) as i32;
|
let n = char_len(&s) as i32;
|
||||||
let mut start = if args.len() > 1 {
|
let mut start = if args.len() > 1 {
|
||||||
@@ -301,21 +314,25 @@ pub fn string_substring<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_to_upper_case<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_to_upper_case<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.toUpperCase called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
NativeResult::Ok(vm.new_string(&s.to_uppercase()))
|
NativeResult::Ok(vm.new_string(&s.to_uppercase()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_to_lower_case<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_to_lower_case<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.toLowerCase called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
NativeResult::Ok(vm.new_string(&s.to_lowercase()))
|
NativeResult::Ok(vm.new_string(&s.to_lowercase()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_trim<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_trim<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.trim called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
NativeResult::Ok(vm.new_string(s.trim()))
|
NativeResult::Ok(vm.new_string(s.trim()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_repeat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_repeat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.repeat called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let n = if args.len() > 1 {
|
let n = if args.len() > 1 {
|
||||||
(oxide_runtime_api::to_number(vm.reg(args[1])) as usize).min(10000)
|
(oxide_runtime_api::to_number(vm.reg(args[1])) as usize).min(10000)
|
||||||
@@ -326,6 +343,7 @@ pub fn string_repeat<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_pad_start<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_pad_start<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.padStart called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let s_len = char_len(&s);
|
let s_len = char_len(&s);
|
||||||
let target = if args.len() > 1 {
|
let target = if args.len() > 1 {
|
||||||
@@ -334,6 +352,7 @@ pub fn string_pad_start<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
s_len
|
s_len
|
||||||
};
|
};
|
||||||
if target > 10000 {
|
if target > 10000 {
|
||||||
|
builtins_error!("String.prototype.padStart: invalid receiver");
|
||||||
return NativeResult::Err(crate::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() };
|
let pad = if args.len() > 2 { as_string(vm, vm.reg(args[2])) } else { " ".to_string() };
|
||||||
@@ -349,6 +368,7 @@ pub fn string_pad_start<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_pad_end<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_pad_end<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.padEnd called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let s_len = char_len(&s);
|
let s_len = char_len(&s);
|
||||||
let target = if args.len() > 1 {
|
let target = if args.len() > 1 {
|
||||||
@@ -357,6 +377,7 @@ pub fn string_pad_end<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
s_len
|
s_len
|
||||||
};
|
};
|
||||||
if target > 10000 {
|
if target > 10000 {
|
||||||
|
builtins_error!("String.prototype.padEnd: invalid receiver");
|
||||||
return NativeResult::Err(crate::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() };
|
let pad = if args.len() > 2 { as_string(vm, vm.reg(args[2])) } else { " ".to_string() };
|
||||||
@@ -372,6 +393,7 @@ pub fn string_pad_end<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_starts_with<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_starts_with<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.startsWith called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let n = char_len(&s);
|
let n = char_len(&s);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
@@ -387,6 +409,7 @@ pub fn string_starts_with<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_ends_with<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_ends_with<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.endsWith called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let n = char_len(&s);
|
let n = char_len(&s);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
@@ -402,6 +425,7 @@ pub fn string_ends_with<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_split<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_split<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.split called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
let parts = vec![s.clone()];
|
let parts = vec![s.clone()];
|
||||||
@@ -441,6 +465,7 @@ pub fn string_split<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_replace<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_replace<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.replace called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
return NativeResult::Ok(vm.new_string(&s));
|
return NativeResult::Ok(vm.new_string(&s));
|
||||||
@@ -467,6 +492,7 @@ pub fn string_replace<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_match_fn<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_match_fn<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.match called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
return NativeResult::Ok(JsValue::undefined());
|
return NativeResult::Ok(JsValue::undefined());
|
||||||
@@ -494,6 +520,7 @@ pub fn string_match_fn<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_search<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_search<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.search called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
return NativeResult::Ok(JsValue::int(-1));
|
return NativeResult::Ok(JsValue::int(-1));
|
||||||
@@ -523,16 +550,19 @@ pub fn string_search<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_trim_start<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_trim_start<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.trimStart called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
NativeResult::Ok(vm.new_string(s.trim_start()))
|
NativeResult::Ok(vm.new_string(s.trim_start()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_trim_end<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_trim_end<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.trimEnd called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
NativeResult::Ok(vm.new_string(s.trim_end()))
|
NativeResult::Ok(vm.new_string(s.trim_end()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_code_point_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_code_point_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.codePointAt called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let pos = if args.len() > 1 {
|
let pos = if args.len() > 1 {
|
||||||
oxide_runtime_api::to_number(vm.reg(args[1])) as usize
|
oxide_runtime_api::to_number(vm.reg(args[1])) as usize
|
||||||
@@ -555,6 +585,7 @@ pub fn string_code_point_at<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_normalize<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_normalize<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.normalize called with {} args", args.len());
|
||||||
use unicode_normalization::UnicodeNormalization;
|
use unicode_normalization::UnicodeNormalization;
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
let form = if args.len() > 1 { as_string(vm, vm.reg(args[1])) } else { "NFC".to_string() };
|
let form = if args.len() > 1 { as_string(vm, vm.reg(args[1])) } else { "NFC".to_string() };
|
||||||
@@ -568,8 +599,10 @@ pub fn string_normalize<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_match_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_match_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.matchAll called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
builtins_error!("String.prototype.matchAll: invalid receiver");
|
||||||
return NativeResult::Err(JsValue::undefined());
|
return NativeResult::Err(JsValue::undefined());
|
||||||
}
|
}
|
||||||
let pattern_val = vm.reg(args[1]);
|
let pattern_val = vm.reg(args[1]);
|
||||||
@@ -589,6 +622,7 @@ pub fn string_match_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_replace_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_replace_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
|
builtins_debug!("String.prototype.replaceAll called with {} args", args.len());
|
||||||
let s = this_string(vm, args);
|
let s = this_string(vm, args);
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
return NativeResult::Ok(vm.new_string(&s));
|
return NativeResult::Ok(vm.new_string(&s));
|
||||||
|
|||||||
@@ -830,12 +830,14 @@ impl Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(&self, program: &oxide_parser::Program) -> Result<CompiledModule, String> {
|
pub fn compile(&self, program: &oxide_parser::Program) -> Result<CompiledModule, String> {
|
||||||
|
crate::compiler_debug!("compile: starting...");
|
||||||
let mut ctx = CompileCtx::new();
|
let mut ctx = CompileCtx::new();
|
||||||
ctx.pre_register_builtins();
|
ctx.pre_register_builtins();
|
||||||
|
|
||||||
for stmt in &program.body {
|
for stmt in &program.body {
|
||||||
self.count_statement(stmt, &mut ctx);
|
self.count_statement(stmt, &mut ctx);
|
||||||
}
|
}
|
||||||
|
crate::compiler_debug!("counter: {} instructions estimated", ctx.projected_pc);
|
||||||
ctx.max_regs = ctx.max_regs.max(1);
|
ctx.max_regs = ctx.max_regs.max(1);
|
||||||
ctx.reg_overflow = false;
|
ctx.reg_overflow = false;
|
||||||
ctx.reset_regs();
|
ctx.reset_regs();
|
||||||
@@ -859,6 +861,7 @@ impl Compiler {
|
|||||||
None => last_result = None,
|
None => last_result = None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
crate::compiler_debug!("emitter: {} bytes emitted", ctx.bytecode.len());
|
||||||
|
|
||||||
if let Some(r) = last_result {
|
if let Some(r) = last_result {
|
||||||
ctx.emit(opcode::encode(OpCode::LOAD_VAR, 0, r, 0));
|
ctx.emit(opcode::encode(OpCode::LOAD_VAR, 0, r, 0));
|
||||||
@@ -883,6 +886,8 @@ impl Compiler {
|
|||||||
return Err("RangeError: jump offset out of range".into());
|
return Err("RangeError: jump offset out of range".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate::compiler_debug!("compile: done, {} instructions, {} constants", ctx.bytecode.len(), ctx.constants.len());
|
||||||
|
|
||||||
Ok(CompiledModule {
|
Ok(CompiledModule {
|
||||||
bytecode: ctx.bytecode,
|
bytecode: ctx.bytecode,
|
||||||
constants: ctx.constants,
|
constants: ctx.constants,
|
||||||
|
|||||||
Reference in New Issue
Block a user