291 lines
7.3 KiB
Go
291 lines
7.3 KiB
Go
|
package otto
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
func TestRegExp(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
[
|
||
|
/abc/.toString(),
|
||
|
/abc/gim.toString(),
|
||
|
""+/abc/gi.toString(),
|
||
|
new RegExp("1(\\d+)").toString(),
|
||
|
];
|
||
|
`, "/abc/,/abc/gim,/abc/gi,/1(\\d+)/")
|
||
|
|
||
|
test(`
|
||
|
[
|
||
|
new RegExp("abc").exec("123abc456"),
|
||
|
null === new RegExp("xyzzy").exec("123abc456"),
|
||
|
new RegExp("1(\\d+)").exec("123abc456"),
|
||
|
new RegExp("xyzzy").test("123abc456"),
|
||
|
new RegExp("1(\\d+)").test("123abc456"),
|
||
|
new RegExp("abc").exec("123abc456"),
|
||
|
];
|
||
|
`, "abc,true,123,23,false,true,abc")
|
||
|
|
||
|
test(`new RegExp("abc").toString()`, "/abc/")
|
||
|
test(`new RegExp("abc", "g").toString()`, "/abc/g")
|
||
|
test(`new RegExp("abc", "mig").toString()`, "/abc/gim")
|
||
|
|
||
|
result := test(`/(a)?/.exec('b')`, ",")
|
||
|
is(result._object().get("0"), "")
|
||
|
is(result._object().get("1"), "undefined")
|
||
|
is(result._object().get("length"), 2)
|
||
|
|
||
|
result = test(`/(a)?(b)?/.exec('b')`, "b,,b")
|
||
|
is(result._object().get("0"), "b")
|
||
|
is(result._object().get("1"), "undefined")
|
||
|
is(result._object().get("2"), "b")
|
||
|
is(result._object().get("length"), 3)
|
||
|
|
||
|
test(`/\u0041/.source`, "\\u0041")
|
||
|
test(`/\a/.source`, "\\a")
|
||
|
test(`/\;/.source`, "\\;")
|
||
|
|
||
|
test(`/a\a/.source`, "a\\a")
|
||
|
test(`/,\;/.source`, ",\\;")
|
||
|
test(`/ \ /.source`, " \\ ")
|
||
|
|
||
|
// Start sanity check...
|
||
|
test("eval(\"/abc/\").source", "abc")
|
||
|
test("eval(\"/\u0023/\").source", "#")
|
||
|
test("eval(\"/\u0058/\").source", "X")
|
||
|
test("eval(\"/\\\u0023/\").source == \"\\\u0023\"", true)
|
||
|
test("'0x' + '0058'", "0x0058")
|
||
|
test("'\\\\' + '0x' + '0058'", "\\0x0058")
|
||
|
// ...stop sanity check
|
||
|
|
||
|
test(`abc = '\\' + String.fromCharCode('0x' + '0058'); eval('/' + abc + '/').source`, "\\X")
|
||
|
test(`abc = '\\' + String.fromCharCode('0x0058'); eval('/' + abc + '/').source == "\\\u0058"`, true)
|
||
|
test(`abc = '\\' + String.fromCharCode('0x0023'); eval('/' + abc + '/').source == "\\\u0023"`, true)
|
||
|
test(`abc = '\\' + String.fromCharCode('0x0078'); eval('/' + abc + '/').source == "\\\u0078"`, true)
|
||
|
|
||
|
test(`
|
||
|
var abc = Object.getOwnPropertyDescriptor(RegExp, "prototype");
|
||
|
[ [ typeof RegExp.prototype ],
|
||
|
[ abc.writable, abc.enumerable, abc.configurable ] ];
|
||
|
`, "object,false,false,false")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_global(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
var abc = /(?:ab|cd)\d?/g;
|
||
|
var found = [];
|
||
|
do {
|
||
|
match = abc.exec("ab cd2 ab34 cd");
|
||
|
if (match !== null) {
|
||
|
found.push(match[0]);
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
} while (true);
|
||
|
found;
|
||
|
`, "ab,cd2,ab3,cd")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_exec(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
abc = /./g;
|
||
|
def = '123456';
|
||
|
ghi = 0;
|
||
|
while (ghi < 100 && abc.exec(def) !== null) {
|
||
|
ghi += 1;
|
||
|
}
|
||
|
[ ghi, def.length, ghi == def.length ];
|
||
|
`, "6,6,true")
|
||
|
|
||
|
test(`
|
||
|
abc = /[abc](\d)?/g;
|
||
|
def = 'a0 b c1 d3';
|
||
|
ghi = 0;
|
||
|
lastIndex = 0;
|
||
|
while (ghi < 100 && abc.exec(def) !== null) {
|
||
|
lastIndex = abc.lastIndex;
|
||
|
ghi += 1;
|
||
|
|
||
|
}
|
||
|
[ ghi, lastIndex ];
|
||
|
`, "3,7")
|
||
|
|
||
|
test(`
|
||
|
var abc = /[abc](\d)?/.exec("a0 b c1 d3");
|
||
|
[ abc.length, abc.input, abc.index, abc ];
|
||
|
`, "2,a0 b c1 d3,0,a0,0")
|
||
|
|
||
|
test(`raise:
|
||
|
var exec = RegExp.prototype.exec;
|
||
|
exec("Xyzzy");
|
||
|
`, "TypeError: Calling RegExp.exec on a non-RegExp object")
|
||
|
|
||
|
test(`
|
||
|
var abc = /\w{3}\d?/.exec("CE\uFFFFL\uFFDDbox127");
|
||
|
[ abc.input.length, abc.length, abc.input, abc.index, abc ];
|
||
|
`, "11,1,CE\uFFFFL\uFFDDbox127,5,box1")
|
||
|
|
||
|
test(`RegExp.prototype.exec.length`, 1)
|
||
|
test(`RegExp.prototype.exec.prototype`, "undefined")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_test(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`RegExp.prototype.test.length`, 1)
|
||
|
test(`RegExp.prototype.test.prototype`, "undefined")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_toString(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`RegExp.prototype.toString.length`, 0)
|
||
|
test(`RegExp.prototype.toString.prototype`, "undefined")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_zaacbbbcac(t *testing.T) {
|
||
|
if true {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
// FIXME? TODO /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac")
|
||
|
test(`
|
||
|
var abc = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac");
|
||
|
[ abc.length, abc.index, abc ];
|
||
|
`, "6,0,zaacbbbcac,z,ac,a,,c")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExpCopying(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
abc = /xyzzy/i;
|
||
|
def = RegExp(abc);
|
||
|
abc.indicator = 1;
|
||
|
[ abc.indicator, def.indicator ];
|
||
|
`, "1,1")
|
||
|
|
||
|
test(`raise:
|
||
|
RegExp(new RegExp("\\d"), "1");
|
||
|
`, "TypeError: Cannot supply flags when constructing one RegExp from another")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_multiline(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
var abc = /s$/m.exec("pairs\nmakes\tdouble");
|
||
|
[ abc.length, abc.index, abc ];
|
||
|
`, "1,4,s")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_source(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
[ /xyzzy/i.source, /./i.source ];
|
||
|
`, "xyzzy,.")
|
||
|
|
||
|
test(`
|
||
|
var abc = /./i;
|
||
|
var def = new RegExp(abc);
|
||
|
[ abc.source, def.source, abc.source === def.source ];
|
||
|
`, ".,.,true")
|
||
|
|
||
|
test(`
|
||
|
var abc = /./i;
|
||
|
var def = abc.hasOwnProperty("source");
|
||
|
var ghi = abc.source;
|
||
|
abc.source = "xyzzy";
|
||
|
[ def, abc.source ];
|
||
|
`, "true,.")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_newRegExp(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
Math.toString();
|
||
|
var abc = new RegExp(Math,eval("\"g\""));
|
||
|
[ abc, abc.global ];
|
||
|
`, "/[object Math]/g,true")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_flags(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
var abc = /./i;
|
||
|
var def = new RegExp(abc);
|
||
|
[ abc.multiline == def.multiline, abc.global == def.global, abc.ignoreCase == def.ignoreCase ];
|
||
|
`, "true,true,true")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_controlCharacter(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
for code := 0x41; code < 0x5a; code++ {
|
||
|
string_ := string(code - 64)
|
||
|
test(fmt.Sprintf(`
|
||
|
var code = 0x%x;
|
||
|
var string = String.fromCharCode(code %% 32);
|
||
|
var result = (new RegExp("\\c" + String.fromCharCode(code))).exec(string);
|
||
|
[ code, string, result ];
|
||
|
`, code), fmt.Sprintf("%d,%s,%s", code, string_, string_))
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_notNotEmptyCharacterClass(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
var abc = /[\s\S]a/m.exec("a\naba");
|
||
|
[ abc.length, abc.input, abc ];
|
||
|
`, "1,a\naba,\na")
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestRegExp_compile(t *testing.T) {
|
||
|
tt(t, func() {
|
||
|
test, _ := test()
|
||
|
|
||
|
test(`
|
||
|
var abc = /[\s\S]a/;
|
||
|
abc.compile('^\w+');
|
||
|
`, "undefined")
|
||
|
})
|
||
|
}
|