@@ -1,5 +1,5 @@
use oxide_kernel ::shape_forge ::EMPTY_SHAPE_ID ;
use oxide_types ::object ::{ JsObject , NativeFnPtr , PropAttributes } ;
use oxide_types ::object ::{ JsObject , NativeFnPtr } ;
use oxide_types ::value ::JsValue ;
use num_bigint ::BigInt ;
@@ -25,15 +25,28 @@ macro_rules! native_try {
} ;
}
/// ToIndex( ECMA-262 §7.1.19):ToNumber → NaN 归 0 → 非有限抛 RangeError → trunc →
/// 负值抛 RangeError。
///
/// # 边界与前提
/// - 序位按规范步序:trunc 先于判负(-0.99999 归 0,不抛)。
/// - 强转失败(对象 valueOf/toString 抛错、Symbol、BigInt)以 `Err` 传播原异常值,
/// 调用方不得吞成 NaN。
fn to_index < H : VmHost > ( vm : & mut H , value : JsValue , msg : & str ) -> Result < usize , JsValue > {
let n = vm . coerce_number_bounded ( value ) . unwrap_or ( f64 ::NAN ) ;
let n = vm
. coerce_number_bounded ( value )
. map_err ( | e | crate ::iterator ::engine_error ( vm , & e ) ) ? ;
if n . is_nan ( ) {
return Ok ( 0 ) ;
}
if ! n . is_finite ( ) | | n < 0.0 {
if ! n . is_finite ( ) {
return Err ( crate ::error ::create_range_error ( vm , msg ) ) ;
}
Ok ( n . trunc ( ) as usize )
let truncated = n . trunc ( ) ;
if truncated < 0.0 {
return Err ( crate ::error ::create_range_error ( vm , msg ) ) ;
}
Ok ( truncated as usize )
}
fn is_little_endian < H : VmHost > ( vm : & mut H , args : & [ u8 ] , idx : usize ) -> bool {
@@ -42,15 +55,33 @@ fn is_little_endian<H: VmHost>(vm: &mut H, args: &[u8], idx: usize) -> bool {
. unwrap_or ( false )
}
fn numeric_arg < H : VmHost > ( vm : & mut H , args : & [ u8 ] , idx : usize ) -> f64 {
args . get ( idx )
. map ( | reg | vm . coerce_number_bounded ( vm . reg ( * reg ) ) . unwrap_or ( f64 ::NAN ) )
. unwrap_or ( 0.0 )
/// 可选 byteOffset 实参的 ToIndex(缺省 → 0),强转失败传播。
fn to_index_arg < H : VmHost > ( vm : & mut H , args : & [ u8 ] , idx : usize ) -> Result < usize , JsValue > {
if args . len ( ) > idx {
to_index ( vm , vm . reg ( args [ idx ] ) , " DataView offset out of bounds " )
} else {
Ok ( 0 )
}
}
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 ) ;
/// value 实参的 ToNumber(缺省 → undefined → NaN),强转失败传播。
fn coerce_value_arg < H : VmHost > ( vm : & mut H , args : & [ u8 ] , idx : usize ) -> Result < f64 , JsValue > {
let value = if args . len ( ) > idx { vm . reg ( args [ idx ] ) } else { JsValue ::undefined ( ) } ;
vm . coerce_number_bounded ( value )
. map_err ( | e | crate ::iterator ::engine_error ( vm , & e ) )
}
/// ToInt32 回卷:0/±Infinity 归 0, trunc 后对 2^32 取模再按符号解释(位模式口径)。
fn to_int32 ( n : f64 ) -> i32 {
if n = = 0.0 | | ! n . is_finite ( ) {
return 0 ;
}
let int = n . trunc ( ) . rem_euclid ( 4_294_967_296.0 ) as u32 ;
if int > i32 ::MAX as u32 {
( int as i64 - 4_294_967_296 i64 ) as i32
} else {
int as i32
}
}
fn get_data_view_data < H : VmHost > ( vm : & mut H , this_val : JsValue ) -> Result < DataViewData , JsValue > {
@@ -87,14 +118,8 @@ fn checked_absolute_offset<H: VmHost>(
Ok ( view . byte_offset + offset )
}
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 {
to_index ( vm , vm . reg ( args [ 1 ] ) , " DataView offset out of bounds " ) ?
} else {
0
} ;
/// GetViewValue 后半:按已校验的视图与偏移读 N 字节(越界抛 RangeError)。
fn read_bytes_at < const N : usize , H : VmHost > ( vm : & mut H , view : DataViewData , offset : usize ) -> Result < [ u8 ; N ] , JsValue > {
let abs = checked_absolute_offset ( vm , view , offset , N ) ? ;
let buffer_ptr = array_buffer_data_ptr ( vm , view . buffer ) ? ;
let buffer = unsafe { & * buffer_ptr } ;
@@ -106,14 +131,10 @@ fn read_bytes<const N: usize, H: VmHost>(vm: &mut H, args: &[u8]) -> Result<[u8;
Ok ( out )
}
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 {
to_index ( vm , vm . reg ( args [ 1 ] ) , " DataView offset out of bounds " ) ?
} else {
0
} ;
/// SetViewValue 后半:按已校验的视图与偏移写 N 字节(越界抛 RangeError)。
fn write_bytes < const N : usize , H : VmHost > (
vm : & mut H , view : DataViewData , offset : usize , bytes : [ u8 ; N ] ,
) -> Result < ( ) , JsValue > {
let abs = checked_absolute_offset ( vm , view , offset , N ) ? ;
let buffer_ptr = array_buffer_data_ptr ( vm , view . buffer ) ? ;
let buffer = unsafe { & mut * buffer_ptr } ;
@@ -124,8 +145,52 @@ fn write_bytes<const N: usize, H: VmHost>(vm: &mut H, args: &[u8], bytes: [u8; N
Ok ( ( ) )
}
/// 校验 receiver 原型链含 `%DataView.prototype%`( `new DataView` 构造出的实例
/// 特征,普通调用面 this = globalThis 不满足)。
fn has_data_view_proto < H : VmHost > ( vm : & mut H , this_val : JsValue ) -> bool {
if ! this_val . is_object ( ) {
return false ;
}
let target = vm . session ( ) . builtin_world ( ) . data_view_proto . as_ptr ( ) as * mut JsObject ;
let mut cursor = this_val ;
for _ in 0 .. 1024 {
if ! cursor . is_object ( ) {
return false ;
}
let ptr = cursor . as_js_object_ptr ( ) ;
if ptr . is_null ( ) {
return false ;
}
if std ::ptr ::eq ( ptr , target ) {
return true ;
}
cursor = unsafe { & * ptr } . proto ( ) ;
}
false
}
/// `DataView(buffer, byteOffset, byteLength)` 构造逻辑:在 ArrayBuffer 上建立定点字节视图。
///
/// # 步骤
/// 1. receiver 原型链不含 %DataView.prototype% → TypeError(普通调用面:
/// this = globalThis 不满足;构造路径恒传 DataView 原型链上的 receiver)。
/// 2. buffer 品牌校验(ArrayBufferData)。
/// 3. offset = ToIndex(byteOffset) 传播式;offset > bufferLen → RangeError。
/// 4. byteLength 缺省/undefined → bufferLen - offset,否则 ToIndex 传播式;
/// offset + byteLength > bufferLen → RangeError。
/// 5. GetPrototypeFromConstructor:经 `ordinary_get` 读 NewTarget( regs[255])
/// 的 `prototype`(触发访问器,读期异常原值传播);非对象回落 %DataView.prototype%。
/// 6. 分配 OBJ_TYPE_DATA_VIEW 对象并挂 DataViewData 状态盒。
///
/// # 边界与前提
/// - 原型读取在全部校验之后:越界 RangeError 先于抛错的 prototype getter。
/// - NewTarget 非对象(直调/缺省面)时直接回落默认原型,不抛错。
pub fn data_view_constructor < H : VmHost > ( vm : & mut H , args : & [ u8 ] ) -> NativeResult {
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
if ! has_data_view_proto ( vm , this_val ) {
return NativeResult ::Err ( crate ::error ::create_type_error ( vm , " DataView must be called with new " ) ) ;
}
let new_target = vm . reg ( 255 ) ;
if args . len ( ) < 2 {
return NativeResult ::Err ( crate ::error ::create_type_error ( vm , " DataView requires an ArrayBuffer " ) ) ;
}
@@ -141,8 +206,14 @@ pub fn data_view_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
return NativeResult ::Err ( crate ::error ::create_range_error ( vm , " DataView byteOffset out of bounds " ) ) ;
}
let default_len = buffer_len - byte_offset ;
// byteLength 显式 undefined 视同缺省(ToIndex(undefined) = 0 会吞掉视图长度)。
let byte_length = if args . len ( ) > 3 {
native_try! ( to_index ( vm , vm . reg ( args [ 3 ] ) , " DataView byteLength out of bounds " ) )
let bl_val = vm . reg ( args [ 3 ] ) ;
if bl_val . is_undefined ( ) {
default_len
} else {
native_try! ( to_index ( vm , bl_val , " DataView byteLength out of bounds " ) )
}
} else {
default_len
} ;
@@ -150,8 +221,28 @@ pub fn data_view_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
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 ;
let mut obj = JsObject ::new_empty ( EMPTY_SHAPE_ID , JsValue ::from_js_object ( proto ) ) ;
// GetPrototypeFromConstructor:普通读触发原型链上的访问器 getter,
// 读期用户异常经原值槽恢复后重抛。NewTarget 非对象(直调/缺省面)时
// 回落默认原型,不抛错。
let default_proto = JsValue ::from_js_object ( vm . session ( ) . builtin_world ( ) . data_view_proto . as_ptr ( ) as * mut JsObject ) ;
let proto = if new_target . is_object ( ) {
let nt_ptr = new_target . as_js_object_ptr ( ) ;
let nt_obj = unsafe { & * nt_ptr } ;
let proto_si = vm . kernel_core ( ) . perm_interner ( ) . intern ( " prototype " ) . 0 ;
let proto_val = match vm . ordinary_get ( nt_obj , proto_si , new_target ) {
Ok ( v ) = > v ,
Err ( e ) = > return NativeResult ::Err ( crate ::iterator ::engine_error ( vm , & e ) ) ,
} ;
if proto_val . is_object ( ) {
proto_val
} else {
default_proto
}
} else {
default_proto
} ;
let mut obj = JsObject ::new_empty ( EMPTY_SHAPE_ID , proto ) ;
obj . type_tag = JsObject ::OBJ_TYPE_DATA_VIEW ;
let data = Box ::into_raw ( Box ::new ( DataViewData {
buffer ,
@@ -161,21 +252,6 @@ pub fn data_view_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
// SAFETY: DataView 对象不可调用,native_fn 存不透明 `Box<DataViewData>` 指针,
// 与 ArrayBuffer / RegExp 的类型化存储模式一致。
obj . set_native_fn ( Some ( unsafe { NativeFnPtr ::from_raw ( data as * const ( ) ) } ) ) ;
set_named_prop ( vm , & mut obj , " buffer " , buffer , PropAttributes ::new ( false , false , false ) ) ;
set_named_prop (
vm ,
& mut obj ,
" byteOffset " ,
JsValue ::int ( byte_offset as i32 ) ,
PropAttributes ::new ( false , false , false ) ,
) ;
set_named_prop (
vm ,
& mut obj ,
" byteLength " ,
JsValue ::int ( byte_length as i32 ) ,
PropAttributes ::new ( false , false , false ) ,
) ;
NativeResult ::Ok ( JsValue ::from_js_object ( vm . alloc_object ( obj ) ) )
}
@@ -263,19 +339,28 @@ pub fn drop_data_view_native(obj: &mut JsObject) -> u64 {
/// `DataView.prototype.getInt8(byteOffset)`:读取 1 字节有符号整数。
pub fn data_view_get_int8 < H : VmHost > ( vm : & mut H , args : & [ u8 ] ) -> NativeResult {
let bytes = native_try! ( read_bytes ::< 1 , H > ( vm , args ) ) ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 1 , H > ( vm , view , offset ) ) ;
NativeResult ::Ok ( JsValue ::int ( i8 ::from_ne_bytes ( bytes ) as i32 ) )
}
/// `DataView.prototype.getUint8(byteOffset)`:读取 1 字节无符号整数。
pub fn data_view_get_uint8 < H : VmHost > ( vm : & mut H , args : & [ u8 ] ) -> NativeResult {
let bytes = native_try! ( read_bytes ::< 1 , H > ( vm , args ) ) ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 1 , H > ( vm , view , offset ) ) ;
NativeResult ::Ok ( JsValue ::int ( bytes [ 0 ] as i32 ) )
}
/// `DataView.prototype.getInt16(byteOffset, littleEndian)`:读取 2 字节有符号整数。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 2 , H > ( vm , view , offset ) ) ;
let n = if is_little_endian ( vm , args , 2 ) {
i16 ::from_le_bytes ( bytes )
} else {
@@ -286,7 +371,10 @@ pub fn data_view_get_int16<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
/// `DataView.prototype.getUint16(byteOffset, littleEndian)`:读取 2 字节无符号整数。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 2 , H > ( vm , view , offset ) ) ;
let n = if is_little_endian ( vm , args , 2 ) {
u16 ::from_le_bytes ( bytes )
} else {
@@ -297,7 +385,10 @@ pub fn data_view_get_uint16<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
/// `DataView.prototype.getInt32(byteOffset, littleEndian)`:读取 4 字节有符号整数。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 4 , H > ( vm , view , offset ) ) ;
let n = if is_little_endian ( vm , args , 2 ) {
i32 ::from_le_bytes ( bytes )
} else {
@@ -308,7 +399,10 @@ pub fn data_view_get_int32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
/// `DataView.prototype.getUint32(byteOffset, littleEndian)`:读取 4 字节无符号整数。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 4 , H > ( vm , view , offset ) ) ;
let n = if is_little_endian ( vm , args , 2 ) {
u32 ::from_le_bytes ( bytes )
} else {
@@ -319,7 +413,10 @@ pub fn data_view_get_uint32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
/// `DataView.prototype.getFloat32(byteOffset, littleEndian)`:读取 4 字节单精度浮点。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 4 , H > ( vm , view , offset ) ) ;
let n = if is_little_endian ( vm , args , 2 ) {
f32 ::from_le_bytes ( bytes )
} else {
@@ -330,7 +427,10 @@ pub fn data_view_get_float32<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
/// `DataView.prototype.getFloat16(byteOffset, littleEndian)`:读取 2 字节半精度浮点。
pub fn data_view_get_float16 < H : VmHost > ( vm : & mut H , args : & [ u8 ] ) -> NativeResult {
let bytes = native_try! ( read_bytes ::< 2 , H > ( vm , args ) ) ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 2 , H > ( vm , view , offset ) ) ;
let bits = if is_little_endian ( vm , args , 2 ) {
u16 ::from_le_bytes ( bytes )
} else {
@@ -341,7 +441,10 @@ pub fn data_view_get_float16<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
/// `DataView.prototype.getFloat64(byteOffset, littleEndian)`:读取 8 字节双精度浮点。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 8 , H > ( vm , view , offset ) ) ;
let n = if is_little_endian ( vm , args , 2 ) {
f64 ::from_le_bytes ( bytes )
} else {
@@ -353,7 +456,10 @@ pub fn data_view_get_float64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
/// `DataView.prototype.getBigInt64(byteOffset, littleEndian)`:读取 8 字节有符号 64 位
/// 整数并返回 BigInt 值。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 8 , H > ( vm , view , offset ) ) ;
let n = if is_little_endian ( vm , args , 2 ) {
i64 ::from_le_bytes ( bytes )
} else {
@@ -365,7 +471,10 @@ pub fn data_view_get_big_int64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResu
/// `DataView.prototype.getBigUint64(byteOffset, littleEndian)`:读取 8 字节无符号
/// 64 位整数并返回 BigInt 值。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let bytes = native_try! ( read_bytes_at ::< 8 , H > ( vm , view , offset ) ) ;
let n = if is_little_endian ( vm , args , 2 ) {
u64 ::from_le_bytes ( bytes )
} else {
@@ -375,108 +484,138 @@ pub fn data_view_get_big_uint64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeRes
}
/// `DataView.prototype.setInt8(byteOffset, value)`:写入 1 字节有符号整数。
///
/// 步序:品牌 → ToIndex(byteOffset) → ToInt32(value) 回卷 → 越界 RangeError → 写。
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 ( ) ) ) ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let n = to_int32 ( native_try! ( coerce_value_arg ( vm , args , 2 ) ) ) ;
native_try! ( write_bytes ::< 1 , H > ( vm , view , offset , [ n as u8 ] ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setUint8(byteOffset, value)`:写入 1 字节无符号整数。
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 ] ) ) ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let n = to_int32 ( native_try! ( coerce_value_arg ( vm , args , 2 ) ) ) ;
native_try! ( write_bytes ::< 1 , H > ( vm , view , offset , [ n as u8 ] ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setInt16(byteOffset, value, littleEndian)`:写入 2 字节有符号整数。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let n = to_int32 ( native_try! ( coerce_value_arg ( vm , args , 2 ) ) ) ;
let bytes = if is_little_endian ( vm , args , 3 ) {
value . to_le_bytes ( )
( n as u16 ) . to_le_bytes ( )
} else {
value . to_be_bytes ( )
( n as u16 ) . to_be_bytes ( )
} ;
native_try! ( write_bytes ( vm , args , bytes ) ) ;
native_try! ( write_bytes :: < 2 , H > ( vm , view , offset , bytes ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setUint16(byteOffset, value, littleEndian)`:写入 2 字节无符号整数。
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 this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let n = to_int32 ( native_try! ( coerce_value_arg ( vm , args , 2 ) ) ) ;
let bytes = if is_little_endian ( vm , args , 3 ) {
value . to_le_bytes ( )
( n as u16 ) . to_le_bytes ( )
} else {
value . to_be_bytes ( )
( n as u16 ) . to_be_bytes ( )
} ;
native_try! ( write_bytes ( vm , args , bytes ) ) ;
native_try! ( write_bytes :: < 2 , H > ( vm , view , offset , bytes ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setInt32(byteOffset, value, littleEndian)`:写入 4 字节有符号整数。
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 ( )
} else {
value . to_be_bytes ( )
} ;
native_try! ( write_bytes ( vm , args , bytes ) ) ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let n = to_int32 ( native_try! ( coerce_value_arg ( vm , args , 2 ) ) ) ;
let bytes = if is_little_endian ( vm , args , 3 ) { n . to_le_bytes ( ) } else { n . to_be_bytes ( ) } ;
native_try! ( write_bytes ::< 4 , H > ( vm , view , offset , bytes ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setUint32(byteOffset, value, littleEndian)`:写入 4 字节无符号整数。
pub fn data_view_set_uint32 < H : VmHost > ( vm : & mut H , args : & [ u8 ] ) -> NativeResult {
let value = numeric_arg ( vm , args , 2 ) as u32 ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let n = to_int32 ( native_try! ( coerce_value_arg ( vm , args , 2 ) ) ) ;
let bytes = if is_little_endian ( vm , args , 3 ) {
value . to_le_bytes ( )
( n as u32 ) . to_le_bytes ( )
} else {
value . to_be_bytes ( )
( n as u32 ) . to_be_bytes ( )
} ;
native_try! ( write_bytes ( vm , args , bytes ) ) ;
native_try! ( write_bytes :: < 4 , H > ( vm , view , offset , bytes ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setFloat32(byteOffset, value, littleEndian)`:写入单精度浮点。
pub fn data_view_set_float32 < H : VmHost > ( vm : & mut H , args : & [ u8 ] ) -> NativeResult {
let value = numeric_arg ( vm , args , 2 ) as f32 ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let value = native_try! ( coerce_value_arg ( vm , args , 2 ) ) as f32 ;
let bytes = if is_little_endian ( vm , args , 3 ) {
value . to_le_bytes ( )
} else {
value . to_be_bytes ( )
} ;
native_try! ( write_bytes ( vm , args , bytes ) ) ;
native_try! ( write_bytes :: < 4 , H > ( vm , view , offset , bytes ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setFloat16(byteOffset, value, littleEndian)`:按 IEEE 754
/// binary16 舍入写入 2 字节半精度浮点(NaN 规范化由 `f64_to_f16_bits` 处理)。
pub fn data_view_set_float16 < H : VmHost > ( vm : & mut H , args : & [ u8 ] ) -> NativeResult {
let value = numeric_arg ( vm , args , 2 ) ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let value = native_try! ( coerce_value_arg ( vm , args , 2 ) ) ;
let bits = crate ::math ::f64_to_f16_bits ( value ) ;
let bytes = if is_little_endian ( vm , args , 3 ) {
bits . to_le_bytes ( )
} else {
bits . to_be_bytes ( )
} ;
native_try! ( write_bytes ( vm , args , bytes ) ) ;
native_try! ( write_bytes :: < 2 , H > ( vm , view , offset , bytes ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setFloat64(byteOffset, value, littleEndian)`:写入双精度浮点。
pub fn data_view_set_float64 < H : VmHost > ( vm : & mut H , args : & [ u8 ] ) -> NativeResult {
let value = numeric_arg ( vm , args , 2 ) ;
let this_val = vm . reg ( if args . is_empty ( ) { 0 } else { args [ 0 ] } ) ;
let view = native_try! ( get_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let value = native_try! ( coerce_value_arg ( vm , args , 2 ) ) ;
let bytes = if is_little_endian ( vm , args , 3 ) {
value . to_le_bytes ( )
} else {
value . to_be_bytes ( )
} ;
native_try! ( write_bytes ( vm , args , bytes ) ) ;
native_try! ( write_bytes :: < 8 , H > ( vm , view , offset , bytes ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setBigInt64(byteOffset, value, littleEndian)`:按 ToBigInt
/// 语义接收值(Number 入参抛 TypeError),取低 64 位位模式写入 8 字节有符号整数。
///
/// 步序:品牌 → ToIndex(byteOffset) → ToBigInt(value) → 越界 RangeError → 写。
pub fn data_view_set_big_int64 < 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_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let value = if args . len ( ) > 2 { vm . reg ( args [ 2 ] ) } else { JsValue ::undefined ( ) } ;
let b =
native_try! ( oxide_runtime_api ::to_bigint_full ( value , vm ) . map_err ( | e | crate ::iterator ::engine_error ( vm , & e ) ) ) ;
@@ -486,13 +625,16 @@ pub fn data_view_set_big_int64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResu
} else {
low . to_be_bytes ( )
} ;
native_try! ( write_bytes ( vm , args , bytes ) ) ;
native_try! ( write_bytes :: < 8 , H > ( vm , view , offset , bytes ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
/// `DataView.prototype.setBigUint64(byteOffset, value, littleEndian)`:按 ToBigInt
/// 语义接收值(Number 入参抛 TypeError),取低 64 位位模式写入 8 字节无符号整数。
pub fn data_view_set_big_uint64 < 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_data_view_data ( vm , this_val ) ) ;
let offset = native_try! ( to_index_arg ( vm , args , 1 ) ) ;
let value = if args . len ( ) > 2 { vm . reg ( args [ 2 ] ) } else { JsValue ::undefined ( ) } ;
let b =
native_try! ( oxide_runtime_api ::to_bigint_full ( value , vm ) . map_err ( | e | crate ::iterator ::engine_error ( vm , & e ) ) ) ;
@@ -502,7 +644,7 @@ pub fn data_view_set_big_uint64<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeRes
} else {
low . to_be_bytes ( )
} ;
native_try! ( write_bytes ( vm , args , bytes ) ) ;
native_try! ( write_bytes :: < 8 , H > ( vm , view , offset , bytes ) ) ;
NativeResult ::Ok ( JsValue ::undefined ( ) )
}
@@ -518,3 +660,24 @@ pub fn data_view_to_string<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
native_try! ( get_data_view_data ( vm , this_val ) ) ;
NativeResult ::Ok ( vm . new_string ( " [object DataView] " ) )
}
/// `DataView.prototype.buffer` getter:返回该视图所锚定的 ArrayBuffer 对象。
pub fn data_view_buffer_getter < 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_data_view_data ( vm , this_val ) ) ;
NativeResult ::Ok ( view . buffer )
}
/// `DataView.prototype.byteOffset` getter:返回视图起始字节在 buffer 内的偏移。
pub fn data_view_byte_offset_getter < 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_data_view_data ( vm , this_val ) ) ;
NativeResult ::Ok ( JsValue ::float ( view . byte_offset as f64 ) )
}
/// `DataView.prototype.byteLength` getter:返回视图覆盖的字节长度。
pub fn data_view_byte_length_getter < 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_data_view_data ( vm , this_val ) ) ;
NativeResult ::Ok ( JsValue ::float ( view . byte_length as f64 ) )
}