1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/// Equivalent to the normal `try!` macro for JSRT function calls.
macro_rules! jstry {
    ($e: expr) => { ::util::jstry($e)?; }
}

/// Asserts the return value of a JSRT function call.
macro_rules! jsassert {
    ($e: expr, $name: expr) => {
        let result = $e;

        // In many cases idiomatic code prevents any errors from happening
        // (except for memory resource issues).
        assert!(result == ::chakracore_sys::JsErrorCode::NoError,
                format!("JSRT call to '{}' failed unexpectedly with: {:?}", $name, result));
    };

    ($e: expr) => {
        jsassert!($e, stringify!($e));
    };
}

/// Shared base reference implementation.
macro_rules! reference_base {
    ($typ:ident) => {
        impl $typ {
            /// Creates an instance from a raw pointer.
            ///
            /// This is used for managing the lifetime of JSRT objects. They are
            /// tracked using reference counting; incrementing with `from_raw`,
            /// and decrementing with `drop`.
            ///
            /// This is required to support items stored on the heap, since the
            /// JSRT runtime only observes the stack.
            ///
            /// If used in conjunction with a `Property` or any `Value`, it is
            /// assumed a `Context` is active.
            pub unsafe fn from_raw(value: JsRef) -> $typ {
                jsassert!(JsAddRef(value, ::std::ptr::null_mut()));
                $typ(value)
            }

            /// Returns the underlying raw pointer.
            pub fn as_raw(&self) -> JsRef {
                self.0
            }
        }

        impl Clone for $typ {
            /// Duplicates a reference counted type.
            ///
            /// The underlying pointer will be copied, and its reference count
            /// will be incremented, returned wrapped as the type.
            fn clone(&self) -> $typ {
                unsafe { $typ::from_raw(self.as_raw()) }
            }
        }
    }
}

/// Implements JSRT reference counting for a non-value type.
macro_rules! reference {
    ($typ:ident) => {
        reference_base!($typ);

        impl Drop for $typ {
            /// Decrements the reference counter.
            fn drop(&mut self) {
                ::util::release_reference(self.as_raw());
            }
        }
    };
}