regexp-static.js revision 85b71799222b55eb5dd74ea26efe0c64ab655c8c
1// Copyright 2008 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// Test that we throw exceptions when calling test and exec with no
29// input.  This is not part of the spec, but we do it for
30// compatibility with JSC.
31assertThrows("/a/.test()");
32assertThrows("/a/.exec()");
33
34// Test that we do not throw exceptions once the static RegExp.input
35// field has been set.
36RegExp.input = "a";
37assertDoesNotThrow("/a/.test()");
38assertDoesNotThrow("/a/.exec()");
39
40// Test the (deprecated as of JS 1.5) properties of the RegExp function.
41var re = /((\d+)\.(\d+))/;
42var s = 'abc123.456def';
43
44re.exec(s);
45
46assertEquals(s, RegExp.input);
47assertEquals('123.456', RegExp.lastMatch);
48assertEquals('456', RegExp.lastParen);
49assertEquals('abc', RegExp.leftContext);
50assertEquals('def', RegExp.rightContext);
51
52assertEquals(s, RegExp['$_']);
53assertEquals('123.456', RegExp['$&']);
54assertEquals('456', RegExp['$+']);
55assertEquals('abc', RegExp['$`']);
56assertEquals('def', RegExp["$'"]);
57
58assertEquals('123.456', RegExp['$1']);
59assertEquals('123', RegExp['$2']);
60assertEquals('456', RegExp['$3']);
61for (var i = 4; i < 10; ++i) {
62  assertEquals('', RegExp['$' + i]);
63}
64
65// They should be read only.
66RegExp['$1'] = 'fisk';
67assertEquals('123.456', RegExp['$1']);
68
69// String.prototype.match and String.prototype.replace (when given a
70// regexp) and also RegExp.prototype.test should all behave as if
71// RegExp.prototype.exec were called.
72s = 'ghi789.012jkl';
73s.match(re);
74assertEquals(s, RegExp.input);
75assertEquals('789.012', RegExp.lastMatch);
76assertEquals('012', RegExp.lastParen);
77assertEquals('ghi', RegExp.leftContext);
78assertEquals('jkl', RegExp.rightContext);
79assertEquals(s, RegExp['$_']);
80assertEquals('789.012', RegExp['$&']);
81assertEquals('012', RegExp['$+']);
82assertEquals('ghi', RegExp['$`']);
83assertEquals('jkl', RegExp["$'"]);
84assertEquals('789.012', RegExp['$1']);
85assertEquals('789', RegExp['$2']);
86assertEquals('012', RegExp['$3']);
87for (var i = 4; i < 10; ++i) {
88  assertEquals('', RegExp['$' + i]);
89}
90
91s = 'abc123.456def';
92s.replace(re, 'whocares');
93assertEquals(s, RegExp.input);
94assertEquals('123.456', RegExp.lastMatch);
95assertEquals('456', RegExp.lastParen);
96assertEquals('abc', RegExp.leftContext);
97assertEquals('def', RegExp.rightContext);
98assertEquals(s, RegExp['$_']);
99assertEquals('123.456', RegExp['$&']);
100assertEquals('456', RegExp['$+']);
101assertEquals('abc', RegExp['$`']);
102assertEquals('def', RegExp["$'"]);
103assertEquals('123.456', RegExp['$1']);
104assertEquals('123', RegExp['$2']);
105assertEquals('456', RegExp['$3']);
106for (var i = 4; i < 10; ++i) {
107  assertEquals('', RegExp['$' + i]);
108}
109
110s = 'ghi789.012jkl';
111re.test(s);
112assertEquals(s, RegExp.input);
113assertEquals('789.012', RegExp.lastMatch);
114assertEquals('012', RegExp.lastParen);
115assertEquals('ghi', RegExp.leftContext);
116assertEquals('jkl', RegExp.rightContext);
117assertEquals(s, RegExp['$_']);
118assertEquals('789.012', RegExp['$&']);
119assertEquals('012', RegExp['$+']);
120assertEquals('ghi', RegExp['$`']);
121assertEquals('jkl', RegExp["$'"]);
122assertEquals('789.012', RegExp['$1']);
123assertEquals('789', RegExp['$2']);
124assertEquals('012', RegExp['$3']);
125for (var i = 4; i < 10; ++i) {
126  assertEquals('', RegExp['$' + i]);
127}
128
129// String.prototype.replace must interleave matching and replacing when a
130// global regexp is matched and replaced with the result of a function, in
131// case the function uses the static properties of the regexp constructor.
132re = /(.)/g;
133function f() { return RegExp.$1; };
134assertEquals('abcd', 'abcd'.replace(re, f));
135
136// lastParen where the last parenthesis didn't match.
137assertEquals(["foo",undefined], /foo(?:a(x))?/.exec("foobx"),
138             "lastParen setup");
139assertEquals("", RegExp.lastParen, "lastParen");
140
141// The same test for $1 to $9.
142for (var i = 1; i <= 9; i++) {
143  var haystack = "foo";
144  var re_text = "^foo";
145  for (var j = 0; j < i - 1; j++) {
146    haystack += "x";
147    re_text += "(x)";
148  }
149  re_text += "(?:a(x))?";
150  haystack += "bx";
151  var re = new RegExp(re_text);
152  assertTrue(re.test(haystack), "$" + i + " setup");
153  for (var j = 1; j < i - 1; j++) {
154    assertEquals("x", RegExp['$' + j], "$" + j + " in $" + i + " setup");
155  }
156  assertEquals("", RegExp['$' + (i)], "$" + i);
157}
158
159RegExp.multiline = "foo";
160assertTrue(typeof RegExp.multiline == typeof Boolean(), "RegExp.multiline coerces values to booleans");
161RegExp.input = Number();
162assertTrue(typeof RegExp.input == typeof String(), "RegExp.input coerces values to booleans");
163
164// Ensure that we save the correct string as the last subject when
165// we do a match on a sliced string (the top one not the underlying).
166var foo = "lsdfj sldkfj sdklfj læsdfjl sdkfjlsdk fjsdl fjsdljskdj flsj flsdkj flskd regexp: /foobar/\nldkfj sdlkfj sdkl";
167assertTrue(/^([a-z]+): (.*)/.test(foo.substring(foo.indexOf("regexp:"))), "regexp: setup");
168assertEquals("regexp", RegExp.$1, "RegExp.$1");
169