mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-26 19:51:11 +08:00
feat: GetAsyncIterator 已定义非可调用方法抛 TypeError,补齐三态分支
This commit is contained in:
Generated
+19
-19
@@ -1160,7 +1160,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_builtins"
|
name = "oxide_builtins"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"fast-float",
|
"fast-float",
|
||||||
@@ -1185,7 +1185,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_bytecode"
|
name = "oxide_bytecode"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1193,7 +1193,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cfg"
|
name = "oxide_cfg"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_emit",
|
"oxide_emit",
|
||||||
@@ -1204,7 +1204,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cli"
|
name = "oxide_cli"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
@@ -1226,7 +1226,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_code_cache"
|
name = "oxide_code_cache"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lru",
|
"lru",
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
@@ -1235,7 +1235,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_compiler"
|
name = "oxide_compiler"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1255,7 +1255,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_dce"
|
name = "oxide_dce"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1269,7 +1269,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_emit"
|
name = "oxide_emit"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
@@ -1284,7 +1284,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_engine"
|
name = "oxide_engine"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_compiler",
|
"oxide_compiler",
|
||||||
@@ -1296,7 +1296,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_ir"
|
name = "oxide_ir"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1305,7 +1305,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_kernel"
|
name = "oxide_kernel"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
@@ -1319,7 +1319,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_liveness"
|
name = "oxide_liveness"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1331,7 +1331,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_log"
|
name = "oxide_log"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
@@ -1340,7 +1340,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_parser"
|
name = "oxide_parser"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
"oxc_ast",
|
"oxc_ast",
|
||||||
@@ -1355,7 +1355,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_regalloc"
|
name = "oxide_regalloc"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1371,7 +1371,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_runtime_api"
|
name = "oxide_runtime_api"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
@@ -1384,7 +1384,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_test262"
|
name = "oxide_test262"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_compiler",
|
"oxide_compiler",
|
||||||
@@ -1402,7 +1402,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_types"
|
name = "oxide_types"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
@@ -1415,7 +1415,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_vm"
|
name = "oxide_vm"
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.13.9"
|
version = "0.13.10"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
rust-version = "1.80"
|
rust-version = "1.80"
|
||||||
|
|||||||
@@ -19,16 +19,19 @@ const INNER_PROP: &str = "__inner__";
|
|||||||
/// `@@asyncIterator` 的 well-known symbol 键序号。
|
/// `@@asyncIterator` 的 well-known symbol 键序号。
|
||||||
const ASYNC_ITERATOR_SYMBOL_ID: u32 = 8;
|
const ASYNC_ITERATOR_SYMBOL_ID: u32 = 8;
|
||||||
|
|
||||||
/// GetAsyncIterator(ECMA-262):取 `value[@@asyncIterator]`,不可调用时回退同步
|
/// GetAsyncIterator(ECMA-262):取 `value[@@asyncIterator]`,可调用则调用;
|
||||||
/// 迭代器并包 AsyncFromSyncIterator。
|
/// undefined/null 时回退同步迭代器并包 AsyncFromSyncIterator;
|
||||||
|
/// 已定义但不可调用时抛 TypeError。
|
||||||
///
|
///
|
||||||
/// # 步骤
|
/// # 步骤
|
||||||
/// 1. ToObject 后读取 `@@asyncIterator`,可调用则调用并校验结果为对象。
|
/// 1. ToObject 后读取 `@@asyncIterator`,可调用则调用并校验结果为对象。
|
||||||
/// 2. 否则经同步迭代协议取迭代器包装器,包成 AsyncFromSyncIterator。
|
/// 2. 已定义但不可调用时抛 TypeError(GetMethod 步 4)。
|
||||||
|
/// 3. undefined/null 时经同步迭代协议取迭代器包装器,包成 AsyncFromSyncIterator。
|
||||||
///
|
///
|
||||||
/// # 返回值
|
/// # 返回值
|
||||||
/// - `Ok(iterator)`:异步迭代器对象;
|
/// - `Ok(iterator)`:异步迭代器对象;
|
||||||
/// - `Err`:`@@asyncIterator` getter/调用抛错或 ToObject 失败,透传原异常值。
|
/// - `Err`:`@@asyncIterator` getter/调用抛错或 ToObject 失败(透传原异常值),
|
||||||
|
/// 或已定义但不可调用(构造 TypeError)。
|
||||||
pub(crate) fn make_async_iterator(vm: &mut Vm, value: JsValue) -> Result<JsValue, JsValue> {
|
pub(crate) fn make_async_iterator(vm: &mut Vm, value: JsValue) -> Result<JsValue, JsValue> {
|
||||||
let obj_value = if value.is_object() {
|
let obj_value = if value.is_object() {
|
||||||
value
|
value
|
||||||
@@ -69,6 +72,10 @@ pub(crate) fn make_async_iterator(vm: &mut Vm, value: JsValue) -> Result<JsValue
|
|||||||
}
|
}
|
||||||
return Ok(iterator);
|
return Ok(iterator);
|
||||||
}
|
}
|
||||||
|
if !method.is_null() && !method.is_undefined() {
|
||||||
|
// GetMethod 步 4:已定义非可调用方法 → TypeError,不落入同步回退。
|
||||||
|
return Err(oxide_builtins::error::create_type_error(vm, "value is not async iterable"));
|
||||||
|
}
|
||||||
let sync = oxide_builtins::iterator::make_iterator_for_value(vm, value)?;
|
let sync = oxide_builtins::iterator::make_iterator_for_value(vm, value)?;
|
||||||
Ok(vm.create_async_from_sync_iterator(sync))
|
Ok(vm.create_async_from_sync_iterator(sync))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,3 +409,80 @@ fn t21_async_gen_multi_layer_escape_no_signal_leak_into_async_func() {
|
|||||||
.to_string();
|
.to_string();
|
||||||
assert_eq!(eval(&source), "\"body,c2,c1,f-body,f-finally|f-done|g:true:42\"");
|
assert_eq!(eval(&source), "\"body,c2,c1,f-body,f-finally|f-done|g:true:42\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// T22:`@@asyncIterator` 已定义但不可调用(对象形)——GetMethod 步 4 抛 TypeError
|
||||||
|
// 入委托 body,可捕获;同步 `@@iterator` getter 不得被触发(若触发,拒绝原因会是
|
||||||
|
// getter 抛值而非 TypeError)。
|
||||||
|
#[test]
|
||||||
|
fn t22_async_iterator_not_callable_object_typeerror() {
|
||||||
|
assert_eq!(
|
||||||
|
eval(
|
||||||
|
"async function* g() { try { yield* { \
|
||||||
|
get [Symbol.iterator]() { throw 'no-sync-iter'; }, \
|
||||||
|
[Symbol.asyncIterator]: {} }; } \
|
||||||
|
catch (e) { return 'caught:' + e.name; } } \
|
||||||
|
(async function run() { const it = g(); const r = await it.next(); \
|
||||||
|
return r.value + ':' + r.done; })()"
|
||||||
|
),
|
||||||
|
"\"caught:TypeError:true\""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// T23:`@@asyncIterator` 为 null——null/undefined 形保持同步回退,元素正常让出。
|
||||||
|
#[test]
|
||||||
|
fn t23_async_iterator_null_sync_fallback() {
|
||||||
|
assert_eq!(
|
||||||
|
eval(
|
||||||
|
"async function* g() { yield* { [Symbol.asyncIterator]: null, \
|
||||||
|
[Symbol.iterator]: function* () { yield 1; yield 2; } }; } \
|
||||||
|
(async function run() { const it = g(); \
|
||||||
|
const a = (await it.next()).value; const b = (await it.next()).value; \
|
||||||
|
const c = (await it.next()).done; return a + ',' + b + ',' + c; })()"
|
||||||
|
),
|
||||||
|
"\"1,2,true\""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// T24:`@@asyncIterator` 为 undefined——undefined/null 形保持同步回退,元素正常让出。
|
||||||
|
#[test]
|
||||||
|
fn t24_async_iterator_undefined_sync_fallback() {
|
||||||
|
assert_eq!(
|
||||||
|
eval(
|
||||||
|
"async function* g() { yield* { [Symbol.asyncIterator]: undefined, \
|
||||||
|
[Symbol.iterator]: function* () { yield 3; } }; } \
|
||||||
|
(async function run() { const it = g(); \
|
||||||
|
const a = (await it.next()).value; const b = (await it.next()).done; \
|
||||||
|
return a + ':' + b; })()"
|
||||||
|
),
|
||||||
|
"\"3:true\""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// T25:for-await-of 臂——`@@asyncIterator` 已定义但不可调用,TypeError 被外围
|
||||||
|
// try/catch 捕获(验证 Err 臂经 unwind 透传原异常值)。
|
||||||
|
#[test]
|
||||||
|
fn t25_for_await_of_not_callable_typeerror_caught() {
|
||||||
|
assert_eq!(
|
||||||
|
eval(
|
||||||
|
"async function f() { try { for await (const x of { [Symbol.asyncIterator]: {} }) { } } \
|
||||||
|
catch (e) { return 'caught:' + e.name; } } \
|
||||||
|
(async function run() { return await f(); })()"
|
||||||
|
),
|
||||||
|
"\"caught:TypeError\""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// T26:`@@asyncIterator` 在原型上不可调用(boolean 形)——ToObject 装箱后读原型,
|
||||||
|
// GetMethod 步 4 抛 TypeError,可捕获(覆盖原始值走原型链的形态)。
|
||||||
|
#[test]
|
||||||
|
fn t26_async_iterator_not_callable_boolean_primitive() {
|
||||||
|
assert_eq!(
|
||||||
|
eval(
|
||||||
|
"Boolean.prototype[Symbol.asyncIterator] = {}; \
|
||||||
|
async function* g() { try { yield* true; } catch (e) { return 'caught:' + e.name; } } \
|
||||||
|
(async function run() { const it = g(); const r = await it.next(); \
|
||||||
|
return r.value + ':' + r.done; })()"
|
||||||
|
),
|
||||||
|
"\"caught:TypeError:true\""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user