2019-09-05 11:14:55 +00:00
|
|
|
// Copyright 2019 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
//
|
2021-01-26 00:50:44 +00:00
|
|
|
// Flags: --harmony-regexp-match-indices --allow-natives-syntax
|
|
|
|
// Flags: --expose-gc --stack-size=100
|
|
|
|
// Flags: --no-force-slow-path
|
2019-09-05 11:14:55 +00:00
|
|
|
|
|
|
|
// Sanity test.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+(?<Z>z)?/d;
|
2019-09-05 11:14:55 +00:00
|
|
|
const m = re.exec("xaaaz");
|
|
|
|
|
|
|
|
assertEquals(m.indices, [[1, 5], [4, 5]]);
|
|
|
|
assertEquals(m.indices.groups, {'Z': [4, 5]})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Capture groups that are not matched return `undefined`.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+(?<Z>z)?/d;
|
2019-09-05 11:14:55 +00:00
|
|
|
const m = re.exec("xaaay");
|
|
|
|
|
|
|
|
assertEquals(m.indices, [[1, 4], undefined]);
|
|
|
|
assertEquals(m.indices.groups, {'Z': undefined});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Two capture groups.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+(?<A>zz)?(?<B>ii)?/d;
|
2019-09-05 11:14:55 +00:00
|
|
|
const m = re.exec("xaaazzii");
|
|
|
|
|
|
|
|
assertEquals(m.indices, [[1, 8], [4, 6], [6, 8]]);
|
|
|
|
assertEquals(m.indices.groups, {'A': [4, 6], 'B': [6, 8]});
|
|
|
|
}
|
|
|
|
|
|
|
|
// No capture groups.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+/d;
|
2019-09-05 11:14:55 +00:00
|
|
|
const m = re.exec("xaaazzii");
|
|
|
|
|
2021-01-26 00:50:44 +00:00
|
|
|
assertEquals(m.indices, [[1, 4]]);
|
2019-09-05 11:14:55 +00:00
|
|
|
assertEquals(m.indices.groups, undefined);
|
|
|
|
}
|
|
|
|
|
|
|
|
// No match.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+/d;
|
2019-09-05 11:14:55 +00:00
|
|
|
const m = re.exec("xzzii");
|
|
|
|
|
|
|
|
assertEquals(null, m);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unnamed capture groups.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+(z)?/d;
|
|
|
|
const m = re.exec("xaaaz");
|
2019-09-05 11:14:55 +00:00
|
|
|
|
|
|
|
assertEquals(m.indices, [[1, 5], [4, 5]]);
|
|
|
|
assertEquals(m.indices.groups, undefined)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Named and unnamed capture groups.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+(z)?(?<Y>y)?/d;
|
2019-09-05 11:14:55 +00:00
|
|
|
const m = re.exec("xaaazyy")
|
|
|
|
|
|
|
|
assertEquals(m.indices, [[1, 6], [4, 5], [5, 6]]);
|
|
|
|
assertEquals(m.indices.groups, {'Y': [5, 6]})
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Verify property overwrite.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+(?<Z>z)?/d;
|
2019-09-05 11:14:55 +00:00
|
|
|
const m = re.exec("xaaaz");
|
|
|
|
|
|
|
|
m.indices = null;
|
|
|
|
assertEquals(null, m.indices);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mess with array prototype, we should still do the right thing.
|
|
|
|
{
|
|
|
|
Object.defineProperty(Array.prototype, "groups", {
|
|
|
|
get: () => {
|
|
|
|
assertUnreachable();
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
set: (x) => {
|
|
|
|
assertUnreachable();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Object.defineProperty(Array.prototype, "0", {
|
|
|
|
get: () => {
|
|
|
|
assertUnreachable();
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
set: (x) => {
|
|
|
|
assertUnreachable();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+(?<Z>z)?/d;
|
2019-09-05 11:14:55 +00:00
|
|
|
const m = re.exec("xaaaz");
|
|
|
|
|
|
|
|
assertEquals(m.indices.groups, {'Z': [4, 5]})
|
|
|
|
}
|
2019-10-21 17:48:07 +00:00
|
|
|
|
2019-11-20 15:13:43 +00:00
|
|
|
// Test atomic regexp.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const m = (/undefined/d).exec();
|
2019-11-20 15:13:43 +00:00
|
|
|
|
|
|
|
assertEquals(m.indices, [[0, 9]]);
|
|
|
|
}
|
|
|
|
|
2019-10-21 17:48:07 +00:00
|
|
|
// Test deleting unrelated fields does not break.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const m = (/undefined/d).exec();
|
2019-10-21 17:48:07 +00:00
|
|
|
delete m['index'];
|
|
|
|
gc();
|
|
|
|
assertEquals(m.indices, [[0, 9]]);
|
|
|
|
}
|
2019-11-20 15:13:43 +00:00
|
|
|
|
|
|
|
// Stack overflow.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+(?<Z>z)?/d;
|
2019-11-20 15:13:43 +00:00
|
|
|
const m = re.exec("xaaaz");
|
|
|
|
|
|
|
|
function rec() {
|
|
|
|
try {
|
|
|
|
return rec();
|
|
|
|
} catch (e) {
|
|
|
|
assertEquals(m.indices, [[1, 5], [4, 5]]);
|
|
|
|
assertEquals(m.indices.groups, {'Z': [4, 5]})
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assertTrue(rec());
|
|
|
|
}
|
2019-11-22 16:32:09 +00:00
|
|
|
|
|
|
|
// Match between matches.
|
|
|
|
{
|
2021-01-26 00:50:44 +00:00
|
|
|
const re = /a+(?<A>zz)?(?<B>ii)?/d;
|
2019-11-22 16:32:09 +00:00
|
|
|
const m = re.exec("xaaazzii");
|
|
|
|
assertTrue(/b+(?<C>cccc)?/.test("llllllbbbbbbcccc"));
|
|
|
|
assertEquals(m.indices, [[1, 8], [4, 6], [6, 8]]);
|
|
|
|
assertEquals(m.indices.groups, {'A': [4, 6], 'B': [6, 8]});
|
|
|
|
}
|
2021-01-26 00:50:44 +00:00
|
|
|
|
|
|
|
// Redefined hasIndices should reflect in flags.
|
|
|
|
{
|
|
|
|
let re = /./;
|
|
|
|
Object.defineProperty(re, "hasIndices", { get: function() { return true; } });
|
|
|
|
assertEquals("d", re.flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// The flags field of a regexp should be sorted.
|
|
|
|
assertEquals("dgmsy", (/asdf/dymsg).flags);
|
|
|
|
|
|
|
|
// The 'hasIndices' member should be set according to the hasIndices flag.
|
|
|
|
assertTrue((/asdf/dymsg).hasIndices);
|
|
|
|
assertFalse((/asdf/ymsg).hasIndices);
|
|
|
|
|
|
|
|
// The new fields installed on the regexp prototype map shouldn't make
|
|
|
|
// unmodified regexps slow.
|
2021-02-04 10:42:49 +00:00
|
|
|
|
|
|
|
// TODO(v8:11248) Enabling v8_dict_property_const_tracking currently evokes
|
|
|
|
// that the original fast mode prototype for regexes is converted to a
|
|
|
|
// dictionary mode one, which makes %RegexpIsUnmodified fail. Once we support
|
|
|
|
// directly creating the regex prototype in dictionary mode if
|
|
|
|
// v8_dict_property_const_tracking is enabled, change %RegexpIsUnmodified to
|
|
|
|
// know about the canonical dictionary mode prototype, too.
|
|
|
|
if (!%IsDictPropertyConstTrackingEnabled()) {
|
|
|
|
%RegexpIsUnmodified(/asdf/);
|
|
|
|
%RegexpIsUnmodified(/asdf/d);
|
|
|
|
}
|
2021-01-26 00:50:44 +00:00
|
|
|
}
|