Skip to main content

mozjs/
error.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5//! Functions to throw JavaScript exceptions from Rust.
6
7#![deny(missing_docs)]
8
9use crate::context::{JSContext, RawJSContext};
10use crate::jsapi::{JSErrorFormatString, JSExnType, JS_ReportErrorNumberUTF8};
11use libc;
12use std::ffi::CStr;
13use std::{mem, os, ptr};
14
15/// Format string used to throw javascript errors.
16static ERROR_FORMAT_STRING_STRING: &CStr = c"{0}";
17
18/// Format string struct used to throw `TypeError`s.
19static mut TYPE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
20    name: c"RUSTMSG_TYPE_ERROR".as_ptr(),
21    format: ERROR_FORMAT_STRING_STRING.as_ptr(),
22    argCount: 1,
23    exnType: JSExnType::JSEXN_TYPEERR as i16,
24};
25
26/// Format string struct used to throw `RangeError`s.
27static mut RANGE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
28    name: c"RUSTMSG_RANGE_ERROR".as_ptr(),
29    format: ERROR_FORMAT_STRING_STRING.as_ptr(),
30    argCount: 1,
31    exnType: JSExnType::JSEXN_RANGEERR as i16,
32};
33
34/// Callback used to throw javascript errors.
35/// See throw_js_error for info about error_number.
36unsafe extern "C" fn get_error_message(
37    _user_ref: *mut os::raw::c_void,
38    error_number: libc::c_uint,
39) -> *const JSErrorFormatString {
40    let num: JSExnType = mem::transmute(error_number);
41    match num {
42        JSExnType::JSEXN_TYPEERR => &raw const TYPE_ERROR_FORMAT_STRING,
43        JSExnType::JSEXN_RANGEERR => &raw const RANGE_ERROR_FORMAT_STRING,
44        _ => panic!(
45            "Bad js error number given to get_error_message: {}",
46            error_number
47        ),
48    }
49}
50
51/// Helper fn to throw a javascript error with the given message and number.
52/// Reuse the jsapi error codes to distinguish the error_number
53/// passed back to the get_error_message callback.
54/// c_uint is u32, so this cast is safe, as is casting to/from i32 from there.
55unsafe fn throw_js_error(cx: *mut RawJSContext, error: &CStr, error_number: u32) {
56    JS_ReportErrorNumberUTF8(
57        cx,
58        Some(get_error_message),
59        ptr::null_mut(),
60        error_number,
61        error.as_ptr(),
62    );
63}
64
65/// Throw a `TypeError` with the given message.
66#[deprecated = "use throw_type_error_safe instead"]
67pub unsafe fn throw_type_error(cx: *mut RawJSContext, error: &CStr) {
68    throw_js_error(cx, error, JSExnType::JSEXN_TYPEERR as u32);
69}
70
71/// Throw a `RangeError` with the given message.
72#[deprecated = "use throw_range_error_safe instead"]
73pub unsafe fn throw_range_error(cx: *mut RawJSContext, error: &CStr) {
74    throw_js_error(cx, error, JSExnType::JSEXN_RANGEERR as u32);
75}
76
77/// Throw an `InternalError` with the given message.
78#[deprecated = "use throw_internal_error_safe instead"]
79pub unsafe fn throw_internal_error(cx: *mut RawJSContext, error: &CStr) {
80    throw_js_error(cx, error, JSExnType::JSEXN_INTERNALERR as u32);
81}
82
83/// Throw a `TypeError` with the given message.
84pub fn throw_type_error_safe(cx: &mut JSContext, error: &CStr) {
85    unsafe { throw_js_error(cx.raw_cx(), error, JSExnType::JSEXN_TYPEERR as u32) };
86}
87
88/// Throw a `RangeError` with the given message.
89pub fn throw_range_error_safe(cx: &mut JSContext, error: &CStr) {
90    unsafe { throw_js_error(cx.raw_cx(), error, JSExnType::JSEXN_RANGEERR as u32) };
91}
92
93/// Throw an `InternalError` with the given message.
94pub fn throw_internal_error_safe(cx: &mut JSContext, error: &CStr) {
95    unsafe { throw_js_error(cx.raw_cx(), error, JSExnType::JSEXN_INTERNALERR as u32) };
96}