1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
// GENERATED, DO NOT EDIT
// file: regExpUtils.js
// 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 = Reflect.apply(String.fromCodePoint, null, loneCodePoints);
for (let i = 0; i < ranges.length; i++) {
const range = ranges[i];
const start = range[0];
const end = range[1];
const codePoints = [];
for (let length = 0, codePoint = start; codePoint <= end; codePoint++) {
codePoints[length++] = codePoint;
if (length === CHUNK_SIZE) {
result += Reflect.apply(String.fromCodePoint, null, codePoints);
codePoints.length = length = 0;
}
}
result += Reflect.apply(String.fromCodePoint, 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 (const symbol of string) {
const formatted = printCodePoint(symbol.codePointAt(0));
buf.push(formatted);
}
return buf.join(' ');
}
function testPropertyEscapes(regExp, string, expression) {
if (!regExp.test(string)) {
for (const symbol of string) {
const 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 (const 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 (const 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');
}
}
|