shell.js (3685B)
1 // GENERATED, DO NOT EDIT 2 // file: regExpUtils.js 3 // Copyright (C) 2017 Mathias Bynens. All rights reserved. 4 // This code is governed by the BSD license found in the LICENSE file. 5 /*--- 6 description: | 7 Collection of functions used to assert the correctness of RegExp objects. 8 defines: [buildString, testPropertyEscapes, testPropertyOfStrings, testExtendedCharacterClass, matchValidator] 9 ---*/ 10 11 function buildString(args) { 12 // Use member expressions rather than destructuring `args` for improved 13 // compatibility with engines that only implement assignment patterns 14 // partially or not at all. 15 const loneCodePoints = args.loneCodePoints; 16 const ranges = args.ranges; 17 const CHUNK_SIZE = 10000; 18 let result = String.fromCodePoint.apply(null, loneCodePoints); 19 for (let i = 0; i < ranges.length; i++) { 20 let range = ranges[i]; 21 let start = range[0]; 22 let end = range[1]; 23 let codePoints = []; 24 for (let length = 0, codePoint = start; codePoint <= end; codePoint++) { 25 codePoints[length++] = codePoint; 26 if (length === CHUNK_SIZE) { 27 result += String.fromCodePoint.apply(null, codePoints); 28 codePoints.length = length = 0; 29 } 30 } 31 result += String.fromCodePoint.apply(null, codePoints); 32 } 33 return result; 34 } 35 36 function printCodePoint(codePoint) { 37 const hex = codePoint 38 .toString(16) 39 .toUpperCase() 40 .padStart(6, "0"); 41 return `U+${hex}`; 42 } 43 44 function printStringCodePoints(string) { 45 const buf = []; 46 for (let symbol of string) { 47 let formatted = printCodePoint(symbol.codePointAt(0)); 48 buf.push(formatted); 49 } 50 return buf.join(' '); 51 } 52 53 function testPropertyEscapes(regExp, string, expression) { 54 if (!regExp.test(string)) { 55 for (let symbol of string) { 56 let formatted = printCodePoint(symbol.codePointAt(0)); 57 assert( 58 regExp.test(symbol), 59 `\`${ expression }\` should match ${ formatted } (\`${ symbol }\`)` 60 ); 61 } 62 } 63 } 64 65 function testPropertyOfStrings(args) { 66 // Use member expressions rather than destructuring `args` for improved 67 // compatibility with engines that only implement assignment patterns 68 // partially or not at all. 69 const regExp = args.regExp; 70 const expression = args.expression; 71 const matchStrings = args.matchStrings; 72 const nonMatchStrings = args.nonMatchStrings; 73 const allStrings = matchStrings.join(''); 74 if (!regExp.test(allStrings)) { 75 for (let string of matchStrings) { 76 assert( 77 regExp.test(string), 78 `\`${ expression }\` should match ${ string } (${ printStringCodePoints(string) })` 79 ); 80 } 81 } 82 83 if (!nonMatchStrings) return; 84 85 const allNonMatchStrings = nonMatchStrings.join(''); 86 if (regExp.test(allNonMatchStrings)) { 87 for (let string of nonMatchStrings) { 88 assert( 89 !regExp.test(string), 90 `\`${ expression }\` should not match ${ string } (${ printStringCodePoints(string) })` 91 ); 92 } 93 } 94 } 95 96 // The exact same logic can be used to test extended character classes 97 // as enabled through the RegExp `v` flag. This is useful to test not 98 // just standalone properties of strings, but also string literals, and 99 // set operations. 100 const testExtendedCharacterClass = testPropertyOfStrings; 101 102 // Returns a function that validates a RegExp match result. 103 // 104 // Example: 105 // 106 // var validate = matchValidator(['b'], 1, 'abc'); 107 // validate(/b/.exec('abc')); 108 // 109 function matchValidator(expectedEntries, expectedIndex, expectedInput) { 110 return function(match) { 111 assert.compareArray(match, expectedEntries, 'Match entries'); 112 assert.sameValue(match.index, expectedIndex, 'Match index'); 113 assert.sameValue(match.input, expectedInput, 'Match input'); 114 } 115 }