Browse Source

Fixed some extra regex panics (#1031)

pull/1036/head
Iban Eguia 4 years ago committed by GitHub
parent
commit
553ea529f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 76
      boa/src/builtins/regexp/mod.rs
  2. 4
      boa/src/object/internal_methods.rs

76
boa/src/builtins/regexp/mod.rs

@ -317,14 +317,18 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.test
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
pub(crate) fn test(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let mut last_index = this.get_field("lastIndex", context)?.to_index(context)?;
let result = if let Some(object) = this.as_object() {
// 3. Let string be ? ToString(S).
let arg_str = args
.get(0)
.expect("could not get argument")
.cloned()
.unwrap_or_default()
.to_string(context)?;
let mut last_index = this.get_field("lastIndex", context)?.to_index(context)?;
let result = if let Some(object) = this.as_object() {
// 4. Let match be ? RegExpExec(R, string).
let object = object.borrow();
let regex = object.as_regexp().unwrap();
if let Some(regex) = object.as_regexp() {
let result =
if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() {
if regex.use_last_index {
@ -337,9 +341,17 @@ impl RegExp {
}
false
};
// 5. If match is not null, return true; else return false.
Ok(Value::boolean(result))
} else {
panic!("object is not a regexp")
return context
.throw_type_error("RegExp.prototype.exec method called on incompatible value");
}
} else {
// 2. If Type(R) is not Object, throw a TypeError exception.
return context
.throw_type_error("RegExp.prototype.exec method called on incompatible value");
};
this.set_field("lastIndex", Value::from(last_index), context)?;
result
@ -358,14 +370,18 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.exec
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
pub(crate) fn exec(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let arg_str = args
.get(0)
.expect("could not get argument")
.to_string(context)?;
// 4. Return ? RegExpBuiltinExec(R, S).
let mut last_index = this.get_field("lastIndex", context)?.to_index(context)?;
let result = if let Some(object) = this.as_object() {
let object = object.borrow();
let regex = object.as_regexp().unwrap();
if let Some(regex) = object.as_regexp() {
// 3. Let S be ? ToString(string).
let arg_str = args
.get(0)
.cloned()
.unwrap_or_default()
.to_string(context)?;
let result = {
if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() {
if regex.use_last_index {
@ -384,8 +400,12 @@ impl RegExp {
}
let result = Value::from(result);
result.set_property("index", DataDescriptor::new(m.start(), Attribute::all()));
result.set_property("input", DataDescriptor::new(arg_str, Attribute::all()));
result.set_property(
"index",
DataDescriptor::new(m.start(), Attribute::all()),
);
result
.set_property("input", DataDescriptor::new(arg_str, Attribute::all()));
result
} else {
if regex.use_last_index {
@ -394,10 +414,17 @@ impl RegExp {
Value::null()
}
};
Ok(result)
} else {
panic!("object is not a regexp")
// 2. Perform ? RequireInternalSlot(R, [[RegExpMatcher]]).
context
.throw_type_error("RegExp.prototype.exec method called on incompatible value")
}
} else {
return context.throw_type_error("exec method called on incompatible value");
};
this.set_field("lastIndex", Value::from(last_index), context)?;
result
}
@ -415,10 +442,15 @@ impl RegExp {
pub(crate) fn r#match(this: &Value, arg: RcString, context: &mut Context) -> Result<Value> {
let (matcher, flags) = if let Some(object) = this.as_object() {
let object = object.borrow();
let regex = object.as_regexp().unwrap();
if let Some(regex) = object.as_regexp() {
(regex.matcher.clone(), regex.flags.clone())
} else {
panic!("object is not a regexp")
return context
.throw_type_error("RegExp.prototype.exec method called on incompatible value");
}
} else {
return context
.throw_type_error("RegExp.prototype.match method called on incompatible value");
};
if flags.contains('g') {
let mut matches = Vec::new();
@ -473,7 +505,7 @@ impl RegExp {
pub(crate) fn match_all(this: &Value, arg_str: String, context: &mut Context) -> Result<Value> {
let matches = if let Some(object) = this.as_object() {
let object = object.borrow();
let regex = object.as_regexp().unwrap();
if let Some(regex) = object.as_regexp() {
let mut matches = Vec::new();
for mat in regex.matcher.find_iter(&arg_str) {
@ -487,7 +519,8 @@ impl RegExp {
let match_val = Value::from(match_vec);
match_val.set_property("index", DataDescriptor::new(mat.start(), Attribute::all()));
match_val
.set_property("index", DataDescriptor::new(mat.start(), Attribute::all()));
match_val.set_property(
"input",
DataDescriptor::new(arg_str.clone(), Attribute::all()),
@ -501,7 +534,14 @@ impl RegExp {
matches
} else {
panic!("object is not a regexp")
return context.throw_type_error(
"RegExp.prototype.match_all method called on incompatible value",
);
}
} else {
return context.throw_type_error(
"RegExp.prototype.match_all method called on incompatible value",
);
};
let length = matches.len();

4
boa/src/object/internal_methods.rs

@ -246,6 +246,7 @@ impl GcObject {
///
/// [spec]: https://tc39.es/ecma262/#table-essential-internal-methods
#[inline]
#[track_caller]
pub fn own_property_keys(&self) -> Vec<PropertyKey> {
self.borrow().keys().collect()
}
@ -330,12 +331,14 @@ impl GcObject {
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getprototypeof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf
#[inline]
#[track_caller]
pub fn get_prototype_of(&self) -> Value {
self.borrow().prototype.clone()
}
/// Helper function for property insertion.
#[inline]
#[track_caller]
pub(crate) fn insert<K, P>(&mut self, key: K, property: P) -> Option<PropertyDescriptor>
where
K: Into<PropertyKey>,
@ -346,6 +349,7 @@ impl GcObject {
/// Helper function for property removal.
#[inline]
#[track_caller]
pub(crate) fn remove(&mut self, key: &PropertyKey) -> Option<PropertyDescriptor> {
self.borrow_mut().remove(key)
}

Loading…
Cancel
Save