Browse Source

Upgraded regress to 0.2.0 (#905)

* Upgraded regress to 0.2.0

* Addressed review comments
pull/909/head
Iban Eguia 4 years ago committed by GitHub
parent
commit
da61d3738d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      Cargo.lock
  2. 2
      boa/Cargo.toml
  3. 51
      boa/src/builtins/regexp/mod.rs
  4. 12
      boa/src/builtins/string/mod.rs

5
Cargo.lock generated

@ -970,11 +970,12 @@ checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c"
[[package]] [[package]]
name = "regress" name = "regress"
version = "0.1.4" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d669f9db16c334d72d7f92d52874373eb0df8f642230401952a6901872fee4c5" checksum = "8ade8c280902120cc06e8694a76a5aa846e875df975da904d5a1a025fa7a5b4e"
dependencies = [ dependencies = [
"memchr", "memchr",
"structopt",
] ]
[[package]] [[package]]

2
boa/Cargo.toml

@ -21,7 +21,7 @@ gc = { version = "0.3.6", features = ["derive"] }
serde_json = "1.0.59" serde_json = "1.0.59"
rand = "0.7.3" rand = "0.7.3"
num-traits = "0.2.12" num-traits = "0.2.12"
regress = "0.1.4" regress = "0.2.0"
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
num-bigint = { version = "0.3.0", features = ["serde"] } num-bigint = { version = "0.3.0", features = ["serde"] }
num-integer = "0.1.43" num-integer = "0.1.43"

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

@ -17,7 +17,7 @@ use crate::{
value::{RcString, Value}, value::{RcString, Value},
BoaProfiler, Context, Result, BoaProfiler, Context, Result,
}; };
use regress::{Flags, Regex}; use regress::Regex;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -32,7 +32,7 @@ pub struct RegExp {
use_last_index: bool, use_last_index: bool,
/// String of parsed flags. /// String of parsed flags.
flags: String, flags: Box<str>,
/// Flag 's' - dot matches newline characters. /// Flag 's' - dot matches newline characters.
dot_all: bool, dot_all: bool,
@ -52,10 +52,11 @@ pub struct RegExp {
/// Flag 'u' - Unicode. /// Flag 'u' - Unicode.
unicode: bool, unicode: bool,
pub(crate) original_source: String, pub(crate) original_source: Box<str>,
original_flags: String, original_flags: Box<str>,
} }
// Only safe while regress::Regex doesn't implement Trace itself.
unsafe impl Trace for RegExp { unsafe impl Trace for RegExp {
empty_trace!(); empty_trace!();
} }
@ -99,26 +100,32 @@ impl RegExp {
/// Create a new `RegExp` /// Create a new `RegExp`
pub(crate) fn constructor(this: &Value, args: &[Value], _: &mut Context) -> Result<Value> { pub(crate) fn constructor(this: &Value, args: &[Value], _: &mut Context) -> Result<Value> {
let arg = args.get(0).ok_or_else(Value::undefined)?; let arg = args.get(0).ok_or_else(Value::undefined)?;
let mut regex_body = String::new();
let mut regex_flags = String::new(); let (regex_body, mut regex_flags) = match arg {
match arg {
Value::String(ref body) => { Value::String(ref body) => {
// first argument is a string -> use it as regex pattern // first argument is a string -> use it as regex pattern
regex_body = body.to_string(); (
body.to_string().into_boxed_str(),
String::new().into_boxed_str(),
)
} }
Value::Object(ref obj) => { Value::Object(ref obj) => {
let obj = obj.borrow(); let obj = obj.borrow();
if let Some(regex) = obj.as_regexp() { if let Some(regex) = obj.as_regexp() {
// first argument is another `RegExp` object, so copy its pattern and flags // first argument is another `RegExp` object, so copy its pattern and flags
regex_body = regex.original_source.clone(); (regex.original_source.clone(), regex.original_flags.clone())
regex_flags = regex.original_flags.clone(); } else {
(
String::new().into_boxed_str(),
String::new().into_boxed_str(),
)
} }
} }
_ => return Err(Value::undefined()), _ => return Err(Value::undefined()),
} };
// if a second argument is given and it's a string, use it as flags // if a second argument is given and it's a string, use it as flags
if let Some(Value::String(flags)) = args.get(1) { if let Some(Value::String(flags)) = args.get(1) {
regex_flags = flags.to_string(); regex_flags = flags.to_string().into_boxed_str();
} }
// parse flags // parse flags
@ -154,12 +161,12 @@ impl RegExp {
sorted_flags.push('y'); sorted_flags.push('y');
} }
let matcher = Regex::newf(regex_body.as_str(), Flags::from(sorted_flags.as_str())) let matcher = Regex::with_flags(&regex_body, sorted_flags.as_str())
.expect("failed to create matcher"); .expect("failed to create matcher");
let regexp = RegExp { let regexp = RegExp {
matcher, matcher,
use_last_index: global || sticky, use_last_index: global || sticky,
flags: sorted_flags, flags: sorted_flags.into_boxed_str(),
dot_all, dot_all,
global, global,
ignore_case, ignore_case,
@ -314,7 +321,7 @@ impl RegExp {
let result = let result =
if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() { if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() {
if regex.use_last_index { if regex.use_last_index {
last_index = m.total().end; last_index = m.end();
} }
true true
} else { } else {
@ -355,7 +362,7 @@ impl RegExp {
let result = { let result = {
if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() { if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() {
if regex.use_last_index { if regex.use_last_index {
last_index = m.total().end; last_index = m.end();
} }
let groups = m.captures.len() + 1; let groups = m.captures.len() + 1;
let mut result = Vec::with_capacity(groups); let mut result = Vec::with_capacity(groups);
@ -370,10 +377,7 @@ impl RegExp {
} }
let result = Value::from(result); let result = Value::from(result);
result.set_property( result.set_property("index", DataDescriptor::new(m.start(), Attribute::all()));
"index",
DataDescriptor::new(m.total().start, Attribute::all()),
);
result.set_property("input", DataDescriptor::new(arg_str, Attribute::all())); result.set_property("input", DataDescriptor::new(arg_str, Attribute::all()));
result result
} else { } else {
@ -412,7 +416,7 @@ impl RegExp {
if flags.contains('g') { if flags.contains('g') {
let mut matches = Vec::new(); let mut matches = Vec::new();
for mat in matcher.find_iter(&arg) { for mat in matcher.find_iter(&arg) {
matches.push(Value::from(&arg[mat.total()])); matches.push(Value::from(&arg[mat.range()]));
} }
if matches.is_empty() { if matches.is_empty() {
return Ok(Value::null()); return Ok(Value::null());
@ -476,10 +480,7 @@ impl RegExp {
let match_val = Value::from(match_vec); let match_val = Value::from(match_vec);
match_val.set_property( match_val.set_property("index", DataDescriptor::new(mat.start(), Attribute::all()));
"index",
DataDescriptor::new(mat.total().start, Attribute::all()),
);
match_val.set_property( match_val.set_property(
"input", "input",
DataDescriptor::new(arg_str.clone(), Attribute::all()), DataDescriptor::new(arg_str.clone(), Attribute::all()),

12
boa/src/builtins/string/mod.rs

@ -513,7 +513,7 @@ impl String {
if let Some(regexp) = obj.as_regexp() { if let Some(regexp) = obj.as_regexp() {
// first argument is another `RegExp` object, so copy its pattern and flags // first argument is another `RegExp` object, so copy its pattern and flags
return regexp.original_source.clone(); return regexp.original_source.clone().into();
} }
"undefined".to_string() "undefined".to_string()
} }
@ -587,16 +587,16 @@ impl String {
} }
(Some('&'), _) => { (Some('&'), _) => {
// $& // $&
result.push_str(&primitive_val[mat.total()]); result.push_str(&primitive_val[mat.range()]);
} }
(Some('`'), _) => { (Some('`'), _) => {
// $` // $`
let start_of_match = mat.total().start; let start_of_match = mat.start();
result.push_str(&primitive_val[..start_of_match]); result.push_str(&primitive_val[..start_of_match]);
} }
(Some('\''), _) => { (Some('\''), _) => {
// $' // $'
let end_of_match = mat.total().end; let end_of_match = mat.end();
result.push_str(&primitive_val[end_of_match..]); result.push_str(&primitive_val[end_of_match..]);
} }
(Some(second), Some(third)) (Some(second), Some(third))
@ -666,7 +666,7 @@ impl String {
.collect(); .collect();
// Returns the starting byte offset of the match // Returns the starting byte offset of the match
let start = mat.total().start; let start = mat.start();
results.push(Value::from(start)); results.push(Value::from(start));
// Push the whole string being examined // Push the whole string being examined
results.push(Value::from(primitive_val.to_string())); results.push(Value::from(primitive_val.to_string()));
@ -682,7 +682,7 @@ impl String {
}; };
Ok(Value::from(primitive_val.replacen( Ok(Value::from(primitive_val.replacen(
&primitive_val[mat.total()], &primitive_val[mat.range()],
&replace_value, &replace_value,
1, 1,
))) )))

Loading…
Cancel
Save