| // 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, 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 hex = printCodePoint(symbol.codePointAt(0)); |
| assert( |
| regExp.test(symbol), |
| `\`${ expression }\` should match U+${ hex } (\`${ 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 } (U+${ printStringCodePoints(string) })` |
| ); |
| } |
| } |
| |
| const allNonMatchStrings = nonMatchStrings.join(''); |
| if (regExp.test(allNonMatchStrings)) { |
| for (const string of nonMatchStrings) { |
| assert( |
| !regExp.test(string), |
| `\`${ expression }\` should not match ${ string } (U+${ printStringCodePoints(string) })` |
| ); |
| } |
| } |
| } |
| |
| // 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'); |
| } |
| } |