1#![doc(
12 html_logo_url = "https://raw.githubusercontent.com/jasonwilliams/boa/master/assets/logo.svg",
13 html_favicon_url = "https://raw.githubusercontent.com/jasonwilliams/boa/master/assets/logo.svg"
14)]
15#![deny(
16 clippy::all,
17 unused_qualifications,
18 unused_import_braces,
19 unused_lifetimes,
20 unreachable_pub,
21 trivial_numeric_casts,
22 missing_debug_implementations,
24 missing_copy_implementations,
25 deprecated_in_future,
26 meta_variable_misuse,
27 non_ascii_idents,
28 rust_2018_compatibility,
29 rust_2018_idioms,
30 future_incompatible,
31 nonstandard_style,
32)]
33#![warn(clippy::perf, clippy::single_match_else, clippy::dbg_macro)]
34#![allow(
35 clippy::missing_inline_in_public_items,
36 clippy::cognitive_complexity,
37 clippy::must_use_candidate,
38 clippy::missing_errors_doc,
39 clippy::as_conversions,
40 clippy::let_unit_value,
41 rustdoc::missing_doc_code_examples
42)]
43
44pub mod bigint;
45pub mod builtins;
46pub mod class;
47pub mod context;
48pub mod environment;
49pub mod exec;
50pub mod gc;
51pub mod object;
52pub mod profiler;
53pub mod property;
54pub mod realm;
55pub mod string;
56pub mod symbol;
57pub mod syntax;
58pub mod value;
59
60#[cfg(feature = "vm")]
61pub mod bytecompiler;
62#[cfg(feature = "vm")]
63pub mod vm;
64
65pub mod prelude {
67 pub use crate::{object::JsObject, Context, JsBigInt, JsResult, JsString, JsValue};
68}
69
70use std::result::Result as StdResult;
71
72pub(crate) use crate::{exec::Executable, profiler::BoaProfiler};
73
74#[doc(inline)]
76pub use crate::{
77 bigint::JsBigInt, context::Context, string::JsString, symbol::JsSymbol, value::JsValue,
78};
79
80use crate::syntax::{
81 ast::node::StatementList,
82 parser::{ParseError, Parser},
83};
84
85#[must_use]
87pub type JsResult<T> = StdResult<T, JsValue>;
88
89#[inline]
94pub fn parse<T: AsRef<[u8]>>(src: T, strict_mode: bool) -> StdResult<StatementList, ParseError> {
95 let src_bytes: &[u8] = src.as_ref();
96 Parser::new(src_bytes, strict_mode).parse_all()
97}
98
99#[cfg(test)]
102pub(crate) fn forward<T: AsRef<[u8]>>(context: &mut Context, src: T) -> String {
103 let src_bytes: &[u8] = src.as_ref();
104
105 let expr = match parse(src_bytes, false) {
107 Ok(res) => res,
108 Err(e) => {
109 return format!(
110 "Uncaught {}",
111 context
112 .throw_syntax_error(e.to_string())
113 .expect_err("interpreter.throw_syntax_error() did not return an error")
114 .display()
115 );
116 }
117 };
118 expr.run(context).map_or_else(
119 |e| format!("Uncaught {}", e.display()),
120 |v| v.display().to_string(),
121 )
122}
123
124#[allow(clippy::unit_arg, clippy::drop_copy)]
129#[cfg(test)]
130pub(crate) fn forward_val<T: AsRef<[u8]>>(context: &mut Context, src: T) -> JsResult<JsValue> {
131 let main_timer = BoaProfiler::global().start_event("Main", "Main");
132
133 let src_bytes: &[u8] = src.as_ref();
134 let result = parse(src_bytes, false)
136 .map_err(|e| {
137 context
138 .throw_syntax_error(e.to_string())
139 .expect_err("interpreter.throw_syntax_error() did not return an error")
140 })
141 .and_then(|expr| expr.run(context));
142
143 drop(main_timer);
145 BoaProfiler::global().drop();
146
147 result
148}
149
150#[cfg(test)]
152pub(crate) fn exec<T: AsRef<[u8]>>(src: T) -> String {
153 let src_bytes: &[u8] = src.as_ref();
154
155 match Context::new().eval(src_bytes) {
156 Ok(value) => value.display().to_string(),
157 Err(error) => error.display().to_string(),
158 }
159}
160
161#[cfg(test)]
162pub(crate) enum TestAction {
163 Execute(&'static str),
164 TestEq(&'static str, &'static str),
165 TestStartsWith(&'static str, &'static str),
166}
167
168#[cfg(test)]
172#[track_caller]
173pub(crate) fn check_output(actions: &[TestAction]) {
174 let mut context = Context::new();
175
176 let mut i = 1;
177 for action in actions {
178 match action {
179 TestAction::Execute(src) => {
180 forward(&mut context, src);
181 }
182 TestAction::TestEq(case, expected) => {
183 assert_eq!(
184 &forward(&mut context, case),
185 expected,
186 "Test case {} ('{}')",
187 i,
188 case
189 );
190 i += 1;
191 }
192 TestAction::TestStartsWith(case, expected) => {
193 assert!(
194 &forward(&mut context, case).starts_with(expected),
195 "Test case {} ('{}')",
196 i,
197 case
198 );
199 i += 1;
200 }
201 }
202 }
203}