@@ -12440,6 +12440,13 @@ pub fn evaluate_call_dispatch<'gc>(
1244012440 } else if let Some(method) = name.strip_prefix("TypedArray.prototype.") {
1244112441 let this_v = this_val.unwrap_or(&Value::Undefined);
1244212442 Ok(crate::js_typedarray::handle_typedarray_method(mc, this_v, method, eval_args, env)?)
12443+ } else if let Some(method) = name.strip_prefix("Uint8Array.prototype.") {
12444+ let this_v = this_val.unwrap_or(&Value::Undefined);
12445+ Ok(crate::js_typedarray::handle_uint8array_proto_method(
12446+ mc, this_v, method, eval_args, env,
12447+ )?)
12448+ } else if let Some(method) = name.strip_prefix("Uint8Array.") {
12449+ Ok(crate::js_typedarray::handle_uint8array_static_method(mc, method, eval_args, env)?)
1244312450 } else if name == "TypedArrayIterator.prototype.next" {
1244412451 let this_v = this_val.unwrap_or(&Value::Undefined);
1244512452 Ok(crate::js_typedarray::handle_typedarray_iterator_next(mc, this_v)?)
@@ -13476,16 +13483,33 @@ pub fn evaluate_call_dispatch<'gc>(
1347613483 Value::String(crate::unicode::utf8_to_utf16(&value_to_string(&prim)))
1347713484 };
1347813485 // The constructor's "prototype" property points to the error prototype
13479- if let Some(prototype_rc) = object_get_key_value(obj, "prototype")
13486+ let err = if let Some(prototype_rc) = object_get_key_value(obj, "prototype")
1348013487 && let Value::Object(proto_ptr) = &*prototype_rc.borrow()
1348113488 {
13482- let err = crate::core::create_error(mc, Some(*proto_ptr), msg_val)?;
13483- Ok(err)
13489+ crate::core::create_error(mc, Some(*proto_ptr), msg_val)?
1348413490 } else {
13485- // Fallback: create error with no prototype
13486- let err = crate::core::create_error(mc, None, msg_val)?;
13487- Ok(err)
13491+ crate::core::create_error(mc, None, msg_val)?
13492+ };
13493+ // error-cause: InstallErrorCause(O, options) per §20.5.8.1
13494+ if let Some(options_val) = eval_args.get(1)
13495+ && let Value::Object(options_obj) = options_val
13496+ {
13497+ let has_cause = if let Some(proxy_cell) = crate::core::slot_get(options_obj, &InternalSlot::Proxy)
13498+ && let Value::Proxy(proxy) = &*proxy_cell.borrow()
13499+ {
13500+ crate::js_proxy::proxy_has_property(mc, proxy, "cause")?
13501+ } else {
13502+ crate::core::has_property_key(options_obj, "cause")
13503+ };
13504+ if has_cause {
13505+ let cause_val = crate::core::eval::get_property_with_accessors(mc, env, options_obj, "cause")?;
13506+ if let Value::Object(err_obj) = &err {
13507+ object_set_key_value(mc, err_obj, "cause", &cause_val)?;
13508+ err_obj.borrow_mut(mc).set_non_enumerable("cause");
13509+ }
13510+ }
1348813511 }
13512+ Ok(err)
1348913513 } else if name == crate::unicode::utf8_to_utf16("Promise") {
1349013514 // Promise() called without new must throw TypeError per §27.2.3.1 step 1
1349113515 Err(raise_type_error!("Promise constructor cannot be invoked without 'new'").into())
@@ -16953,6 +16977,7 @@ fn evaluate_expr_property<'gc>(
1695316977 | "Math.floor"
1695416978 | "Math.fround"
1695516979 | "Math.f16round"
16980+ | "Math.sumPrecise"
1695616981 | "Math.log"
1695716982 | "Math.log1p"
1695816983 | "Math.log2"
@@ -16971,6 +16996,10 @@ fn evaluate_expr_property<'gc>(
1697116996 | "Reflect.preventExtensions"
1697216997 | "ArrayBuffer.isView"
1697316998 | "ArrayBuffer.prototype.resize"
16999+ | "Uint8Array.fromBase64"
17000+ | "Uint8Array.fromHex"
17001+ | "Uint8Array.prototype.setFromBase64"
17002+ | "Uint8Array.prototype.setFromHex"
1697417003 | "RegExp.prototype.exec"
1697517004 | "RegExp.prototype.test"
1697617005 | "RegExp.prototype.match"
@@ -17055,6 +17084,8 @@ fn evaluate_expr_property<'gc>(
1705517084 | "String.prototype.substring"
1705617085 | "String.prototype.substr" => 2.0,
1705717086 "Function.prototype.[Symbol.hasInstance]" | "SharedArrayBuffer.prototype.grow" => 1.0,
17087+ "Uint8Array.prototype.toBase64" | "Uint8Array.prototype.toHex" => 0.0,
17088+ "ArrayBuffer.prototype.transfer" | "ArrayBuffer.prototype.transferToFixedLength" => 0.0,
1705817089 "Object.defineProperty" | "JSON.stringify" | "Reflect.apply" | "Reflect.defineProperty" | "Reflect.set" => 3.0,
1705917090 _ => {
1706017091 if func_name.starts_with("DataView.prototype.get") {
@@ -17687,6 +17718,26 @@ fn evaluate_expr_delete<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'g
1768717718 return Ok(Value::Boolean(deleted));
1768817719 }
1768917720
17721+ // TypedArray [[Delete]]: numeric indices cannot be deleted
17722+ if let Some(ta_val) = slot_get(&obj, &InternalSlot::TypedArray)
17723+ && let Value::TypedArray(ta) = &*ta_val.borrow()
17724+ && let Some(numeric_index) = crate::js_typedarray::canonical_numeric_index_string(key)
17725+ {
17726+ // If detached, return true
17727+ if ta.buffer.borrow().detached {
17728+ return Ok(Value::Boolean(true));
17729+ }
17730+ // If not a valid index, return true
17731+ if !crate::js_typedarray::is_valid_integer_index(ta, numeric_index) {
17732+ return Ok(Value::Boolean(true));
17733+ }
17734+ // Valid index on non-detached buffer: cannot delete → false
17735+ if env_get_strictness(env) {
17736+ return Err(crate::raise_type_error!(format!("Cannot delete property '{key}' of a TypedArray")).into());
17737+ }
17738+ return Ok(Value::Boolean(false));
17739+ }
17740+
1769017741 if obj.borrow().non_configurable.contains(&key_val) {
1769117742 if env_get_strictness(env) {
1769217743 Err(crate::raise_type_error!(format!("Cannot delete non-configurable property '{key}'",)).into())
@@ -17766,6 +17817,29 @@ fn evaluate_expr_delete<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'g
1776617817 }
1776717818 return Ok(Value::Boolean(true));
1776817819 }
17820+ // TypedArray [[Delete]]: numeric indices cannot be deleted
17821+ if let Some(ta_val) = slot_get(&obj, &InternalSlot::TypedArray)
17822+ && let Value::TypedArray(ta) = &*ta_val.borrow()
17823+ {
17824+ let key_str = match &key {
17825+ PropertyKey::String(s) => Some(s.clone()),
17826+ _ => None,
17827+ };
17828+ if let Some(ref s) = key_str
17829+ && let Some(numeric_index) = crate::js_typedarray::canonical_numeric_index_string(s)
17830+ {
17831+ if ta.buffer.borrow().detached {
17832+ return Ok(Value::Boolean(true));
17833+ }
17834+ if !crate::js_typedarray::is_valid_integer_index(ta, numeric_index) {
17835+ return Ok(Value::Boolean(true));
17836+ }
17837+ if env_get_strictness(env) {
17838+ return Err(crate::raise_type_error!(format!("Cannot delete property '{}' of a TypedArray", s)).into());
17839+ }
17840+ return Ok(Value::Boolean(false));
17841+ }
17842+ }
1776917843 if obj.borrow().non_configurable.contains(&key) {
1777017844 if env_get_strictness(env) {
1777117845 Err(crate::raise_type_error!(format!(
@@ -18367,6 +18441,10 @@ fn evaluate_expr_index<'gc>(
1836718441 | "Object.prototype.__lookupSetter__"
1836818442 | "ArrayBuffer.isView"
1836918443 | "ArrayBuffer.prototype.resize"
18444+ | "Uint8Array.fromBase64"
18445+ | "Uint8Array.fromHex"
18446+ | "Uint8Array.prototype.setFromBase64"
18447+ | "Uint8Array.prototype.setFromHex"
1837018448 | "Array.prototype.sort"
1837118449 | "encodeURI"
1837218450 | "encodeURIComponent"
@@ -18425,6 +18503,7 @@ fn evaluate_expr_index<'gc>(
1842518503 | "Math.floor"
1842618504 | "Math.fround"
1842718505 | "Math.f16round"
18506+ | "Math.sumPrecise"
1842818507 | "Math.log"
1842918508 | "Math.log1p"
1843018509 | "Math.log2"
@@ -20506,6 +20585,35 @@ pub fn call_native_function<'gc>(
2050620585 }
2050720586 }
2050820587
20588+ // arraybuffer-transfer: transfer, transferToFixedLength, detached
20589+ if name == "ArrayBuffer.prototype.transfer" || name == "ArrayBuffer.prototype.transferToFixedLength" {
20590+ let this_v = this_val.unwrap_or(&Value::Undefined);
20591+ let method_name = if name.ends_with("transferToFixedLength") {
20592+ "transferToFixedLength"
20593+ } else {
20594+ "transfer"
20595+ };
20596+ if let Value::Object(obj) = this_v {
20597+ return Ok(Some(crate::js_typedarray::handle_arraybuffer_method(
20598+ mc,
20599+ env,
20600+ obj,
20601+ method_name,
20602+ args,
20603+ )?));
20604+ } else {
20605+ return Err(raise_type_error!(format!("ArrayBuffer.prototype.{} called on non-object", method_name)).into());
20606+ }
20607+ }
20608+
20609+ if name == "get detached" || name == "ArrayBuffer.prototype.detached" {
20610+ let this_v = this_val.unwrap_or(&Value::Undefined);
20611+ if let Value::Object(obj) = this_v {
20612+ return Ok(Some(crate::js_typedarray::handle_arraybuffer_accessor(mc, obj, "detached")?));
20613+ }
20614+ return Err(raise_type_error!("Method ArrayBuffer.prototype.detached called on incompatible receiver").into());
20615+ }
20616+
2050920617 if name == "SharedArrayBuffer.prototype.byteLength" {
2051020618 let this_v = this_val.unwrap_or(&Value::Undefined);
2051120619 if let Value::Object(obj) = this_v {
@@ -20565,6 +20673,18 @@ pub fn call_native_function<'gc>(
2056520673 }
2056620674 }
2056720675
20676+ // Uint8Array prototype methods (toBase64, toHex, setFromBase64, setFromHex)
20677+ if let Some(method) = name.strip_prefix("Uint8Array.prototype.") {
20678+ let this_v = this_val.unwrap_or(&Value::Undefined);
20679+ return Ok(Some(crate::js_typedarray::handle_uint8array_proto_method(
20680+ mc, this_v, method, args, env,
20681+ )?));
20682+ }
20683+ // Uint8Array static methods (fromBase64, fromHex)
20684+ if let Some(method) = name.strip_prefix("Uint8Array.") {
20685+ return Ok(Some(crate::js_typedarray::handle_uint8array_static_method(mc, method, args, env)?));
20686+ }
20687+
2056820688 // %TypedArray%.species — get [Symbol.species]() { return this; }
2056920689 if name == "TypedArray.species" {
2057020690 let this_v = this_val.unwrap_or(&Value::Undefined);
@@ -22670,7 +22790,17 @@ fn evaluate_expr_new<'gc>(
2267022790 name_str.as_str(),
2267122791 "Error" | "ReferenceError" | "TypeError" | "RangeError" | "SyntaxError" | "EvalError" | "URIError"
2267222792 ) {
22673- let msg = eval_args.first().cloned().unwrap_or(Value::Undefined);
22793+ let raw_msg = eval_args.first().cloned().unwrap_or(Value::Undefined);
22794+ // ToString(message) per spec §20.5.1.1 step 3
22795+ let msg = if matches!(raw_msg, Value::Undefined) {
22796+ Value::Undefined
22797+ } else {
22798+ let prim = crate::core::to_primitive(mc, &raw_msg, "string", env)?;
22799+ if matches!(prim, Value::Symbol(_)) {
22800+ return Err(raise_type_error!("Cannot convert a Symbol value to a string").into());
22801+ }
22802+ Value::String(crate::unicode::utf8_to_utf16(&value_to_string(&prim)))
22803+ };
2267422804 let prototype = if let Some(proto_val) = object_get_key_value(&obj, "prototype") {
2267522805 let prototype_val = match &*proto_val.borrow() {
2267622806 Value::Property { value: Some(v), .. } => v.borrow().clone(),
@@ -22688,6 +22818,24 @@ fn evaluate_expr_new<'gc>(
2268822818 let err_val = crate::core::js_error::create_error(mc, prototype, msg)?;
2268922819 if let Value::Object(err_obj) = &err_val {
2269022820 object_set_key_value(mc, err_obj, "name", &Value::String(name.clone()))?;
22821+ // error-cause: InstallErrorCause(O, options) per §20.5.8.1
22822+ if let Some(options_val) = eval_args.get(1)
22823+ && let Value::Object(options_obj) = options_val
22824+ {
22825+ // HasProperty(options, "cause") — must go through Proxy [[HasProperty]]
22826+ let has_cause = if let Some(proxy_cell) = crate::core::slot_get(options_obj, &InternalSlot::Proxy)
22827+ && let Value::Proxy(proxy) = &*proxy_cell.borrow()
22828+ {
22829+ crate::js_proxy::proxy_has_property(mc, proxy, "cause")?
22830+ } else {
22831+ crate::core::has_property_key(options_obj, "cause")
22832+ };
22833+ if has_cause {
22834+ let cause_val = crate::core::eval::get_property_with_accessors(mc, env, options_obj, "cause")?;
22835+ object_set_key_value(mc, err_obj, "cause", &cause_val)?;
22836+ err_obj.borrow_mut(mc).set_non_enumerable("cause");
22837+ }
22838+ }
2269122839 }
2269222840 return Ok(err_val);
2269322841 } else if name_str == "AggregateError" {
0 commit comments