boa/builtins/error/
mod.rs1use crate::{
14 builtins::BuiltIn,
15 context::StandardObjects,
16 object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
17 profiler::BoaProfiler,
18 property::Attribute,
19 Context, JsResult, JsValue,
20};
21
22pub(crate) mod eval;
23pub(crate) mod range;
24pub(crate) mod reference;
25pub(crate) mod syntax;
26pub(crate) mod r#type;
27pub(crate) mod uri;
28
29#[cfg(test)]
30mod tests;
31
32pub(crate) use self::eval::EvalError;
33pub(crate) use self::r#type::TypeError;
34pub(crate) use self::range::RangeError;
35pub(crate) use self::reference::ReferenceError;
36pub(crate) use self::syntax::SyntaxError;
37pub(crate) use self::uri::UriError;
38
39#[derive(Debug, Clone, Copy)]
41pub(crate) struct Error;
42
43impl BuiltIn for Error {
44 const NAME: &'static str = "Error";
45
46 fn attribute() -> Attribute {
47 Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
48 }
49
50 fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
51 let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
52
53 let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
54 let error_object = ConstructorBuilder::with_standard_object(
55 context,
56 Self::constructor,
57 context.standard_objects().error_object().clone(),
58 )
59 .name(Self::NAME)
60 .length(Self::LENGTH)
61 .property("name", Self::NAME, attribute)
62 .property("message", "", attribute)
63 .method(Self::to_string, "toString", 0)
64 .build();
65
66 (Self::NAME, error_object.into(), Self::attribute())
67 }
68}
69
70impl Error {
71 pub(crate) const LENGTH: usize = 1;
73
74 pub(crate) fn constructor(
78 new_target: &JsValue,
79 args: &[JsValue],
80 context: &mut Context,
81 ) -> JsResult<JsValue> {
82 let prototype =
83 get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
84 let obj = context.construct_object();
85 obj.set_prototype_instance(prototype.into());
86 let this = JsValue::new(obj);
87 if let Some(message) = args.get(0) {
88 if !message.is_undefined() {
89 this.set_field("message", message.to_string(context)?, false, context)?;
90 }
91 }
92
93 this.set_data(ObjectData::error());
96 Ok(this)
97 }
98
99 #[allow(clippy::wrong_self_convention)]
110 pub(crate) fn to_string(
111 this: &JsValue,
112 _: &[JsValue],
113 context: &mut Context,
114 ) -> JsResult<JsValue> {
115 if !this.is_object() {
116 return context.throw_type_error("'this' is not an Object");
117 }
118 let name = this.get_field("name", context)?;
119 let name_to_string;
120 let name = if name.is_undefined() {
121 "Error"
122 } else {
123 name_to_string = name.to_string(context)?;
124 name_to_string.as_str()
125 };
126
127 let message = this.get_field("message", context)?;
128 let message_to_string;
129 let message = if message.is_undefined() {
130 ""
131 } else {
132 message_to_string = message.to_string(context)?;
133 message_to_string.as_str()
134 };
135
136 if name.is_empty() {
137 Ok(message.into())
138 } else if message.is_empty() {
139 Ok(name.into())
140 } else {
141 Ok(format!("{}: {}", name, message).into())
142 }
143 }
144}