control_character_escapes.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  6. function matchRegExp(str, regexpLiteral, expectedResult)
  7. {
  8. matchResultLiteral = str.match(regexpLiteral);
  9. errorMsgBase = "Expected result of match between string: '" + str + "' and regular expression: " + regexpLiteral + " to be " +
  10. expectedResult + " but was "
  11. actualResultLiteral = matchResultLiteral == null ? null : matchResultLiteral[0];
  12. assert.areEqual(expectedResult, actualResultLiteral, errorMsgBase + actualResultLiteral);
  13. regexpConstructor = new RegExp(regexpLiteral);
  14. matchResultConstructor = str.match(regexpConstructor);
  15. actualResultConstructor = matchResultConstructor == null ? null : matchResultConstructor[0];
  16. assert.areEqual(expectedResult, actualResultConstructor, errorMsgBase + actualResultConstructor);
  17. }
  18. var tests = [
  19. {
  20. name : "Control characters followed by a word character ([A-Za-z0-9_])",
  21. body : function ()
  22. {
  23. re = /[\c6]+/; //'6' = ascii x36, parsed as [\x16]+
  24. matchRegExp("6", re, null);
  25. matchRegExp("\\", re, null);
  26. matchRegExp("\\c6", re, null);
  27. matchRegExp("c", re, null);
  28. matchRegExp("\x16", re, "\x16");
  29. re = /\c6/; //'6' = ascii x36, parsed as "\\c6"
  30. matchRegExp("\\c6", re, "\\c6");
  31. matchRegExp("\\", re, null);
  32. matchRegExp("6", re, null);
  33. matchRegExp("c", re, null);
  34. matchRegExp("\x16", re, null);
  35. re = /\c6[\c6]+/; //'6' = ascii x36, parsed as "\\c6"[\x16]+
  36. matchRegExp("\\c6\x16", re, "\\c6\x16");
  37. matchRegExp("\\", re, null);
  38. matchRegExp("c", re, null);
  39. matchRegExp("\x16", re, null);
  40. re = /[\ca]+/; //'a' = ascii x61, parsed as [\x01]+
  41. matchRegExp("a", re, null);
  42. matchRegExp("\\", re, null);
  43. matchRegExp("c", re, null);
  44. matchRegExp("00xyzabc123\x01qrst", re, "\x01");
  45. re = /[\c_]+/; //'_' = ascii 0x5F, parsed as [\x1F]+
  46. matchRegExp("\x1F\x1F\x05", re, "\x1F\x1F");
  47. matchRegExp("\\\\\\", re, null);
  48. matchRegExp("////", re, null);
  49. matchRegExp("ccc_", re, null);
  50. re = /[\cG]*/; //'G' = ascii x47, parsed as [\x07]*
  51. matchRegExp("\x07\x06\x05", re, "\x07");
  52. matchRegExp("\\\\", re, "");
  53. matchRegExp("////", re, "");
  54. matchRegExp("cccG", re, "");
  55. re = /[\cG\c6\cf]+/; //'G' = ascii x47, '6' = ascii x36, 'f' = ascii x66, parsed as [\x07\x16\x06]+
  56. matchRegExp("\x00\x03\x07\x06\x16\x07\x08", re, "\x07\x06\x16\x07");
  57. matchRegExp("\\\\", re, null);
  58. matchRegExp("////", re, null);
  59. matchRegExp("cfG6", re, null);
  60. re = /\cG\cf/; //'G' = ascii x47, 'f' = ascii x66, parsed as "\x07\x06"
  61. matchRegExp("\x00\x03\x07\x06\x16\x07\x08", re, "\x07\x06");
  62. matchRegExp("\\", re, null);
  63. matchRegExp("/", re, null);
  64. matchRegExp("\\cG\\c6\\cf", re, null);
  65. re = /[\cz\cZ]+/; //'z' = ascii x7A, 'Z' = ascii x5A, have the same lowest 5 bits, parsed as [\x1A]+
  66. matchRegExp("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
  67. "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", re, "\x1a");
  68. matchRegExp("\\\\", re, null);
  69. matchRegExp("////", re, null);
  70. matchRegExp("ccczZ", re, null);
  71. }
  72. },
  73. {
  74. name : "Control characters followed by a non-word character ([^A-Za-z0-9_])",
  75. body : function ()
  76. {
  77. re = /[\c*]+/; //'*' = ascii 42, parsed as [\\c*]+
  78. matchRegExp("\x0a\x09\x08", re, null);
  79. matchRegExp("a*c*b*d*", re, "*c*");
  80. matchRegExp("\\\\", re, "\\\\");
  81. matchRegExp("////", re, null);
  82. matchRegExp("ccc", re, "ccc");
  83. re = /[\c}]*/; //'}' = ascii 125, parsed as [\\c}]*
  84. matchRegExp("\x1d\x7d\x3d", re, "");
  85. matchRegExp("}c}}cd*c*b*d*", re, "}c}}c");
  86. matchRegExp("\\\\", re, "\\\\");
  87. matchRegExp("////", re, "");
  88. matchRegExp("ccc", re, "ccc");
  89. re = /[\c;]+/; //';' = ascii 59, parsed as [\\c;]+
  90. matchRegExp("\x1b\x1c", re, null);
  91. matchRegExp("d;c;d;*", re, ";c;");
  92. matchRegExp("\\\\", re, "\\\\");
  93. matchRegExp("////", re, null);
  94. matchRegExp("ccc", re, "ccc");
  95. re = /\c%/; //'%' = ascii x25, parsed as \\c%
  96. matchRegExp("\\", re, null);
  97. matchRegExp("\\", re, null);
  98. matchRegExp("\\c%", re, "\\c%");
  99. matchRegExp("\x05", re, null);
  100. }
  101. },
  102. {
  103. name : "Control Character tests with unicode flag present",
  104. body : function ()
  105. {
  106. re = /[\cAg]+/u; //'A' = ascii x41, parsed as [g\x01]+
  107. matchRegExp("abcdefghi", re, "g");
  108. matchRegExp("\\\\", re, null);
  109. matchRegExp("////", re, null);
  110. matchRegExp("\x01\x01gg\x02\x04ggg", re, "\x01\x01gg");
  111. re = /[\czA]+/u; //'z' = ascii x7A, parsed as [\x1AA]+
  112. matchRegExp("abcdefghi", re, null);
  113. matchRegExp("\\\\", re, null);
  114. matchRegExp("////", re, null);
  115. matchRegExp("YZA\x1aABC", re, "A\x1aA");
  116. assert.throws(() => eval("\"\".match(/[\\c]/u)"), SyntaxError, "(Character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by no character here.",
  117. "Invalid regular expression: invalid escape in unicode pattern");
  118. assert.throws(() => eval("\"\".match(/[\\c-d]/u)"), SyntaxError, "(Character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by a dash, '-', here.",
  119. "Invalid regular expression: invalid escape in unicode pattern");
  120. assert.throws(() => eval("\"\".match(/[ab\\c_$]/u)"), SyntaxError, "(Character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by an underscore, '_', here.",
  121. "Invalid regular expression: invalid escape in unicode pattern");
  122. assert.throws(() => eval("\"\".match(/[ab\\c\\d]/u)"), SyntaxError, "(Character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by a backslash, '\\', here.",
  123. "Invalid regular expression: invalid escape in unicode pattern");
  124. assert.throws(() => eval("\"\".match(/[ab\\c3]/u)"), SyntaxError, "(Character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by a number, '3', here.",
  125. "Invalid regular expression: invalid escape in unicode pattern");
  126. re = /\cAg/u; //'A' = ascii x41, parsed as "\x01g"
  127. matchRegExp("abcdefghi", re, null);
  128. matchRegExp("\\\\", re, null);
  129. matchRegExp("////", re, null);
  130. matchRegExp("\x01\x01gg\x02\x04ggg", re, "\x01g");
  131. re = /\czA/u; //'z' = ascii x7A, parsed as "\x1aA"
  132. matchRegExp("abcdefghi", re, null);
  133. matchRegExp("\\\\", re, null);
  134. matchRegExp("////", re, null);
  135. matchRegExp("YZA\x1aABC", re, "\x1aA");
  136. assert.throws(() => eval("\"\".match(/\\c/u)"), SyntaxError, "(Non-character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by no character here.",
  137. "Invalid regular expression: invalid escape in unicode pattern");
  138. assert.throws(() => eval("\"\".match(/\\c-d/u)"), SyntaxError, "(Non-character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by a dash, '-', here.",
  139. "Invalid regular expression: invalid escape in unicode pattern");
  140. assert.throws(() => eval("\"\".match(/ab\\c_$/u)"), SyntaxError, "(Non-character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by an underscore, '_', here.",
  141. "Invalid regular expression: invalid escape in unicode pattern");
  142. assert.throws(() => eval("\"\".match(/ab\\c\\d/u)"), SyntaxError, "(Non-character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by a backslash, '\\', here.",
  143. "Invalid regular expression: invalid escape in unicode pattern");
  144. assert.throws(() => eval("\"\".match(/ab\\c3/u)"), SyntaxError, "(Non-character class) Expected an error because escaped c must be followed by a letter when unicode flag is present, but is followed by a number, '3', here.",
  145. "Invalid regular expression: invalid escape in unicode pattern");
  146. }
  147. },
  148. {
  149. name : "Control character edge cases",
  150. body : function ()
  151. {
  152. re = /[\c-g]+/; //'-' = ascii x2D, parsed as [\\c-g]+
  153. matchRegExp("abcdefghi", re, "cdefg");
  154. matchRegExp("\\\\", re, "\\\\");
  155. matchRegExp("////", re, null);
  156. matchRegExp("\x0d", re, null);
  157. matchRegExp("aobd\\f\\d", re, "d\\f\\d");
  158. re = /[\c-]+/; //'-' = ascii x2D, parsed as [\\c-]+
  159. matchRegExp("abcdefghi", re, "c");
  160. matchRegExp("\x0dc--c", re, "c--c");
  161. matchRegExp("\\\\", re, "\\\\");
  162. matchRegExp("////", re, null);
  163. matchRegExp("aobd\\f\\d", re, "\\");
  164. assert.throws(() => eval("\"\".match(/[\\c-a]/)"), SyntaxError, "Expected an error due to 'c-a' being an invalid range.", "Invalid range in character set");
  165. }
  166. }
  167. ];
  168. testRunner.runTests(tests, {
  169. verbose : WScript.Arguments[0] != "summary"
  170. });