quickjs_runtime/jsutils/
mod.rs

1//! This contains abstract traits and structs for use with different javascript runtimes
2//! the Adapter traits are use in the worker thread (EventLoop) of the Runtime and thus are not Send, they should never leave the thread
3//! The facade classes are for use outside the worker thread, they are Send
4//!
5
6use crate::values::JsValueFacade;
7use backtrace::Backtrace;
8use std::fmt::{Debug, Display, Error, Formatter};
9
10pub mod helper_tasks;
11pub mod jsproxies;
12pub mod modules;
13pub mod promises;
14
15pub trait ScriptPreProcessor {
16    fn process(&self, script: &mut Script) -> Result<(), JsError>;
17}
18
19/// the JsValueType represents the type of value for a JSValue
20#[derive(PartialEq, Copy, Clone, Eq)]
21pub enum JsValueType {
22    I32,
23    F64,
24    String,
25    Boolean,
26    Object,
27    Function,
28    BigInt,
29    Promise,
30    Date,
31    Null,
32    Undefined,
33    Array,
34    Error,
35}
36
37impl Display for JsValueType {
38    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
39        match self {
40            JsValueType::I32 => f.write_str("I32"),
41            JsValueType::F64 => f.write_str("F64"),
42            JsValueType::String => f.write_str("String"),
43            JsValueType::Boolean => f.write_str("Boolean"),
44            JsValueType::Object => f.write_str("Object"),
45            JsValueType::Function => f.write_str("Function"),
46            JsValueType::BigInt => f.write_str("BigInt"),
47            JsValueType::Promise => f.write_str("Promise"),
48            JsValueType::Date => f.write_str("Date"),
49            JsValueType::Null => f.write_str("Null"),
50            JsValueType::Undefined => f.write_str("Undefined"),
51            JsValueType::Array => f.write_str("Array"),
52            JsValueType::Error => f.write_str("Error"),
53        }
54    }
55}
56
57#[derive(Debug)]
58pub struct JsError {
59    name: String,
60    message: String,
61    stack: String,
62    cause: Option<Box<JsValueFacade>>,
63}
64
65impl JsError {
66    pub fn new(name: String, message: String, stack: String) -> Self {
67        Self {
68            name,
69            message,
70            stack,
71            cause: None,
72        }
73    }
74    pub fn new2(name: String, message: String, stack: String, cause: JsValueFacade) -> Self {
75        Self {
76            name,
77            message,
78            stack,
79            cause: Some(Box::new(cause)),
80        }
81    }
82    pub fn new_str(err: &str) -> Self {
83        Self::new_string(err.to_string())
84    }
85    pub fn new_string(err: String) -> Self {
86        let bt = Backtrace::new();
87        JsError {
88            name: "Error".to_string(),
89            message: err,
90            stack: format!("{bt:?}"),
91            cause: None,
92        }
93    }
94    pub fn get_message(&self) -> &str {
95        self.message.as_str()
96    }
97    pub fn get_stack(&self) -> &str {
98        self.stack.as_str()
99    }
100    pub fn get_name(&self) -> &str {
101        self.name.as_str()
102    }
103    pub fn get_cause(&self) -> &Option<Box<JsValueFacade>> {
104        &self.cause
105    }
106}
107
108impl std::error::Error for JsError {
109    fn description(&self) -> &str {
110        self.get_message()
111    }
112}
113
114impl From<anyhow::Error> for JsError {
115    fn from(err: anyhow::Error) -> Self {
116        JsError::new_string(format!("{err:?}"))
117    }
118}
119impl std::fmt::Display for JsError {
120    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
121        let e = format!("{}: {}\n{}", self.name, self.message, self.stack);
122        f.write_str(e.as_str())
123    }
124}
125
126impl From<Error> for JsError {
127    fn from(e: Error) -> Self {
128        JsError::new_string(format!("{e:?}"))
129    }
130}
131
132pub struct Script {
133    path: String,
134    code: String,
135    transpiled_code: Option<String>,
136    map: Option<String>,
137}
138
139impl Debug for Script {
140    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
141        f.write_str(format!("Script:{}", self.path.as_str()).as_str())
142    }
143}
144
145impl Script {
146    pub fn new(absolute_path: &str, script_code: &str) -> Self {
147        Self {
148            path: absolute_path.to_string(),
149            code: script_code.to_string(),
150            transpiled_code: None,
151            map: None,
152        }
153    }
154    pub fn get_path(&self) -> &str {
155        self.path.as_str()
156    }
157    pub fn get_code(&self) -> &str {
158        self.code.as_str()
159    }
160    pub fn get_runnable_code(&self) -> &str {
161        if let Some(t_code) = self.transpiled_code.as_ref() {
162            t_code.as_str()
163        } else {
164            self.code.as_str()
165        }
166    }
167    pub fn set_code(&mut self, code: String) {
168        self.code = code;
169    }
170    pub fn set_transpiled_code(&mut self, transpiled_code: String, map: Option<String>) {
171        self.transpiled_code = Some(transpiled_code);
172        self.map = map;
173    }
174    pub fn get_map(&self) -> Option<&str> {
175        self.map.as_deref()
176    }
177}
178
179impl Clone for Script {
180    fn clone(&self) -> Self {
181        Self {
182            path: self.path.clone(),
183            code: self.code.clone(),
184            transpiled_code: self.transpiled_code.clone(),
185            map: self.map.clone(),
186        }
187    }
188}