atmos/os_lib/js/builtins/
errors_misc.rs1use super::*;
4
5pub(crate) fn build_error_stack(name: &str, msg: &str) -> String {
19 if msg.is_empty() {
20 String::from(name)
21 } else {
22 alloc::format!("{name}: {msg}")
23 }
24}
25pub(crate) fn set_error_props(it: &Interp, t: Value, msg: String, name: &str) -> Value {
26 match &t {
27 Value::Object(o) => {
28 let mut b = o.borrow_mut();
29 b.props.insert("stack".into(), Value::str(build_error_stack(name, &msg)));
30 b.props.insert("message".into(), Value::str(msg));
31 b.props.insert("name".into(), Value::str(name));
32 drop(b);
33 t
34 }
35 _ => {
36 let stack = build_error_stack(name, &msg);
39 let err = it.error(msg);
40 if let Value::Object(o) = &err {
41 let mut b = o.borrow_mut();
42 b.props.insert("name".into(), Value::str(name));
43 b.props.insert("stack".into(), Value::str(stack));
44 }
45 err
46 }
47 }
48}
49pub(crate) fn apply_error_cause(err: &Value, options: &Value) -> Value {
54 if let Value::Object(opt_obj) = options {
55 let has_cause = opt_obj.borrow().props.contains_key("cause");
56 if has_cause {
57 let cause = opt_obj.borrow().props.get("cause").cloned().unwrap_or(Value::Undefined);
58 if let Value::Object(o) = err {
59 o.borrow_mut().props.insert("cause".into(), cause);
60 }
61 }
62 }
63 err.clone()
64}
65pub(crate) fn error_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
66 let err = set_error_props(it, t, arg(a, 0).to_js_string(), "Error");
67 Ok(apply_error_cause(&err, &arg(a, 1)))
68}
69pub(crate) fn type_error_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
70 let err = set_error_props(it, t, arg(a, 0).to_js_string(), "TypeError");
71 Ok(apply_error_cause(&err, &arg(a, 1)))
72}
73pub(crate) fn range_error_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
74 let err = set_error_props(it, t, arg(a, 0).to_js_string(), "RangeError");
75 Ok(apply_error_cause(&err, &arg(a, 1)))
76}
77pub(crate) fn syntax_error_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
78 let err = set_error_props(it, t, arg(a, 0).to_js_string(), "SyntaxError");
79 Ok(apply_error_cause(&err, &arg(a, 1)))
80}
81pub(crate) fn suppressed_error_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
84 let err = set_error_props(it, t, arg(a, 2).to_js_string(), "SuppressedError");
85 if let Value::Object(o) = &err {
86 let mut b = o.borrow_mut();
87 b.props.insert("error".into(), arg(a, 0));
88 b.props.insert("suppressed".into(), arg(a, 1));
89 }
90 Ok(err)
91}
92pub(crate) fn aggregate_error_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
95 let errors_list = it.iter_to_vec(&arg(a, 0));
96 let msg = arg(a, 1).to_js_string();
97 let err = set_error_props(it, t, msg, "AggregateError");
98 if let Value::Object(o) = &err {
99 o.borrow_mut().props.insert("errors".into(), Value::Object(Obj::array(errors_list)));
100 }
101 Ok(err)
102}
103pub(crate) fn error_is_error(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
109 let error_proto = match it.global.borrow().vars.get("Error") {
110 Some(Value::Object(ctor)) => match ctor.borrow().props.get("prototype") {
111 Some(Value::Object(p)) => Some(p.clone()),
112 _ => None,
113 },
114 _ => None,
115 };
116 let error_proto = match error_proto {
117 Some(p) => p,
118 None => return Ok(Value::Bool(false)),
119 };
120 let mut cur = match arg(a, 0) {
121 Value::Object(o) => Some(o),
122 _ => None,
123 };
124 let mut guard = 0;
125 while let Some(c) = cur {
126 if Rc::ptr_eq(&c, &error_proto) {
127 return Ok(Value::Bool(true));
128 }
129 cur = c.borrow().proto.clone();
130 guard += 1;
131 if guard > 1000 {
132 break;
133 }
134 }
135 Ok(Value::Bool(false))
136}
137pub(crate) fn make_aggregate_error(it: &Interp, errors: Vec<Value>, msg: &str) -> Value {
140 let o = Obj::plain();
141 o.borrow_mut().props.insert("message".into(), Value::str(msg));
142 o.borrow_mut().props.insert("name".into(), Value::str("AggregateError"));
143 o.borrow_mut().props.insert("errors".into(), Value::Object(Obj::array(errors)));
144 if let Some(Value::Object(ctor)) = it.global.borrow().vars.get("AggregateError") {
145 if let Some(Value::Object(proto)) = ctor.borrow().props.get("prototype") {
146 o.borrow_mut().proto = Some(proto.clone());
147 }
148 }
149 Value::Object(o)
150}
151
152pub(crate) fn fr_register(_: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
154 Ok(Value::Undefined)
155}
156pub(crate) fn fr_unregister(_: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
157 Ok(Value::Bool(false))
158}
159pub(crate) fn finalization_registry_ctor(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
160 let cb = arg(a, 0);
161 let obj = Obj::plain();
162 {
163 let mut b = obj.borrow_mut();
164 b.props.insert("_cb".into(), cb);
165 b.props.insert("register".into(), nv("register", fr_register));
166 b.props.insert("unregister".into(), nv("unregister", fr_unregister));
167 b.props.insert("cleanupSome".into(), nv("cleanupSome", dom_noop));
168 }
169 Ok(Value::Object(obj))
170}
171
172pub(crate) fn idle_time_remaining(_: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
174 Ok(Value::Number(50.0))
175}
176pub(crate) fn request_idle_callback(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
177 let cb = arg(a, 0);
178 let deadline = Obj::plain();
179 {
180 let mut b = deadline.borrow_mut();
181 b.props.insert("didTimeout".into(), Value::Bool(false));
182 b.props.insert("timeRemaining".into(), nv("timeRemaining", idle_time_remaining));
183 }
184 it.call_listener(
185 &cb,
186 Value::Undefined,
187 &[Value::Object(deadline)],
188 "requestIdleCallback callback",
189 );
190 Ok(Value::Number(0.0))
191}
192
193pub(crate) fn object_has_own_static(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
195 let obj = arg(a, 0);
196 let key = arg(a, 1).to_js_string();
197 if let Value::Object(o) = &obj {
198 return Ok(Value::Bool(has_own_property(o, &key)));
199 }
200 Ok(Value::Bool(false))
201}
202
203pub(crate) fn object_group_by(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
205 let items = it.iter_to_vec(&arg(a, 0));
206 let f = arg(a, 1);
207 let result = Obj::plain();
208 result.borrow_mut().null_proto = true;
211 for (i, v) in items.iter().enumerate() {
212 let key = it
213 .call_value(&f, Value::Undefined, &[v.clone(), Value::Number(i as f64)])?
214 .to_js_string();
215 let mut b = result.borrow_mut();
216 let entry = b
217 .props
218 .entry(key)
219 .or_insert_with(|| Value::Object(Obj::array(alloc::vec![])));
220 if let Value::Object(arr) = entry {
221 if let ObjKind::Array(vec) = &mut arr.borrow_mut().kind {
222 vec.push(v.clone());
223 }
224 }
225 }
226 Ok(Value::Object(result))
227}
228
229pub(crate) fn map_group_by(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
232 let items: Vec<Value> = it.iter_to_vec(&arg(a, 0));
233 let f = arg(a, 1);
234 let mut entries: Vec<(Value, Value)> = Vec::new();
235 for (i, v) in items.iter().enumerate() {
236 let key = it.call_value(&f, Value::Undefined, &[v.clone(), Value::Number(i as f64)])?;
237 if let Some(slot) = entries.iter_mut().find(|(ek, _)| same_value_zero(ek, &key)) {
238 if let Value::Object(arr) = &slot.1 {
239 if let ObjKind::Array(vec) = &mut arr.borrow_mut().kind {
240 vec.push(v.clone());
241 }
242 }
243 } else {
244 entries.push((key, Value::Object(Obj::array(alloc::vec![v.clone()]))));
245 }
246 }
247 Ok(Value::Object(Obj::map_obj(entries)))
248}