Skip to content

Commit

Permalink
Feature URIError (#806)
Browse files Browse the repository at this point in the history
- Add tests
  • Loading branch information
HalidOdat authored Oct 6, 2020
1 parent 327d71b commit a77ceb6
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 4 deletions.
4 changes: 2 additions & 2 deletions boa/src/builtins/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub(crate) mod range;
pub(crate) mod reference;
pub(crate) mod syntax;
pub(crate) mod r#type;
// pub(crate) mod uri;
pub(crate) mod uri;

#[cfg(test)]
mod tests;
Expand All @@ -33,7 +33,7 @@ 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::uri::UriError;
pub(crate) use self::uri::UriError;

/// Built-in `Error` object.
#[derive(Debug, Clone, Copy)]
Expand Down
25 changes: 25 additions & 0 deletions boa/src/builtins/error/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,28 @@ fn eval_error_to_string() {
"\"EvalError\""
);
}

#[test]
fn uri_error_name() {
let mut ctx = Context::new();
assert_eq!(forward(&mut ctx, "URIError.name"), "\"URIError\"");
}

#[test]
fn uri_error_length() {
let mut ctx = Context::new();
assert_eq!(forward(&mut ctx, "URIError.length"), "1");
}

#[test]
fn uri_error_to_string() {
let mut ctx = Context::new();
assert_eq!(
forward(&mut ctx, "new URIError('hello').toString()"),
"\"URIError: hello\""
);
assert_eq!(
forward(&mut ctx, "new URIError().toString()"),
"\"URIError\""
);
}
68 changes: 68 additions & 0 deletions boa/src/builtins/error/uri.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! This module implements the global `URIError` object.
//!
//! The `URIError` object represents an error when a global URI handling
//! function was used in a wrong way.
//!
//! More information:
//! - [MDN documentation][mdn]
//! - [ECMAScript reference][spec]
//!
//! [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-urierror
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError

use crate::{
builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData},
profiler::BoaProfiler,
property::Attribute,
Context, Result, Value,
};

/// JavaScript `URIError` impleentation.
#[derive(Debug, Clone, Copy)]
pub(crate) struct UriError;

impl BuiltIn for UriError {
const NAME: &'static str = "URIError";

fn attribute() -> Attribute {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}

fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");

let error_prototype = context.standard_objects().error_object().prototype();
let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
let uri_error_object = ConstructorBuilder::with_standard_object(
context,
Self::constructor,
context.standard_objects().uri_error_object().clone(),
)
.name(Self::NAME)
.length(Self::LENGTH)
.inherit(error_prototype.into())
.property("name", Self::NAME, attribute)
.property("message", "", attribute)
.build();

(Self::NAME, uri_error_object.into(), Self::attribute())
}
}

impl UriError {
/// The amount of arguments this function object takes.
pub(crate) const LENGTH: usize = 1;

/// Create a new error object.
pub(crate) fn constructor(this: &Value, args: &[Value], ctx: &mut Context) -> Result<Value> {
if let Some(message) = args.get(0) {
this.set_field("message", message.to_string(ctx)?);
}

// 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);
Ok(this.clone())
}
}
3 changes: 2 additions & 1 deletion boa/src/builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub(crate) use self::{
bigint::BigInt,
boolean::Boolean,
date::Date,
error::{Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError},
error::{Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, UriError},
function::BuiltInFunctionObject,
global_this::GlobalThis,
infinity::Infinity,
Expand Down Expand Up @@ -83,6 +83,7 @@ pub fn init(context: &mut Context) {
TypeError::init,
SyntaxError::init,
EvalError::init,
UriError::init,
#[cfg(feature = "console")]
console::Console::init,
];
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl Object {
/// [spec]: https://tc39.es/ecma262/#sec-object.defineproperties
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties
pub fn define_properties(_: &Value, args: &[Value], ctx: &mut Context) -> Result<Value> {
let arg = args.get(0).cloned().unwrap_or(Value::undefined());
let arg = args.get(0).cloned().unwrap_or_default();
let arg_obj = arg.as_object_mut();
if let Some(mut obj) = arg_obj {
let props = args.get(1).cloned().unwrap_or_else(Value::undefined);
Expand Down
26 changes: 26 additions & 0 deletions boa/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub struct StandardObjects {
range_error: StandardConstructor,
syntax_error: StandardConstructor,
eval_error: StandardConstructor,
uri_error: StandardConstructor,
}

impl StandardObjects {
Expand Down Expand Up @@ -159,6 +160,10 @@ impl StandardObjects {
pub fn eval_error_object(&self) -> &StandardConstructor {
&self.eval_error
}

pub fn uri_error_object(&self) -> &StandardConstructor {
&self.uri_error
}
}

/// Javascript context. It is the primary way to interact with the runtime.
Expand Down Expand Up @@ -393,6 +398,19 @@ impl Context {
.expect("Into<String> used as message")
}

/// Constructs a `URIError` with the specified message.
pub fn construct_uri_error<M>(&mut self, message: M) -> Value
where
M: Into<String>,
{
New::from(Call::new(
Identifier::from("URIError"),
vec![Const::from(message.into()).into()],
))
.run(self)
.expect("Into<String> used as message")
}

/// Throws a `EvalError` with the specified message.
pub fn throw_eval_error<M>(&mut self, message: M) -> Result<Value>
where
Expand All @@ -401,6 +419,14 @@ impl Context {
Err(self.construct_eval_error(message))
}

/// Throws a `URIError` with the specified message.
pub fn throw_uri_error<M>(&mut self, message: M) -> Result<Value>
where
M: Into<String>,
{
Err(self.construct_uri_error(message))
}

/// Utility to create a function Value for Function Declarations, Arrow Functions or Function Expressions
pub(crate) fn create_function<P, B>(
&mut self,
Expand Down

0 comments on commit a77ceb6

Please sign in to comment.