mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 18:51:13 +08:00
fix: 删后裸读已知全局内置名经 A 侧抛 ReferenceError
This commit is contained in:
@@ -65,7 +65,13 @@ impl Emitter {
|
||||
// 隐式全局槽(读侧登记与写侧登记同属一个槽)同样读全局对象属性:属性是
|
||||
// 隐式全局值的唯一真源,嵌套函数内 delete 真删后外层裸读据此可见,引擎侧
|
||||
// 镜像槽不反映删除。
|
||||
if self.is_global_tier_name(ctx, name) || ctx.is_implicit_global_reg(var_reg) {
|
||||
// 已知 builtin 名(非局部遮蔽)同走全局对象属性:镜像槽无法自区分「A 侧
|
||||
// 缺位」与「A 侧在位值 undefined」(两者槽值皆 undefined),delete 真删后
|
||||
// 裸读须经属性在位判定抛 ReferenceError。
|
||||
if self.is_global_tier_name(ctx, name)
|
||||
|| ctx.is_implicit_global_reg(var_reg)
|
||||
|| (ctx.is_builtin(name) && !ctx.is_local_shadowing_builtin(name))
|
||||
{
|
||||
let key_idx = ctx.add_constant(Constant::String(name.to_string()));
|
||||
ctx.inst(Inst::new(OpCode::LOAD_GLOBAL, Operand::Reg(r), Operand::Const(key_idx), Operand::None));
|
||||
} else {
|
||||
@@ -145,7 +151,19 @@ impl Emitter {
|
||||
Operand::None,
|
||||
));
|
||||
} else if let Some(reg) = ctx.scopes.symbols.lookup_any(name) {
|
||||
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(reg), Operand::None));
|
||||
// 已知 builtin 名(非局部遮蔽)读 A 侧全局对象属性,与静态读臂同形;
|
||||
// 局部遮蔽绑定保持 LOAD_VAR 读局部槽。
|
||||
if ctx.is_builtin(name) && !ctx.is_local_shadowing_builtin(name) {
|
||||
let key_idx = ctx.add_constant(Constant::String(name.to_string()));
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::LOAD_GLOBAL,
|
||||
Operand::Reg(result_reg),
|
||||
Operand::Const(key_idx),
|
||||
Operand::None,
|
||||
));
|
||||
} else {
|
||||
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(reg), Operand::None));
|
||||
}
|
||||
} else {
|
||||
let undef_idx = ctx.add_constant(Constant::Undefined);
|
||||
ctx.inst(Inst::load_const(Operand::Reg(result_reg), undef_idx));
|
||||
|
||||
@@ -372,7 +372,10 @@ impl Emitter {
|
||||
// ReferenceError(typeof 对 unresolvable 引用不抛)。
|
||||
let implicit_global = binding.is_some_and(|(b, _)| ctx.is_implicit_global_reg(b.reg));
|
||||
let is_tier = self.is_global_tier_name(ctx, name);
|
||||
if !in_with_dynamic && !captured && (is_tier || binding.is_none() || implicit_global) {
|
||||
// 已知 builtin 名(非局部遮蔽)同走属性路:delete 真删后缺失 →
|
||||
// "undefined" 而非经镜像槽读 undefined 同值巧合。
|
||||
let is_builtin_slot = ctx.is_builtin(name) && !ctx.is_local_shadowing_builtin(name);
|
||||
if !in_with_dynamic && !captured && (is_tier || binding.is_none() || implicit_global || is_builtin_slot) {
|
||||
let key_idx = ctx.add_constant(Constant::String(name.to_string()));
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
|
||||
Reference in New Issue
Block a user