Files
OxideJS-New/crates/oxide_emit/src/expr/template/template_literal.rs
T
pjh123 0c750fa74c emit/kernel/vm/builtins: 常量池键编码 + 键物化真实串值面 + 16 回归钉——emit 侧字面量/键/模板统一改存无标志键编码:lone_surrogates 字面量与模板 cooked 按 oxc marker 解码还原真单元序列(FFFD+hex4≠fffd→surrogate 单元、FFFD+fffd→FFFD、FFFD+非 hex 防御臂),无标志串 encode_key(encode_utf16()) 入池(BMP 无 FFFD 键恒等 = 现值,池条目零漂移),string_pool 集中收口 9 处入池点;interner string_ptr 由单元物化(含孤立→FlatU16、良形→Flat);键物化面改真实 JS 串值(key_si_to_js_value 经 decode_key,Object.keys/ownKeys/entries/Reflect.ownKeys/json reviver 键同源;整数键反解数字串);批内修复三处子集 A/B 差分撞出回归:replace $n 展开按 spec GetSubstitution 重写(digitCount 2/1、越界回退 1 位、越界含 $0 原文输出,node 13 用例对照钉住)、String 构造器 Symbol 路径按 new.target 分流(String(sym)→描述串、new String(sym)→TypeError,恢复 to_string_for_string_constructor)、padStart/padEnd 未给 fill 时按单空格补(原 lossy 串取 'un' 杂质,pre-existing 一并归零);迭代器 dispose 钉改回真值断言(String(Symbol.dispose) 现合法返回描述串);property-escapes 613/0/0(B167 基线 582/31/0,31 归零)、String 子集 963/250/10 vs BASE 949/264/10(14 修 0 回归)、for-of +1(string-astral-truncated)、五 crate 113 套件 2680/0、clippy/fmt 零新增(JSON 面与全量 test262 收尾在 131.2 后续 commit 闭合)
2026-09-14 03:04:23 +00:00

52 lines
1.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 模板字面量 emit:`emit_template_literal_expression` 生成 TEMPLATE_STR 指令
//! 拼接字面量段与内插表达式。
use crate::{CompileCtx, Emitter};
use oxide_bytecode::module::Constant;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
impl Emitter {
pub(crate) fn emit_template_literal_expression(
&self, tl: &oxide_parser::TemplateLiteral, ctx: &mut CompileCtx,
) -> Result<u32, String> {
let r = ctx.alloc_reg();
let quasis = &tl.quasis;
let expressions = &tl.expressions;
let segment_count = quasis.len() + expressions.len();
let expr_regs: Vec<u32> = expressions
.iter()
.map(|e| self.emit_expression(e, ctx))
.collect::<Result<Vec<_>, _>>()?;
let mut quasi_keys: Vec<String> = Vec::with_capacity(quasis.len());
for q in quasis {
quasi_keys.push(match &q.value.cooked {
Some(c) => crate::shared::string_pool::pool_key_marker(c, q.lone_surrogates),
None => String::new(),
});
}
let quasi_const_idxs: Vec<u16> = quasi_keys
.iter()
.map(|s| ctx.add_constant(Constant::String(s.clone())))
.collect();
// 容量提示按单元数口径(键文本经物化解码还原单元序列)。
let total_len_hint: usize = quasi_keys.iter().map(|k| oxide_kernel::string_forge::decode_key(k).len()).sum();
let mut parts = Vec::with_capacity(quasi_const_idxs.len() * 2);
let mut expr_iter = expr_regs.iter();
for const_idx in quasi_const_idxs.iter() {
parts.push(*const_idx as u32 & 0x7FFF_FFFF);
if let Some(expr_reg) = expr_iter.next() {
parts.push(0x8000_0000u32 | (*expr_reg));
}
}
ctx.inst(Inst::template_str(Operand::Reg(r), segment_count as u32, total_len_hint as u16, &parts));
Ok(r)
}
}