121 lines
3.1 KiB
JavaScript
121 lines
3.1 KiB
JavaScript
|
// Copyright 2024 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.
|
||
|
//
|
||
|
// Flags: --allow-natives-syntax --default-to-experimental-regexp-engine --experimental-regexp-engine-capture-group-opt
|
||
|
|
||
|
// Tests captures in positive and negative look-ahead in regular expressions.
|
||
|
|
||
|
function stringEscape(string) {
|
||
|
// Converts string to source literal.
|
||
|
return '"' + string.replace(/["\\]/g, '\\$1') + '"';
|
||
|
}
|
||
|
|
||
|
function testRE(re, input, expected_result) {
|
||
|
assertEquals(%RegexpTypeTag(re), 'EXPERIMENTAL');
|
||
|
|
||
|
var testName = re + '.test(' + stringEscape(input) + ')';
|
||
|
if (expected_result) {
|
||
|
assertTrue(re.test(input), testName);
|
||
|
} else {
|
||
|
assertFalse(re.test(input), testName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function execRE(re, input, expected_result) {
|
||
|
assertEquals(%RegexpTypeTag(re), 'EXPERIMENTAL');
|
||
|
|
||
|
var testName = re + ".exec('" + stringEscape(input) + "')";
|
||
|
assertEquals(expected_result, re.exec(input), testName);
|
||
|
}
|
||
|
|
||
|
// Test of simple positive lookahead.
|
||
|
|
||
|
var re = /^(?=a)/;
|
||
|
testRE(re, 'a', true);
|
||
|
testRE(re, 'b', false);
|
||
|
execRE(re, 'a', ['']);
|
||
|
|
||
|
re = /^(?=\woo)f\w/;
|
||
|
testRE(re, 'foo', true);
|
||
|
testRE(re, 'boo', false);
|
||
|
testRE(re, 'fao', false);
|
||
|
testRE(re, 'foa', false);
|
||
|
execRE(re, 'foo', ['fo']);
|
||
|
|
||
|
re = /(?=\w).(?=\W)/;
|
||
|
testRE(re, '.a! ', true);
|
||
|
testRE(re, '.! ', false);
|
||
|
testRE(re, '.ab! ', true);
|
||
|
execRE(re, '.ab! ', ['b']);
|
||
|
|
||
|
re = /(?=f(?=[^f]o))../;
|
||
|
testRE(re, ', foo!', true);
|
||
|
testRE(re, ', fo!', false);
|
||
|
testRE(re, ', ffo', false);
|
||
|
execRE(re, ', foo!', ['fo']);
|
||
|
|
||
|
re = /^(?:(?=(.))a|b|c)$/;
|
||
|
testRE(re, 'a', true);
|
||
|
testRE(re, 'b', true);
|
||
|
testRE(re, 'c', true);
|
||
|
testRE(re, 'd', false);
|
||
|
execRE(re, 'a', ['a', 'a']);
|
||
|
execRE(re, 'b', ['b', undefined]);
|
||
|
execRE(re, 'c', ['c', undefined]);
|
||
|
|
||
|
execRE(/^(?=(b))b/, 'b', ['b', 'b']);
|
||
|
execRE(/^(?:(?=(b))|a)b/, 'ab', ['ab', undefined]);
|
||
|
execRE(/^(?:(?=(b)(?:(?=(c))|d))|)bd/, 'bd', ['bd', 'b', undefined]);
|
||
|
|
||
|
// Test of Negative Look-Ahead.
|
||
|
|
||
|
re = /(?!x)./;
|
||
|
testRE(re, 'y', true);
|
||
|
testRE(re, 'x', false);
|
||
|
execRE(re, 'y', ['y']);
|
||
|
|
||
|
re = /(?!(\d))|\d/;
|
||
|
testRE(re, '4', true);
|
||
|
execRE(re, '4', ['4', undefined]);
|
||
|
execRE(re, 'x', ['', undefined]);
|
||
|
|
||
|
// Test mixed nested look-ahead with captures.
|
||
|
|
||
|
re = /^(?=(x)(?=(y)))/;
|
||
|
testRE(re, 'xy', true);
|
||
|
testRE(re, 'xz', false);
|
||
|
execRE(re, 'xy', ['', 'x', 'y']);
|
||
|
|
||
|
re = /^(?!(x)(?!(y)))/;
|
||
|
testRE(re, 'xy', true);
|
||
|
testRE(re, 'xz', false);
|
||
|
execRE(re, 'xy', ['', undefined, undefined]);
|
||
|
|
||
|
re = /^(?=(x)(?!(y)))/;
|
||
|
testRE(re, 'xz', true);
|
||
|
testRE(re, 'xy', false);
|
||
|
execRE(re, 'xz', ['', 'x', undefined]);
|
||
|
|
||
|
re = /^(?!(x)(?=(y)))/;
|
||
|
testRE(re, 'xz', true);
|
||
|
testRE(re, 'xy', false);
|
||
|
execRE(re, 'xz', ['', undefined, undefined]);
|
||
|
|
||
|
re = /^(?=(x)(?!(y)(?=(z))))/;
|
||
|
testRE(re, 'xaz', true);
|
||
|
testRE(re, 'xya', true);
|
||
|
testRE(re, 'xyz', false);
|
||
|
testRE(re, 'a', false);
|
||
|
execRE(re, 'xaz', ['', 'x', undefined, undefined]);
|
||
|
execRE(re, 'xya', ['', 'x', undefined, undefined]);
|
||
|
|
||
|
re = /^(?!(x)(?=(y)(?!(z))))/;
|
||
|
testRE(re, 'a', true);
|
||
|
testRE(re, 'xa', true);
|
||
|
testRE(re, 'xyz', true);
|
||
|
testRE(re, 'xya', false);
|
||
|
execRE(re, 'a', ['', undefined, undefined, undefined]);
|
||
|
execRE(re, 'xa', ['', undefined, undefined, undefined]);
|
||
|
execRE(re, 'xyz', ['', undefined, undefined, undefined]);
|