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