fix: 字符串面 GetIterator 尊重用户 @@iterator 覆盖

String 臂此前对原始串与装箱串一律走码元步进、忽略用户覆盖的
@@iterator。改为按 GetMethod 语义以值自身为 receiver 读 @@iterator
(原始串落 String.prototype、装箱串读自身→原型链),默认迭代器
自别名即 @@iterator 槽本身、以绑定层捕获的函数指针比较走快速
路径避免递归回本臂;覆盖则调用、receiver 为值。peek 对非字符串
原始值先装箱再读 @@iterator;Iterator.from 增 GetIteratorFlattenable
前置校验,非字符串原始值非对象 → TypeError(不装箱)。
This commit is contained in:
2026-09-15 02:18:12 +00:00
parent 4b0b52ade3
commit 0f5bd1577e
4 changed files with 252 additions and 6 deletions
+13
View File
@@ -301,6 +301,11 @@ pub struct BuiltinWorld {
pub set_iterator_proto: P<JsObject>,
/// `%StringIteratorPrototype%`:String.prototype[@@iterator] 返回的迭代器。
pub string_iterator_proto: P<JsObject>,
/// String.prototype[@@iterator] 默认迭代器函数对象指针(绑定层捕获,原始值指针、
/// 所有权归 wrapper 释放表)。String 臂覆盖判定以此做指针比较:默认迭代器即
/// @@iterator 槽本身(自别名),集合式锚点槽比较不可复用,须独立存指针。
/// `Cell` 供绑定层经 `&Arc<BuiltinWorld>` 共享引用写入。
pub string_default_iterator: std::cell::Cell<*const JsObject>,
/// `%RegExpStringIteratorPrototype%`:matchAll 返回的迭代器。
pub regexp_string_iterator_proto: P<JsObject>,
/// `%IteratorHelperPrototype%`:Iterator helpers 结果对象的共享原型,链到 %IteratorPrototype%。
@@ -1246,9 +1251,12 @@ impl BuiltinWorld {
let iterator_helper_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let disposable_stack_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let async_disposable_stack_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
// 默认迭代器指针初值空(绑定层随后经 bind_string 捕获写入)。
let string_default_iterator = std::cell::Cell::new(std::ptr::null());
let world = Self {
object_proto,
string_default_iterator,
array_proto,
function_proto,
string_proto,
@@ -1687,6 +1695,11 @@ impl BuiltinWorld {
let world = BuiltinWorld {
object_proto,
string_default_iterator: std::cell::Cell::new(if dirty.string {
std::ptr::null()
} else {
current.string_default_iterator.get()
}),
array_proto,
function_proto,
string_proto,