mirror of https://github.com/tc39/test262.git
114 lines
3.5 KiB
JavaScript
114 lines
3.5 KiB
JavaScript
// Copyright (C) 2017 Mathias Bynens. All rights reserved.
|
|
// This code is governed by the BSD license found in the LICENSE file.
|
|
/*---
|
|
description: |
|
|
Collection of functions used to assert the correctness of RegExp objects.
|
|
defines: [buildString, testPropertyEscapes, testPropertyOfStrings, testExtendedCharacterClass, matchValidator]
|
|
---*/
|
|
|
|
function buildString(args) {
|
|
// Use member expressions rather than destructuring `args` for improved
|
|
// compatibility with engines that only implement assignment patterns
|
|
// partially or not at all.
|
|
const loneCodePoints = args.loneCodePoints;
|
|
const ranges = args.ranges;
|
|
const CHUNK_SIZE = 10000;
|
|
let result = String.fromCodePoint.apply(null, loneCodePoints);
|
|
for (let i = 0; i < ranges.length; i++) {
|
|
let range = ranges[i];
|
|
let start = range[0];
|
|
let end = range[1];
|
|
let codePoints = [];
|
|
for (let length = 0, codePoint = start; codePoint <= end; codePoint++) {
|
|
codePoints[length++] = codePoint;
|
|
if (length === CHUNK_SIZE) {
|
|
result += String.fromCodePoint.apply(null, codePoints);
|
|
codePoints.length = length = 0;
|
|
}
|
|
}
|
|
result += String.fromCodePoint.apply(null, codePoints);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function printCodePoint(codePoint) {
|
|
const hex = codePoint
|
|
.toString(16)
|
|
.toUpperCase()
|
|
.padStart(6, "0");
|
|
return `U+${hex}`;
|
|
}
|
|
|
|
function printStringCodePoints(string) {
|
|
const buf = [];
|
|
for (let symbol of string) {
|
|
let formatted = printCodePoint(symbol.codePointAt(0));
|
|
buf.push(formatted);
|
|
}
|
|
return buf.join(' ');
|
|
}
|
|
|
|
function testPropertyEscapes(regExp, string, expression) {
|
|
if (!regExp.test(string)) {
|
|
for (let symbol of string) {
|
|
let formatted = printCodePoint(symbol.codePointAt(0));
|
|
assert(
|
|
regExp.test(symbol),
|
|
`\`${ expression }\` should match ${ formatted } (\`${ symbol }\`)`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function testPropertyOfStrings(args) {
|
|
// Use member expressions rather than destructuring `args` for improved
|
|
// compatibility with engines that only implement assignment patterns
|
|
// partially or not at all.
|
|
const regExp = args.regExp;
|
|
const expression = args.expression;
|
|
const matchStrings = args.matchStrings;
|
|
const nonMatchStrings = args.nonMatchStrings;
|
|
const allStrings = matchStrings.join('');
|
|
if (!regExp.test(allStrings)) {
|
|
for (let string of matchStrings) {
|
|
assert(
|
|
regExp.test(string),
|
|
`\`${ expression }\` should match ${ string } (${ printStringCodePoints(string) })`
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!nonMatchStrings) return;
|
|
|
|
const allNonMatchStrings = nonMatchStrings.join('');
|
|
if (regExp.test(allNonMatchStrings)) {
|
|
for (let string of nonMatchStrings) {
|
|
assert(
|
|
!regExp.test(string),
|
|
`\`${ expression }\` should not match ${ string } (${ printStringCodePoints(string) })`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// The exact same logic can be used to test extended character classes
|
|
// as enabled through the RegExp `v` flag. This is useful to test not
|
|
// just standalone properties of strings, but also string literals, and
|
|
// set operations.
|
|
const testExtendedCharacterClass = testPropertyOfStrings;
|
|
|
|
// Returns a function that validates a RegExp match result.
|
|
//
|
|
// Example:
|
|
//
|
|
// var validate = matchValidator(['b'], 1, 'abc');
|
|
// validate(/b/.exec('abc'));
|
|
//
|
|
function matchValidator(expectedEntries, expectedIndex, expectedInput) {
|
|
return function(match) {
|
|
assert.compareArray(match, expectedEntries, 'Match entries');
|
|
assert.sameValue(match.index, expectedIndex, 'Match index');
|
|
assert.sameValue(match.input, expectedInput, 'Match input');
|
|
}
|
|
}
|