Browse Source

Feature `SyntaxError` (#536)

pull/538/head
HalidOdat 4 years ago committed by GitHub
parent
commit
070b78c357
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      boa/src/builtins/error/mod.rs
  2. 17
      boa/src/builtins/error/range.rs
  3. 17
      boa/src/builtins/error/reference.rs
  4. 89
      boa/src/builtins/error/syntax.rs
  5. 16
      boa/src/builtins/error/type.rs
  6. 3
      boa/src/builtins/mod.rs
  7. 21
      boa/src/exec/exception.rs

23
boa/src/builtins/error/mod.rs

@ -20,16 +20,19 @@ use crate::{
profiler::BoaProfiler,
};
// mod eval;
pub(crate) mod range;
pub(crate) mod reference;
// mod syntax;
pub(crate) mod syntax;
pub(crate) mod r#type;
// mod uri;
// pub(crate) mod eval;
// pub(crate) mod uri;
pub(crate) use self::r#type::TypeError;
pub(crate) use self::range::RangeError;
pub(crate) use self::reference::ReferenceError;
pub(crate) use self::syntax::SyntaxError;
// pub(crate) use self::eval::EvalError;
// pub(crate) use self::uri::UriError;
/// Built-in `Error` object.
#[derive(Debug, Clone, Copy)]
@ -43,17 +46,11 @@ impl Error {
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
if !args.is_empty() {
this.set_field(
"message",
Value::from(
args.get(0)
.expect("failed getting error message")
.to_string(),
),
);
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
if let Some(message) = args.get(0) {
this.set_field("message", ctx.to_string(message)?);
}
// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::Error);

17
boa/src/builtins/error/range.rs

@ -32,17 +32,11 @@ impl RangeError {
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
if !args.is_empty() {
this.set_field(
"message",
Value::from(
args.get(0)
.expect("failed getting error message")
.to_string(),
),
);
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
if let Some(message) = args.get(0) {
this.set_field("message", ctx.to_string(message)?);
}
// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::Error);
@ -69,7 +63,8 @@ impl RangeError {
/// Create a new `RangeError` object.
pub(crate) fn create(global: &Value) -> Value {
let prototype = Value::new_object(Some(global));
prototype.set_field("message", Value::from(""));
prototype.set_field("name", Self::NAME);
prototype.set_field("message", "");
make_builtin_fn(Self::to_string, "toString", &prototype, 0);

17
boa/src/builtins/error/reference.rs

@ -31,17 +31,11 @@ impl ReferenceError {
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
if !args.is_empty() {
this.set_field(
"message",
Value::from(
args.get(0)
.expect("failed getting error message")
.to_string(),
),
);
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
if let Some(message) = args.get(0) {
this.set_field("message", ctx.to_string(message)?);
}
// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::Error);
@ -68,7 +62,8 @@ impl ReferenceError {
/// Create a new `ReferenceError` object.
pub(crate) fn create(global: &Value) -> Value {
let prototype = Value::new_object(Some(global));
prototype.set_field("message", Value::from(""));
prototype.set_field("name", Self::NAME);
prototype.set_field("message", "");
make_builtin_fn(Self::to_string, "toString", &prototype, 0);

89
boa/src/builtins/error/syntax.rs

@ -0,0 +1,89 @@
//! This module implements the global `SyntaxError` object.
//!
//! The SyntaxError object represents an error when trying to interpret syntactically invalid code.
//! It is thrown when the JavaScript engine encounters tokens or token order that does not conform
//! to the syntax of the language when parsing code.
//!
//! More information:
//! - [MDN documentation][mdn]
//! - [ECMAScript reference][spec]
//!
//! [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-syntaxerror
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError
use crate::{
builtins::{
function::make_builtin_fn,
function::make_constructor_fn,
object::ObjectData,
value::{ResultValue, Value},
},
exec::Interpreter,
profiler::BoaProfiler,
};
/// JavaScript `SyntaxError` impleentation.
#[derive(Debug, Clone, Copy)]
pub(crate) struct SyntaxError;
impl SyntaxError {
/// The name of the object.
pub(crate) const NAME: &'static str = "SyntaxError";
/// The amount of arguments this function object takes.
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
if let Some(message) = args.get(0) {
this.set_field("message", ctx.to_string(message)?);
}
// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::Error);
Err(this.clone())
}
/// `Error.prototype.toString()`
///
/// The toString() method returns a string representing the specified Error object.
///
/// More information:
/// - [MDN documentation][mdn]
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-error.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
let name = this.get_field("name");
let message = this.get_field("message");
Ok(format!("{}: {}", name, message).into())
}
/// Create a new `SyntaxError` object.
pub(crate) fn create(global: &Value) -> Value {
let prototype = Value::new_object(Some(global));
prototype.set_field("name", Self::NAME);
prototype.set_field("message", "");
make_builtin_fn(Self::to_string, "toString", &prototype, 0);
make_constructor_fn(
Self::NAME,
Self::LENGTH,
Self::make_error,
global,
prototype,
true,
)
}
/// Initialise the global object with the `SyntaxError` object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, Self::create(global))
}
}

16
boa/src/builtins/error/type.rs

@ -38,16 +38,9 @@ impl TypeError {
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
if !args.is_empty() {
this.set_field(
"message",
Value::from(
args.get(0)
.expect("failed getting error message")
.to_string(),
),
);
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
if let Some(message) = args.get(0) {
this.set_field("message", ctx.to_string(message)?);
}
// This value is used by console.log and other routines to match Object type
@ -76,7 +69,8 @@ impl TypeError {
/// Create a new `RangeError` object.
pub(crate) fn create(global: &Value) -> Value {
let prototype = Value::new_object(Some(global));
prototype.set_field("message", Value::from(""));
prototype.set_field("name", Self::NAME);
prototype.set_field("message", "");
make_builtin_fn(Self::to_string, "toString", &prototype, 0);

3
boa/src/builtins/mod.rs

@ -24,7 +24,7 @@ pub(crate) use self::{
array::Array,
bigint::BigInt,
boolean::Boolean,
error::{Error, RangeError, ReferenceError, TypeError},
error::{Error, RangeError, ReferenceError, SyntaxError, TypeError},
global_this::GlobalThis,
infinity::Infinity,
json::Json,
@ -60,6 +60,7 @@ pub fn init(global: &Value) {
RangeError::init,
ReferenceError::init,
TypeError::init,
SyntaxError::init,
// Global properties.
NaN::init,
Infinity::init,

21
boa/src/exec/exception.rs

@ -72,4 +72,25 @@ impl Interpreter {
{
Err(self.construct_reference_error(message))
}
/// Constructs a `SyntaxError` with the specified message.
pub fn construct_syntax_error<M>(&mut self, message: M) -> Value
where
M: Into<String>,
{
New::from(Call::new(
Identifier::from("SyntaxError"),
vec![Const::from(message.into()).into()],
))
.run(self)
.expect_err("SyntaxError should always throw")
}
/// Throws a `SyntaxError` with the specified message.
pub fn throw_syntax_error<M>(&mut self, message: M) -> ResultValue
where
M: Into<String>,
{
Err(self.construct_syntax_error(message))
}
}

Loading…
Cancel
Save