mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-27 04:01:11 +08:00
types/kernel/vm/builtins: JsString UTF-16 载荷层(FlatU16 变体 + 单元入口)——原 UTF-8 载荷只存 well-formed 串、孤立 surrogate lossy 转 U+FFFD 回写,FromCodePoint/属性转义与字符串面码点语义皆破;现载荷直存 [u64;3](Flat well-formed / FlatU16 单元序列 / Cons 拼接),utf16_len 独立 32 位字,32B 布局锚保持;from_units 智能路由(含孤立→FlatU16),as_str 仅限 Flat,units/units_borrowed 单元借用,as_lossy_str 宽容读;string_forge 编解码 surrogate 感知(孤立 surrogate 逃逸 hex4 编码、解码展开 astral 代理对、string_ptr 由单元物化);VmHost 单元物化/分配/查询入口 + runtime_api 单元 API;字符串内置全法单元化(charAt/slice/substr/split/replace/search/match/matchAll 单元定位;空模式边界:search→0、match→[""]、replace 插 0 位、matchAll 游标耗尽守卫;接收者 ToString 错误原样传播);正则内置单元化(exec/test/search/symbol_* 单元文本,替换串 \u{...} 与孤立 surrogate 文本处理,lastIndex 与 matchAll 游标单元化);字符串迭代器码点化(高代理+后续低代理成对产出,astral 值回真实码点);String(Symbol) 抛 TypeError;回归钉更新五处(charAt/split/slice/substr 单元精确语义 + dispose 钉改 TypeError 断言);四 crate 全绿(oxide_vm 98 套件 2403 测)+ clippy/fmt 零新增
This commit is contained in:
@@ -1487,6 +1487,30 @@ fn get_iterator<H: VmHost>(vm: &mut H, value: JsValue) -> Result<Option<(JsValue
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// 字符串迭代的一个产出元素:单个码元,或整个合法代理对(超平面字符,
|
||||
/// 按 Unicode 标量产出单元素)。
|
||||
#[derive(Clone, Copy)]
|
||||
enum StrIterElem {
|
||||
One(u16),
|
||||
Pair(u16, u16),
|
||||
}
|
||||
|
||||
/// 单元序列的字符串迭代步进(Unicode 标量口径):合法代理对整体产出一个
|
||||
/// 2 单元元素(游标推进 2),否则产出单单元元素(推进 1);越界产出 None。
|
||||
fn str_iter_step(units: &[u16], at: usize) -> (usize, Option<StrIterElem>) {
|
||||
let Some(&u) = units.get(at) else {
|
||||
return (0, None);
|
||||
};
|
||||
if (0xD800..=0xDBFF).contains(&u) {
|
||||
if let Some(lo) = units.get(at + 1) {
|
||||
if (0xDC00..=0xDFFF).contains(lo) {
|
||||
return (at + 2, Some(StrIterElem::Pair(u, *lo)));
|
||||
}
|
||||
}
|
||||
}
|
||||
(at + 1, Some(StrIterElem::One(u)))
|
||||
}
|
||||
|
||||
fn next_array_like<H: VmHost>(
|
||||
vm: &mut H, wrapper: &mut JsObject, inner: JsValue, index_si: u32,
|
||||
) -> Result<Option<JsValue>, JsValue> {
|
||||
@@ -1513,18 +1537,47 @@ fn next_array_like<H: VmHost>(
|
||||
}
|
||||
|
||||
if inner.is_string() {
|
||||
// index 槽在字符串分支存字节游标(每步推进一个 char 的 UTF-8 宽度)而非
|
||||
// 元素序号:该槽只被 next 内部读写、无外部消费者,包装器创建后类型固定
|
||||
// 不跨类型复用,故可安全借用语义(字符串=字节偏移)。
|
||||
let byteoff = current_index(vm, wrapper, index_si);
|
||||
// 源串裸指针借用压缩到单个表达式:ch 是 Copy 的 char,不携带借用,
|
||||
// index 槽在字符串分支存游标(按载荷形态钉死):单元形态(FlatU16/Cons)
|
||||
// 存单元偏移;Flat 形态存 字节偏移×2(与单元口径对齐,每字符步长按其
|
||||
// UTF-16 单元数)。游标只被 next 内部读写、无外部消费者,包装器创建后
|
||||
// 类型固定不跨类型复用。
|
||||
//
|
||||
// 产出按 Unicode 标量(规格口径):合法代理对整体产出一个 2 单元元素,
|
||||
// 孤立 surrogate 各产出 1 单元元素。
|
||||
let cursor = current_index(vm, wrapper, index_si);
|
||||
// 源串裸指针借用压缩到单个表达式:产出元素为 Copy 值,不携带借用,
|
||||
// 之后对 VM 状态的可变访问不再与源串借用共存。
|
||||
let ch = unsafe { &*inner.as_string_ptr() }.as_str()[byteoff..].chars().next();
|
||||
if let Some(ch) = ch {
|
||||
vm.set_or_create_prop_value(wrapper, index_si, JsValue::int((byteoff + ch.len_utf8()) as i32));
|
||||
let value = match vm.single_char(ch) {
|
||||
Some(v) => v,
|
||||
None => vm.new_string(&ch.to_string()),
|
||||
let (next_cursor, elem): (usize, Option<StrIterElem>) = unsafe {
|
||||
let sp = &*inner.as_string_ptr();
|
||||
if sp.is_flat() {
|
||||
let byteoff = cursor / 2;
|
||||
match sp.as_str().get(byteoff..).unwrap_or("").chars().next() {
|
||||
// 超平面字符:出整个代理对(单元素),游标跳越字符。
|
||||
Some(c) if c.len_utf8() == 4 => {
|
||||
let v = c as u32;
|
||||
let hi = (0xD800 + (((v - 0x10000) >> 10) & 0x3FF)) as u16;
|
||||
let lo = (0xDC00 + ((v - 0x10000) & 0x3FF)) as u16;
|
||||
((byteoff + 4) * 2, Some(StrIterElem::Pair(hi, lo)))
|
||||
}
|
||||
Some(c) => ((byteoff + c.len_utf8()) * 2, Some(StrIterElem::One(c as u16))),
|
||||
None => (0, None),
|
||||
}
|
||||
} else if let Some(units) = sp.units_borrowed() {
|
||||
str_iter_step(units, cursor)
|
||||
} else {
|
||||
let units = sp.units();
|
||||
str_iter_step(&units, cursor)
|
||||
}
|
||||
};
|
||||
if let Some(elem) = elem {
|
||||
vm.set_or_create_prop_value(wrapper, index_si, JsValue::int(next_cursor as i32));
|
||||
let value = match elem {
|
||||
// ASCII 单元走单字符缓存零分配,其余(含孤立 surrogate)落串创建。
|
||||
StrIterElem::One(u) => match vm.single_unit(u) {
|
||||
Some(v) => v,
|
||||
None => vm.new_string_units(&[u]),
|
||||
},
|
||||
StrIterElem::Pair(hi, lo) => vm.new_string_units(&[hi, lo]),
|
||||
};
|
||||
return Ok(Some(make_iter_result(vm, value, false)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user