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:: as *const (), 2); // 静态方法 escape 装到构造器对象(wrapper 的 length/name 与槽属性由 bind_method 统一保证)。 apply_binding_table( env, ctor, &[("escape", oxide_builtins::regexp::regexp_escape:: as *const (), 1)], ); apply_binding_table( env, proto, &[ ("exec", oxide_builtins::regexp::regexp_exec:: as *const (), 1), ("test", oxide_builtins::regexp::regexp_test:: as *const (), 1), ("toString", oxide_builtins::regexp::regexp_to_string:: as *const (), 0), ("compile", oxide_builtins::regexp::regexp_compile:: as *const (), 2), ("toSource", oxide_builtins::to_source::to_source_regexp:: 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:: as *const (), oxide_builtins::regexp::regexp_legacy_set_input:: as *const (), ); bind_getset( "$_", oxide_builtins::regexp::regexp_legacy_get_input:: as *const (), oxide_builtins::regexp::regexp_legacy_set_input:: as *const (), ); // 其余 18 个 getter(set 恒 undefined)。 for (name, getter) in [ ( "lastMatch", oxide_builtins::regexp::regexp_legacy_get_last_match:: as *const (), ), ("$&", oxide_builtins::regexp::regexp_legacy_get_last_match:: as *const ()), ( "lastParen", oxide_builtins::regexp::regexp_legacy_get_last_paren:: as *const (), ), ("$+", oxide_builtins::regexp::regexp_legacy_get_last_paren:: as *const ()), ( "leftContext", oxide_builtins::regexp::regexp_legacy_get_left_context:: as *const (), ), ("$`", oxide_builtins::regexp::regexp_legacy_get_left_context:: as *const ()), ( "rightContext", oxide_builtins::regexp::regexp_legacy_get_right_context:: as *const (), ), ( "$'", oxide_builtins::regexp::regexp_legacy_get_right_context:: as *const (), ), ("index", oxide_builtins::regexp::regexp_legacy_get_index:: as *const ()), ("$1", oxide_builtins::regexp::regexp_legacy_get_dollar_1:: as *const ()), ("$2", oxide_builtins::regexp::regexp_legacy_get_dollar_2:: as *const ()), ("$3", oxide_builtins::regexp::regexp_legacy_get_dollar_3:: as *const ()), ("$4", oxide_builtins::regexp::regexp_legacy_get_dollar_4:: as *const ()), ("$5", oxide_builtins::regexp::regexp_legacy_get_dollar_5:: as *const ()), ("$6", oxide_builtins::regexp::regexp_legacy_get_dollar_6:: as *const ()), ("$7", oxide_builtins::regexp::regexp_legacy_get_dollar_7:: as *const ()), ("$8", oxide_builtins::regexp::regexp_legacy_get_dollar_8:: as *const ()), ("$9", oxide_builtins::regexp::regexp_legacy_get_dollar_9:: 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:: as *const (), ); bind_accessor_getter( env, proto, "flags", oxide_builtins::regexp::regexp_get_flags:: as *const (), ); // 8 个单 flag 只读访问器(set 恒 undefined,getter 读实例 flags 串判码元)。 bind_accessor_getter( env, proto, "global", oxide_builtins::regexp::regexp_get_global:: as *const (), ); bind_accessor_getter( env, proto, "ignoreCase", oxide_builtins::regexp::regexp_get_ignore_case:: as *const (), ); bind_accessor_getter( env, proto, "multiline", oxide_builtins::regexp::regexp_get_multiline:: as *const (), ); bind_accessor_getter( env, proto, "dotAll", oxide_builtins::regexp::regexp_get_dot_all:: as *const (), ); bind_accessor_getter( env, proto, "sticky", oxide_builtins::regexp::regexp_get_sticky:: as *const (), ); bind_accessor_getter( env, proto, "unicode", oxide_builtins::regexp::regexp_get_unicode:: as *const (), ); bind_accessor_getter( env, proto, "hasIndices", oxide_builtins::regexp::regexp_get_has_indices:: as *const (), ); bind_accessor_getter( env, proto, "unicodeSets", oxide_builtins::regexp::regexp_get_unicode_sets:: 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:: as *const (), 1, ); bind_well_known_method( env, proto, 2, "[Symbol.replace]", oxide_builtins::regexp::regexp_symbol_replace:: as *const (), 2, ); bind_well_known_method( env, proto, 3, "[Symbol.search]", oxide_builtins::regexp::regexp_symbol_search:: as *const (), 1, ); bind_well_known_method( env, proto, 4, "[Symbol.split]", oxide_builtins::regexp::regexp_symbol_split:: as *const (), 2, ); bind_well_known_method( env, proto, 7, "[Symbol.matchAll]", oxide_builtins::regexp::regexp_symbol_match_all:: 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:: as *const (), ); bind_constructor!(env, global, "RegExp", ctor_ptr, oxide_builtins::regexp::regexp_constructor::, 2, hash: true); }