use crate::bindings::{apply_binding_table, configure_native_constructor, BindEnv}; use oxide_kernel::builtin::StringMethods; use oxide_types::object::{JsObject, PropAttributes}; use oxide_types::value::JsValue; /// 把 String 构造器与原型方法绑定到 global。 /// /// `realm_id` 是目标所属 realm 的编号:`@@iterator` 符号键按 (realm 编号, 局部 /// 下标) 编码,realm 编号为 0 时与旧编码逐字节一致。 pub fn bind_string(env: BindEnv<'_>, global: &mut JsObject) { let string_methods = StringMethods { from_char_code: oxide_builtins::string::string_from_char_code:: as *const (), index_of: oxide_builtins::string::string_index_of:: as *const (), includes: oxide_builtins::string::string_includes:: as *const (), char_at: oxide_builtins::string::string_char_at:: as *const (), char_code_at: oxide_builtins::string::string_char_code_at:: as *const (), concat: oxide_builtins::string::string_concat:: as *const (), slice: oxide_builtins::string::string_slice:: as *const (), substring: oxide_builtins::string::string_substring:: as *const (), to_upper_case: oxide_builtins::string::string_to_upper_case:: as *const (), to_lower_case: oxide_builtins::string::string_to_lower_case:: as *const (), to_locale_upper_case: oxide_builtins::string::string_to_locale_upper_case:: as *const (), to_locale_lower_case: oxide_builtins::string::string_to_locale_lower_case:: as *const (), locale_compare: oxide_builtins::string::string_locale_compare:: as *const (), trim: oxide_builtins::string::string_trim:: as *const (), repeat: oxide_builtins::string::string_repeat:: as *const (), pad_start: oxide_builtins::string::string_pad_start:: as *const (), pad_end: oxide_builtins::string::string_pad_end:: as *const (), starts_with: oxide_builtins::string::string_starts_with:: as *const (), ends_with: oxide_builtins::string::string_ends_with:: as *const (), split: oxide_builtins::string::string_split:: as *const (), replace: oxide_builtins::string::string_replace:: as *const (), match_fn: oxide_builtins::string::string_match_fn:: as *const (), search: oxide_builtins::string::string_search:: as *const (), trim_start: oxide_builtins::string::string_trim_start:: as *const (), trim_end: oxide_builtins::string::string_trim_end:: as *const (), code_point_at: oxide_builtins::string::string_code_point_at:: as *const (), normalize: oxide_builtins::string::string_normalize:: as *const (), match_all: oxide_builtins::string::string_match_all:: as *const (), replace_all: oxide_builtins::string::string_replace_all:: as *const (), value_of: oxide_builtins::string::string_value_of:: as *const (), substr: oxide_builtins::string::string_substr:: as *const (), at: oxide_builtins::string::string_at:: as *const (), last_index_of: oxide_builtins::string::string_last_index_of:: as *const (), from_code_point: oxide_builtins::string::string_from_code_point:: as *const (), is_well_formed: oxide_builtins::string::string_is_well_formed:: as *const (), to_well_formed: oxide_builtins::string::string_to_well_formed:: as *const (), from_raw: oxide_builtins::string::string_raw:: as *const (), anchor: oxide_builtins::string::string_anchor:: as *const (), big: oxide_builtins::string::string_big:: as *const (), blink: oxide_builtins::string::string_blink:: as *const (), bold: oxide_builtins::string::string_bold:: as *const (), fixed: oxide_builtins::string::string_fixed:: as *const (), fontcolor: oxide_builtins::string::string_fontcolor:: as *const (), fontsize: oxide_builtins::string::string_fontsize:: as *const (), italics: oxide_builtins::string::string_italics:: as *const (), link: oxide_builtins::string::string_link:: as *const (), small: oxide_builtins::string::string_small:: as *const (), strike: oxide_builtins::string::string_strike:: as *const (), sub: oxide_builtins::string::string_sub:: as *const (), sup: oxide_builtins::string::string_sup:: as *const (), }; env.world() .bind_string_methods(&string_methods, env.string_forge(), env.shape_forge()); let ctor_ptr = env.world().string_constructor.as_ptr() as *mut JsObject; let ctor = unsafe { &mut *ctor_ptr }; configure_native_constructor(ctor, oxide_builtins::string::string_constructor:: as *const (), 1); // String.length = 1,描述符 { writable:false, enumerable:false, configurable:true }。 let length_si = env.string_forge().intern("length").0; let length_shape = env.shape_forge().make_shape(ctor.shape_id(), length_si); ctor.set_shape_id(length_shape); ctor.ensure_hash_props().push(JsValue::int(1)); let length_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1); ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true)); let proto_ptr = env.world().string_proto.as_ptr() as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; apply_binding_table( env, proto, &[ ("toString", oxide_builtins::string::string_to_string:: as *const (), 0), ("toSource", oxide_builtins::to_source::to_source_string:: as *const (), 0), ], ); // String.prototype[@@iterator]:逐 code point 迭代字符;name 属性按规范 // 落 "[Symbol.iterator]"。 super::bind_well_known_method( env, proto, 0, "[Symbol.iterator]", oxide_builtins::string::string_symbol_iterator:: as *const (), 0, ); // 捕获默认迭代器函数对象指针写入 world:String 臂覆盖判定以此做指针比较。 // 此时槽为初始数据属性(用户覆盖尚未可能),读回即默认函数本体。 let iter_key = oxide_types::private_key::encode_symbol_key(env.realm_id, 0); if let Some(pos) = env.shape_forge().lookup_position(proto.shape_id(), iter_key) { let v = proto.get_prop_at(pos); if v.is_object() { env.world().string_default_iterator.set(v.as_js_object_ptr() as *const JsObject); } } // 全局 String 槽位既有槽原位更新(旧家族构造器指针不得滞留在属性 vec), // 无槽时开新槽;描述符非枚举(规范 { writable:true, enumerable:false, configurable:true })。 let si_str = env.string_forge().intern("String").0; let str_val = JsValue::from_js_object(env.world().string_constructor.as_ptr() as *mut JsObject); if let Some(pos) = env.shape_forge().lookup_position(global.shape_id(), si_str) { global.set_prop_at(pos, str_val); } else { let str_shape = env.shape_forge().make_shape(global.shape_id(), si_str); global.set_shape_id(str_shape); global.ensure_hash_props().push(str_val); let pos = global.prop_vec_len().saturating_sub(1) as u32; global.set_data_meta(pos, PropAttributes::new(true, false, true)); global.bump_generation(); } }