mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
perf: 程序模块入口名字收集切单趟,删旧收集器
This commit is contained in:
Generated
+20
-20
@@ -1160,7 +1160,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_builtins"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"fast-float",
|
||||
@@ -1185,7 +1185,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_bytecode"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"oxide_log",
|
||||
@@ -1193,7 +1193,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_cfg"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_emit",
|
||||
@@ -1204,7 +1204,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_cli"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"bumpalo",
|
||||
@@ -1228,7 +1228,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_code_cache"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"lru",
|
||||
"oxide_bytecode",
|
||||
@@ -1237,7 +1237,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_compiler"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_cfg",
|
||||
@@ -1257,7 +1257,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_dce"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_cfg",
|
||||
@@ -1271,7 +1271,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_emit"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"oxc_allocator",
|
||||
@@ -1286,7 +1286,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_engine"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_compiler",
|
||||
@@ -1298,7 +1298,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_ir"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_log",
|
||||
@@ -1307,7 +1307,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_kernel"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"dashmap",
|
||||
@@ -1321,7 +1321,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_liveness"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_cfg",
|
||||
@@ -1333,7 +1333,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_log"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
@@ -1342,11 +1342,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_net"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
|
||||
[[package]]
|
||||
name = "oxide_parser"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
@@ -1361,7 +1361,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_regalloc"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_cfg",
|
||||
@@ -1377,7 +1377,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_runtime_api"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
@@ -1390,7 +1390,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_test262"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_compiler",
|
||||
@@ -1410,7 +1410,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_types"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"dashmap",
|
||||
@@ -1423,7 +1423,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_vm"
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"chrono",
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
rust-version = "1.80"
|
||||
|
||||
@@ -18,13 +18,7 @@ use std::collections::HashSet;
|
||||
|
||||
pub(crate) use captured::collect_captured_bindings;
|
||||
pub(crate) use guard::has_nested_function;
|
||||
pub(crate) use names::collect_block_level_decl_names;
|
||||
pub(crate) use names::collect_direct_lexical_names;
|
||||
pub(crate) use names::collect_fn_scope_names;
|
||||
pub(crate) use names::collect_own_binding_names;
|
||||
pub(crate) use names::collect_top_level_function_names;
|
||||
pub(crate) use names::collect_top_level_function_names_ordered;
|
||||
pub(crate) use names::collect_var_binding_names;
|
||||
pub(crate) use names::FnScopeNames;
|
||||
pub(crate) use upvalues::collect_upvalue_names;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -434,10 +434,18 @@ impl Emitter {
|
||||
// 让 next_reg 与 builtin 槽位对齐,参数在 builtin 槽之后分配。
|
||||
ctx.reset_regs();
|
||||
|
||||
// 函数作用域六个名字面单趟收集(形参名先注入 own 面):本函数体编译链
|
||||
// 各调用点(参数 prologue / builtin 排除 / 入口实例化)共用此结果。
|
||||
// 函数作用域八个名字面单趟收集(形参名先注入 own 面与抑制面):本函数体
|
||||
// 编译链各调用点(参数 prologue / builtin 排除 / 块函数 / 入口实例化)
|
||||
// 共用此结果。
|
||||
let param_name_refs: Vec<&str> = param_specs.iter().map(|s| s.register_name()).collect();
|
||||
let scope_names = collect_fn_scope_names(¶m_name_refs, body_stmts);
|
||||
let mut scope_names = collect_fn_scope_names(¶m_name_refs, body_stmts);
|
||||
// 抑制集口径是规范 paramNames(含解构叶名),合并趟形参注入按登记名,
|
||||
// 叶名在此补入(登记名已入集,重复插入无副作用)。
|
||||
for name in ctx.param_names.iter() {
|
||||
if !param_name_refs.contains(&name.as_str()) {
|
||||
scope_names.block_fn_suppressed.insert(name.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let param_base = self.emit_params_prologue(
|
||||
param_specs,
|
||||
@@ -478,10 +486,10 @@ impl Emitter {
|
||||
// (形参/词法声明同名,该形退化为纯块作用域)则不建。求值期声明点把
|
||||
// 函数对象写回此绑定(见函数声明 emit)。
|
||||
if !ctx.is_strict {
|
||||
ctx.block_fn_suppressed = self.collect_block_fn_suppressed_names(body_stmts, &ctx.param_names);
|
||||
for name in self.collect_block_function_names(body_stmts) {
|
||||
if !ctx.block_fn_suppressed.contains(&name) {
|
||||
self.predeclare_var_name(&name, &mut ctx);
|
||||
ctx.block_fn_suppressed = scope_names.block_fn_suppressed.clone();
|
||||
for name in &scope_names.block_function_names {
|
||||
if !ctx.block_fn_suppressed.contains(name) {
|
||||
self.predeclare_var_name(name, &mut ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1013,13 +1021,12 @@ impl Emitter {
|
||||
// 语义覆盖此初值。
|
||||
let mut captured_entry_names = scope_names.var_binding_names.clone();
|
||||
// 块级函数外层 var 名与 instantiate_var_bindings 同源并入;抑制名(形参/
|
||||
// 词法声明同名)无外层绑定,不并入。抑制集在此独立计算:本循环早于函数体
|
||||
// 的 block_fn_suppressed 构建。
|
||||
// 词法声明同名)无外层绑定,不并入。
|
||||
if !ctx.is_strict {
|
||||
let suppressed = self.collect_block_fn_suppressed_names(body_stmts, &ctx.param_names);
|
||||
for name in self.collect_block_function_names(body_stmts) {
|
||||
if !suppressed.contains(&name) {
|
||||
captured_entry_names.insert(name);
|
||||
let suppressed = &scope_names.block_fn_suppressed;
|
||||
for name in &scope_names.block_function_names {
|
||||
if !suppressed.contains(name) {
|
||||
captured_entry_names.insert(name.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1107,9 +1114,9 @@ impl Emitter {
|
||||
.filter_map(|fd| fd.id.as_ref())
|
||||
.map(|id| id.name.as_str())
|
||||
.collect();
|
||||
for name in self.collect_block_function_names(body_stmts) {
|
||||
if !ctx.block_fn_suppressed.contains(&name) && !labeled_hoisted.contains(name.as_str()) {
|
||||
name_set.insert(name);
|
||||
for name in &scope_names.block_function_names {
|
||||
if !ctx.block_fn_suppressed.contains(name) && !labeled_hoisted.contains(name.as_str()) {
|
||||
name_set.insert(name.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
//! emit 前置 pass,块级函数名收集:web-compat 外层 var 绑定实例化支撑——
|
||||
//! 语句树内块级普通函数声明名源序去重收集、词法声明名抑制集(块函数名与词法名
|
||||
//! 同名时退化为纯块作用域)、形参名 ∪ 词法名抑制集构建。
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::capture::collect_binding_pattern_names;
|
||||
use crate::Emitter;
|
||||
use oxide_parser::{Declaration, Statement, VariableDeclarationKind};
|
||||
|
||||
impl Emitter {
|
||||
/// 递归收集语句树内块级普通函数声明名(源序去重),供 sloppy 模式浏览器兼容
|
||||
/// 行为(Annex B.3.3 为块级普通函数声明建外层 var 绑定)下的外层 var 绑定实例化。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 只收普通 `FunctionDeclaration`:Annex B.3.3 的 web-compat 仅改写普通函数
|
||||
/// 声明,async 函数、生成器与 async 生成器是各自独立的块级词法绑定,块外
|
||||
/// 不可见,不入名集。
|
||||
/// - 调用点直接子级(函数体/程序顶层直接子句)是提升 var 声明,非块级
|
||||
/// 函数,不收集;进入嵌套语句(块/if/循环/switch case/try 各区)后的
|
||||
/// 函数声明才是块级。
|
||||
/// - 不递归进嵌套函数体:那是独立编译单元,其内部块函数名由该单元自身收集。
|
||||
/// - switch 不推作用域(case 内函数声明随外层块),收集须进入 case 才能到达
|
||||
/// case 内的 for/块等块级形。
|
||||
pub(crate) fn collect_block_function_names(&self, statements: &[Statement]) -> Vec<String> {
|
||||
let mut names = Vec::new();
|
||||
self.collect_block_function_names_into(statements, &mut names, false);
|
||||
names
|
||||
}
|
||||
|
||||
fn collect_block_function_names_into(&self, statements: &[Statement], names: &mut Vec<String>, block_level: bool) {
|
||||
for statement in statements {
|
||||
match statement {
|
||||
Statement::FunctionDeclaration(f) => {
|
||||
if block_level && !f.generator && !f.r#async {
|
||||
if let Some(id) = &f.id {
|
||||
let name = id.name.to_string();
|
||||
if !names.contains(&name) {
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Statement::BlockStatement(bs) => self.collect_block_function_names_into(&bs.body, names, true),
|
||||
Statement::IfStatement(is) => {
|
||||
self.collect_block_function_names_into(std::slice::from_ref(&is.consequent), names, true);
|
||||
if let Some(alt) = &is.alternate {
|
||||
self.collect_block_function_names_into(std::slice::from_ref(alt), names, true);
|
||||
}
|
||||
}
|
||||
Statement::WhileStatement(wh) => {
|
||||
self.collect_block_function_names_into(std::slice::from_ref(&wh.body), names, true)
|
||||
}
|
||||
Statement::DoWhileStatement(dw) => {
|
||||
self.collect_block_function_names_into(std::slice::from_ref(&dw.body), names, true)
|
||||
}
|
||||
Statement::ForStatement(fs) => {
|
||||
self.collect_block_function_names_into(std::slice::from_ref(&fs.body), names, true)
|
||||
}
|
||||
Statement::ForInStatement(fi) => {
|
||||
self.collect_block_function_names_into(std::slice::from_ref(&fi.body), names, true)
|
||||
}
|
||||
Statement::ForOfStatement(fo) => {
|
||||
self.collect_block_function_names_into(std::slice::from_ref(&fo.body), names, true)
|
||||
}
|
||||
Statement::SwitchStatement(sw) => {
|
||||
for case in &sw.cases {
|
||||
self.collect_block_function_names_into(&case.consequent, names, true);
|
||||
}
|
||||
}
|
||||
Statement::TryStatement(ts) => {
|
||||
self.collect_block_function_names_into(&ts.block.body, names, true);
|
||||
if let Some(handler) = &ts.handler {
|
||||
self.collect_block_function_names_into(&handler.body.body, names, true);
|
||||
}
|
||||
if let Some(finalizer) = &ts.finalizer {
|
||||
self.collect_block_function_names_into(&finalizer.body, names, true);
|
||||
}
|
||||
}
|
||||
Statement::LabeledStatement(ls) => {
|
||||
self.collect_block_function_names_into(std::slice::from_ref(&ls.body), names, true)
|
||||
}
|
||||
Statement::WithStatement(ws) => {
|
||||
self.collect_block_function_names_into(std::slice::from_ref(&ws.body), names, true)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 收集语句树内的词法声明名(let/const/class 含解构叶、for 头词法名、catch
|
||||
/// 参数):块级函数名与树内任意词法声明同名时退化为纯块作用域(无外层
|
||||
/// 绑定、无求值写回)。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 不递归进嵌套函数体/class 元素体:独立编译单元,其词法名不撞本单元的
|
||||
/// 块函数名。
|
||||
/// - var 声明是 var 绑定,不撞词法环境,不入集。
|
||||
fn collect_lexical_name_suppressions(&self, statements: &[Statement], names: &mut HashSet<String>) {
|
||||
for statement in statements {
|
||||
match statement {
|
||||
Statement::VariableDeclaration(vd) => {
|
||||
if !matches!(vd.kind, VariableDeclarationKind::Var) {
|
||||
for d in &vd.declarations {
|
||||
collect_binding_pattern_names(&d.id, names);
|
||||
}
|
||||
}
|
||||
}
|
||||
Statement::ClassDeclaration(cd) => {
|
||||
if let Some(id) = &cd.id {
|
||||
names.insert(id.name.to_string());
|
||||
}
|
||||
}
|
||||
Statement::ForStatement(fs) => {
|
||||
if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init {
|
||||
if !matches!(decl.kind, VariableDeclarationKind::Var) {
|
||||
for d in &decl.declarations {
|
||||
collect_binding_pattern_names(&d.id, names);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.collect_lexical_name_suppressions(std::slice::from_ref(&fs.body), names);
|
||||
}
|
||||
Statement::ForInStatement(fi) => {
|
||||
if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fi.left {
|
||||
if !matches!(decl.kind, VariableDeclarationKind::Var) {
|
||||
for d in &decl.declarations {
|
||||
collect_binding_pattern_names(&d.id, names);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.collect_lexical_name_suppressions(std::slice::from_ref(&fi.body), names);
|
||||
}
|
||||
Statement::ForOfStatement(fo) => {
|
||||
if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fo.left {
|
||||
if !matches!(decl.kind, VariableDeclarationKind::Var) {
|
||||
for d in &decl.declarations {
|
||||
collect_binding_pattern_names(&d.id, names);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.collect_lexical_name_suppressions(std::slice::from_ref(&fo.body), names);
|
||||
}
|
||||
Statement::TryStatement(ts) => {
|
||||
// catch 参数是 handler 环境的词法绑定。
|
||||
if let Some(handler) = &ts.handler {
|
||||
if let Some(param) = &handler.param {
|
||||
collect_binding_pattern_names(¶m.pattern, names);
|
||||
}
|
||||
self.collect_lexical_name_suppressions(&handler.body.body, names);
|
||||
}
|
||||
self.collect_lexical_name_suppressions(&ts.block.body, names);
|
||||
if let Some(finalizer) = &ts.finalizer {
|
||||
self.collect_lexical_name_suppressions(&finalizer.body, names);
|
||||
}
|
||||
}
|
||||
Statement::BlockStatement(bs) => self.collect_lexical_name_suppressions(&bs.body, names),
|
||||
Statement::IfStatement(is) => {
|
||||
self.collect_lexical_name_suppressions(std::slice::from_ref(&is.consequent), names);
|
||||
if let Some(alt) = &is.alternate {
|
||||
self.collect_lexical_name_suppressions(std::slice::from_ref(alt), names);
|
||||
}
|
||||
}
|
||||
Statement::WhileStatement(wh) => {
|
||||
self.collect_lexical_name_suppressions(std::slice::from_ref(&wh.body), names)
|
||||
}
|
||||
Statement::DoWhileStatement(dw) => {
|
||||
self.collect_lexical_name_suppressions(std::slice::from_ref(&dw.body), names)
|
||||
}
|
||||
Statement::SwitchStatement(sw) => {
|
||||
for case in &sw.cases {
|
||||
self.collect_lexical_name_suppressions(&case.consequent, names);
|
||||
}
|
||||
}
|
||||
Statement::LabeledStatement(ls) => {
|
||||
self.collect_lexical_name_suppressions(std::slice::from_ref(&ls.body), names)
|
||||
}
|
||||
Statement::WithStatement(ws) => {
|
||||
self.collect_lexical_name_suppressions(std::slice::from_ref(&ws.body), names)
|
||||
}
|
||||
Statement::ExportNamedDeclaration(exp) => {
|
||||
if let Some(Declaration::VariableDeclaration(vd)) = &exp.declaration {
|
||||
if !matches!(vd.kind, VariableDeclarationKind::Var) {
|
||||
for d in &vd.declarations {
|
||||
collect_binding_pattern_names(&d.id, names);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 块级函数名的外层 var 绑定抑制集(sloppy 模式浏览器兼容行为):形参名
|
||||
/// (含解构叶/rest)∪ 语句树内词法声明名。命中抑制的名字不建外层 var 绑定、
|
||||
/// 不求值写回。
|
||||
pub(crate) fn collect_block_fn_suppressed_names(
|
||||
&self, statements: &[Statement], param_names: &HashSet<String>,
|
||||
) -> HashSet<String> {
|
||||
let mut names = param_names.clone();
|
||||
self.collect_lexical_name_suppressions(statements, &mut names);
|
||||
names
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,5 @@
|
||||
//! (builtin_reg_map),避免与临时寄存器池冲突;同时预声明函数/var 声明,
|
||||
//! 支持提升语义。
|
||||
|
||||
mod block_fn;
|
||||
mod builtin_scan;
|
||||
mod declare;
|
||||
|
||||
@@ -16,10 +16,7 @@ use oxide_ir::operand::Operand;
|
||||
use oxide_ir::IRFunction;
|
||||
use oxide_parser::Statement;
|
||||
|
||||
use crate::capture::{
|
||||
collect_block_level_decl_names, collect_captured_bindings, collect_direct_lexical_names, collect_own_binding_names,
|
||||
collect_top_level_function_names, collect_top_level_function_names_ordered, collect_var_binding_names,
|
||||
};
|
||||
use crate::capture::{collect_captured_bindings, collect_fn_scope_names};
|
||||
use crate::compile_ctx::CompileCtx;
|
||||
use crate::Emitter;
|
||||
|
||||
@@ -231,10 +228,10 @@ impl Emitter {
|
||||
/// # 边界与前提
|
||||
/// - 仅普通脚本调用(`is_eval_script` 面由调用点按条件判定排除);eval 动态
|
||||
/// 路径与 eval 三常量编译期条件开关零触碰。
|
||||
/// - 仅遍历语句列表直接子级具名函数声明(生成器/异步声明同节点类型,天然
|
||||
/// 覆盖);块内函数声明与 `export default function` 不入全局检查面。
|
||||
pub(crate) fn emit_gdi_func_decl_checks(&self, stmts: &[Statement], ctx: &mut CompileCtx) {
|
||||
let names = collect_top_level_function_names_ordered(stmts);
|
||||
/// - `names` 为顶层函数声明名列表(声明序,由调用点经合并单趟收集):仅
|
||||
/// 直接子级具名函数声明(生成器/异步声明同节点类型,天然覆盖);块内函数
|
||||
/// 声明与 `export default function` 不入全局检查面。
|
||||
pub(crate) fn emit_gdi_func_decl_checks(&self, names: &[String], ctx: &mut CompileCtx) {
|
||||
let mut seen = HashSet::new();
|
||||
for name in names.iter().rev() {
|
||||
// 逆序首见即源序最后声明者(规范去重口径),重名只查一次。
|
||||
@@ -272,6 +269,11 @@ impl Emitter {
|
||||
// 脚本顶层严格模式由源码 "use strict" directive 决定(嵌套函数经父 ctx 继承)。
|
||||
ctx.is_strict = program.has_use_strict_directive();
|
||||
|
||||
// 程序作用域八个名字面单趟收集(程序无形参,param_names 传空):
|
||||
// GDI 检查 / eval 门禁 / builtin 排除 / 块函数 / own 绑定 / tier 名集 /
|
||||
// 入口实例化各调用点共用此结果。
|
||||
let scope_names = collect_fn_scope_names(&[], &program.body);
|
||||
|
||||
// eval 代码顶层函数声明撞不可写全局内置(三常量的全局绑定在任何符合规范的
|
||||
// 实现中均不可配置,声明实例化无法建立全局绑定):规范在建立全局 var 绑定
|
||||
// 之前抛 TypeError(step 8 的 abrupt 先于绑定实例化),故 throw 发为程序首
|
||||
@@ -279,7 +281,7 @@ impl Emitter {
|
||||
// 严格 eval 代码函数声明绑定 eval 自身 lexical 环境、不触全局、不抛,门禁
|
||||
// 随 !is_strict 关闭,其写点抑制在声明发射处。
|
||||
if ctx.is_eval_script && !ctx.is_strict {
|
||||
for name in collect_top_level_function_names_ordered(&program.body) {
|
||||
for name in &scope_names.top_level_function_names_ordered {
|
||||
if NON_WRITABLE_GLOBAL_BUILTINS.contains(&name.as_str()) {
|
||||
let _ = self.emit_throw_error(
|
||||
"TypeError",
|
||||
@@ -295,7 +297,7 @@ impl Emitter {
|
||||
// 顶层函数声明撞既有不可配置全局属性抛 TypeError,sloppy/strict 同形。
|
||||
// eval 面零触碰:静态三常量面由上方 eval 三常量编译期门禁拦,动态臂另归口。
|
||||
if !ctx.is_eval_script {
|
||||
self.emit_gdi_func_decl_checks(&program.body, &mut ctx);
|
||||
self.emit_gdi_func_decl_checks(&scope_names.top_level_function_names_ordered, &mut ctx);
|
||||
}
|
||||
|
||||
self.predeclare_function_declarations(&program.body, &mut ctx);
|
||||
@@ -303,7 +305,7 @@ impl Emitter {
|
||||
// 预注册 builtin 引用(先于任何临时寄存器),builtin 槽不进入临时寄存器池。
|
||||
// 顶层词法声明名(let/const/class)排除登记:词法绑定遮蔽同名全局属性,
|
||||
// 镜像占位先建会与词法预声明撞 scope 0 致合法遮蔽形被编译期误拒。
|
||||
let lexical_excluded = collect_direct_lexical_names(&program.body);
|
||||
let lexical_excluded = scope_names.direct_lexical_names.clone();
|
||||
self.pre_register_builtin_references(&program.body, &lexical_excluded, &mut ctx);
|
||||
|
||||
// 预声明顶层 `var` 名,使首个 sub-pass 中提升的函数声明能解析外层 var。
|
||||
@@ -320,8 +322,8 @@ impl Emitter {
|
||||
// (define-if-absent,既有属性不改动值)。strict 代码不建。
|
||||
let mut block_fn_names: Vec<String> = Vec::new();
|
||||
if !ctx.is_strict {
|
||||
ctx.block_fn_suppressed = self.collect_block_fn_suppressed_names(&program.body, &ctx.param_names);
|
||||
block_fn_names = self.collect_block_function_names(&program.body);
|
||||
ctx.block_fn_suppressed = scope_names.block_fn_suppressed.clone();
|
||||
block_fn_names = scope_names.block_function_names.clone();
|
||||
for name in &block_fn_names {
|
||||
if !ctx.block_fn_suppressed.contains(name) && !CompileCtx::is_non_writable_global_builtin(name) {
|
||||
self.predeclare_var_name(name, &mut ctx);
|
||||
@@ -330,7 +332,7 @@ impl Emitter {
|
||||
}
|
||||
|
||||
// 闭包捕获分析(AST 级,emit 前确定)
|
||||
ctx.own_bindings = collect_own_binding_names(&[], &program.body);
|
||||
ctx.own_bindings = scope_names.own_binding_names.clone();
|
||||
// 顶层已声明名(全局对象属性为唯一存储):裸读走全局对象属性、裸写走感知
|
||||
// 全局对象属性描述符的写,不落引擎侧镜像副本——从捕获集剔除,使嵌套函数经
|
||||
// 继承 scope 0 直连全局。
|
||||
@@ -338,9 +340,9 @@ impl Emitter {
|
||||
// 其全局对象属性值由首个 sub-pass(`emit_program` 顶层的内部阶段划分:先
|
||||
// 声明实例化、后用户代码发射)以真闭包建立,先于任何用户代码。
|
||||
// 仅在此顶层调用点过滤:嵌套函数的局部同名遮蔽是独立绑定,其调用点不过滤。
|
||||
let var_names = collect_var_binding_names(&program.body);
|
||||
let var_names = scope_names.var_binding_names.clone();
|
||||
let mut tier_names = var_names.clone();
|
||||
tier_names.extend(collect_top_level_function_names(&program.body));
|
||||
tier_names.extend(scope_names.top_level_function_names.iter().cloned());
|
||||
// 块级函数泄漏名并入:求值期写回与块入口头写同走全局对象属性(全局对象
|
||||
// 属性为唯一存储)。
|
||||
for name in &block_fn_names {
|
||||
@@ -353,7 +355,7 @@ impl Emitter {
|
||||
// 顶层 tier 名(顶层 var/函数)的全局对象属性是唯一存储,从捕获集剔除;
|
||||
// 被同名块级绑定(catch 参数 / 块级 let/const)遮蔽时保留,使块级绑定能
|
||||
// 追加新索引供闭包捕获(顶层 var 本身不建 cell,回填与解析点均跳过)。
|
||||
let block_level_names = collect_block_level_decl_names(&program.body);
|
||||
let block_level_names = scope_names.block_level_decl_names.clone();
|
||||
ctx.captured_bindings
|
||||
.retain(|n, _| !ctx.global_tier_names.contains(n) || block_level_names.contains(n));
|
||||
// 顶层函数级绑定 cell 索引回填:预声明已完成,绑定已齐。
|
||||
@@ -388,9 +390,11 @@ impl Emitter {
|
||||
// 创建的闭包指向此未初始化 cell,声明前读写经运行时抛真 TDZ;声明语句
|
||||
// 的 MAKE_CELL 按占位更新语义原位翻转为已初始化。名集取捕获集交集
|
||||
// (直接子级词法名,块级名不提升到顶层),排序保证发射序跨进程稳定。
|
||||
let mut lex_names: Vec<String> = collect_direct_lexical_names(&program.body)
|
||||
.into_iter()
|
||||
.filter(|n| ctx.captured_bindings.contains_key(n))
|
||||
let mut lex_names: Vec<String> = scope_names
|
||||
.direct_lexical_names
|
||||
.iter()
|
||||
.filter(|n| ctx.captured_bindings.contains_key(*n))
|
||||
.cloned()
|
||||
.collect();
|
||||
lex_names.sort();
|
||||
if !lex_names.is_empty() {
|
||||
@@ -420,7 +424,7 @@ impl Emitter {
|
||||
// 把全局属性值预载进固定寄存器槽),既有属性不改动值,值幂等保留。
|
||||
// 序言名集 = 顶层 var 名 ∪ 顶层块级函数泄漏名(sloppy 模式浏览器兼容行为的
|
||||
// 外层绑定同样在求值前实例化,同走 define-if-absent)。
|
||||
let mut gdi_var_names: Vec<String> = collect_var_binding_names(&program.body).into_iter().collect();
|
||||
let mut gdi_var_names: Vec<String> = scope_names.var_binding_names.iter().cloned().collect();
|
||||
gdi_var_names.extend(
|
||||
block_fn_names
|
||||
.iter()
|
||||
|
||||
@@ -375,3 +375,27 @@ fn source_encoded_regex_pool_key() {
|
||||
assert!(!enc.contains("\\ud800"));
|
||||
assert!(pool_strings(&static_ir).contains("\\ud800"), "静态源池键为明文转义文本");
|
||||
}
|
||||
|
||||
/// 面 12:块函数抑制集含解构形参叶名——块函数名撞叶名时不建外层 var 绑定、
|
||||
/// 声明点不写回(STORE_VAR 少一条写回);非抑制名块函数有入口 undefined 写
|
||||
/// 与声明点写回。
|
||||
#[test]
|
||||
fn block_fn_suppressed_by_destructured_param_leaf() {
|
||||
// 撞解构叶名:叶名绑定(1)+ 块函数物化自写(1)= 2,无外层 var 写回。
|
||||
let suppressed = emit_ir("function f({x}) { { function x() { return 1; } } return 2; }");
|
||||
let f = &suppressed.nested[0];
|
||||
assert_eq!(
|
||||
count_op(&f.insts, OpCode::STORE_VAR),
|
||||
2,
|
||||
"撞解构叶名的块函数被抑制:无外层 var 写回"
|
||||
);
|
||||
|
||||
// 非抑制对照:入口 undefined 写(1)+ 块函数物化自写(1)+ 外层 var 写回(1)= 3。
|
||||
let control = emit_ir("function f() { { function y() { return 1; } } return 2; }");
|
||||
let fc = &control.nested[0];
|
||||
assert_eq!(
|
||||
count_op(&fc.insts, OpCode::STORE_VAR),
|
||||
3,
|
||||
"非抑制块函数应有入口 undefined 写与外层 var 写回"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user