Browse Source

Throw TypeError if regex is passed to startsWith, endsWith, includes (#782)

pull/787/head
(´⌣`ʃƪ) 4 years ago committed by GitHub
parent
commit
aad860db84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 49
      boa/src/builtins/string/mod.rs
  2. 84
      boa/src/builtins/string/tests.rs

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

@ -331,11 +331,15 @@ impl String {
// Then we convert it into a Rust String by wrapping it in from_value // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
// TODO: Should throw TypeError if pattern is regular expression let arg = args.get(0).cloned().unwrap_or_else(Value::undefined);
let search_string = args
.get(0) if Self::is_regexp_object(&arg) {
.expect("failed to get argument for String method") ctx.throw_type_error(
.to_string(ctx)?; "First argument to String.prototype.startsWith must not be a regular expression",
)?;
}
let search_string = arg.to_string(ctx)?;
let length = primitive_val.chars().count() as i32; let length = primitive_val.chars().count() as i32;
let search_length = search_string.chars().count() as i32; let search_length = search_string.chars().count() as i32;
@ -374,11 +378,15 @@ impl String {
// Then we convert it into a Rust String by wrapping it in from_value // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
// TODO: Should throw TypeError if search_string is regular expression let arg = args.get(0).cloned().unwrap_or_else(Value::undefined);
let search_string = args
.get(0) if Self::is_regexp_object(&arg) {
.expect("failed to get argument for String method") ctx.throw_type_error(
.to_string(ctx)?; "First argument to String.prototype.endsWith must not be a regular expression",
)?;
}
let search_string = arg.to_string(ctx)?;
let length = primitive_val.chars().count() as i32; let length = primitive_val.chars().count() as i32;
let search_length = search_string.chars().count() as i32; let search_length = search_string.chars().count() as i32;
@ -420,11 +428,15 @@ impl String {
// Then we convert it into a Rust String by wrapping it in from_value // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
// TODO: Should throw TypeError if search_string is regular expression let arg = args.get(0).cloned().unwrap_or_else(Value::undefined);
let search_string = args
.get(0) if Self::is_regexp_object(&arg) {
.expect("failed to get argument for String method") ctx.throw_type_error(
.to_string(ctx)?; "First argument to String.prototype.includes must not be a regular expression",
)?;
}
let search_string = arg.to_string(ctx)?;
let length = primitive_val.chars().count() as i32; let length = primitive_val.chars().count() as i32;
@ -462,6 +474,13 @@ impl String {
} }
} }
fn is_regexp_object(value: &Value) -> bool {
match value {
Value::Object(ref obj) => obj.borrow().is_regexp(),
_ => false,
}
}
/// `String.prototype.replace( regexp|substr, newSubstr|function )` /// `String.prototype.replace( regexp|substr, newSubstr|function )`
/// ///
/// The `replace()` method returns a new string with some or all matches of a `pattern` replaced by a `replacement`. /// The `replace()` method returns a new string with some or all matches of a `pattern` replaced by a `replacement`.

84
boa/src/builtins/string/tests.rs

@ -320,6 +320,26 @@ fn starts_with() {
assert_eq!(forward(&mut engine, "zhLiteral.startsWith('中')"), "true"); assert_eq!(forward(&mut engine, "zhLiteral.startsWith('中')"), "true");
} }
#[test]
fn starts_with_with_regex_arg() {
let mut engine = Context::new();
let scenario = r#"
try {
'Saturday night'.startsWith(/Saturday/);
} catch (e) {
e.toString();
}
"#;
assert_eq!(
forward(
&mut engine, scenario
),
"\"TypeError: First argument to String.prototype.startsWith must not be a regular expression\""
)
}
#[test] #[test]
fn ends_with() { fn ends_with() {
let mut engine = Context::new(); let mut engine = Context::new();
@ -344,6 +364,70 @@ fn ends_with() {
assert_eq!(forward(&mut engine, "zhLiteral.endsWith('文')"), "true"); assert_eq!(forward(&mut engine, "zhLiteral.endsWith('文')"), "true");
} }
#[test]
fn ends_with_with_regex_arg() {
let mut engine = Context::new();
let scenario = r#"
try {
'Saturday night'.endsWith(/night/);
} catch (e) {
e.toString();
}
"#;
assert_eq!(
forward(
&mut engine, scenario
),
"\"TypeError: First argument to String.prototype.endsWith must not be a regular expression\""
)
}
#[test]
fn includes() {
let mut engine = Context::new();
let init = r#"
var empty = new String('');
var en = new String('english');
var zh = new String('');
var emptyLiteral = '';
var enLiteral = 'english';
var zhLiteral = '';
"#;
forward(&mut engine, init);
assert_eq!(forward(&mut engine, "empty.includes('')"), "true");
assert_eq!(forward(&mut engine, "en.includes('g')"), "true");
assert_eq!(forward(&mut engine, "zh.includes('文')"), "true");
assert_eq!(forward(&mut engine, "emptyLiteral.includes('')"), "true");
assert_eq!(forward(&mut engine, "enLiteral.includes('g')"), "true");
assert_eq!(forward(&mut engine, "zhLiteral.includes('文')"), "true");
}
#[test]
fn includes_with_regex_arg() {
let mut engine = Context::new();
let scenario = r#"
try {
'Saturday night'.includes(/day/);
} catch (e) {
e.toString();
}
"#;
assert_eq!(
forward(
&mut engine, scenario
),
"\"TypeError: First argument to String.prototype.includes must not be a regular expression\""
)
}
#[test] #[test]
fn match_all() { fn match_all() {
let mut engine = Context::new(); let mut engine = Context::new();

Loading…
Cancel
Save