feat: for-await-of + Symbol.asyncIterator + AsyncFromSyncIterator

This commit is contained in:
2026-08-10 03:21:37 +08:00
parent 5ced83e8c0
commit a5a910a24e
15 changed files with 696 additions and 16 deletions
+402
View File
@@ -0,0 +1,402 @@
//! AsyncFromSyncIterator:把同步迭代器包装为异步迭代器,供 for-await-of 回退消费。
//!
//! GetAsyncIterator 对没有 `@@asyncIterator` 的普通可迭代对象(数组/字符串等)
//! 走同步迭代协议取迭代器,再包一层 AsyncFromSyncIterator:其 `next`/`return`/`throw`
//! 转发内层同步迭代器并把结果包成 Promise(非对象结果按 TypeError 拒绝),
//! `@@asyncIterator` 返回自身。
use oxide_builtins::iterator::make_iter_result;
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_runtime_api::NativeResult;
use oxide_types::object::{JsObject, NativeFnPtr};
use oxide_types::private_key::make_well_known_symbol_key;
use oxide_types::value::JsValue;
use crate::vm::Vm;
/// AsyncFromSyncIterator 对象上存内层同步迭代器的属性名。
const INNER_PROP: &str = "__inner__";
/// `@@asyncIterator` 的 well-known symbol 键序号。
const ASYNC_ITERATOR_SYMBOL_ID: u32 = 8;
/// GetAsyncIterator(ECMA-262):取 `value[@@asyncIterator]`,不可调用时回退同步
/// 迭代器并包 AsyncFromSyncIterator。
///
/// # 步骤
/// 1. ToObject 后读取 `@@asyncIterator`,可调用则调用并校验结果为对象。
/// 2. 否则经同步迭代协议取迭代器包装器,包成 AsyncFromSyncIterator。
///
/// # 返回值
/// - `Ok(iterator)`:异步迭代器对象;
/// - `Err`:`@@asyncIterator` getter/调用抛错或 ToObject 失败,透传原异常值。
pub(crate) fn make_async_iterator(vm: &mut Vm, value: JsValue) -> Result<JsValue, JsValue> {
let obj_value = if value.is_object() {
value
} else {
match oxide_runtime_api::to_object(value, vm) {
Ok(o) => o,
Err(e) => return Err(oxide_builtins::error::create_type_error(vm, &e)),
}
};
let obj = unsafe { &*obj_value.as_js_object_ptr() };
let aiter_key = make_well_known_symbol_key(ASYNC_ITERATOR_SYMBOL_ID);
let method = match vm.ordinary_get(obj, aiter_key, obj_value) {
Ok(m) => m,
Err(e) => {
let exc = vm
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_type_error(vm, &e));
return Err(exc);
}
};
if oxide_builtins::iterator::is_callable(method) {
let iterator = match vm.call_function_sync(method, obj_value, &[]) {
Ok(it) => it,
Err(e) => {
let exc = vm
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_type_error(vm, &e));
return Err(exc);
}
};
if !iterator.is_object() {
return Err(oxide_builtins::error::create_type_error(
vm,
"Result of the Symbol.asyncIterator method is not an object",
));
}
return Ok(iterator);
}
let sync = oxide_builtins::iterator::make_iterator_for_value(vm, value)?;
Ok(vm.create_async_from_sync_iterator(sync))
}
impl Vm {
/// 创建 AsyncFromSyncIterator 包装器:挂内层同步迭代器,装 next/return/throw 与
/// `@@asyncIterator`(返回自身)方法。
pub(crate) fn create_async_from_sync_iterator(&mut self, sync_iter: JsValue) -> JsValue {
let next_fn = make_wrapper_fn(self, async_from_sync_next as *const ());
let return_fn = make_wrapper_fn(self, async_from_sync_return as *const ());
let throw_fn = make_wrapper_fn(self, async_from_sync_throw as *const ());
let self_fn = make_wrapper_fn(self, async_from_sync_symbol_async_iterator as *const ());
let object_proto = self.session.builtin_world().object_proto.as_ptr() as *mut JsObject;
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto)));
let obj = unsafe { &mut *ptr };
let inner_si = self.kernel_core.perm_interner().intern(INNER_PROP).0;
self.set_or_create_prop_value(obj, inner_si, sync_iter);
let next_si = self.kernel_core.perm_interner().intern("next").0;
self.set_or_create_prop_value(obj, next_si, next_fn);
let return_si = self.kernel_core.perm_interner().intern("return").0;
self.set_or_create_prop_value(obj, return_si, return_fn);
let throw_si = self.kernel_core.perm_interner().intern("throw").0;
self.set_or_create_prop_value(obj, throw_si, throw_fn);
let aiter_key = make_well_known_symbol_key(ASYNC_ITERATOR_SYMBOL_ID);
self.set_or_create_prop_value(obj, aiter_key, self_fn);
JsValue::from_js_object(ptr)
}
}
/// 构造包装器方法 native 函数对象(name/length 属性由 `add_fn_name_length` 补全)。
fn make_wrapper_fn(vm: &mut Vm, native_fn: *const ()) -> JsValue {
let fn_proto = vm.session.builtin_world().fn_proto_val();
let mut func = JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto);
func.set_function(true);
// SAFETY: native_fn 来自 NativeFn 函数项。
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(native_fn) }));
func.set_native_arg_count(1);
let ptr = vm.alloc_object(func);
let obj = unsafe { &mut *ptr };
vm.add_fn_name_length(obj, "", 1);
JsValue::from_js_object(ptr)
}
/// 读取包装器对象上的内层同步迭代器;接收者非法或内层缺失时返回 TypeError。
fn sync_inner(vm: &mut Vm, this_val: JsValue) -> Result<JsValue, JsValue> {
if !this_val.is_object() {
return Err(oxide_builtins::error::create_type_error(
vm,
"AsyncFromSyncIterator methods called on non-object",
));
}
let obj = unsafe { &*this_val.as_js_object_ptr() };
let inner_si = vm.kernel_core.perm_interner().intern(INNER_PROP).0;
match vm.ordinary_get(obj, inner_si, this_val) {
Ok(inner) if !inner.is_undefined() => Ok(inner),
_ => Err(oxide_builtins::error::create_type_error(vm, "AsyncFromSyncIterator has no sync iterator")),
}
}
/// AsyncFromSyncIteratorContinuation 的 unwrap 函数闭包上存目标 resolve 的属性名。
const ASFS_RESOLVE_PROP: &str = "__oxide_asfs_resolve__";
/// unwrap 函数闭包上存 done 标志的属性名。
const ASFS_DONE_PROP: &str = "__oxide_asfs_done__";
/// reject-close 闭包上存目标 reject 的属性名。
const ASFS_REJECT_PROP: &str = "__oxide_asfs_reject__";
/// reject-close 闭包上存内层同步迭代器的属性名。
const ASFS_INNER_PROP: &str = "__oxide_asfs_inner__";
/// AsyncFromSyncIteratorContinuation:解出同步迭代器结果对象的 done/value,
/// value 经 PromiseResolve 后 await,最终以 `{value: 解开值, done}` 结算能力。
/// 任一步骤抛错(done/value getter、PromiseResolve 的 constructor getter)都拒绝;
/// `close_on_rejection` 时 valueWrapper 拒绝还会先关闭内层同步迭代器。
///
/// # 参数
/// - `inner`:内层同步迭代器(关闭目标)。
/// - `result`:内层同步方法调用结果(`Err` 为调用抛出的字符串展平文本)。
fn continue_async_from_sync(vm: &mut Vm, inner: JsValue, result: Result<JsValue, String>, close_on_rejection: bool) -> NativeResult {
let (promise, resolve, reject) = vm.new_promise_capability();
let reject_with = |vm: &mut Vm, exc: JsValue| {
if close_on_rejection {
close_sync_iterator(vm, inner);
}
let _ = vm.reject_promise(promise, exc);
};
match result {
Ok(r) if r.is_object() => {
let result_obj = unsafe { &*r.as_js_object_ptr() };
let done_si = vm.kernel_core.perm_interner().intern("done").0;
let done = match vm.ordinary_get(result_obj, done_si, r) {
Ok(d) => oxide_runtime_api::to_boolean(d),
Err(e) => {
let exc = vm
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_error(vm, &e));
reject_with(vm, exc);
return NativeResult::Ok(promise);
}
};
let value_si = vm.kernel_core.perm_interner().intern("value").0;
let value = match vm.ordinary_get(result_obj, value_si, r) {
Ok(v) => v,
Err(e) => {
let exc = vm
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_error(vm, &e));
reject_with(vm, exc);
return NativeResult::Ok(promise);
}
};
let value_wrapper = match vm.promise_resolve(value) {
Ok(w) => w,
Err(e) => {
reject_with(vm, e);
return NativeResult::Ok(promise);
}
};
let fulfill = make_unwrap_fn(vm, resolve, done);
let on_rejected = if close_on_rejection {
make_reject_close_fn(vm, reject, inner)
} else {
reject
};
let _ = vm.perform_promise_then(value_wrapper, fulfill, on_rejected);
NativeResult::Ok(promise)
}
Ok(_) => {
let err = oxide_builtins::error::create_type_error(vm, "sync iterator result is not an object");
reject_with(vm, err);
NativeResult::Ok(promise)
}
Err(e) => {
let exc = vm
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_error(vm, &e));
reject_with(vm, exc);
NativeResult::Ok(promise)
}
}
}
/// 同步关闭内层迭代器(IteratorClose 的 return 调用),忽略 return 自身抛错。
fn close_sync_iterator(vm: &mut Vm, inner: JsValue) {
if !inner.is_object() {
return;
}
let inner_obj = unsafe { &*inner.as_js_object_ptr() };
let return_si = vm.kernel_core.perm_interner().intern("return").0;
let return_fn = match vm.ordinary_get(inner_obj, return_si, inner) {
Ok(f) => f,
Err(_) => return,
};
if oxide_builtins::iterator::is_callable(return_fn) {
let _ = vm.call_function_sync(return_fn, inner, &[]);
}
}
/// 构造 valueWrapper 拒绝时关闭迭代器的闭包:携带目标 reject 与内层同步迭代器。
fn make_reject_close_fn(vm: &mut Vm, reject: JsValue, inner: JsValue) -> JsValue {
let fn_proto = vm.session.builtin_world().fn_proto_val();
let mut func = JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto);
func.set_function(true);
// SAFETY: async_from_sync_reject_close 是 NativeFn 函数项。
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(async_from_sync_reject_close as *const ()) }));
func.set_native_arg_count(1);
let ptr = vm.alloc_object(func);
let obj = unsafe { &mut *ptr };
let rej_si = vm.kernel_core.perm_interner().intern(ASFS_REJECT_PROP).0;
vm.set_or_create_prop_value(obj, rej_si, reject);
let inner_si = vm.kernel_core.perm_interner().intern(ASFS_INNER_PROP).0;
vm.set_or_create_prop_value(obj, inner_si, inner);
vm.add_fn_name_length(obj, "", 1);
JsValue::from_js_object(ptr)
}
/// reject-close 闭包:关闭内层同步迭代器后以原拒绝原因结算能力。
fn async_from_sync_reject_close(vm: &mut Vm, args: &[u8]) -> NativeResult {
let callee = vm.reg(254);
if !callee.is_object() {
return NativeResult::Err(oxide_builtins::error::create_type_error(vm, "reject handler is invalid"));
}
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
let rej_si = vm.kernel_core.perm_interner().intern(ASFS_REJECT_PROP).0;
let reject = vm.resolve_property(callee_obj, rej_si).unwrap_or(JsValue::undefined());
let inner_si = vm.kernel_core.perm_interner().intern(ASFS_INNER_PROP).0;
let inner = vm.resolve_property(callee_obj, inner_si).unwrap_or(JsValue::undefined());
let error = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
close_sync_iterator(vm, inner);
let _ = vm.call_function_sync(reject, JsValue::undefined(), &[error]);
NativeResult::Ok(JsValue::undefined())
}
/// 构造 AsyncFromSyncIteratorContinuation 的 value unwrap 闭包:携带目标 resolve 与
/// done 标志,valueWrapper settle 后把解开值包成 `{value, done}` 结算。
fn make_unwrap_fn(vm: &mut Vm, resolve: JsValue, done: bool) -> JsValue {
let fn_proto = vm.session.builtin_world().fn_proto_val();
let mut func = JsObject::new_empty(EMPTY_SHAPE_ID, fn_proto);
func.set_function(true);
// SAFETY: async_from_sync_unwrap 是 NativeFn 函数项。
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(async_from_sync_unwrap as *const ()) }));
func.set_native_arg_count(1);
let ptr = vm.alloc_object(func);
let obj = unsafe { &mut *ptr };
let res_si = vm.kernel_core.perm_interner().intern(ASFS_RESOLVE_PROP).0;
vm.set_or_create_prop_value(obj, res_si, resolve);
let done_si = vm.kernel_core.perm_interner().intern(ASFS_DONE_PROP).0;
vm.set_or_create_prop_value(obj, done_si, JsValue::bool(done));
vm.add_fn_name_length(obj, "", 1);
JsValue::from_js_object(ptr)
}
/// value unwrap 闭包:读自身 prop 的 resolve 与 done,把入参包装为迭代器结果结算。
fn async_from_sync_unwrap(vm: &mut Vm, args: &[u8]) -> NativeResult {
let callee = vm.reg(254);
if !callee.is_object() {
return NativeResult::Err(oxide_builtins::error::create_type_error(vm, "unwrap handler is invalid"));
}
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
let res_si = vm.kernel_core.perm_interner().intern(ASFS_RESOLVE_PROP).0;
let resolve = vm.resolve_property(callee_obj, res_si).unwrap_or(JsValue::undefined());
let done_si = vm.kernel_core.perm_interner().intern(ASFS_DONE_PROP).0;
let done = vm
.resolve_property(callee_obj, done_si)
.map_or(false, oxide_runtime_api::to_boolean);
let value = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
let result = make_iter_result(vm, value, done);
let _ = vm.call_function_sync(resolve, JsValue::undefined(), &[result]);
NativeResult::Ok(JsValue::undefined())
}
/// `AsyncFromSyncIterator.next(value)`:转发内层 `next`,结果经 continuation 结算。
/// 未传实参时不向 `next` 传参(与 IteratorNext 的空实参调用一致)。
fn async_from_sync_next(vm: &mut Vm, args: &[u8]) -> NativeResult {
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
let inner = match sync_inner(vm, this_val) {
Ok(i) => i,
Err(e) => return NativeResult::Err(e),
};
let next_si = vm.kernel_core.perm_interner().intern("next").0;
let next_fn = match vm.ordinary_get(unsafe { &*inner.as_js_object_ptr() }, next_si, inner) {
Ok(f) => f,
Err(e) => {
let exc = vm
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_error(vm, &e));
return NativeResult::Err(exc);
}
};
let result = if args.len() > 1 {
vm.call_function_sync(next_fn, inner, &[vm.reg(args[1])])
} else {
vm.call_function_sync(next_fn, inner, &[])
};
continue_async_from_sync(vm, inner, result, true)
}
/// `AsyncFromSyncIterator.return(value)`:内层无 `return` 时直接以 `{value, done:true}`
/// 完成,否则转发并经 continuation 结算。
fn async_from_sync_return(vm: &mut Vm, args: &[u8]) -> NativeResult {
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
let arg = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
let inner = match sync_inner(vm, this_val) {
Ok(i) => i,
Err(e) => return NativeResult::Err(e),
};
let return_si = vm.kernel_core.perm_interner().intern("return").0;
let return_fn = match vm.ordinary_get(unsafe { &*inner.as_js_object_ptr() }, return_si, inner) {
Ok(f) => f,
Err(e) => {
let exc = vm
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_error(vm, &e));
return NativeResult::Err(exc);
}
};
if !oxide_builtins::iterator::is_callable(return_fn) {
let result = make_iter_result(vm, arg, true);
let (promise, _, _) = vm.new_promise_capability();
let _ = vm.resolve_promise(promise, result);
return NativeResult::Ok(promise);
}
let result = if args.len() > 1 {
vm.call_function_sync(return_fn, inner, &[arg])
} else {
vm.call_function_sync(return_fn, inner, &[])
};
continue_async_from_sync(vm, inner, result, false)
}
/// `AsyncFromSyncIterator.throw(value)`:内层无 `throw` 时拒绝,否则转发并经 continuation 结算。
fn async_from_sync_throw(vm: &mut Vm, args: &[u8]) -> NativeResult {
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
let arg = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
let inner = match sync_inner(vm, this_val) {
Ok(i) => i,
Err(e) => return NativeResult::Err(e),
};
let throw_si = vm.kernel_core.perm_interner().intern("throw").0;
let throw_fn = match vm.ordinary_get(unsafe { &*inner.as_js_object_ptr() }, throw_si, inner) {
Ok(f) => f,
Err(e) => {
let exc = vm
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_error(vm, &e));
return NativeResult::Err(exc);
}
};
if !oxide_builtins::iterator::is_callable(throw_fn) {
let (promise, _, _reject) = vm.new_promise_capability();
let err = oxide_builtins::error::create_type_error(vm, "sync iterator has no throw method");
let _ = vm.reject_promise(promise, err);
return NativeResult::Ok(promise);
}
let result = if args.len() > 1 {
vm.call_function_sync(throw_fn, inner, &[arg])
} else {
vm.call_function_sync(throw_fn, inner, &[])
};
continue_async_from_sync(vm, inner, result, false)
}
/// `AsyncFromSyncIterator[@@asyncIterator]`:返回自身。
fn async_from_sync_symbol_async_iterator(vm: &mut Vm, args: &[u8]) -> NativeResult {
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
NativeResult::Ok(this_val)
}
+12 -1
View File
@@ -391,11 +391,22 @@ impl Vm {
/// - 异步生成器内(`async_gen_dispatch`)登记异步生成器恢复闭包并置
/// `async_gen_suspended`;普通异步函数走 `async_suspended`。
pub(crate) fn dispatch_await(&mut self, rd: usize) -> Result<(), String> {
let value = self.regs[rd];
self.perform_await(value)
}
/// await 核心:PromiseResolve 包装被等待值、登记恢复反应,置挂起信号。
///
/// # 副作用
/// - 被等待值为原生 Promise 时直接复用,否则建新 promise 并 PromiseResolve。
/// - 经 `perform_promise_then` 登记 fulfill/reject 恢复反应(微任务入队)。
/// - 异步生成器内(`async_gen_dispatch`)登记异步生成器恢复闭包并置
/// `async_gen_suspended`;普通异步函数走 `async_suspended`。
pub(crate) fn perform_await(&mut self, value: JsValue) -> Result<(), String> {
let ctx = match self.async_context {
Some(c) => c,
None => return Err("AWAIT executed outside async function".into()),
};
let value = self.regs[rd];
let promise = if self.is_promise_value(value) {
value
} else {
+18
View File
@@ -826,6 +826,12 @@ pub(crate) fn async_generator_throw(vm: &mut Vm, args: &[u8]) -> NativeResult {
}
}
/// `%AsyncGeneratorPrototype%[@@asyncIterator]`:异步生成器自身即是异步迭代器,返回 `this`。
pub(crate) fn async_generator_symbol_async_iterator(vm: &mut Vm, args: &[u8]) -> NativeResult {
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
NativeResult::Ok(this_val)
}
/// 初始化/重建异步生成器内建对象:`%AsyncGeneratorPrototype%`、
/// `%AsyncGeneratorFunction.prototype%` 与占位 `%AsyncGeneratorFunction%`。
///
@@ -853,6 +859,18 @@ pub(crate) fn init_async_generator_intrinsics(vm: &mut Vm) {
ag_proto.set_shape_id(tag_shape);
let tag_pos = ag_proto.push_prop(JsValue::perm_string(sf.string_ptr(sf.intern("AsyncGenerator").0)));
ag_proto.set_data_meta(tag_pos, PropAttributes::new(false, false, true));
// @@asyncIterator:返回自身(异步生成器是异步可迭代对象,供 for-await-of 消费)。
let aiter_key = oxide_types::private_key::make_well_known_symbol_key(8);
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method_key_static(
&mut ag_proto,
sh,
sf,
aiter_key,
"@@asyncIterator",
unsafe { oxide_types::object::NativeFnPtr::from_raw(async_generator_symbol_async_iterator as *const ()) },
0,
fn_proto_val,
);
vm.async_generator_proto = P::new(*ag_proto);
// %AsyncGeneratorFunction.prototype%:proto = Function.prototype,constructor = %AsyncGeneratorFunction%。
@@ -66,6 +66,10 @@ pub fn bind_symbol(core: &Arc<KernelCore>, session: &KernelSession, global: &mut
"matchAll",
JsValue::from_js_object(session.builtin_world().sym_match_all.as_ptr() as *mut JsObject),
),
(
"asyncIterator",
JsValue::from_js_object(session.builtin_world().sym_async_iterator.as_ptr() as *mut JsObject),
),
] {
bind_well_known_symbol(core, ctor, name, val);
}
+1
View File
@@ -8,6 +8,7 @@
//! session 内存回收;`bindings` 把内置对象绑定到每个 session 的 global 上。
mod async_func;
mod async_from_sync;
mod async_generator;
/// 内置对象绑定模块:向 session 的 global 对象安装 Object/Array/... 及各原型。
pub mod bindings;
+33
View File
@@ -373,6 +373,39 @@ impl Vm {
Ok(())
}
/// PromiseResolve(%Promise%, value)核心:value 为原生 Promise 时读取其
/// `constructor`,与 %Promise% 相同则原样返回;否则新建能力并经能力 resolve
/// 结算(thenable 委托)。constructor getter / 结算抛错时透传原异常值。
pub(crate) fn promise_resolve(&mut self, value: JsValue) -> Result<JsValue, JsValue> {
if self.is_promise_value(value) {
let obj = unsafe { &*value.as_js_object_ptr() };
let ctor_si = self.kernel_core.perm_interner().intern("constructor").0;
let ctor = match self.ordinary_get(obj, ctor_si, value) {
Ok(c) => c,
Err(e) => {
let exc = self
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_error(self, &e));
return Err(exc);
}
};
let intrinsic = JsValue::from_js_object(self.promise_constructor.as_ptr() as *mut JsObject);
if oxide_runtime_api::same_value(ctor, intrinsic) {
return Ok(value);
}
}
let (promise, _resolve, _) = self.new_promise_capability();
if let Err(e) = self.resolve_promise(promise, value) {
let exc = self
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_error(self, &e));
return Err(exc);
}
Ok(promise)
}
/// `PerformPromiseThen` 核心:注册 fulfill/reject 两条反应;已 settle 则直接入队。
pub(crate) fn perform_promise_then(
&mut self, this_val: JsValue, on_fulfilled: JsValue, on_rejected: JsValue,
+24
View File
@@ -782,6 +782,8 @@ impl Vm {
Some(6)
} else if std::ptr::eq(ptr, world.sym_match_all.as_ptr()) {
Some(7)
} else if std::ptr::eq(ptr, world.sym_async_iterator.as_ptr()) {
Some(8)
} else {
None
};
@@ -1520,6 +1522,28 @@ impl Vm {
self.dispatch_for_of_close()?;
}
OpCode::FOR_AWAIT_OF_INIT => {
self.dispatch_for_await_of_init(a)?;
}
OpCode::FOR_AWAIT_OF_NEXT => {
self.dispatch_for_await_of_next(rd)?;
}
OpCode::FOR_AWAIT_OF_DONE => {
self.dispatch_for_await_of_done(rd, a)?;
}
OpCode::FOR_AWAIT_OF_CLOSE => {
self.dispatch_for_await_of_close()?;
// 异步 IteratorClose 可能经 await 挂起(return() 的 promise),
// 挂起时须像 AWAIT 一样让内嵌 dispatch 返回,由恢复方快照状态。
if self.async_suspended || self.async_gen_suspended {
self.profiling.set_instruction_count(steps);
return Ok(JsValue::undefined());
}
}
OpCode::REST_OBJECT => {
self.dispatch_rest_object(rd, a, b)?;
}
+105
View File
@@ -460,6 +460,111 @@ impl Vm {
}
}
/// for-await-of 初始化:按 GetAsyncIterator 协议取异步迭代器(缺失 `@@asyncIterator`
/// 时回退同步迭代器并包 AsyncFromSyncIterator),压入 for-of 迭代器栈。
pub(crate) fn dispatch_for_await_of_init(&mut self, a: usize) -> Result<(), String> {
vm_trace!("FOR_AWAIT_OF_INIT r{}={:?}", a, self.regs[a]);
let iterable = self.regs[a];
match crate::async_from_sync::make_async_iterator(self, iterable) {
Ok(iterator) => {
self.iters.push_for_of(iterator);
self.iters.clear_last_for_of_result();
Ok(())
}
Err(err) => {
self.exception_value = Some(err);
self.pending_error_kind = Some(self.thrown_error_kind(err));
self.unwind()
}
}
}
/// for-await-of 步进:调用迭代器 `next()`,把返回的 promise 写入 rd。
/// 随后的 `AWAIT` 负责挂起等待;next() 抛出时弹出迭代器并透传(与同步 for-of 一致)。
pub(crate) fn dispatch_for_await_of_next(&mut self, rd: usize) -> Result<(), String> {
vm_trace!("FOR_AWAIT_OF_NEXT rd={}", rd);
self.last_uncaught_value = None;
let Some(iterator) = self.iters.last_for_of() else {
return Err("FOR_AWAIT_OF_NEXT without active iterator".into());
};
if !iterator.is_object() {
return Err("FOR_AWAIT_OF_NEXT iterator is not an object".into());
}
let iter_obj = unsafe { &*iterator.as_js_object_ptr() };
let next_si = self.kernel_core.perm_interner().intern("next").0;
let next_fn = match self.ordinary_get(iter_obj, next_si, iterator) {
Ok(v) => v,
Err(e) => return self.throw_for_of_error(e),
};
let result = match self.call_function_sync(next_fn, iterator, &[]) {
Ok(v) => v,
Err(e) => return self.throw_for_of_error(e),
};
self.regs[rd] = result;
Ok(())
}
/// for-await-of 步进完成检查:读取 `AWAIT` 恢复值(a 槽,即迭代器结果对象)的
/// `done`,写入 last_for_of_result 并把 `!done` 写 rd(供 JMP_IF_FALSE 分支)。
pub(crate) fn dispatch_for_await_of_done(&mut self, rd: usize, a: usize) -> Result<(), String> {
vm_trace!("FOR_AWAIT_OF_DONE rd={} r{}={:?}", rd, a, self.regs[a]);
let result = self.regs[a];
if !result.is_object() {
return self.raise_type_error("iterator result is not an object");
}
self.iters.set_last_for_of_result(result);
let result_obj = unsafe { &*result.as_js_object_ptr() };
let done_si = self.kernel_core.perm_interner().intern("done").0;
let done_val = match self.ordinary_get(result_obj, done_si, result) {
Ok(v) => v,
Err(e) => return self.throw_for_of_error(e),
};
self.regs[rd] = JsValue::bool(!to_boolean(done_val));
Ok(())
}
/// for-await-of 收尾:迭代器自然 done 时跳过;否则执行异步 IteratorClose——
/// 调用 `return()`,其返回的 promise 经 await 挂起,恢复后继续循环后的指令。
pub(crate) fn dispatch_for_await_of_close(&mut self) -> Result<(), String> {
vm_trace!("FOR_AWAIT_OF_CLOSE");
let Some(iterator) = self.iters.pop_for_of() else {
return Ok(());
};
let result = self.iters.last_for_of_result();
if result.is_object() {
let result_obj = unsafe { &*result.as_js_object_ptr() };
let done_si = self.kernel_core.perm_interner().intern("done").0;
if let Ok(done_val) = self.ordinary_get(result_obj, done_si, result) {
if to_boolean(done_val) {
return Ok(());
}
}
}
if !iterator.is_object() {
return Ok(());
}
let iter_obj = unsafe { &*iterator.as_js_object_ptr() };
let return_si = self.kernel_core.perm_interner().intern("return").0;
let return_fn = match self.ordinary_get(iter_obj, return_si, iterator) {
Ok(v) => v,
Err(e) => return Err(e),
};
if !return_fn.is_object() {
return Ok(());
}
if !unsafe { &*return_fn.as_js_object_ptr() }.is_function() {
return Ok(());
}
let inner = match self.call_function_sync(return_fn, iterator, &[]) {
Ok(v) => v,
Err(e) => return Err(e),
};
if !inner.is_object() {
return self.raise_type_error("iterator return() result is not an object");
}
self.perform_await(inner)
}
pub(crate) fn dispatch_for_of_done(&mut self, rd: usize) -> Result<(), String> {
vm_trace!("FOR_OF_DONE rd={}", rd);
let Some(iterator) = self.iters.last_for_of() else {