Files
OxideJS-New/crates/oxide_vm/src/bindings/bind_regexp.rs
T

218 lines
8.4 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.
use crate::bindings::{
apply_binding_table, bind_accessor_getset, bind_accessor_getter, bind_accessor_getter_key, bind_well_known_method,
configure_native_constructor, BindEnv,
};
use oxide_types::object::JsObject;
use crate::bind_constructor;
/// 把 RegExp 构造器与原型方法绑定到 global。
///
/// `realm_id` 是目标所属 realm 的编号:well-known 符号键按 (realm 编号, 局部
/// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。
pub fn bind_regexp(env: BindEnv<'_>, global: &mut JsObject) {
let ctor_ptr = env.world().regexp_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
let proto_ptr = env.world().regexp_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &mut *proto_ptr };
configure_native_constructor(ctor, oxide_builtins::regexp::regexp_constructor::<crate::vm::Vm> as *const (), 2);
// 静态方法 escape 装到构造器对象(wrapper 的 length/name 与槽属性由 bind_method 统一保证)。
apply_binding_table(
env,
ctor,
&[("escape", oxide_builtins::regexp::regexp_escape::<crate::vm::Vm> as *const (), 1)],
);
apply_binding_table(
env,
proto,
&[
("exec", oxide_builtins::regexp::regexp_exec::<crate::vm::Vm> as *const (), 1),
("test", oxide_builtins::regexp::regexp_test::<crate::vm::Vm> as *const (), 1),
("toString", oxide_builtins::regexp::regexp_to_string::<crate::vm::Vm> as *const (), 0),
("compile", oxide_builtins::regexp::regexp_compile::<crate::vm::Vm> as *const (), 2),
("toSource", oxide_builtins::to_source::to_source_regexp::<crate::vm::Vm> as *const (), 0),
],
);
// 遗留静态访问器(Annex B):15 个访问器落 %RegExp% 构造器,描述符
// {enumerable:false, configurable:true}。仅 input/$_ 为 get+set 对(共享
// [[RegExpInput]] 槽);其余 18 个为 getter(set 恒 undefined):lastMatch/$&、
// lastParen/$+、leftContext/$`、rightContext/$' 各共享一槽,index 与 $1-$9 各
// 独占一槽。
let sf = env.string_forge();
let mut bind_getset = |name: &str, getter: *const (), setter: *const ()| {
let key = sf.intern(name).0;
bind_accessor_getset(env, ctor, key, &format!("get {name}"), &format!("set {name}"), getter, setter);
};
// input/$_:get+set 对(唯一带 setter 的遗留访问器)。
bind_getset(
"input",
oxide_builtins::regexp::regexp_legacy_get_input::<crate::vm::Vm> as *const (),
oxide_builtins::regexp::regexp_legacy_set_input::<crate::vm::Vm> as *const (),
);
bind_getset(
"$_",
oxide_builtins::regexp::regexp_legacy_get_input::<crate::vm::Vm> as *const (),
oxide_builtins::regexp::regexp_legacy_set_input::<crate::vm::Vm> as *const (),
);
// 其余 18 个 getter(set 恒 undefined)。
for (name, getter) in [
(
"lastMatch",
oxide_builtins::regexp::regexp_legacy_get_last_match::<crate::vm::Vm> as *const (),
),
("$&", oxide_builtins::regexp::regexp_legacy_get_last_match::<crate::vm::Vm> as *const ()),
(
"lastParen",
oxide_builtins::regexp::regexp_legacy_get_last_paren::<crate::vm::Vm> as *const (),
),
("$+", oxide_builtins::regexp::regexp_legacy_get_last_paren::<crate::vm::Vm> as *const ()),
(
"leftContext",
oxide_builtins::regexp::regexp_legacy_get_left_context::<crate::vm::Vm> as *const (),
),
("$`", oxide_builtins::regexp::regexp_legacy_get_left_context::<crate::vm::Vm> as *const ()),
(
"rightContext",
oxide_builtins::regexp::regexp_legacy_get_right_context::<crate::vm::Vm> as *const (),
),
(
"$'",
oxide_builtins::regexp::regexp_legacy_get_right_context::<crate::vm::Vm> as *const (),
),
("index", oxide_builtins::regexp::regexp_legacy_get_index::<crate::vm::Vm> as *const ()),
("$1", oxide_builtins::regexp::regexp_legacy_get_dollar_1::<crate::vm::Vm> as *const ()),
("$2", oxide_builtins::regexp::regexp_legacy_get_dollar_2::<crate::vm::Vm> as *const ()),
("$3", oxide_builtins::regexp::regexp_legacy_get_dollar_3::<crate::vm::Vm> as *const ()),
("$4", oxide_builtins::regexp::regexp_legacy_get_dollar_4::<crate::vm::Vm> as *const ()),
("$5", oxide_builtins::regexp::regexp_legacy_get_dollar_5::<crate::vm::Vm> as *const ()),
("$6", oxide_builtins::regexp::regexp_legacy_get_dollar_6::<crate::vm::Vm> as *const ()),
("$7", oxide_builtins::regexp::regexp_legacy_get_dollar_7::<crate::vm::Vm> as *const ()),
("$8", oxide_builtins::regexp::regexp_legacy_get_dollar_8::<crate::vm::Vm> as *const ()),
("$9", oxide_builtins::regexp::regexp_legacy_get_dollar_9::<crate::vm::Vm> as *const ()),
] {
bind_accessor_getter(env, ctor, name, getter);
}
// source/flags 只读访问器(set 恒 undefined,getter 读实例字段)。
bind_accessor_getter(
env,
proto,
"source",
oxide_builtins::regexp::regexp_get_source::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
env,
proto,
"flags",
oxide_builtins::regexp::regexp_get_flags::<crate::vm::Vm> as *const (),
);
// 8 个单 flag 只读访问器(set 恒 undefined,getter 读实例 flags 串判码元)。
bind_accessor_getter(
env,
proto,
"global",
oxide_builtins::regexp::regexp_get_global::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
env,
proto,
"ignoreCase",
oxide_builtins::regexp::regexp_get_ignore_case::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
env,
proto,
"multiline",
oxide_builtins::regexp::regexp_get_multiline::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
env,
proto,
"dotAll",
oxide_builtins::regexp::regexp_get_dot_all::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
env,
proto,
"sticky",
oxide_builtins::regexp::regexp_get_sticky::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
env,
proto,
"unicode",
oxide_builtins::regexp::regexp_get_unicode::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
env,
proto,
"hasIndices",
oxide_builtins::regexp::regexp_get_has_indices::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
env,
proto,
"unicodeSets",
oxide_builtins::regexp::regexp_get_unicode_sets::<crate::vm::Vm> as *const (),
);
// well-known symbol 方法按 Symbol 键安装,name 属性取 `[Symbol.match]` 式标签,供 `re[Symbol.match]` 等读取。
bind_well_known_method(
env,
proto,
1,
"[Symbol.match]",
oxide_builtins::regexp::regexp_symbol_match::<crate::vm::Vm> as *const (),
1,
);
bind_well_known_method(
env,
proto,
2,
"[Symbol.replace]",
oxide_builtins::regexp::regexp_symbol_replace::<crate::vm::Vm> as *const (),
2,
);
bind_well_known_method(
env,
proto,
3,
"[Symbol.search]",
oxide_builtins::regexp::regexp_symbol_search::<crate::vm::Vm> as *const (),
1,
);
bind_well_known_method(
env,
proto,
4,
"[Symbol.split]",
oxide_builtins::regexp::regexp_symbol_split::<crate::vm::Vm> as *const (),
2,
);
bind_well_known_method(
env,
proto,
7,
"[Symbol.matchAll]",
oxide_builtins::regexp::regexp_symbol_match_all::<crate::vm::Vm> as *const (),
1,
);
// RegExp[Symbol.species] 访问器:getter 返回 receiver,派生类沿静态原型链解析
// @@species 得自身构造器(规范不给 class 默认 static @@species,类上无 own)。
bind_accessor_getter_key(
env,
ctor,
oxide_types::private_key::encode_symbol_key(env.realm_id, oxide_types::private_key::WELL_KNOWN_SYMBOL_SPECIES),
"get [Symbol.species]",
oxide_builtins::array::array_species_get::<crate::vm::Vm> as *const (),
);
bind_constructor!(env, global, "RegExp", ctor_ptr, oxide_builtins::regexp::regexp_constructor::<crate::vm::Vm>, 2, hash: true);
}