fix: 补内建函数 ToNumber 抛错路径与自身属性等正确性

This commit is contained in:
2026-09-24 16:06:41 +00:00
parent e29e74341e
commit 44ead358ed
8 changed files with 114 additions and 21 deletions
+19 -11
View File
@@ -191,21 +191,29 @@ impl Vm {
/// 入队一个请求;生成器处于可恢复状态(New/YieldSuspended/Completed)时立即
/// 启动处理,正在执行 / await 挂起时留待当前请求结算后再处理。
///
/// 坏 receiver(非对象或非异步生成器对象)按规范不同步抛错,而是返回
/// 携带 TypeError 的 rejected Promise。
pub(crate) fn async_generator_enqueue(
&mut self, gen_val: JsValue, mode: GeneratorResumeMode,
) -> Result<JsValue, JsValue> {
if !gen_val.is_object() {
return Err(oxide_builtins::error::create_type_error(
let is_gen = if gen_val.is_object() {
unsafe { &*gen_val.as_js_object_ptr() }.is_async_generator_obj()
} else {
false
};
if !is_gen {
let (promise, _, _) = self.new_promise_capability();
let exc = oxide_builtins::error::create_type_error(
self,
"AsyncGenerator methods called on non-object",
));
}
let obj = unsafe { &*gen_val.as_js_object_ptr() };
if !obj.is_async_generator_obj() {
return Err(oxide_builtins::error::create_type_error(
self,
"AsyncGenerator methods called on incompatible receiver",
));
if gen_val.is_object() {
"AsyncGenerator methods called on incompatible receiver"
} else {
"AsyncGenerator methods called on non-object"
},
);
let _ = self.reject_promise(promise, exc);
return Ok(promise);
}
let (promise, resolve, reject) = self.new_promise_capability();
let state_ptr = self.async_gen_state_ptr(gen_val);
@@ -38,5 +38,24 @@ pub fn bind_function(core: &Arc<KernelCore>, session: &KernelSession, global: &m
ctor.ensure_hash_props().push(JsValue::int(1));
let length_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true));
// Function.prototype 自身属性:length = 0、name = ""(不可写不可枚举可配置),
// 自身属性名序 length 在 name 之前。
let proto_ptr = session.builtin_world().function_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
let proto_length_shape = core.shape_forge().make_shape(proto.shape_id(), length_si);
proto.set_shape_id(proto_length_shape);
proto.ensure_hash_props().push(JsValue::int(0));
let proto_length_pos = proto.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
proto.set_data_meta(proto_length_pos, PropAttributes::new(false, false, true));
let name_si = core.perm_interner().intern("name").0;
let name_shape = core.shape_forge().make_shape(proto.shape_id(), name_si);
proto.set_shape_id(name_shape);
proto
.ensure_hash_props()
.push(JsValue::perm_string(core.perm_interner().string_ptr(core.perm_interner().intern("").0)));
let name_pos = proto.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
proto.set_data_meta(name_pos, PropAttributes::new(false, false, true));
bind_global_value(core, global, "Function", JsValue::from_js_object(function_ctor));
}
+4 -2
View File
@@ -28,7 +28,8 @@ pub fn bind_number(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
oxide_builtins::number::number_is_safe_integer::<crate::vm::Vm> as *const (),
1,
),
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 1),
// parseInt 形式参数为 (string, radix),length 按规范取 2。
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 2),
("parseFloat", oxide_builtins::number::number_parse_float::<crate::vm::Vm> as *const (), 1),
],
);
@@ -86,7 +87,8 @@ pub fn bind_number(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
global,
core,
&[
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 1),
// parseInt 形式参数为 (string, radix),length 按规范取 2。
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 2),
("parseFloat", oxide_builtins::number::number_parse_float::<crate::vm::Vm> as *const (), 1),
("isNaN", oxide_builtins::global::global_is_nan::<crate::vm::Vm> as *const (), 1),
("isFinite", oxide_builtins::global::global_is_finite::<crate::vm::Vm> as *const (), 1),
+2 -1
View File
@@ -775,7 +775,8 @@ fn bind_global_functions(core: &Arc<KernelCore>, session: &KernelSession, global
global,
core,
&[
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 1),
// parseInt 形式参数为 (string, radix),length 按规范取 2。
("parseInt", oxide_builtins::number::number_parse_int::<crate::vm::Vm> as *const (), 2),
("parseFloat", oxide_builtins::number::number_parse_float::<crate::vm::Vm> as *const (), 1),
("isNaN", oxide_builtins::global::global_is_nan::<crate::vm::Vm> as *const (), 1),
("isFinite", oxide_builtins::global::global_is_finite::<crate::vm::Vm> as *const (), 1),