regexflags.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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 bindFlagsGetter(thisArg) {
  7. var getter = Object.getOwnPropertyDescriptor(RegExp.prototype, "flags").get;
  8. return getter.bind(thisArg);
  9. }
  10. function generatePrototypeFlagsTests() {
  11. var testsGroupedByFlag =
  12. [['global', 'g'],
  13. ['ignoreCase', 'i'],
  14. ['multiline', 'm'],
  15. ['sticky', 'y'],
  16. ['unicode', 'u']].map(function ([propertyName, flag]) {
  17. return [
  18. {
  19. name: "RegExp.prototype.flags should include '" + flag + "' when '" + propertyName + "' is 'true'",
  20. body: function () {
  21. var object = {};
  22. object[propertyName] = true;
  23. var flags = bindFlagsGetter(object)();
  24. assert.isTrue(flags.includes(flag));
  25. }
  26. },
  27. {
  28. name: "RegExp.prototype.flags should not include '" + flag + "' when '" + propertyName + "' is 'false'",
  29. body: function () {
  30. var object = {};
  31. object[propertyName] = false;
  32. var flags = bindFlagsGetter(object)();
  33. assert.isFalse(flags.includes(flag));
  34. }
  35. },
  36. {
  37. name: "RegExp.prototype.flags should coerce '" + flag + "' to Boolean",
  38. body: function () {
  39. var object = {};
  40. object[propertyName] = 123;
  41. var flags = bindFlagsGetter(object)();
  42. assert.isTrue(flags.includes(flag), "123 -> true");
  43. object[propertyName] = null;
  44. var flags = bindFlagsGetter(object)();
  45. assert.isFalse(flags.includes(flag), "null -> false");
  46. }
  47. },
  48. ];
  49. });
  50. return Array.prototype.concat.apply([], testsGroupedByFlag);
  51. }
  52. var tests = [
  53. {
  54. name: "Test sticky and unicode getter on RegExp.prototype",
  55. body: function () {
  56. assert.isFalse(RegExp.prototype.unicode, "RegExp.prototype.unicode");
  57. assert.isFalse(RegExp.prototype.sticky, "RegExp.prototype.sticky");
  58. function verifier(r, expectedUnicode, expectedSticky)
  59. {
  60. r.unicode = true; // no-op
  61. r.sticky = true; // no-op
  62. assert.areEqual(expectedUnicode, r.unicode, r + ": unicode");
  63. assert.areEqual(expectedSticky, r.sticky, r + ": sticky");
  64. }
  65. verifier(/.?\d+/, false, false);
  66. RegExp.prototype.unicode = true; // no-op
  67. verifier(/.?\d+/gu, true, false);
  68. verifier(/.?\d+/iy, false, true);
  69. RegExp.prototype.sticky = true; // no-op
  70. verifier(new RegExp("a*bc", "g"), false, false);
  71. verifier(new RegExp("a*bc", "u"), true, false);
  72. verifier(new RegExp("a*bc?","y"), false, true);
  73. verifier(new RegExp("a*b\d\s?","iuy"), true, true);
  74. }
  75. },
  76. {
  77. name: "Test sticky bit with exec()",
  78. body: function () {
  79. var pattern = /hello\d\s?/y;
  80. var text = "hello1 hello2 hello3";
  81. [["hello1 ", 7],
  82. ["hello2 ", 14],
  83. ["hello3", 20],
  84. [null, 0]].forEach(function ([expectedMatchedString, expectedLastIndex]) {
  85. var result = pattern.exec(text);
  86. if (expectedMatchedString !== null) {
  87. assert.areEqual(expectedMatchedString, result[0], "matched string");
  88. }
  89. else {
  90. assert.areEqual(null, result, "result");
  91. }
  92. assert.areEqual(expectedLastIndex, pattern.lastIndex, "lastIndex");
  93. });
  94. }
  95. },
  96. {
  97. name: "Test sticky bit with test()",
  98. body: function () {
  99. var pattern = /hello\d\s?/y;
  100. var text = "hello1 hello2 hello3";
  101. [[true, 7],
  102. [true, 14],
  103. [true, 20],
  104. [false, 0]].forEach(function ([expectedResult, expectedLastIndex]) {
  105. assert.areEqual(expectedResult, pattern.test(text), "result");
  106. assert.areEqual(expectedLastIndex, pattern.lastIndex, "lastIndex");
  107. });
  108. }
  109. },
  110. {
  111. name: "Test sticky bit with search()",
  112. body: function () {
  113. var pattern = /hello\d\s?/y;
  114. var text = "hello1 hello2 hello3";
  115. assert.areEqual(0, text.search(pattern), "result");
  116. assert.areEqual(0, pattern.lastIndex, "lastIndex")
  117. }
  118. },
  119. {
  120. name: "Test sticky bit with replace()",
  121. body: function () {
  122. var pattern = /hello\d\s?/y;
  123. var text = "hello1 hello2 hello3";
  124. // should replace 1st occurrence because global is false and last index should be at 7.
  125. assert.areEqual("world hello2 hello3", text.replace(pattern, "world "), "result");
  126. assert.areEqual(7, pattern.lastIndex, "lastIndex");
  127. }
  128. },
  129. {
  130. name: "Test sticky bit with replace() with global flag.",
  131. body: function () {
  132. var pattern = /hello\d\s?/g;
  133. var text = "hello1 hello2 hello3";
  134. // should replace all occurrences because global is true and last index should be at 0.
  135. assert.areEqual("world world world ", text.replace(pattern, "world "), "result");
  136. assert.areEqual(0, pattern.lastIndex, "lastIndex");
  137. }
  138. },
  139. {
  140. name: "Test sticky bit with replace() with global/sticky flag.",
  141. body: function () {
  142. var pattern = /hello\d\s?/gy;
  143. var text = "hello1 hello2 hello3";
  144. // should replace all occurrences because global is true irrespective of sticky bit and last index should be at 0.
  145. assert.areEqual("world world world ", text.replace(pattern, "world "), "result");
  146. assert.areEqual(0, pattern.lastIndex, "lastIndex");
  147. }
  148. },
  149. {
  150. name: "Test sticky bit with match()",
  151. body: function () {
  152. var pattern = /hello\d\s?/y;
  153. var text = "hello1 hello2 hello3";
  154. // should match 1st occurrence because global is false and last index should be at 7.
  155. var result = text.match(pattern);
  156. assert.areEqual(1, result.length, "result length");
  157. assert.areEqual("hello1 ", result[0], "result[0]");
  158. assert.areEqual(7, pattern.lastIndex, "lastIndex");
  159. }
  160. },
  161. {
  162. name: "Test sticky bit with match() with global flag.",
  163. body: function () {
  164. var pattern = /hello\d\s?/g;
  165. var text = "hello1 hello2 hello3";
  166. // should match all occurrence because global is true and last index should be at 0.
  167. var result = text.match(pattern);
  168. assert.areEqual(3, result.length, "result length");
  169. assert.areEqual("hello1 ", result[0], "result[0]");
  170. assert.areEqual("hello2 ", result[1], "result[1]");
  171. assert.areEqual("hello3", result[2], "result[2]");
  172. assert.areEqual(0, pattern.lastIndex, "lastIndex");
  173. }
  174. },
  175. {
  176. name: "Test sticky bit with match() with global/sticky flag.",
  177. body: function () {
  178. var pattern = /hello\d\s?/gy;
  179. var text = "hello1 hello2 hello3";
  180. // should match all occurrence because global is true and last index should be at 0 irrespective of sticky bit flag.
  181. var result = text.match(pattern);
  182. assert.areEqual(3, result.length, "result length");
  183. assert.areEqual("hello1 ", result[0], "result[0]");
  184. assert.areEqual("hello2 ", result[1], "result[1]");
  185. assert.areEqual("hello3", result[2], "result[2]");
  186. assert.areEqual(0, pattern.lastIndex, "lastIndex");
  187. }
  188. },
  189. {
  190. name: "Test sticky bit with split()",
  191. body: function () {
  192. var pattern = /\d/y;
  193. var text = "hello1 hello2 hello3";
  194. // sticky bit flag is ignored and lastIndex is set to 0.
  195. var result = text.split(pattern);
  196. assert.areEqual(4, result.length, "result length");
  197. assert.areEqual("hello", result[0], "result[0]");
  198. assert.areEqual(" hello", result[1], "result[1]");
  199. assert.areEqual(" hello", result[2], "result[2]");
  200. assert.areEqual("", result[3], "result[3]");
  201. assert.areEqual(0, pattern.lastIndex, "lastIndex");
  202. }
  203. },
  204. {
  205. name: "RegExp.prototype.flags should throw an exception when 'this' isn't an Object",
  206. body: function () {
  207. var nonObject = "string";
  208. assert.throws(bindFlagsGetter(nonObject), TypeError);
  209. }
  210. },
  211. {
  212. name: "RegExp.prototype.flags should be callable when 'this' is an ordinary Object",
  213. body: function () {
  214. assert.doesNotThrow(bindFlagsGetter({}));
  215. }
  216. },
  217. {
  218. name: "RegExp.prototype.flags should return an empty String when no flag exists",
  219. body: function () {
  220. assert.areEqual("", bindFlagsGetter({})());
  221. }
  222. },
  223. {
  224. name: "RegExp.prototype.flags should return the flags in the correct order",
  225. body: function () {
  226. var object = {
  227. ignoreCase: true,
  228. unicode: true,
  229. sticky: true,
  230. multiline: true,
  231. global: true
  232. };
  233. assert.areEqual("gimuy", bindFlagsGetter(object)());
  234. }
  235. },
  236. ];
  237. tests = tests.concat(generatePrototypeFlagsTests());
  238. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });