mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: 顶层类声明绑定改为可变
This commit is contained in:
@@ -279,6 +279,10 @@ impl Emitter {
|
||||
/// 建立 TDZ 占位)。使声明点之前的读取在编译期可分辨为 TDZ 而非隐式全局,
|
||||
/// 声明点复用预登记槽位。
|
||||
///
|
||||
/// class 声明绑定外层形态是可变的(`let` 类),`C = null` 合法;类定义期
|
||||
/// 类体(方法/构造器/访问器)对类名的引用由类自身注入的独立不可变绑定承载,
|
||||
/// 不依赖此预声明标志。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 只扫描直接子语句;不递归块/if/for/while/switch case/try 区(嵌套块与
|
||||
/// switch CaseBlock 各自预声明;单语句 body 不接受 lexical 声明——lexical
|
||||
@@ -307,7 +311,7 @@ impl Emitter {
|
||||
if let Some(id) = &cd.id {
|
||||
check_restricted_global_lexical(id.name.as_str(), global_lexical)?;
|
||||
let reg = ctx.alloc_reg();
|
||||
let _ = ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true);
|
||||
let _ = ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Let, false);
|
||||
}
|
||||
}
|
||||
Statement::ExportNamedDeclaration(exp) => {
|
||||
@@ -329,8 +333,8 @@ impl Emitter {
|
||||
let _ = ctx.declare_predeclared(
|
||||
id.name.as_str(),
|
||||
reg,
|
||||
VariableDeclarationKind::Const,
|
||||
true,
|
||||
VariableDeclarationKind::Let,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -343,8 +347,7 @@ impl Emitter {
|
||||
if let Some(id) = &cd.id {
|
||||
check_restricted_global_lexical(id.name.as_str(), global_lexical)?;
|
||||
let reg = ctx.alloc_reg();
|
||||
let _ =
|
||||
ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true);
|
||||
let _ = ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Let, false);
|
||||
}
|
||||
}
|
||||
ExportDefaultDeclarationKind::FunctionDeclaration(fd) => {
|
||||
|
||||
@@ -853,3 +853,12 @@ fn class_declaration_captured_name_cell_still_initialized() {
|
||||
.unwrap();
|
||||
assert_num(result, 51.0);
|
||||
}
|
||||
|
||||
// 类声明的外层绑定是可变的(let 类):顶层重赋类名合法并生效。
|
||||
// 类体内对类名的引用另由独立不可变绑定承载,见 name-binding/const.js 语料。
|
||||
#[test]
|
||||
fn class_declaration_outer_binding_is_mutable() {
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(&mut vm, "class A { m(){ return 1; } } A = 1; A").unwrap();
|
||||
assert_num(result, 1.0);
|
||||
}
|
||||
|
||||
@@ -96,3 +96,19 @@ fn dependent_module_namespace_contract_intact() {
|
||||
let r = probe(&mut vm, "globalThis.__dep === true");
|
||||
assert!(r.is_bool() && r.as_bool(), "依赖命名空间值应正确流入,实际 {r:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exported_class_declaration_binding_is_mutable() {
|
||||
// 模块顶层 class 外层绑定是可变 let 类:`export class` 与具名
|
||||
// `export default class` 均允许声明后重赋(CreateMutableBinding)。
|
||||
let allocator = oxide_parser::Allocator::default();
|
||||
let source = "export class C {}\nC = null;\nexport default class D {}\nD = null;\nglobalThis.__mutable = C === null && D === null;";
|
||||
let program = oxide_parser::parse_module(&allocator, source).expect("parse module");
|
||||
let module = Compiler::new()
|
||||
.compile_module(&program, "test.mjs", &mut FileLoader)
|
||||
.expect("compile module");
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&Arc::new(module)).expect("module run");
|
||||
let r = probe(&mut vm, "globalThis.__mutable === true");
|
||||
assert!(r.is_bool() && r.as_bool(), "模块 class 外层绑定应可重赋,实际 {r:?}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user