ferrijs_std/utils/
primordials.rs1use std::any::type_name;
2
3use rquickjs::{
4 atom::PredefinedAtom, function::Constructor, runtime::UserDataGuard, Ctx, Exception, Function,
5 JsLifetime, Object, Result,
6};
7
8use crate::utils::result::ResultExt;
9
10#[derive(JsLifetime)]
11pub struct BasePrimordials<'js> {
12 pub constructor_map: Constructor<'js>,
14 pub constructor_set: Constructor<'js>,
15 pub constructor_date: Constructor<'js>,
16 pub constructor_error: Constructor<'js>,
17 pub constructor_type_error: Constructor<'js>,
18 pub constructor_range_error: Constructor<'js>,
19 pub constructor_regexp: Constructor<'js>,
20 pub constructor_uint8array: Constructor<'js>,
21 pub constructor_array_buffer: Constructor<'js>,
22 pub constructor_proxy: Constructor<'js>,
23 pub constructor_object: Constructor<'js>,
24 pub constructor_bool: Constructor<'js>,
25 pub constructor_number: Constructor<'js>,
26 pub constructor_string: Constructor<'js>,
27
28 pub prototype_object: Object<'js>,
30 pub prototype_date: Object<'js>,
31 pub prototype_regexp: Object<'js>,
32 pub prototype_set: Object<'js>,
33 pub prototype_map: Object<'js>,
34 pub prototype_error: Object<'js>,
35
36 pub function_array_from: Function<'js>,
38 pub function_array_buffer_is_view: Function<'js>,
39 pub function_get_own_property_descriptor: Function<'js>,
40 pub function_reflect_own_keys: Function<'js>,
41 pub function_parse_int: Function<'js>,
42 pub function_parse_float: Function<'js>,
43 pub prototype_iterator: Object<'js>,
44}
45
46pub trait Primordial<'js>
47where
48 Self: Sized + JsLifetime<'js>,
49{
50 fn get<'a>(ctx: &'a Ctx<'js>) -> Result<UserDataGuard<'a, Self>> {
51 let userdata = ctx.userdata::<Self>().or_throw_msg(
52 ctx,
53 &[
54 "Userdata of ",
55 type_name::<Self>(),
56 " not initialized. Call init(&ctx) on this type.",
57 ]
58 .concat(),
59 )?;
60
61 Ok(userdata)
62 }
63
64 fn init<'a>(ctx: &'a Ctx<'js>) -> Result<()> {
65 if ctx.userdata::<Self>().is_none() {
66 let primoridals = Self::new(ctx)?;
67 let _ = ctx.store_userdata(primoridals);
68 }
69
70 Ok(())
71 }
72 fn new(ctx: &Ctx<'js>) -> Result<Self>;
73}
74
75impl<'js> Primordial<'js> for BasePrimordials<'js> {
76 fn new(ctx: &Ctx<'js>) -> Result<Self> {
77 let globals = ctx.globals();
78
79 let constructor_object: Constructor = globals.get(PredefinedAtom::Object)?;
80 let prototype_object: Object = constructor_object.get(PredefinedAtom::Prototype)?;
81
82 let constructor_proxy: Constructor = globals.get(PredefinedAtom::Proxy)?;
83
84 let function_get_own_property_descriptor: Function =
85 constructor_object.get(PredefinedAtom::GetOwnPropertyDescriptor)?;
86
87 let constructor_date: Constructor = globals.get(PredefinedAtom::Date)?;
88 let prototype_date: Object = constructor_date.get(PredefinedAtom::Prototype)?;
89
90 let constructor_map: Constructor = globals.get(PredefinedAtom::Map)?;
91 let prototype_map: Object = constructor_map.get(PredefinedAtom::Prototype)?;
92
93 let constructor_set: Constructor = globals.get(PredefinedAtom::Set)?;
94 let prototype_set: Object = constructor_set.get(PredefinedAtom::Prototype)?;
95
96 let constructor_regexp: Constructor = globals.get(PredefinedAtom::RegExp)?;
97 let prototype_regexp: Object = constructor_regexp.get(PredefinedAtom::Prototype)?;
98
99 let constructor_uint8array: Constructor = globals.get(PredefinedAtom::Uint8Array)?;
100 let constructor_arraybuffer: Constructor = globals.get(PredefinedAtom::ArrayBuffer)?;
101
102 let constructor_error: Constructor = globals.get(PredefinedAtom::Error)?;
103 let constructor_type_error: Constructor = ctx.globals().get(PredefinedAtom::TypeError)?;
104 let constructor_range_error: Constructor = ctx.globals().get(PredefinedAtom::RangeError)?;
105 let prototype_error: Object = constructor_error.get(PredefinedAtom::Prototype)?;
106
107 let constructor_array: Object = globals.get(PredefinedAtom::Array)?;
108 let function_array_from: Function = constructor_array.get(PredefinedAtom::From)?;
109
110 let constructor_array_buffer: Object = globals.get(PredefinedAtom::ArrayBuffer)?;
111 let function_array_buffer_is_view: Function = constructor_array_buffer.get("isView")?;
112
113 let constructor_bool: Constructor = globals.get(PredefinedAtom::Boolean)?;
114
115 let constructor_number: Constructor = globals.get(PredefinedAtom::Number)?;
116 let function_parse_float: Function = constructor_number.get("parseFloat")?;
117 let function_parse_int: Function = constructor_number.get("parseInt")?;
118
119 let constructor_string: Constructor = globals.get(PredefinedAtom::String)?;
120
121 let reflect: Object = globals.get("Reflect")?;
122 let function_reflect_own_keys: Function = reflect.get("ownKeys")?;
123
124 let array = rquickjs::Array::new(ctx.clone())?;
126 let iter_fn: Function = array
127 .as_object()
128 .get(rquickjs::atom::PredefinedAtom::SymbolIterator)?;
129 let array_iter: Object = iter_fn.call((rquickjs::function::This(array),))?;
130 let prototype_iterator = array_iter
131 .get_prototype()
132 .and_then(|p| p.get_prototype())
133 .ok_or_else(|| Exception::throw_internal(ctx, "missing %IteratorPrototype%"))?;
134
135 Ok(Self {
136 constructor_map,
137 constructor_set,
138 constructor_date,
139 constructor_proxy,
140 constructor_error,
141 constructor_type_error,
142 constructor_range_error,
143 constructor_regexp,
144 constructor_uint8array,
145 constructor_array_buffer: constructor_arraybuffer,
146 constructor_object,
147 constructor_bool,
148 constructor_number,
149 constructor_string,
150 prototype_object,
151 prototype_date,
152 prototype_regexp,
153 prototype_set,
154 prototype_map,
155 prototype_error,
156 function_array_from,
157 function_array_buffer_is_view,
158 function_get_own_property_descriptor,
159 function_reflect_own_keys,
160 function_parse_float,
161 function_parse_int,
162 prototype_iterator,
163 })
164 }
165}