use crate::{forward, Context};
#[test]
fn constructors() {
let mut context = Context::new();
let init = r#"
var constructed = new RegExp("[0-9]+(\\.[0-9]+)?");
var literal = /[0-9]+(\.[0-9]+)?/;
var ctor_literal = new RegExp(/[0-9]+(\.[0-9]+)?/);
"#;
eprintln!("{}", forward(&mut context, init));
assert_eq!(forward(&mut context, "constructed.test('1.0')"), "true");
assert_eq!(forward(&mut context, "literal.test('1.0')"), "true");
assert_eq!(forward(&mut context, "ctor_literal.test('1.0')"), "true");
}
#[test]
fn species() {
let mut context = Context::new();
let init = r#"
var descriptor = Object.getOwnPropertyDescriptor(RegExp, Symbol.species);
var accessor = Object.getOwnPropertyDescriptor(RegExp, Symbol.species).get;
var name = Object.getOwnPropertyDescriptor(descriptor.get, "name");
var length = Object.getOwnPropertyDescriptor(descriptor.get, "length");
var thisVal = {};
"#;
eprintln!("{}", forward(&mut context, init));
assert_eq!(forward(&mut context, "descriptor.get.length"), "0");
assert_eq!(forward(&mut context, "length.enumerable"), "false");
assert_eq!(forward(&mut context, "length.writable"), "false");
assert_eq!(forward(&mut context, "length.configurable"), "true");
assert_eq!(
forward(&mut context, "Object.is(accessor.call(thisVal), thisVal)"),
"true"
);
assert_eq!(
forward(&mut context, "descriptor.get.name"),
"\"get [Symbol.species]\""
);
assert_eq!(forward(&mut context, "name.enumerable"), "false");
assert_eq!(forward(&mut context, "name.writable"), "false");
assert_eq!(forward(&mut context, "name.configurable"), "true");
assert_eq!(forward(&mut context, "descriptor.set"), "undefined");
assert_eq!(
forward(&mut context, "typeof descriptor.get"),
"\"function\""
);
assert_eq!(forward(&mut context, "descriptor.enumerable"), "false");
assert_eq!(forward(&mut context, "descriptor.configurable"), "true");
}
#[test]
fn last_index() {
let mut context = Context::new();
let init = r#"
var regex = /[0-9]+(\.[0-9]+)?/g;
"#;
eprintln!("{}", forward(&mut context, init));
assert_eq!(forward(&mut context, "regex.lastIndex"), "0");
assert_eq!(forward(&mut context, "regex.test('1.0foo')"), "true");
assert_eq!(forward(&mut context, "regex.lastIndex"), "3");
assert_eq!(forward(&mut context, "regex.test('1.0foo')"), "false");
assert_eq!(forward(&mut context, "regex.lastIndex"), "0");
}
#[test]
fn exec() {
let mut context = Context::new();
let init = r#"
var re = /quick\s(brown).+?(jumps)/ig;
var result = re.exec('The Quick Brown Fox Jumps Over The Lazy Dog');
"#;
eprintln!("{}", forward(&mut context, init));
assert_eq!(
forward(&mut context, "result[0]"),
"\"Quick Brown Fox Jumps\""
);
assert_eq!(forward(&mut context, "result[1]"), "\"Brown\"");
assert_eq!(forward(&mut context, "result[2]"), "\"Jumps\"");
assert_eq!(forward(&mut context, "result.index"), "4");
assert_eq!(
forward(&mut context, "result.input"),
"\"The Quick Brown Fox Jumps Over The Lazy Dog\""
);
}
#[test]
fn to_string() {
let mut context = Context::new();
assert_eq!(
forward(&mut context, "(new RegExp('a+b+c')).toString()"),
"\"/a+b+c/\""
);
assert_eq!(
forward(&mut context, "(new RegExp('bar', 'g')).toString()"),
"\"/bar/g\""
);
assert_eq!(
forward(&mut context, "(new RegExp('\\\\n', 'g')).toString()"),
"\"/\\n/g\""
);
assert_eq!(forward(&mut context, "/\\n/g.toString()"), "\"/\\n/g\"");
}
#[test]
fn no_panic_on_invalid_character_escape() {
let mut context = Context::new();
forward(&mut context, r"const a = /,\;/");
}
#[test]
fn search() {
let mut context = Context::new();
assert_eq!(
forward(
&mut context,
r#"
var obj = {
toString: function() {
return 'toString value';
}
};
/ring/[Symbol.search](obj)
"#
),
"4"
);
assert_eq!(forward(&mut context, "/z/[Symbol.search]('a')"), "-1");
assert_eq!(
forward(&mut context, "RegExp.prototype[Symbol.search].length"),
"1"
);
let init =
"var obj = Object.getOwnPropertyDescriptor(RegExp.prototype[Symbol.search], \"length\")";
eprintln!("{}", forward(&mut context, init));
assert_eq!(forward(&mut context, "obj.enumerable"), "false");
assert_eq!(forward(&mut context, "obj.writable"), "false");
assert_eq!(forward(&mut context, "obj.configurable"), "true");
assert_eq!(
forward(&mut context, "RegExp.prototype[Symbol.search].name"),
"\"[Symbol.search]\""
);
let init =
"var obj = Object.getOwnPropertyDescriptor(RegExp.prototype[Symbol.search], \"name\")";
eprintln!("{}", forward(&mut context, init));
assert_eq!(forward(&mut context, "obj.enumerable"), "false");
assert_eq!(forward(&mut context, "obj.writable"), "false");
assert_eq!(forward(&mut context, "obj.configurable"), "true");
let init = "var obj = Object.getOwnPropertyDescriptor(RegExp.prototype, Symbol.search)";
eprintln!("{}", forward(&mut context, init));
assert_eq!(forward(&mut context, "obj.enumerable"), "false");
assert_eq!(forward(&mut context, "obj.writable"), "true");
assert_eq!(forward(&mut context, "obj.configurable"), "true");
assert_eq!(forward(&mut context, "/a/[Symbol.search]('abc')"), "0");
assert_eq!(forward(&mut context, "/b/[Symbol.search]('abc')"), "1");
assert_eq!(forward(&mut context, "/c/[Symbol.search]('abc')"), "2");
let error = "Uncaught \"TypeError\": \"RegExp.prototype[Symbol.search] method called on incompatible value\"";
let init = "var search = RegExp.prototype[Symbol.search]";
eprintln!("{}", forward(&mut context, init));
assert_eq!(forward(&mut context, "search.call()"), error);
assert_eq!(forward(&mut context, "search.call(undefined)"), error);
assert_eq!(forward(&mut context, "search.call(null)"), error);
assert_eq!(forward(&mut context, "search.call(true)"), error);
assert_eq!(forward(&mut context, "search.call('string')"), error);
assert_eq!(forward(&mut context, "search.call(Symbol.search)"), error);
assert_eq!(forward(&mut context, "search.call(86)"), error);
assert_eq!(
forward(&mut context, "/\\udf06/u[Symbol.search]('\\ud834\\udf06')"),
"-1"
);
assert_eq!(forward(&mut context, "/a/[Symbol.search](\"a\")"), "0");
assert_eq!(forward(&mut context, "/a/[Symbol.search](\"ba\")"), "1");
assert_eq!(forward(&mut context, "/a/[Symbol.search](\"bb\")"), "-1");
assert_eq!(forward(&mut context, "/u/[Symbol.search](null)"), "1");
assert_eq!(forward(&mut context, "/d/[Symbol.search](undefined)"), "2");
}