Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: src/regexp.js

Issue 6580038: [Isolates] Merge from bleeding_edge, revisions 5934-6100. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/property.cc ('k') | src/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 // Expect $Object = global.Object; 28 // Expect $Object = global.Object;
29 // Expect $Array = global.Array; 29 // Expect $Array = global.Array;
30 30
31 const $RegExp = global.RegExp; 31 const $RegExp = global.RegExp;
32 32
33 // A recursive descent parser for Patterns according to the grammar of 33 // A recursive descent parser for Patterns according to the grammar of
34 // ECMA-262 15.10.1, with deviations noted below. 34 // ECMA-262 15.10.1, with deviations noted below.
35 function DoConstructRegExp(object, pattern, flags, isConstructorCall) { 35 function DoConstructRegExp(object, pattern, flags) {
36 // RegExp : Called as constructor; see ECMA-262, section 15.10.4. 36 // RegExp : Called as constructor; see ECMA-262, section 15.10.4.
37 if (IS_REGEXP(pattern)) { 37 if (IS_REGEXP(pattern)) {
38 if (!IS_UNDEFINED(flags)) { 38 if (!IS_UNDEFINED(flags)) {
39 throw MakeTypeError('regexp_flags', []); 39 throw MakeTypeError('regexp_flags', []);
40 } 40 }
41 flags = (pattern.global ? 'g' : '') 41 flags = (pattern.global ? 'g' : '')
42 + (pattern.ignoreCase ? 'i' : '') 42 + (pattern.ignoreCase ? 'i' : '')
43 + (pattern.multiline ? 'm' : ''); 43 + (pattern.multiline ? 'm' : '');
44 pattern = pattern.source; 44 pattern = pattern.source;
45 } 45 }
(...skipping 27 matching lines...) Expand all
73 73
74 %RegExpInitializeObject(object, pattern, global, ignoreCase, multiline); 74 %RegExpInitializeObject(object, pattern, global, ignoreCase, multiline);
75 75
76 // Call internal function to compile the pattern. 76 // Call internal function to compile the pattern.
77 %RegExpCompile(object, pattern, flags); 77 %RegExpCompile(object, pattern, flags);
78 } 78 }
79 79
80 80
81 function RegExpConstructor(pattern, flags) { 81 function RegExpConstructor(pattern, flags) {
82 if (%_IsConstructCall()) { 82 if (%_IsConstructCall()) {
83 DoConstructRegExp(this, pattern, flags, true); 83 DoConstructRegExp(this, pattern, flags);
84 } else { 84 } else {
85 // RegExp : Called as function; see ECMA-262, section 15.10.3.1. 85 // RegExp : Called as function; see ECMA-262, section 15.10.3.1.
86 if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) { 86 if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) {
87 return pattern; 87 return pattern;
88 } 88 }
89 return new $RegExp(pattern, flags); 89 return new $RegExp(pattern, flags);
90 } 90 }
91 } 91 }
92 92
93 93
94 // Deprecated RegExp.prototype.compile method. We behave like the constructor 94 // Deprecated RegExp.prototype.compile method. We behave like the constructor
95 // were called again. In SpiderMonkey, this method returns the regexp object. 95 // were called again. In SpiderMonkey, this method returns the regexp object.
96 // In JSC, it returns undefined. For compatibility with JSC, we match their 96 // In JSC, it returns undefined. For compatibility with JSC, we match their
97 // behavior. 97 // behavior.
98 function CompileRegExp(pattern, flags) { 98 function CompileRegExp(pattern, flags) {
99 // Both JSC and SpiderMonkey treat a missing pattern argument as the 99 // Both JSC and SpiderMonkey treat a missing pattern argument as the
100 // empty subject string, and an actual undefined value passed as the 100 // empty subject string, and an actual undefined value passed as the
101 // pattern as the string 'undefined'. Note that JSC is inconsistent 101 // pattern as the string 'undefined'. Note that JSC is inconsistent
102 // here, treating undefined values differently in 102 // here, treating undefined values differently in
103 // RegExp.prototype.compile and in the constructor, where they are 103 // RegExp.prototype.compile and in the constructor, where they are
104 // the empty string. For compatibility with JSC, we match their 104 // the empty string. For compatibility with JSC, we match their
105 // behavior. 105 // behavior.
106 if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) { 106 if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) {
107 DoConstructRegExp(this, 'undefined', flags, false); 107 DoConstructRegExp(this, 'undefined', flags);
108 } else { 108 } else {
109 DoConstructRegExp(this, pattern, flags, false); 109 DoConstructRegExp(this, pattern, flags);
110 } 110 }
111 } 111 }
112 112
113 113
114 function DoRegExpExec(regexp, string, index) { 114 function DoRegExpExec(regexp, string, index) {
115 var result = %_RegExpExec(regexp, string, index, lastMatchInfo); 115 var result = %_RegExpExec(regexp, string, index, lastMatchInfo);
116 if (result !== null) lastMatchInfoOverride = null; 116 if (result !== null) lastMatchInfoOverride = null;
117 return result; 117 return result;
118 } 118 }
119 119
120 120
121 function BuildResultFromMatchInfo(lastMatchInfo, s) { 121 function BuildResultFromMatchInfo(lastMatchInfo, s) {
122 var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1; 122 var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
123 var result = %_RegExpConstructResult(numResults, lastMatchInfo[CAPTURE0], s); 123 var start = lastMatchInfo[CAPTURE0];
124 if (numResults === 1) { 124 var end = lastMatchInfo[CAPTURE1];
125 var matchStart = lastMatchInfo[CAPTURE(0)]; 125 var result = %_RegExpConstructResult(numResults, start, s);
126 var matchEnd = lastMatchInfo[CAPTURE(1)]; 126 if (start + 1 == end) {
127 result[0] = SubString(s, matchStart, matchEnd); 127 result[0] = %_StringCharAt(s, start);
128 } else { 128 } else {
129 for (var i = 0; i < numResults; i++) { 129 result[0] = %_SubString(s, start, end);
130 var matchStart = lastMatchInfo[CAPTURE(i << 1)]; 130 }
131 var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)]; 131 var j = REGEXP_FIRST_CAPTURE + 2;
132 if (matchStart != -1 && matchEnd != -1) { 132 for (var i = 1; i < numResults; i++) {
133 result[i] = SubString(s, matchStart, matchEnd); 133 start = lastMatchInfo[j++];
134 end = lastMatchInfo[j++];
135 if (end != -1) {
136 if (start + 1 == end) {
137 result[i] = %_StringCharAt(s, start);
134 } else { 138 } else {
135 // Make sure the element is present. Avoid reading the undefined 139 result[i] = %_SubString(s, start, end);
136 // property from the global object since this may change.
137 result[i] = void 0;
138 } 140 }
141 } else {
142 // Make sure the element is present. Avoid reading the undefined
143 // property from the global object since this may change.
144 result[i] = void 0;
139 } 145 }
140 } 146 }
141 return result; 147 return result;
142 } 148 }
143 149
144 150
145 function RegExpExecNoTests(regexp, string, start) { 151 function RegExpExecNoTests(regexp, string, start) {
146 // Must be called with RegExp, string and positive integer as arguments. 152 // Must be called with RegExp, string and positive integer as arguments.
147 var matchInfo = DoRegExpExec(regexp, string, start); 153 var matchInfo = %_RegExpExec(regexp, string, start, lastMatchInfo);
148 var result = null;
149 if (matchInfo !== null) { 154 if (matchInfo !== null) {
150 result = BuildResultFromMatchInfo(matchInfo, string); 155 lastMatchInfoOverride = null;
156 return BuildResultFromMatchInfo(matchInfo, string);
151 } 157 }
152 return result; 158 return null;
153 } 159 }
154 160
155 161
156 function RegExpExec(string) { 162 function RegExpExec(string) {
157 if (!IS_REGEXP(this)) { 163 if (!IS_REGEXP(this)) {
158 throw MakeTypeError('incompatible_method_receiver', 164 throw MakeTypeError('incompatible_method_receiver',
159 ['RegExp.prototype.exec', this]); 165 ['RegExp.prototype.exec', this]);
160 } 166 }
161 167
162 if (%_ArgumentsLength() === 0) { 168 if (%_ArgumentsLength() === 0) {
163 var regExpInput = LAST_INPUT(lastMatchInfo); 169 var regExpInput = LAST_INPUT(lastMatchInfo);
164 if (IS_UNDEFINED(regExpInput)) { 170 if (IS_UNDEFINED(regExpInput)) {
165 throw MakeError('no_input_to_regexp', [this]); 171 throw MakeError('no_input_to_regexp', [this]);
166 } 172 }
167 string = regExpInput; 173 string = regExpInput;
168 } 174 }
169 var s; 175 string = TO_STRING_INLINE(string);
170 if (IS_STRING(string)) {
171 s = string;
172 } else {
173 s = ToString(string);
174 }
175 var lastIndex = this.lastIndex; 176 var lastIndex = this.lastIndex;
176 177
177 // Conversion is required by the ES5 specification (RegExp.prototype.exec 178 // Conversion is required by the ES5 specification (RegExp.prototype.exec
178 // algorithm, step 5) even if the value is discarded for non-global RegExps. 179 // algorithm, step 5) even if the value is discarded for non-global RegExps.
179 var i = TO_INTEGER(lastIndex); 180 var i = TO_INTEGER(lastIndex);
180 181
181 var global = this.global; 182 var global = this.global;
182 if (global) { 183 if (global) {
183 if (i < 0 || i > s.length) { 184 if (i < 0 || i > string.length) {
184 this.lastIndex = 0; 185 this.lastIndex = 0;
185 return null; 186 return null;
186 } 187 }
187 } else { 188 } else {
188 i = 0; 189 i = 0;
189 } 190 }
190 191
191 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); 192 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
192 // matchIndices is either null or the lastMatchInfo array. 193 // matchIndices is either null or the lastMatchInfo array.
193 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); 194 var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo);
194 195
195 if (matchIndices === null) { 196 if (matchIndices === null) {
196 if (global) this.lastIndex = 0; 197 if (global) this.lastIndex = 0;
197 return null; 198 return null;
198 } 199 }
199 200
200 // Successful match. 201 // Successful match.
201 lastMatchInfoOverride = null; 202 lastMatchInfoOverride = null;
202 if (global) { 203 if (global) {
203 this.lastIndex = lastMatchInfo[CAPTURE1]; 204 this.lastIndex = lastMatchInfo[CAPTURE1];
204 } 205 }
205 return BuildResultFromMatchInfo(matchIndices, s); 206 return BuildResultFromMatchInfo(matchIndices, string);
206 } 207 }
207 208
208 209
209 // One-element cache for the simplified test regexp. 210 // One-element cache for the simplified test regexp.
210 var regexp_key; 211 var regexp_key;
211 var regexp_val; 212 var regexp_val;
212 213
213 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be 214 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be
214 // that test is defined in terms of String.prototype.exec. However, it probably 215 // that test is defined in terms of String.prototype.exec. However, it probably
215 // means the original value of String.prototype.exec, which is what everybody 216 // means the original value of String.prototype.exec, which is what everybody
216 // else implements. 217 // else implements.
217 function RegExpTest(string) { 218 function RegExpTest(string) {
218 if (!IS_REGEXP(this)) { 219 if (!IS_REGEXP(this)) {
219 throw MakeTypeError('incompatible_method_receiver', 220 throw MakeTypeError('incompatible_method_receiver',
220 ['RegExp.prototype.test', this]); 221 ['RegExp.prototype.test', this]);
221 } 222 }
222 if (%_ArgumentsLength() == 0) { 223 if (%_ArgumentsLength() == 0) {
223 var regExpInput = LAST_INPUT(lastMatchInfo); 224 var regExpInput = LAST_INPUT(lastMatchInfo);
224 if (IS_UNDEFINED(regExpInput)) { 225 if (IS_UNDEFINED(regExpInput)) {
225 throw MakeError('no_input_to_regexp', [this]); 226 throw MakeError('no_input_to_regexp', [this]);
226 } 227 }
227 string = regExpInput; 228 string = regExpInput;
228 } 229 }
229 230
230 var s; 231 string = TO_STRING_INLINE(string);
231 if (IS_STRING(string)) {
232 s = string;
233 } else {
234 s = ToString(string);
235 }
236 232
237 var lastIndex = this.lastIndex; 233 var lastIndex = this.lastIndex;
238 234
239 // Conversion is required by the ES5 specification (RegExp.prototype.exec 235 // Conversion is required by the ES5 specification (RegExp.prototype.exec
240 // algorithm, step 5) even if the value is discarded for non-global RegExps. 236 // algorithm, step 5) even if the value is discarded for non-global RegExps.
241 var i = TO_INTEGER(lastIndex); 237 var i = TO_INTEGER(lastIndex);
242 238
243 if (this.global) { 239 if (this.global) {
244 if (i < 0 || i > s.length) { 240 if (i < 0 || i > string.length) {
245 this.lastIndex = 0; 241 this.lastIndex = 0;
246 return false; 242 return false;
247 } 243 }
248 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); 244 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
249 // matchIndices is either null or the lastMatchInfo array. 245 // matchIndices is either null or the lastMatchInfo array.
250 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); 246 var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo);
251 if (matchIndices === null) { 247 if (matchIndices === null) {
252 this.lastIndex = 0; 248 this.lastIndex = 0;
253 return false; 249 return false;
254 } 250 }
255 lastMatchInfoOverride = null; 251 lastMatchInfoOverride = null;
256 this.lastIndex = lastMatchInfo[CAPTURE1]; 252 this.lastIndex = lastMatchInfo[CAPTURE1];
257 return true; 253 return true;
258 } else { 254 } else {
259 // Non-global regexp. 255 // Non-global regexp.
260 // Remove irrelevant preceeding '.*' in a non-global test regexp. 256 // Remove irrelevant preceeding '.*' in a non-global test regexp.
261 // The expression checks whether this.source starts with '.*' and 257 // The expression checks whether this.source starts with '.*' and
262 // that the third char is not a '?'. 258 // that the third char is not a '?'.
263 if (%_StringCharCodeAt(this.source, 0) == 46 && // '.' 259 if (%_StringCharCodeAt(this.source, 0) == 46 && // '.'
264 %_StringCharCodeAt(this.source, 1) == 42 && // '*' 260 %_StringCharCodeAt(this.source, 1) == 42 && // '*'
265 %_StringCharCodeAt(this.source, 2) != 63) { // '?' 261 %_StringCharCodeAt(this.source, 2) != 63) { // '?'
266 if (!%_ObjectEquals(regexp_key, this)) { 262 if (!%_ObjectEquals(regexp_key, this)) {
267 regexp_key = this; 263 regexp_key = this;
268 regexp_val = new $RegExp(this.source.substring(2, this.source.length), 264 regexp_val = new $RegExp(SubString(this.source, 2, this.source.length),
269 (this.ignoreCase ? 'i' : '') 265 (!this.ignoreCase
270 + (this.multiline ? 'm' : '')); 266 ? !this.multiline ? "" : "m"
267 : !this.multiline ? "i" : "im"));
271 } 268 }
272 if (!regexp_val.test(s)) return false; 269 if (%_RegExpExec(regexp_val, string, 0, lastMatchInfo) === null) {
270 return false;
271 }
273 } 272 }
274 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); 273 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
275 // matchIndices is either null or the lastMatchInfo array. 274 // matchIndices is either null or the lastMatchInfo array.
276 var matchIndices = %_RegExpExec(this, s, 0, lastMatchInfo); 275 var matchIndices = %_RegExpExec(this, string, 0, lastMatchInfo);
277 if (matchIndices === null) return false; 276 if (matchIndices === null) return false;
278 lastMatchInfoOverride = null; 277 lastMatchInfoOverride = null;
279 return true; 278 return true;
280 } 279 }
281 } 280 }
282 281
283 282
284 function RegExpToString() { 283 function RegExpToString() {
285 // If this.source is an empty string, output /(?:)/. 284 // If this.source is an empty string, output /(?:)/.
286 // http://bugzilla.mozilla.org/show_bug.cgi?id=225550 285 // http://bugzilla.mozilla.org/show_bug.cgi?id=225550
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); 474 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
476 475
477 for (var i = 1; i < 10; ++i) { 476 for (var i = 1; i < 10; ++i) {
478 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE); 477 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE);
479 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); 478 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE);
480 } 479 }
481 } 480 }
482 481
483 482
484 SetupRegExp(); 483 SetupRegExp();
OLDNEW
« no previous file with comments | « src/property.cc ('k') | src/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698