mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
feat: direct eval 串按调用方严格性前置严格指令,受限名 catch 参数报 SyntaxError
This commit is contained in:
Generated
+19
-19
@@ -1160,7 +1160,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_builtins"
|
name = "oxide_builtins"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"fast-float",
|
"fast-float",
|
||||||
@@ -1185,7 +1185,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_bytecode"
|
name = "oxide_bytecode"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1193,7 +1193,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cfg"
|
name = "oxide_cfg"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_emit",
|
"oxide_emit",
|
||||||
@@ -1204,7 +1204,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cli"
|
name = "oxide_cli"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
@@ -1226,7 +1226,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_code_cache"
|
name = "oxide_code_cache"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lru",
|
"lru",
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
@@ -1235,7 +1235,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_compiler"
|
name = "oxide_compiler"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1255,7 +1255,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_dce"
|
name = "oxide_dce"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1269,7 +1269,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_emit"
|
name = "oxide_emit"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
@@ -1284,7 +1284,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_engine"
|
name = "oxide_engine"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_compiler",
|
"oxide_compiler",
|
||||||
@@ -1296,7 +1296,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_ir"
|
name = "oxide_ir"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1305,7 +1305,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_kernel"
|
name = "oxide_kernel"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
@@ -1319,7 +1319,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_liveness"
|
name = "oxide_liveness"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1331,7 +1331,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_log"
|
name = "oxide_log"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
@@ -1340,7 +1340,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_parser"
|
name = "oxide_parser"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
"oxc_ast",
|
"oxc_ast",
|
||||||
@@ -1355,7 +1355,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_regalloc"
|
name = "oxide_regalloc"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1371,7 +1371,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_runtime_api"
|
name = "oxide_runtime_api"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
@@ -1384,7 +1384,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_test262"
|
name = "oxide_test262"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_compiler",
|
"oxide_compiler",
|
||||||
@@ -1402,7 +1402,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_types"
|
name = "oxide_types"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
@@ -1415,7 +1415,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_vm"
|
name = "oxide_vm"
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.8.96"
|
version = "0.8.97"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
rust-version = "1.80"
|
rust-version = "1.80"
|
||||||
|
|||||||
@@ -114,13 +114,18 @@ impl Vm {
|
|||||||
/// (属性 configurable:true,区别于普通脚本顶层的 false)。
|
/// (属性 configurable:true,区别于普通脚本顶层的 false)。
|
||||||
///
|
///
|
||||||
/// # 步骤
|
/// # 步骤
|
||||||
/// 1. parse(脚本模式)→ compile(emit_program 置 is_global_scope=true,
|
/// 1. 严格性判定:调用方上下文严格(`current_strict()` 三级回退)时源串前置
|
||||||
|
/// `"use strict";` 指令,使整串按严格编译(direct eval 字符串的严格性随
|
||||||
|
/// 外层脚本与直接调用函数传播)。
|
||||||
|
/// 2. parse(脚本模式)→ compile(emit_program 置 is_global_scope=true,
|
||||||
/// Compiler 置 is_eval_script=true)。
|
/// Compiler 置 is_eval_script=true)。
|
||||||
/// 2. 整棵模块树(根 flat_id=0 + 嵌套函数)追加进平表:`rehome_subtree(&module, base+1)`,
|
/// 3. 整棵模块树(根 flat_id=0 + 嵌套函数)追加进平表:`rehome_subtree(&module, base+1)`,
|
||||||
/// 使根落 base、子函数 old→base+old,CREATE_CLOSURE imm16 同步重写。
|
/// 使根落 base、子函数 old→base+old,CREATE_CLOSURE imm16 同步重写。
|
||||||
/// 3. 扩容当前代际的常量缓存,建函数对象(sub_module_index = base)返回。
|
/// 4. 扩容当前代际的常量缓存,建函数对象(sub_module_index = base)返回。
|
||||||
///
|
///
|
||||||
/// # 边界与前提
|
/// # 边界与前提
|
||||||
|
/// - 严格上下文下整串按严格编译:`this`/`with`/`delete`/赋值语义随严格模式翻转,
|
||||||
|
/// 受限名 catch 参数(eval/arguments)报 SyntaxError。
|
||||||
/// - 顶层 return 不报 SyntaxError(emit 无此检查,与 CLI 脚本路径一致)——已知偏差。
|
/// - 顶层 return 不报 SyntaxError(emit 无此检查,与 CLI 脚本路径一致)——已知偏差。
|
||||||
/// - 动态模块在函数对象存活期间跨 run 有效(同 create_dynamic_function)。
|
/// - 动态模块在函数对象存活期间跨 run 有效(同 create_dynamic_function)。
|
||||||
/// - 返回函数对象仅供内部同步调用,不设 name/length(用户不可见)。
|
/// - 返回函数对象仅供内部同步调用,不设 name/length(用户不可见)。
|
||||||
@@ -130,7 +135,17 @@ impl Vm {
|
|||||||
pub fn create_dynamic_script(&mut self, code: &str) -> Result<JsValue, String> {
|
pub fn create_dynamic_script(&mut self, code: &str) -> Result<JsValue, String> {
|
||||||
// eval 脚本:顶层 var/function 声明落全局属性 configurable:true。
|
// eval 脚本:顶层 var/function 声明落全局属性 configurable:true。
|
||||||
// 动态路径源契约同 `create_dynamic_function`(源码域转义形态传源)。
|
// 动态路径源契约同 `create_dynamic_function`(源码域转义形态传源)。
|
||||||
let module = self.compiler.compile_eval_script(code)?;
|
|
||||||
|
// direct eval 字符串的严格性随外层脚本与直接调用函数传播(与共识引擎口径一致):
|
||||||
|
// oxc 的 SourceType 无 strict 入口,调用方严格性只能由引擎前置严格指令承载,
|
||||||
|
// 使 oxc 既有 strict 绑定检查(catch 参数受限名 eval/arguments 等)报 SyntaxError。
|
||||||
|
let source = if self.current_strict() {
|
||||||
|
format!("\"use strict\";\n{code}")
|
||||||
|
} else {
|
||||||
|
code.to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
let module = self.compiler.compile_eval_script(&source)?;
|
||||||
// 根模块 flat_id=0 传 base+1,重编号后落 base(避开 sub_module_index()==0
|
// 根模块 flat_id=0 传 base+1,重编号后落 base(避开 sub_module_index()==0
|
||||||
// 守卫)。make_mut 彼时平表 Arc 强引用唯一持有者是本表,原地扩展不分叉。
|
// 守卫)。make_mut 彼时平表 Arc 强引用唯一持有者是本表,原地扩展不分叉。
|
||||||
let table = self.current_table_mut();
|
let table = self.current_table_mut();
|
||||||
|
|||||||
@@ -0,0 +1,186 @@
|
|||||||
|
//! direct eval 字符串的严格性随调用方上下文传播:strict 上下文(顶层脚本 / 继承
|
||||||
|
//! 严格函数 / 自带指令函数)下,eval 串整体按严格编译,受限名 catch 参数
|
||||||
|
//! (eval/arguments,含解构模式绑定名)报 SyntaxError;sloppy 上下文不受影响。
|
||||||
|
//!
|
||||||
|
//! 完成值一律收敛为布尔或数值(JsValue 的 Display 只暴露 number/bool,不暴露
|
||||||
|
//! 字符串内容),字符串比较在引擎内完成。
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use oxide_compiler::compiler::Compiler;
|
||||||
|
use oxide_compiler::DefaultCompilerService;
|
||||||
|
use oxide_parser::Allocator;
|
||||||
|
use oxide_vm::vm::Vm;
|
||||||
|
|
||||||
|
fn eval(source: &str) -> String {
|
||||||
|
let allocator = Allocator::default();
|
||||||
|
let program = match oxide_parser::parse(&allocator, source) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(e) => return format!("parse error: {}", e[0].message),
|
||||||
|
};
|
||||||
|
let module = match Compiler::new().compile(&program) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(e) => return format!("compile error: {e}"),
|
||||||
|
};
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
vm.set_compiler_service(Arc::new(DefaultCompilerService));
|
||||||
|
match vm.run(&Arc::new(module)) {
|
||||||
|
Ok(result) => format!("{result}"),
|
||||||
|
Err(e) => format!("vm error: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 断言 strict 上下文 direct eval 抛可捕获 SyntaxError(收敛为布尔 true)。
|
||||||
|
fn assert_syntax_error(source: &str, msg: &str) {
|
||||||
|
let res = eval(source);
|
||||||
|
assert_eq!(res, "true", "{msg}: expected a catchable SyntaxError, got: {res}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── strict 上下文 direct eval 受限名 catch 参数报 SyntaxError ──
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn strict_script_inheriting_fn_eval_catch_arguments_throws() {
|
||||||
|
// strict 脚本 + 无自带指令函数(继承严格)direct eval:受限名 catch 参数报 SyntaxError。
|
||||||
|
assert_syntax_error(
|
||||||
|
r#""use strict";
|
||||||
|
try { (function() { eval("try {} catch (arguments) { }"); })(); false }
|
||||||
|
catch (e) { e instanceof SyntaxError }"#,
|
||||||
|
"strict script + inheriting function direct eval restricted catch name must throw",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn strict_top_level_eval_catch_arguments_throws() {
|
||||||
|
// strict 顶层 direct eval:受限名 catch 参数报 SyntaxError(语料 -throws 同形)。
|
||||||
|
assert_syntax_error(
|
||||||
|
r#""use strict";
|
||||||
|
try { eval("try {} catch (arguments) { }"); false }
|
||||||
|
catch (e) { e instanceof SyntaxError }"#,
|
||||||
|
"strict top-level direct eval restricted catch name must throw",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sloppy_script_strict_fn_eval_catch_arguments_throws() {
|
||||||
|
// sloppy 脚本 + 自带指令严格函数 direct eval:调用方严格性为真,受限名报 SyntaxError。
|
||||||
|
assert_syntax_error(
|
||||||
|
r#"function f() { "use strict"; eval("try {} catch (arguments) { }"); }
|
||||||
|
try { f(); false } catch (e) { e instanceof SyntaxError }"#,
|
||||||
|
"sloppy script + strict function direct eval restricted catch name must throw",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn strict_script_nested_fn_eval_catch_arguments_throws() {
|
||||||
|
// strict 脚本 + 嵌套函数 direct eval:嵌套函数继承严格,受限名报 SyntaxError。
|
||||||
|
assert_syntax_error(
|
||||||
|
r#""use strict";
|
||||||
|
function outer() { function inner() { eval("try {} catch (arguments) { }"); } inner(); }
|
||||||
|
try { outer(); false } catch (e) { e instanceof SyntaxError }"#,
|
||||||
|
"strict script + nested function direct eval restricted catch name must throw",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn strict_ctx_eval_catch_destructure_array_eval_throws() {
|
||||||
|
// strict 上下文 direct eval 解构数组模式绑定名 eval:受限名报 SyntaxError。
|
||||||
|
assert_syntax_error(
|
||||||
|
r#""use strict";
|
||||||
|
try { eval("try {} catch ([eval]) { }"); false }
|
||||||
|
catch (e) { e instanceof SyntaxError }"#,
|
||||||
|
"strict context direct eval array-destructured catch name eval must throw",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn strict_ctx_eval_catch_object_shorthand_eval_throws() {
|
||||||
|
// strict 上下文 direct eval 对象简写模式绑定名 eval:受限名报 SyntaxError。
|
||||||
|
assert_syntax_error(
|
||||||
|
r#""use strict";
|
||||||
|
try { eval("try {} catch ({eval}) { }"); false }
|
||||||
|
catch (e) { e instanceof SyntaxError }"#,
|
||||||
|
"strict context direct eval object-shorthand catch name eval must throw",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 守卫:sloppy 上下文 / 改名 / 完成值不受影响 ──
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sloppy_script_sloppy_fn_eval_legal_completion_preserved() {
|
||||||
|
// sloppy 脚本 + sloppy 函数 direct eval:合法,eval 完成值保留。
|
||||||
|
assert_eq!(
|
||||||
|
eval("function f() { return eval(\"1 + 2\"); } f()"),
|
||||||
|
"3",
|
||||||
|
"sloppy context direct eval stays legal and preserves the completion value"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn strict_ctx_eval_catch_object_renamed_legal() {
|
||||||
|
// 守卫:受限名检查只认绑定名,对象简写改名(eval: e)后合法。
|
||||||
|
assert_eq!(
|
||||||
|
eval(r#""use strict"; try { eval("try {} catch ({eval: e}) { }"); true } catch (e) { false }"#),
|
||||||
|
"true",
|
||||||
|
"renamed object property binding is not a restricted name"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_catch_default_value_throws() {
|
||||||
|
// 守卫:catch 参数默认值恒为 SyntaxError(既有 parse 臂保真,与严格性无关)。
|
||||||
|
assert_syntax_error(
|
||||||
|
r#"try { eval("try {} catch (e = 2) { }"); false } catch (e) { e instanceof SyntaxError }"#,
|
||||||
|
"catch parameter default value must stay a SyntaxError",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function_ctor_catch_arguments_legal() {
|
||||||
|
// 守卫:Function 构造器不继承调用方严格性,受限名 catch 参数合法。
|
||||||
|
assert_eq!(
|
||||||
|
eval("new Function(\"try{}catch(arguments){}\")()"),
|
||||||
|
"undefined",
|
||||||
|
"Function constructor does not inherit caller strictness"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_own_strict_directive_catch_eval_throws() {
|
||||||
|
// 守卫:eval 串自带 'use strict' 指令时,sloppy 上下文亦按严格编译,受限名报 SyntaxError。
|
||||||
|
assert_syntax_error(
|
||||||
|
r#"try { eval("\'use strict\'; try {} catch (eval) { }"); false } catch (e) { e instanceof SyntaxError }"#,
|
||||||
|
"eval string with its own strict directive must reject restricted catch name",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn strict_ctx_indirect_eval_catch_arguments_throws() {
|
||||||
|
// 现状钉:引擎不区分 direct/indirect eval,strict 上下文间接 eval 受限名串亦拒
|
||||||
|
// (node 接受,偏差归 caller 环境通道面,本钉仅记录现状)。
|
||||||
|
assert_syntax_error(
|
||||||
|
r#""use strict";
|
||||||
|
try { (0,eval)("try {} catch (arguments) { }"); false }
|
||||||
|
catch (e) { e instanceof SyntaxError }"#,
|
||||||
|
"indirect eval in strict context currently rejects restricted catch name",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sloppy_eval_completion_value_unaffected() {
|
||||||
|
// 守卫:sloppy 上下文 eval 完成值不受严格性判定影响。
|
||||||
|
assert_eq!(
|
||||||
|
eval("eval(\"1+2\")"),
|
||||||
|
"3",
|
||||||
|
"sloppy context eval completion value is unaffected"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn static_strict_catch_eval_parse_rejected() {
|
||||||
|
// 守卫:静态 strict 脚本 catch (eval) 在 parse 期即被 oxc strict 绑定检查拒绝。
|
||||||
|
let res = eval("\"use strict\"; try {} catch (eval) {}");
|
||||||
|
assert!(
|
||||||
|
res.starts_with("parse error"),
|
||||||
|
"static strict catch (eval) must be rejected at parse time, got: {res}"
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -75,10 +75,15 @@ fn delete_top_var_from_function_scope_returns_false() {
|
|||||||
eval_truthy("var p = 1; (function() { return delete p; })() === false && p === 1");
|
eval_truthy("var p = 1; (function() { return delete p; })() === false && p === 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 绿基线:strict 调用方 + indirect eval(eval 代码不继承调用方严格性) ──
|
// ── 现状钉:strict 调用方 + indirect eval(引擎不区分 direct/indirect,
|
||||||
|
// eval 串继承调用方严格性):delete 未限定名在严格模式报 SyntaxError ──
|
||||||
#[test]
|
#[test]
|
||||||
fn strict_caller_indirect_eval_delete_undeclared_returns_true() {
|
fn strict_caller_indirect_eval_delete_undeclared_throws_syntax_error() {
|
||||||
eval_truthy("(function() { \"use strict\"; return (0, eval)(\"delete zqq_probe\"); })() === true");
|
eval_truthy(
|
||||||
|
"(function() { \"use strict\"; return (function() { \
|
||||||
|
try { (0, eval)(\"delete zqq_probe\"); return false; } \
|
||||||
|
catch (e) { return e instanceof SyntaxError; } })(); })() === true",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 可删全局内置镜像槽臂优先:探针臂不吞 builtin 槽(真删 + 清槽) ──
|
// ── 可删全局内置镜像槽臂优先:探针臂不吞 builtin 槽(真删 + 清槽) ──
|
||||||
|
|||||||
@@ -392,8 +392,13 @@ fn direct_eval_var_and_write_visible_to_outer() {
|
|||||||
eval_truthy("eval('var y = 5'); y === 5 && globalThis.y === 5");
|
eval_truthy("eval('var y = 5'); y === 5 && globalThis.y === 5");
|
||||||
eval_truthy("var q = 1; eval('q = 55'); q === 55 && globalThis.q === 55");
|
eval_truthy("var q = 1; eval('q = 55'); q === 55 && globalThis.q === 55");
|
||||||
eval_truthy("eval('var ev = 1'); Object.getOwnPropertyDescriptor(globalThis, 'ev').configurable === true");
|
eval_truthy("eval('var ev = 1'); Object.getOwnPropertyDescriptor(globalThis, 'ev').configurable === true");
|
||||||
// 嵌套函数内直接 eval:写点经 session 解析全局对象(不依赖 this)。
|
// 嵌套函数内直接 eval:strict 上下文 eval 串继承调用方严格性,写未声明名抛
|
||||||
eval_truthy("var z = 1; (function(){ \"use strict\"; eval('z = 77'); })(); z === 77 && globalThis.z === 77");
|
// ReferenceError(引擎独立编译 eval 程序,不共享调用方作用域,严格模式禁隐式
|
||||||
|
// 全局写入;sloppy 下该形为隐式全局写入,见上三行)。
|
||||||
|
eval_truthy(
|
||||||
|
"var z = 1; (function(){ \"use strict\"; return (function() { \
|
||||||
|
try { eval('z = 77'); return false; } catch (e) { return e instanceof ReferenceError; } })(); })() === true",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 既有属性与顶层 var 声明交互:序言 define-if-absent 零动作,声明值写
|
/// 既有属性与顶层 var 声明交互:序言 define-if-absent 零动作,声明值写
|
||||||
|
|||||||
Reference in New Issue
Block a user