1// Copyright 2013 the V8 project authors. All rights reserved. 2// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions 6// are met: 7// 1. Redistributions of source code must retain the above copyright 8// notice, this list of conditions and the following disclaimer. 9// 2. Redistributions in binary form must reproduce the above copyright 10// notice, this list of conditions and the following disclaimer in the 11// documentation and/or other materials provided with the distribution. 12// 13// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 24description("This page tests handling of parentheses subexpressions."); 25 26var regexp1 = /(a|A)(b|B)/; 27shouldBe("regexp1.exec('abc')", "['ab','a','b']"); 28 29var regexp2 = /(a((b)|c|d))e/; 30shouldBe("regexp2.exec('abacadabe')", "['abe','ab','b','b']"); 31 32var regexp3 = /(a(b|(c)|d))e/; 33shouldBe("regexp3.exec('abacadabe')", "['abe','ab','b',undefined]"); 34 35var regexp4 = /(a(b|c|(d)))e/; 36shouldBe("regexp4.exec('abacadabe')", "['abe','ab','b',undefined]"); 37 38var regexp5 = /(a((b)|(c)|(d)))e/; 39shouldBe("regexp5.exec('abacadabe')", "['abe','ab','b','b',undefined,undefined]"); 40 41var regexp6 = /(a((b)|(c)|(d)))/; 42shouldBe("regexp6.exec('abcde')", "['ab','ab','b','b',undefined,undefined]"); 43 44var regexp7 = /(a(b)??)??c/; 45shouldBe("regexp7.exec('abc')", "['abc','ab','b']"); 46 47var regexp8 = /(a|(e|q))(x|y)/; 48shouldBe("regexp8.exec('bcaddxqy')" , "['qy','q','q','y']"); 49 50var regexp9 = /((t|b)?|a)$/; 51shouldBe("regexp9.exec('asdfjejgsdflaksdfjkeljghkjea')", "['a','a',undefined]"); 52 53var regexp10 = /(?:h|e?(?:t|b)?|a?(?:t|b)?)(?:$)/; 54shouldBe("regexp10.exec('asdfjejgsdflaksdfjkeljghat')", "['at']"); 55 56var regexp11 = /([Jj]ava([Ss]cript)?)\sis\s(fun\w*)/; 57shouldBeNull("regexp11.exec('Developing with JavaScript is dangerous, do not try it without assistance')"); 58 59var regexp12 = /(?:(.+), )?(.+), (..) to (?:(.+), )?(.+), (..)/; 60shouldBe("regexp12.exec('Seattle, WA to Buckley, WA')", "['Seattle, WA to Buckley, WA', undefined, 'Seattle', 'WA', undefined, 'Buckley', 'WA']"); 61 62var regexp13 = /(A)?(A.*)/; 63shouldBe("regexp13.exec('zxcasd;fl\ ^AaaAAaaaf;lrlrzs')", "['AaaAAaaaf;lrlrzs',undefined,'AaaAAaaaf;lrlrzs']"); 64 65var regexp14 = /(a)|(b)/; 66shouldBe("regexp14.exec('b')", "['b',undefined,'b']"); 67 68var regexp15 = /^(?!(ab)de|x)(abd)(f)/; 69shouldBe("regexp15.exec('abdf')", "['abdf',undefined,'abd','f']"); 70 71var regexp16 = /(a|A)(b|B)/; 72shouldBe("regexp16.exec('abc')", "['ab','a','b']"); 73 74var regexp17 = /(a|d|q|)x/i; 75shouldBe("regexp17.exec('bcaDxqy')", "['Dx','D']"); 76 77var regexp18 = /^.*?(:|$)/; 78shouldBe("regexp18.exec('Hello: World')", "['Hello:',':']"); 79 80var regexp19 = /(ab|^.{0,2})bar/; 81shouldBe("regexp19.exec('barrel')", "['bar','']"); 82 83var regexp20 = /(?:(?!foo)...|^.{0,2})bar(.*)/; 84shouldBe("regexp20.exec('barrel')", "['barrel','rel']"); 85shouldBe("regexp20.exec('2barrel')", "['2barrel','rel']"); 86 87var regexp21 = /([a-g](b|B)|xyz)/; 88shouldBe("regexp21.exec('abc')", "['ab','ab','b']"); 89 90var regexp22 = /(?:^|;)\s*abc=([^;]*)/; 91shouldBeNull("regexp22.exec('abcdlskfgjdslkfg')"); 92 93var regexp23 = /"[^<"]*"|'[^<']*'/; 94shouldBe("regexp23.exec('<html xmlns=\"http://www.w3.org/1999/xhtml\"')", "['\"http://www.w3.org/1999/xhtml\"']"); 95 96var regexp24 = /^(?:(?=abc)\w{3}:|\d\d)$/; 97shouldBeNull("regexp24.exec('123')"); 98 99var regexp25 = /^\s*(\*|[\w\-]+)(\b|$)?/; 100shouldBe("regexp25.exec('this is a test')", "['this','this',undefined]"); 101shouldBeNull("regexp25.exec('!this is a test')"); 102 103var regexp26 = /a(b)(a*)|aaa/; 104shouldBe("regexp26.exec('aaa')", "['aaa',undefined,undefined]"); 105 106var regexp27 = new RegExp( 107 "^" + 108 "(?:" + 109 "([^:/?#]+):" + /* scheme */ 110 ")?" + 111 "(?:" + 112 "(//)" + /* authorityRoot */ 113 "(" + /* authority */ 114 "(?:" + 115 "(" + /* userInfo */ 116 "([^:@]*)" + /* user */ 117 ":?" + 118 "([^:@]*)" + /* password */ 119 ")?" + 120 "@" + 121 ")?" + 122 "([^:/?#]*)" + /* domain */ 123 "(?::(\\d*))?" + /* port */ 124 ")" + 125 ")?" + 126 "([^?#]*)" + /*path*/ 127 "(?:\\?([^#]*))?" + /* queryString */ 128 "(?:#(.*))?" /*fragment */ 129); 130shouldBe("regexp27.exec('file:///Users/Someone/Desktop/HelloWorld/index.html')", "['file:///Users/Someone/Desktop/HelloWorld/index.html','file','//','',undefined,undefined,undefined,'',undefined,'/Users/Someone/Desktop/HelloWorld/index.html',undefined,undefined]"); 131 132var regexp28 = new RegExp( 133 "^" + 134 "(?:" + 135 "([^:/?#]+):" + /* scheme */ 136 ")?" + 137 "(?:" + 138 "(//)" + /* authorityRoot */ 139 "(" + /* authority */ 140 "(" + /* userInfo */ 141 "([^:@]*)" + /* user */ 142 ":?" + 143 "([^:@]*)" + /* password */ 144 ")?" + 145 "@" + 146 ")" + 147 ")?" 148); 149shouldBe("regexp28.exec('file:///Users/Someone/Desktop/HelloWorld/index.html')", "['file:','file',undefined,undefined,undefined,undefined,undefined]"); 150 151var regexp29 = /^\s*((\[[^\]]+\])|(u?)("[^"]+"))\s*/; 152shouldBeNull("regexp29.exec('Committer:')"); 153 154var regexp30 = /^\s*((\[[^\]]+\])|m(u?)("[^"]+"))\s*/; 155shouldBeNull("regexp30.exec('Committer:')"); 156 157var regexp31 = /^\s*(m(\[[^\]]+\])|m(u?)("[^"]+"))\s*/; 158shouldBeNull("regexp31.exec('Committer:')"); 159 160var regexp32 = /\s*(m(\[[^\]]+\])|m(u?)("[^"]+"))\s*/; 161shouldBeNull("regexp32.exec('Committer:')"); 162 163var regexp33 = RegExp('^(?:(?:(a)(xyz|[^>"\'\s]*)?)|(/?>)|.[^\w\s>]*)'); 164shouldBe("regexp33.exec('> <head>')","['>',undefined,undefined,'>']"); 165 166var regexp34 = /(?:^|\b)btn-\S+/; 167shouldBeNull("regexp34.exec('xyz123')"); 168shouldBe("regexp34.exec('btn-abc')","['btn-abc']"); 169shouldBeNull("regexp34.exec('btn- abc')"); 170shouldBeNull("regexp34.exec('XXbtn-abc')"); 171shouldBe("regexp34.exec('XX btn-abc')","['btn-abc']"); 172 173var regexp35 = /^((a|b)(x|xxx)|)$/; 174shouldBe("regexp35.exec('ax')", "['ax','ax','a','x']"); 175shouldBeNull("regexp35.exec('axx')"); 176shouldBe("regexp35.exec('axxx')", "['axxx','axxx','a','xxx']"); 177shouldBe("regexp35.exec('bx')", "['bx','bx','b','x']"); 178shouldBeNull("regexp35.exec('bxx')"); 179shouldBe("regexp35.exec('bxxx')", "['bxxx','bxxx','b','xxx']"); 180 181var regexp36 = /^((\/|\.|\-)(\d\d|\d\d\d\d)|)$/; 182shouldBe("regexp36.exec('/2011')", "['/2011','/2011','/','2011']"); 183shouldBe("regexp36.exec('/11')", "['/11','/11','/','11']"); 184shouldBeNull("regexp36.exec('/123')"); 185 186var regexp37 = /^([1][0-2]|[0]\d|\d)(\/|\.|\-)([0-2]\d|[3][0-1]|\d)((\/|\.|\-)(\d\d|\d\d\d\d)|)$/; 187shouldBe("regexp37.exec('7/4/1776')", "['7/4/1776','7','/','4','/1776','/','1776']"); 188shouldBe("regexp37.exec('07-04-1776')", "['07-04-1776','07','-','04','-1776','-','1776']"); 189 190var regexp38 = /^(z|(x|xx)|b|)$/; 191shouldBe("regexp38.exec('xx')", "['xx','xx','xx']"); 192shouldBe("regexp38.exec('b')", "['b','b',undefined]"); 193shouldBe("regexp38.exec('z')", "['z','z',undefined]"); 194shouldBe("regexp38.exec('')", "['','',undefined]"); 195 196var regexp39 = /(8|((?=P)))?/; 197shouldBe("regexp39.exec('')", "['',undefined,undefined]"); 198shouldBe("regexp39.exec('8')", "['8','8',undefined]"); 199shouldBe("regexp39.exec('zP')", "['',undefined,undefined]"); 200 201var regexp40 = /((8)|((?=P){4}))?()/; 202shouldBe("regexp40.exec('')", "['',undefined,undefined,undefined,'']"); 203shouldBe("regexp40.exec('8')", "['8','8','8',undefined,'']"); 204shouldBe("regexp40.exec('zPz')", "['',undefined,undefined,undefined,'']"); 205shouldBe("regexp40.exec('zPPz')", "['',undefined,undefined,undefined,'']"); 206shouldBe("regexp40.exec('zPPPz')", "['',undefined,undefined,undefined,'']"); 207shouldBe("regexp40.exec('zPPPPz')", "['',undefined,undefined,undefined,'']"); 208 209var regexp41 = /(([\w\-]+:\/\/?|www[.])[^\s()<>]+(?:([\w\d]+)|([^\[:punct:\]\s()<>\W]|\/)))/; 210shouldBe("regexp41.exec('Here is a link: http://www.acme.com/our_products/index.html. That is all we want!')", "['http://www.acme.com/our_products/index.html','http://www.acme.com/our_products/index.html','http://','l',undefined]"); 211 212var regexp42 = /((?:(4)?))?/; 213shouldBe("regexp42.exec('')", "['',undefined,undefined]"); 214shouldBe("regexp42.exec('4')", "['4','4','4']"); 215shouldBe("regexp42.exec('4321')", "['4','4','4']"); 216 217shouldBeTrue("/(?!(?=r{0}){2,})|((z)?)?/gi.test('')"); 218 219var regexp43 = /(?!(?:\1+s))/; 220shouldBe("regexp43.exec('SSS')", "['']"); 221 222var regexp44 = /(?!(?:\3+(s+?)))/g; 223shouldBe("regexp44.exec('SSS')", "['',undefined]"); 224 225var regexp45 = /((?!(?:|)v{2,}|))/; 226shouldBeNull("regexp45.exec('vt')"); 227 228var regexp46 = /(w)(?:5{3}|())|pk/; 229shouldBeNull("regexp46.exec('5')"); 230shouldBe("regexp46.exec('pk')", "['pk',undefined,undefined]"); 231shouldBe("regexp46.exec('Xw555')", "['w555','w',undefined]"); 232shouldBe("regexp46.exec('Xw55pk5')", "['w','w','']"); 233 234var regexp47 = /(.*?)(?:(?:\?(.*?)?)?)(?:(?:#)?)$/; 235shouldBe("regexp47.exec('/www.acme.com/this/is/a/path/file.txt')", "['/www.acme.com/this/is/a/path/file.txt','/www.acme.com/this/is/a/path/file.txt',undefined]"); 236 237var regexp48 = /^(?:(\w+):\/*([\w\.\-\d]+)(?::(\d+)|)(?=(?:\/|$))|)(?:$|\/?(.*?)(?:\?(.*?)?|)(?:#(.*)|)$)/; 238/* The regexp on the prior line confuses Xcode syntax highlighting, this coment fixes it! */ 239shouldBe("regexp48.exec('http://www.acme.com/this/is/a/path/file.txt')", "['http://www.acme.com/this/is/a/path/file.txt','http','www.acme.com',undefined,'this/is/a/path/file.txt',undefined,undefined]"); 240 241var regexp49 = /(?:([^:]*?)(?:(?:\?(.*?)?)?)(?:(?:#)?)$)|(?:^(?:(\w+):\/*([\w\.\-\d]+)(?::(\d+)|)(?=(?:\/|$))|)(?:$|\/?(.*?)(?:\?(.*?)?|)(?:#(.*)|)$))/; 242/* The regexp on the prior line confuses Xcode syntax highlighting, this coment fixes it! */ 243shouldBe("regexp49.exec('http://www.acme.com/this/is/a/path/file.txt')", "['http://www.acme.com/this/is/a/path/file.txt',undefined,undefined,'http','www.acme.com',undefined,'this/is/a/path/file.txt',undefined,undefined]"); 244 245var regexp50 = /((a)b{28,}c|d)x/; 246shouldBeNull("regexp50.exec('((a)b{28,}c|d)x')"); 247shouldBe("regexp50.exec('abbbbbbbbbbbbbbbbbbbbbbbbbbbbcx')", "['abbbbbbbbbbbbbbbbbbbbbbbbbbbbcx', 'abbbbbbbbbbbbbbbbbbbbbbbbbbbbc', 'a']"); 248shouldBe("regexp50.exec('dx')", "['dx', 'd', undefined]"); 249 250var s = "((.\s{-}).{28,}\P{Yi}?{,30}\|.)\x9e{-,}\P{Any}"; 251var regexp51 = new RegExp(s); 252shouldBeNull("regexp51.exec('abc')"); 253shouldBe("regexp51.exec(s)", "[')\x9e{-,}P{Any}',')',undefined]"); 254 255var regexp52 = /(Rob)|(Bob)|(Robert)|(Bobby)/; 256shouldBe("'Hi Bob'.match(regexp52)", "['Bob',undefined,'Bob',undefined,undefined]"); 257 258// Test cases discovered by fuzzing that crashed the compiler. 259var regexp53 = /(?=(?:(?:(gB)|(?!cs|<))((?=(?!v6){0,})))|(?=#)+?)/m; 260shouldBe("regexp53.exec('#')", "['',undefined,'']"); 261var regexp54 = /((?:(?:()|(?!))((?=(?!))))|())/m; 262shouldBe("regexp54.exec('#')", "['','',undefined,undefined,'']"); 263var regexp55 = /(?:(?:(?:a?|(?:))((?:)))|a?)/m; 264shouldBe("regexp55.exec('#')", "['','']"); 265 266// Test evaluation order of empty subpattern alternatives. 267var regexp56 = /(|a)/; 268shouldBe("regexp56.exec('a')", "['','']"); 269var regexp57 = /(a|)/; 270shouldBe("regexp57.exec('a')", "['a','a']"); 271 272// Tests that non-greedy repeat quantified parentheses will backtrack through multiple frames of subpattern matches. 273var regexp58 = /a|b(?:[^b])*?c/; 274shouldBe("regexp58.exec('badbc')", "['a']"); 275var regexp59 = /(X(?:.(?!X))*?Y)|(Y(?:.(?!Y))*?Z)/g; 276shouldBe("'Y aaa X Match1 Y aaa Y Match2 Z'.match(regexp59)", "['X Match1 Y','Y Match2 Z']"); 277