boa_engine/builtins/error/
reference.rs

1//! This module implements the global `ReferenceError` object.
2//!
3//! Indicates an error that occurs when de-referencing an invalid reference
4//!
5//! More information:
6//!  - [MDN documentation][mdn]
7//!  - [ECMAScript reference][spec]
8//!
9//! [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-referenceerror
10//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError
11
12use crate::{
13    Context, JsArgs, JsResult, JsString, JsValue,
14    builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject},
15    context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
16    js_string,
17    object::{JsObject, internal_methods::get_prototype_from_constructor},
18    property::Attribute,
19    realm::Realm,
20    string::StaticJsStrings,
21};
22
23use super::{Error, ErrorKind};
24
25#[derive(Debug, Clone, Copy)]
26pub(crate) struct ReferenceError;
27
28impl IntrinsicObject for ReferenceError {
29    fn init(realm: &Realm) {
30        let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
31        BuiltInBuilder::from_standard_constructor::<Self>(realm)
32            .prototype(realm.intrinsics().constructors().error().constructor())
33            .inherits(Some(realm.intrinsics().constructors().error().prototype()))
34            .property(js_string!("name"), Self::NAME, attribute)
35            .property(js_string!("message"), js_string!(), attribute)
36            .build();
37    }
38
39    fn get(intrinsics: &Intrinsics) -> JsObject {
40        Self::STANDARD_CONSTRUCTOR(intrinsics.constructors()).constructor()
41    }
42}
43
44impl BuiltInObject for ReferenceError {
45    const NAME: JsString = StaticJsStrings::REFERENCE_ERROR;
46}
47
48impl BuiltInConstructor for ReferenceError {
49    const CONSTRUCTOR_ARGUMENTS: usize = 1;
50    const PROTOTYPE_STORAGE_SLOTS: usize = 2;
51    const CONSTRUCTOR_STORAGE_SLOTS: usize = 0;
52
53    const STANDARD_CONSTRUCTOR: fn(&StandardConstructors) -> &StandardConstructor =
54        StandardConstructors::reference_error;
55
56    /// Create a new error object.
57    fn constructor(
58        new_target: &JsValue,
59        args: &[JsValue],
60        context: &mut Context,
61    ) -> JsResult<JsValue> {
62        // 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
63        let new_target = &if new_target.is_undefined() {
64            context
65                .active_function_object()
66                .unwrap_or_else(|| {
67                    context
68                        .intrinsics()
69                        .constructors()
70                        .reference_error()
71                        .constructor()
72                })
73                .into()
74        } else {
75            new_target.clone()
76        };
77        // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%NativeError.prototype%", « [[ErrorData]] »).
78        let prototype = get_prototype_from_constructor(
79            new_target,
80            StandardConstructors::reference_error,
81            context,
82        )?;
83        let o = JsObject::from_proto_and_data_with_shared_shape(
84            context.root_shape(),
85            prototype,
86            Error::with_caller_position(ErrorKind::Reference, context),
87        );
88
89        // 3. If message is not undefined, then
90        let message = args.get_or_undefined(0);
91        if !message.is_undefined() {
92            // a. Let msg be ? ToString(message).
93            let msg = message.to_string(context)?;
94
95            // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg).
96            o.create_non_enumerable_data_property_or_throw(js_string!("message"), msg, context);
97        }
98
99        // 4. Perform ? InstallErrorCause(O, options).
100        Error::install_error_cause(&o, args.get_or_undefined(1), context)?;
101
102        // 5. Return O.
103        Ok(o.into())
104    }
105}