PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/dom/tests/mochitest/ajax/prototype/test/unit/string_test.js

https://bitbucket.org/soko/mozilla-central
JavaScript | 540 lines | 467 code | 62 blank | 11 comment | 3 complexity | d3762b6d180addf3ee94d40970acaa41 MD5 | raw file
Possible License(s): GPL-2.0, JSON, 0BSD, LGPL-3.0, AGPL-1.0, MIT, MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.1, Apache-2.0
  1. new Test.Unit.Runner({
  2. testInterpret: function(){
  3. this.assertIdentical('true', String.interpret(true));
  4. this.assertIdentical('123', String.interpret(123));
  5. this.assertIdentical('foo bar', String.interpret('foo bar'));
  6. this.assertIdentical(
  7. 'object string',
  8. String.interpret({ toString: function(){ return 'object string' } }));
  9. this.assertIdentical('0', String.interpret(0));
  10. this.assertIdentical('false', String.interpret(false));
  11. this.assertIdentical('', String.interpret(undefined));
  12. this.assertIdentical('', String.interpret(null));
  13. this.assertIdentical('', String.interpret(''));
  14. },
  15. testGsubWithReplacementFunction: function() {
  16. var source = 'foo boo boz';
  17. this.assertEqual('Foo Boo BoZ',
  18. source.gsub(/[^o]+/, function(match) {
  19. return match[0].toUpperCase()
  20. }));
  21. this.assertEqual('f2 b2 b1z',
  22. source.gsub(/o+/, function(match) {
  23. return match[0].length;
  24. }));
  25. this.assertEqual('f0 b0 b1z',
  26. source.gsub(/o+/, function(match) {
  27. return match[0].length % 2;
  28. }));
  29. },
  30. testGsubWithReplacementString: function() {
  31. var source = 'foo boo boz';
  32. this.assertEqual('foobooboz',
  33. source.gsub(/\s+/, ''));
  34. this.assertEqual(' z',
  35. source.gsub(/(.)(o+)/, ''));
  36. this.assertEqual('ウィメンズ2007<br/>クルーズコレクション',
  37. 'ウィメンズ2007\nクルーズコレクション'.gsub(/\n/,'<br/>'));
  38. this.assertEqual('ウィメンズ2007<br/>クルーズコレクション',
  39. 'ウィメンズ2007\nクルーズコレクション'.gsub('\n','<br/>'));
  40. },
  41. testGsubWithReplacementTemplateString: function() {
  42. var source = 'foo boo boz';
  43. this.assertEqual('-oo-#{1}- -oo-#{1}- -o-#{1}-z',
  44. source.gsub(/(.)(o+)/, '-#{2}-\\#{1}-'));
  45. this.assertEqual('-foo-f- -boo-b- -bo-b-z',
  46. source.gsub(/(.)(o+)/, '-#{0}-#{1}-'));
  47. this.assertEqual('-oo-f- -oo-b- -o-b-z',
  48. source.gsub(/(.)(o+)/, '-#{2}-#{1}-'));
  49. this.assertEqual(' z',
  50. source.gsub(/(.)(o+)/, '#{3}'));
  51. },
  52. testSubWithReplacementFunction: function() {
  53. var source = 'foo boo boz';
  54. this.assertEqual('Foo boo boz',
  55. source.sub(/[^o]+/, function(match) {
  56. return match[0].toUpperCase()
  57. }), 1);
  58. this.assertEqual('Foo Boo boz',
  59. source.sub(/[^o]+/, function(match) {
  60. return match[0].toUpperCase()
  61. }, 2), 2);
  62. this.assertEqual(source,
  63. source.sub(/[^o]+/, function(match) {
  64. return match[0].toUpperCase()
  65. }, 0), 0);
  66. this.assertEqual(source,
  67. source.sub(/[^o]+/, function(match) {
  68. return match[0].toUpperCase()
  69. }, -1), -1);
  70. },
  71. testSubWithReplacementString: function() {
  72. var source = 'foo boo boz';
  73. this.assertEqual('oo boo boz',
  74. source.sub(/[^o]+/, ''));
  75. this.assertEqual('oooo boz',
  76. source.sub(/[^o]+/, '', 2));
  77. this.assertEqual('-f-oo boo boz',
  78. source.sub(/[^o]+/, '-#{0}-'));
  79. this.assertEqual('-f-oo- b-oo boz',
  80. source.sub(/[^o]+/, '-#{0}-', 2));
  81. },
  82. testScan: function() {
  83. var source = 'foo boo boz', results = [];
  84. var str = source.scan(/[o]+/, function(match) {
  85. results.push(match[0].length);
  86. });
  87. this.assertEnumEqual([2, 2, 1], results);
  88. this.assertEqual(source, source.scan(/x/, this.fail));
  89. this.assert(typeof str == 'string');
  90. },
  91. testToArray: function() {
  92. this.assertEnumEqual([],''.toArray());
  93. this.assertEnumEqual(['a'],'a'.toArray());
  94. this.assertEnumEqual(['a','b'],'ab'.toArray());
  95. this.assertEnumEqual(['f','o','o'],'foo'.toArray());
  96. },
  97. /*
  98. Note that camelize() differs from its Rails counterpart,
  99. as it is optimized for dealing with JavaScript object
  100. properties in conjunction with CSS property names:
  101. - Looks for dashes, not underscores
  102. - CamelCases first word if there is a front dash
  103. */
  104. testCamelize: function() {
  105. this.assertEqual('', ''.camelize());
  106. this.assertEqual('', '-'.camelize());
  107. this.assertEqual('foo', 'foo'.camelize());
  108. this.assertEqual('foo_bar', 'foo_bar'.camelize());
  109. this.assertEqual('FooBar', '-foo-bar'.camelize());
  110. this.assertEqual('FooBar', 'FooBar'.camelize());
  111. this.assertEqual('fooBar', 'foo-bar'.camelize());
  112. this.assertEqual('borderBottomWidth', 'border-bottom-width'.camelize());
  113. this.assertEqual('classNameTest','class-name-test'.camelize());
  114. this.assertEqual('classNameTest','className-test'.camelize());
  115. this.assertEqual('classNameTest','class-nameTest'.camelize());
  116. /* this.benchmark(function(){
  117. 'class-name-test'.camelize();
  118. },10000); */
  119. },
  120. testCapitalize: function() {
  121. this.assertEqual('',''.capitalize());
  122. this.assertEqual('Ä','ä'.capitalize());
  123. this.assertEqual('A','A'.capitalize());
  124. this.assertEqual('Hello','hello'.capitalize());
  125. this.assertEqual('Hello','HELLO'.capitalize());
  126. this.assertEqual('Hello','Hello'.capitalize());
  127. this.assertEqual('Hello world','hello WORLD'.capitalize());
  128. },
  129. testUnderscore: function() {
  130. this.assertEqual('', ''.underscore());
  131. this.assertEqual('_', '-'.underscore());
  132. this.assertEqual('foo', 'foo'.underscore());
  133. this.assertEqual('foo', 'Foo'.underscore());
  134. this.assertEqual('foo_bar', 'foo_bar'.underscore());
  135. this.assertEqual('border_bottom', 'borderBottom'.underscore());
  136. this.assertEqual('border_bottom_width', 'borderBottomWidth'.underscore());
  137. this.assertEqual('border_bottom_width', 'border-Bottom-Width'.underscore());
  138. },
  139. testDasherize: function() {
  140. this.assertEqual('', ''.dasherize());
  141. this.assertEqual('foo', 'foo'.dasherize());
  142. this.assertEqual('Foo', 'Foo'.dasherize());
  143. this.assertEqual('foo-bar', 'foo-bar'.dasherize());
  144. this.assertEqual('border-bottom-width', 'border_bottom_width'.dasherize());
  145. },
  146. testTruncate: function() {
  147. var source = 'foo boo boz foo boo boz foo boo boz foo boo boz';
  148. this.assertEqual(source, source.truncate(source.length));
  149. this.assertEqual('foo boo boz foo boo boz foo...', source.truncate(0));
  150. this.assertEqual('fo...', source.truncate(5));
  151. this.assertEqual('foo b', source.truncate(5, ''));
  152. this.assert(typeof 'foo'.truncate(5) == 'string');
  153. this.assert(typeof 'foo bar baz'.truncate(5) == 'string');
  154. },
  155. testStrip: function() {
  156. this.assertEqual('hello world', ' hello world '.strip());
  157. this.assertEqual('hello world', 'hello world'.strip());
  158. this.assertEqual('hello \n world', ' hello \n world '.strip());
  159. this.assertEqual('', ' '.strip());
  160. },
  161. testStripTags: function() {
  162. this.assertEqual('hello world', 'hello world'.stripTags());
  163. this.assertEqual('hello world', 'hello <span>world</span>'.stripTags());
  164. this.assertEqual('hello world', '<a href="#" onclick="moo!">hello</a> world'.stripTags());
  165. this.assertEqual('hello world', 'h<b><em>e</em></b>l<i>l</i>o w<span class="moo" id="x"><b>o</b></span>rld'.stripTags());
  166. this.assertEqual('1\n2', '1\n2'.stripTags());
  167. },
  168. testStripScripts: function() {
  169. this.assertEqual('foo bar', 'foo bar'.stripScripts());
  170. this.assertEqual('foo bar', ('foo <script>boo();<'+'/script>bar').stripScripts());
  171. this.assertEqual('foo bar', ('foo <script type="text/javascript">boo();\nmoo();<'+'/script>bar').stripScripts());
  172. },
  173. testExtractScripts: function() {
  174. this.assertEnumEqual([], 'foo bar'.extractScripts());
  175. this.assertEnumEqual(['boo();'], ('foo <script>boo();<'+'/script>bar').extractScripts());
  176. this.assertEnumEqual(['boo();','boo();\nmoo();'],
  177. ('foo <script>boo();<'+'/script><script type="text/javascript">boo();\nmoo();<'+'/script>bar').extractScripts());
  178. this.assertEnumEqual(['boo();','boo();\nmoo();'],
  179. ('foo <script>boo();<'+'/script>blub\nblub<script type="text/javascript">boo();\nmoo();<'+'/script>bar').extractScripts());
  180. var russianChars = '//кПЌеМтарОй\n';
  181. var longComment = '//' + Array(7000).join('.') + '\n';
  182. var longScript = '\nvar foo = 1;\n' + russianChars + longComment;
  183. var longString = '<script type="text/javascript">'+ longScript + '<'+'/script>';
  184. this.assertEnumEqual([longScript], longString.extractScripts());
  185. this.assertEnumEqual([], ('<!--\n<script>boo();<'+'/script>\n-->').extractScripts());
  186. },
  187. testEvalScripts: function() {
  188. this.assertEqual(0, evalScriptsCounter);
  189. ('foo <script>evalScriptsCounter++<'+'/script>bar').evalScripts();
  190. this.assertEqual(1, evalScriptsCounter);
  191. var stringWithScripts = '';
  192. (3).times(function(){ stringWithScripts += 'foo <script>evalScriptsCounter++<'+'/script>bar' });
  193. stringWithScripts.evalScripts();
  194. this.assertEqual(4, evalScriptsCounter);
  195. },
  196. testEscapeHTML: function() {
  197. this.assertEqual('foo bar', 'foo bar'.escapeHTML());
  198. this.assertEqual('foo &lt;span&gt;bar&lt;/span&gt;', 'foo <span>bar</span>'.escapeHTML());
  199. this.assertEqual('foo ß bar', 'foo ß bar'.escapeHTML());
  200. this.assertEqual('ウィメンズ2007\nクルーズコレクション',
  201. 'ウィメンズ2007\nクルーズコレクション'.escapeHTML());
  202. this.assertEqual('a&lt;a href=&quot;blah&quot;&gt;blub&lt;/a&gt;b&lt;span&gt;&lt;div&gt;&lt;/div&gt;&lt;/span&gt;cdef&lt;strong&gt;!!!!&lt;/strong&gt;g',
  203. 'a<a href="blah">blub</a>b<span><div></div></span>cdef<strong>!!!!</strong>g'.escapeHTML());
  204. this.assertEqual(largeTextEscaped, largeTextUnescaped.escapeHTML());
  205. this.assertEqual('1\n2', '1\n2'.escapeHTML());
  206. this.benchmark(function() { largeTextUnescaped.escapeHTML() }, 1000);
  207. },
  208. testUnescapeHTML: function() {
  209. this.assertEqual('foo bar', 'foo bar'.unescapeHTML());
  210. this.assertEqual('foo <span>bar</span>', 'foo &lt;span&gt;bar&lt;/span&gt;'.unescapeHTML());
  211. this.assertEqual('foo ß bar', 'foo ß bar'.unescapeHTML());
  212. this.assertEqual('a<a href="blah">blub</a>b<span><div></div></span>cdef<strong>!!!!</strong>g',
  213. 'a&lt;a href="blah"&gt;blub&lt;/a&gt;b&lt;span&gt;&lt;div&gt;&lt;/div&gt;&lt;/span&gt;cdef&lt;strong&gt;!!!!&lt;/strong&gt;g'.unescapeHTML());
  214. this.assertEqual(largeTextUnescaped, largeTextEscaped.unescapeHTML());
  215. this.assertEqual('test \xfa', 'test &uacute;'.unescapeHTML());
  216. this.assertEqual('1\n2', '1\n2'.unescapeHTML());
  217. this.assertEqual('Pride & Prejudice', '<h1>Pride &amp; Prejudice</h1>'.unescapeHTML());
  218. var escapedTest = '"&lt;" means "<" in HTML';
  219. this.assertEqual(escapedTest, escapedTest.escapeHTML().unescapeHTML());
  220. this.benchmark(function() { largeTextEscaped.unescapeHTML() }, 1000);
  221. },
  222. testTemplateEvaluation: function() {
  223. var source = '<tr><td>#{name}</td><td>#{age}</td></tr>';
  224. var person = {name: 'Sam', age: 21};
  225. var template = new Template(source);
  226. this.assertEqual('<tr><td>Sam</td><td>21</td></tr>',
  227. template.evaluate(person));
  228. this.assertEqual('<tr><td></td><td></td></tr>',
  229. template.evaluate({}));
  230. },
  231. testTemplateEvaluationWithEmptyReplacement: function() {
  232. var template = new Template('##{}');
  233. this.assertEqual('#', template.evaluate({}));
  234. this.assertEqual('#', template.evaluate({foo: 'bar'}));
  235. template = new Template('#{}');
  236. this.assertEqual('', template.evaluate({}));
  237. },
  238. testTemplateEvaluationWithFalses: function() {
  239. var source = '<tr><td>#{zero}</td><td>#{false_}</td><td>#{undef}</td><td>#{null_}</td><td>#{empty}</td></tr>';
  240. var falses = {zero:0, false_:false, undef:undefined, null_:null, empty:""};
  241. var template = new Template(source);
  242. this.assertEqual('<tr><td>0</td><td>false</td><td></td><td></td><td></td></tr>',
  243. template.evaluate(falses));
  244. },
  245. testTemplateEvaluationWithNested: function() {
  246. var source = '#{name} #{manager.name} #{manager.age} #{manager.undef} #{manager.age.undef} #{colleagues.first.name}';
  247. var subject = { manager: { name: 'John', age: 29 }, name: 'Stephan', age: 22, colleagues: { first: { name: 'Mark' }} };
  248. this.assertEqual('Stephan', new Template('#{name}').evaluate(subject));
  249. this.assertEqual('John', new Template('#{manager.name}').evaluate(subject));
  250. this.assertEqual('29', new Template('#{manager.age}').evaluate(subject));
  251. this.assertEqual('', new Template('#{manager.undef}').evaluate(subject));
  252. this.assertEqual('', new Template('#{manager.age.undef}').evaluate(subject));
  253. this.assertEqual('Mark', new Template('#{colleagues.first.name}').evaluate(subject));
  254. this.assertEqual('Stephan John 29 Mark', new Template(source).evaluate(subject));
  255. },
  256. testTemplateEvaluationWithIndexing: function() {
  257. var source = '#{0} = #{[0]} - #{1} = #{[1]} - #{[2][0]} - #{[2].name} - #{first[0]} - #{[first][0]} - #{[\\]]} - #{first[\\]]}';
  258. var subject = [ 'zero', 'one', [ 'two-zero' ] ];
  259. subject[2].name = 'two-zero-name';
  260. subject.first = subject[2];
  261. subject[']'] = '\\';
  262. subject.first[']'] = 'first\\';
  263. this.assertEqual('zero', new Template('#{[0]}').evaluate(subject));
  264. this.assertEqual('one', new Template('#{[1]}').evaluate(subject));
  265. this.assertEqual('two-zero', new Template('#{[2][0]}').evaluate(subject));
  266. this.assertEqual('two-zero-name', new Template('#{[2].name}').evaluate(subject));
  267. this.assertEqual('two-zero', new Template('#{first[0]}').evaluate(subject));
  268. this.assertEqual('\\', new Template('#{[\\]]}').evaluate(subject));
  269. this.assertEqual('first\\', new Template('#{first[\\]]}').evaluate(subject));
  270. this.assertEqual('empty - empty2', new Template('#{[]} - #{m[]}').evaluate({ '': 'empty', m: {'': 'empty2'}}));
  271. this.assertEqual('zero = zero - one = one - two-zero - two-zero-name - two-zero - two-zero - \\ - first\\', new Template(source).evaluate(subject));
  272. },
  273. testTemplateToTemplateReplacements: function() {
  274. var source = 'My name is #{name}, my job is #{job}';
  275. var subject = {
  276. name: 'Stephan',
  277. getJob: function() { return 'Web developer'; },
  278. toTemplateReplacements: function() { return { name: this.name, job: this.getJob() } }
  279. };
  280. this.assertEqual('My name is Stephan, my job is Web developer', new Template(source).evaluate(subject));
  281. },
  282. testTemplateEvaluationCombined: function() {
  283. var source = '#{name} is #{age} years old, managed by #{manager.name}, #{manager.age}.\n' +
  284. 'Colleagues include #{colleagues[0].name} and #{colleagues[1].name}.';
  285. var subject = {
  286. name: 'Stephan', age: 22,
  287. manager: { name: 'John', age: 29 },
  288. colleagues: [ { name: 'Mark' }, { name: 'Indy' } ]
  289. };
  290. this.assertEqual('Stephan is 22 years old, managed by John, 29.\n' +
  291. 'Colleagues include Mark and Indy.',
  292. new Template(source).evaluate(subject));
  293. },
  294. testInterpolate: function() {
  295. var subject = { name: 'Stephan' };
  296. var pattern = /(^|.|\r|\n)(#\((.*?)\))/;
  297. this.assertEqual('#{name}: Stephan', '\\#{name}: #{name}'.interpolate(subject));
  298. this.assertEqual('#(name): Stephan', '\\#(name): #(name)'.interpolate(subject, pattern));
  299. },
  300. testToQueryParams: function() {
  301. // only the query part
  302. var result = {a:undefined, b:'c'};
  303. this.assertHashEqual({}, ''.toQueryParams(), 'empty query');
  304. this.assertHashEqual({}, 'foo?'.toQueryParams(), 'empty query with URL');
  305. this.assertHashEqual(result, 'foo?a&b=c'.toQueryParams(), 'query with URL');
  306. this.assertHashEqual(result, 'foo?a&b=c#fragment'.toQueryParams(), 'query with URL and fragment');
  307. this.assertHashEqual(result, 'a;b=c'.toQueryParams(';'), 'custom delimiter');
  308. this.assertHashEqual({a:undefined}, 'a'.toQueryParams(), 'key without value');
  309. this.assertHashEqual({a:'b'}, 'a=b&=c'.toQueryParams(), 'empty key');
  310. this.assertHashEqual({a:'b', c:''}, 'a=b&c='.toQueryParams(), 'empty value');
  311. this.assertHashEqual({'a b':'c', d:'e f', g:'h'},
  312. 'a%20b=c&d=e%20f&g=h'.toQueryParams(), 'proper decoding');
  313. this.assertHashEqual({a:'b=c=d'}, 'a=b=c=d'.toQueryParams(), 'multiple equal signs');
  314. this.assertHashEqual({a:'b', c:'d'}, '&a=b&&&c=d'.toQueryParams(), 'proper splitting');
  315. this.assertEnumEqual($w('r g b'), 'col=r&col=g&col=b'.toQueryParams()['col'],
  316. 'collection without square brackets');
  317. var msg = 'empty values inside collection';
  318. this.assertEnumEqual(['r', '', 'b'], 'c=r&c=&c=b'.toQueryParams()['c'], msg);
  319. this.assertEnumEqual(['', 'blue'], 'c=&c=blue'.toQueryParams()['c'], msg);
  320. this.assertEnumEqual(['blue', ''], 'c=blue&c='.toQueryParams()['c'], msg);
  321. },
  322. testInspect: function() {
  323. this.assertEqual('\'\'', ''.inspect());
  324. this.assertEqual('\'test\'', 'test'.inspect());
  325. this.assertEqual('\'test \\\'test\\\' "test"\'', 'test \'test\' "test"'.inspect());
  326. this.assertEqual('\"test \'test\' \\"test\\"\"', 'test \'test\' "test"'.inspect(true));
  327. this.assertEqual('\'\\b\\t\\n\\f\\r"\\\\\'', '\b\t\n\f\r"\\'.inspect());
  328. this.assertEqual('\"\\b\\t\\n\\f\\r\\"\\\\\"', '\b\t\n\f\r"\\'.inspect(true));
  329. this.assertEqual('\'\\b\\t\\n\\f\\r\'', '\x08\x09\x0a\x0c\x0d'.inspect());
  330. this.assertEqual('\'\\u001a\'', '\x1a'.inspect());
  331. },
  332. testInclude: function() {
  333. this.assert('hello world'.include('h'));
  334. this.assert('hello world'.include('hello'));
  335. this.assert('hello world'.include('llo w'));
  336. this.assert('hello world'.include('world'));
  337. this.assert(!'hello world'.include('bye'));
  338. this.assert(!''.include('bye'));
  339. },
  340. testStartsWith: function() {
  341. this.assert('hello world'.startsWith('h'));
  342. this.assert('hello world'.startsWith('hello'));
  343. this.assert(!'hello world'.startsWith('bye'));
  344. this.assert(!''.startsWith('bye'));
  345. this.assert(!'hell'.startsWith('hello'));
  346. },
  347. testEndsWith: function() {
  348. this.assert('hello world'.endsWith('d'));
  349. this.assert('hello world'.endsWith(' world'));
  350. this.assert(!'hello world'.endsWith('planet'));
  351. this.assert(!''.endsWith('planet'));
  352. this.assert('hello world world'.endsWith(' world'));
  353. this.assert(!'z'.endsWith('az'));
  354. },
  355. testBlank: function() {
  356. this.assert(''.blank());
  357. this.assert(' '.blank());
  358. this.assert('\t\r\n '.blank());
  359. this.assert(!'a'.blank());
  360. this.assert(!'\t y \n'.blank());
  361. },
  362. testEmpty: function() {
  363. this.assert(''.empty());
  364. this.assert(!' '.empty());
  365. this.assert(!'\t\r\n '.empty());
  366. this.assert(!'a'.empty());
  367. this.assert(!'\t y \n'.empty());
  368. },
  369. testSucc: function() {
  370. this.assertEqual('b', 'a'.succ());
  371. this.assertEqual('B', 'A'.succ());
  372. this.assertEqual('1', '0'.succ());
  373. this.assertEqual('abce', 'abcd'.succ());
  374. this.assertEqual('{', 'z'.succ());
  375. this.assertEqual(':', '9'.succ());
  376. },
  377. testTimes: function() {
  378. this.assertEqual('', ''.times(0));
  379. this.assertEqual('', ''.times(5));
  380. this.assertEqual('', 'a'.times(-1));
  381. this.assertEqual('', 'a'.times(0));
  382. this.assertEqual('a', 'a'.times(1));
  383. this.assertEqual('aa', 'a'.times(2));
  384. this.assertEqual('aaaaa', 'a'.times(5));
  385. this.assertEqual('foofoofoofoofoo', 'foo'.times(5));
  386. this.assertEqual('', 'foo'.times(-5));
  387. /*window.String.prototype.oldTimes = function(count) {
  388. var result = '';
  389. for (var i = 0; i < count; i++) result += this;
  390. return result;
  391. };
  392. this.benchmark(function() {
  393. 'foo'.times(15);
  394. }, 1000, 'new: ');
  395. this.benchmark(function() {
  396. 'foo'.oldTimes(15);
  397. }, 1000, 'previous: ');*/
  398. },
  399. testToJSON: function() {
  400. this.assertEqual('\"\"', ''.toJSON());
  401. this.assertEqual('\"test\"', 'test'.toJSON());
  402. },
  403. testIsJSON: function() {
  404. this.assert(!''.isJSON());
  405. this.assert(!' '.isJSON());
  406. this.assert('""'.isJSON());
  407. this.assert('"foo"'.isJSON());
  408. this.assert('{}'.isJSON());
  409. this.assert('[]'.isJSON());
  410. this.assert('null'.isJSON());
  411. this.assert('123'.isJSON());
  412. this.assert('true'.isJSON());
  413. this.assert('false'.isJSON());
  414. this.assert('"\\""'.isJSON());
  415. this.assert(!'\\"'.isJSON());
  416. this.assert(!'new'.isJSON());
  417. this.assert(!'\u0028\u0029'.isJSON());
  418. // we use '@' as a placeholder for characters authorized only inside brackets,
  419. // so this tests make sure it is not considered authorized elsewhere.
  420. this.assert(!'@'.isJSON());
  421. },
  422. testEvalJSON: function() {
  423. var valid = '{"test": \n\r"hello world!"}';
  424. var invalid = '{"test": "hello world!"';
  425. var dangerous = '{});attackTarget = "attack succeeded!";({}';
  426. // use smaller huge string size for KHTML
  427. var size = navigator.userAgent.include('KHTML') ? 20 : 100;
  428. var longString = '"' + '123456789\\"'.times(size * 10) + '"';
  429. var object = '{' + longString + ': ' + longString + '},';
  430. var huge = '[' + object.times(size) + '{"test": 123}]';
  431. this.assertEqual('hello world!', valid.evalJSON().test);
  432. this.assertEqual('hello world!', valid.evalJSON(true).test);
  433. this.assertRaise('SyntaxError', function() { invalid.evalJSON() });
  434. this.assertRaise('SyntaxError', function() { invalid.evalJSON(true) });
  435. attackTarget = "scared";
  436. dangerous.evalJSON();
  437. this.assertEqual("attack succeeded!", attackTarget);
  438. attackTarget = "Not scared!";
  439. this.assertRaise('SyntaxError', function(){dangerous.evalJSON(true)});
  440. this.assertEqual("Not scared!", attackTarget);
  441. this.assertEqual('hello world!', ('/*-secure- \r \n ' + valid + ' \n */').evalJSON().test);
  442. var temp = Prototype.JSONFilter;
  443. Prototype.JSONFilter = /^\/\*([\s\S]*)\*\/$/; // test custom delimiters.
  444. this.assertEqual('hello world!', ('/*' + valid + '*/').evalJSON().test);
  445. Prototype.JSONFilter = temp;
  446. this.assertMatch(123, huge.evalJSON(true).last().test);
  447. this.assertEqual('', '""'.evalJSON());
  448. this.assertEqual('foo', '"foo"'.evalJSON());
  449. this.assert('object', typeof '{}'.evalJSON());
  450. this.assert(Object.isArray('[]'.evalJSON()));
  451. this.assertNull('null'.evalJSON());
  452. this.assert(123, '123'.evalJSON());
  453. this.assertIdentical(true, 'true'.evalJSON());
  454. this.assertIdentical(false, 'false'.evalJSON());
  455. this.assertEqual('"', '"\\""'.evalJSON());
  456. }
  457. });