1// Copyright 2009 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28/** 29 * @fileoverview Test String.prototype.replace 30 */ 31 32function replaceTest(result, subject, pattern, replacement) { 33 var name = 34 "\"" + subject + "\".replace(" + pattern + ", " + replacement + ")"; 35 assertEquals(result, subject.replace(pattern, replacement), name); 36} 37 38 39var short = "xaxbxcx"; 40 41replaceTest("axbxcx", short, "x", ""); 42replaceTest("axbxcx", short, /x/, ""); 43replaceTest("abc", short, /x/g, ""); 44 45replaceTest("xaxxcx", short, "b", ""); 46replaceTest("xaxxcx", short, /b/, ""); 47replaceTest("xaxxcx", short, /b/g, ""); 48 49 50replaceTest("[]axbxcx", short, "x", "[]"); 51replaceTest("[]axbxcx", short, /x/, "[]"); 52replaceTest("[]a[]b[]c[]", short, /x/g, "[]"); 53 54replaceTest("xax[]xcx", short, "b", "[]"); 55replaceTest("xax[]xcx", short, /b/, "[]"); 56replaceTest("xax[]xcx", short, /b/g, "[]"); 57 58 59replaceTest("[$]axbxcx", short, "x", "[$$]"); 60replaceTest("[$]axbxcx", short, /x/, "[$$]"); 61replaceTest("[$]a[$]b[$]c[$]", short, /x/g, "[$$]"); 62 63replaceTest("xax[$]xcx", short, "b", "[$$]"); 64replaceTest("xax[$]xcx", short, /b/, "[$$]"); 65replaceTest("xax[$]xcx", short, /b/g, "[$$]"); 66 67 68replaceTest("[]axbxcx", short, "x", "[$`]"); 69replaceTest("[]axbxcx", short, /x/, "[$`]"); 70replaceTest("[]a[xa]b[xaxb]c[xaxbxc]", short, /x/g, "[$`]"); 71 72replaceTest("xax[xax]xcx", short, "b", "[$`]"); 73replaceTest("xax[xax]xcx", short, /b/, "[$`]"); 74replaceTest("xax[xax]xcx", short, /b/g, "[$`]"); 75 76 77replaceTest("[x]axbxcx", short, "x", "[$&]"); 78replaceTest("[x]axbxcx", short, /x/, "[$&]"); 79replaceTest("[x]a[x]b[x]c[x]", short, /x/g, "[$&]"); 80 81replaceTest("xax[b]xcx", short, "b", "[$&]"); 82replaceTest("xax[b]xcx", short, /b/, "[$&]"); 83replaceTest("xax[b]xcx", short, /b/g, "[$&]"); 84 85 86replaceTest("[axbxcx]axbxcx", short, "x", "[$']"); 87replaceTest("[axbxcx]axbxcx", short, /x/, "[$']"); 88replaceTest("[axbxcx]a[bxcx]b[cx]c[]", short, /x/g, "[$']"); 89 90replaceTest("xax[xcx]xcx", short, "b", "[$']"); 91replaceTest("xax[xcx]xcx", short, /b/, "[$']"); 92replaceTest("xax[xcx]xcx", short, /b/g, "[$']"); 93 94 95replaceTest("[$1]axbxcx", short, "x", "[$1]"); 96replaceTest("[$1]axbxcx", short, /x/, "[$1]"); 97replaceTest("[]axbxcx", short, /x()/, "[$1]"); 98replaceTest("[$1]a[$1]b[$1]c[$1]", short, /x/g, "[$1]"); 99replaceTest("[]a[]b[]c[]", short, /x()/g, "[$1]"); 100 101replaceTest("xax[$1]xcx", short, "b", "[$1]"); 102replaceTest("xax[$1]xcx", short, /b/, "[$1]"); 103replaceTest("xax[]xcx", short, /b()/, "[$1]"); 104replaceTest("xax[$1]xcx", short, /b/g, "[$1]"); 105replaceTest("xax[]xcx", short, /b()/g, "[$1]"); 106 107// Bug 317 look-alikes. If "$e" has no meaning, the "$" must be retained. 108replaceTest("xax$excx", short, "b", "$e"); 109replaceTest("xax$excx", short, /b/, "$e"); 110replaceTest("xax$excx", short, /b/g, "$e"); 111 112replaceTest("xaxe$xcx", short, "b", "e$"); 113replaceTest("xaxe$xcx", short, /b/, "e$"); 114replaceTest("xaxe$xcx", short, /b/g, "e$"); 115 116 117replaceTest("[$$$1$$a1abb1bb0$002$3$03][$$$1$$b1bcc1cc0$002$3$03]c", 118 "abc", /(.)(?=(.))/g, "[$$$$$$1$$$$$11$01$2$21$02$020$002$3$03]"); 119 120// Replace with functions. 121 122 123var ctr = 0; 124replaceTest("0axbxcx", short, "x", function r(m, i, s) { 125 assertEquals(3, arguments.length, "replace('x',func) func-args"); 126 assertEquals("x", m, "replace('x',func(m,..))"); 127 assertEquals(0, i, "replace('x',func(..,i,..))"); 128 assertEquals(short, s, "replace('x',func(..,s))"); 129 return String(ctr++); 130}); 131assertEquals(1, ctr, "replace('x',func) num-match"); 132 133ctr = 0; 134replaceTest("0axbxcx", short, /x/, function r(m, i, s) { 135 assertEquals(3, arguments.length, "replace(/x/,func) func-args"); 136 assertEquals("x", m, "replace(/x/,func(m,..))"); 137 assertEquals(0, i, "replace(/x/,func(..,i,..))"); 138 assertEquals(short, s, "replace(/x/,func(..,s))"); 139 return String(ctr++); 140}); 141assertEquals(1, ctr, "replace(/x/,func) num-match"); 142 143ctr = 0; 144replaceTest("0a1b2c3", short, /x/g, function r(m, i, s) { 145 assertEquals(3, arguments.length, "replace(/x/g,func) func-args"); 146 assertEquals("x", m, "replace(/x/g,func(m,..))"); 147 assertEquals(ctr * 2, i, "replace(/x/g,func(..,i,.))"); 148 assertEquals(short, s, "replace(/x/g,func(..,s))"); 149 return String(ctr++); 150}); 151assertEquals(4, ctr, "replace(/x/g,func) num-match"); 152 153ctr = 0; 154replaceTest("0a1b2cx", short, /(x)(?=(.))/g, function r(m, c1, c2, i, s) { 155 assertEquals(5, arguments.length, "replace(/(x)(?=(.))/g,func) func-args"); 156 assertEquals("x", m, "replace(/(x)(?=(.))/g,func(m,..))"); 157 assertEquals("x", c1, "replace(/(x)(?=(.))/g,func(..,c1,..))"); 158 assertEquals(["a","b","c"][ctr], c2, "replace(/(x)(?=(.))/g,func(..,c2,..))"); 159 assertEquals(ctr * 2, i, "replace(/(x)(?=(.))/g,func(..,i,..))"); 160 assertEquals(short, s, "replace(/(x)(?=(.))/g,func(..,s))"); 161 return String(ctr++); 162}); 163assertEquals(3, ctr, "replace(/x/g,func) num-match"); 164 165 166// Test special cases of replacement parts longer than 1<<11. 167var longstring = "xyzzy"; 168longstring = longstring + longstring; 169longstring = longstring + longstring; 170longstring = longstring + longstring; 171longstring = longstring + longstring; 172longstring = longstring + longstring; 173longstring = longstring + longstring; 174longstring = longstring + longstring; 175longstring = longstring + longstring; 176longstring = longstring + longstring; 177longstring = longstring + longstring; 178longstring = longstring + longstring; 179// longstring.length == 5 << 11 180 181replaceTest(longstring + longstring, 182 "<" + longstring + ">", /<(.*)>/g, "$1$1"); 183 184replaceTest("string 42", "string x", /x/g, function() { return 42; }); 185replaceTest("string 42", "string x", /x/, function() { return 42; }); 186replaceTest("string 42", "string x", /[xy]/g, function() { return 42; }); 187replaceTest("string 42", "string x", /[xy]/, function() { return 42; }); 188replaceTest("string true", "string x", /x/g, function() { return true; }); 189replaceTest("string null", "string x", /x/g, function() { return null; }); 190replaceTest("string undefined", "string x", /x/g, function() { return undefined; }); 191 192replaceTest("aundefinedbundefinedcundefined", 193 "abc", /(.)|(.)/g, function(m, m1, m2, i, s) { return m1+m2; }); 194 195// Test nested calls to replace, including that it sets RegExp.$& correctly. 196 197function replacer(m,i,s) { 198 assertEquals(m,RegExp['$&']); 199 return "[" + RegExp['$&'] + "-" 200 + m.replace(/./g,"$&$&") + "-" 201 + m.replace(/./g,function() { return RegExp['$&']; }) 202 + "-" + RegExp['$&'] + "]"; 203} 204 205replaceTest("[ab-aabb-ab-b][az-aazz-az-z]", 206 "abaz", /a./g, replacer); 207 208replaceTest("[ab-aabb-ab-b][az-aazz-az-z]", 209 "abaz", /a(.)/g, replacer); 210 211var str = 'She sells seashells by the seashore.'; 212var re = /sh/g; 213assertEquals('She sells sea$schells by the sea$schore.', 214 str.replace(re,"$$" + 'sch')) 215