| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 (function(global, utils) { | 5 (function(global, utils) { |
| 6 | 6 |
| 7 %CheckIsBootstrapping(); | 7 %CheckIsBootstrapping(); |
| 8 | 8 |
| 9 // ------------------------------------------------------------------- | 9 // ------------------------------------------------------------------- |
| 10 // Imports | 10 // Imports |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 if (start != -1) { | 156 if (start != -1) { |
| 157 end = MATCHINFO[j]; | 157 end = MATCHINFO[j]; |
| 158 result[i] = %_SubString(STRING, start, end); | 158 result[i] = %_SubString(STRING, start, end); |
| 159 } | 159 } |
| 160 j++; | 160 j++; |
| 161 } | 161 } |
| 162 return result; | 162 return result; |
| 163 endmacro | 163 endmacro |
| 164 | 164 |
| 165 | 165 |
| 166 function RegExpExecNoTests(regexp, string, start) { | |
| 167 // Must be called with RegExp, string and positive integer as arguments. | |
| 168 var matchInfo = %_RegExpExec(regexp, string, start, RegExpLastMatchInfo); | |
| 169 if (matchInfo !== null) { | |
| 170 // ES6 21.2.5.2.2 step 18. | |
| 171 if (REGEXP_STICKY(regexp)) regexp.lastIndex = matchInfo[CAPTURE1]; | |
| 172 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, string); | |
| 173 } | |
| 174 regexp.lastIndex = 0; | |
| 175 return null; | |
| 176 } | |
| 177 | |
| 178 | |
| 179 // ES#sec-regexp.prototype.exec | 166 // ES#sec-regexp.prototype.exec |
| 180 // RegExp.prototype.exec ( string ) | 167 // RegExp.prototype.exec ( string ) |
| 181 function RegExpSubclassExecJS(string) { | 168 function RegExpSubclassExecJS(string) { |
| 182 if (!IS_REGEXP(this)) { | 169 if (!IS_REGEXP(this)) { |
| 183 throw %make_type_error(kIncompatibleMethodReceiver, | 170 throw %make_type_error(kIncompatibleMethodReceiver, |
| 184 'RegExp.prototype.exec', this); | 171 'RegExp.prototype.exec', this); |
| 185 } | 172 } |
| 186 | 173 |
| 187 string = TO_STRING(string); | 174 string = TO_STRING(string); |
| 188 var lastIndex = this.lastIndex; | 175 var lastIndex = this.lastIndex; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 if (!IS_RECEIVER(result) && !IS_NULL(result)) { | 259 if (!IS_RECEIVER(result) && !IS_NULL(result)) { |
| 273 throw %make_type_error(kInvalidRegExpExecResult); | 260 throw %make_type_error(kInvalidRegExpExecResult); |
| 274 } | 261 } |
| 275 return result; | 262 return result; |
| 276 } | 263 } |
| 277 return %_Call(RegExpExecJS, regexp, string); | 264 return %_Call(RegExpExecJS, regexp, string); |
| 278 } | 265 } |
| 279 %SetForceInlineFlag(RegExpSubclassExec); | 266 %SetForceInlineFlag(RegExpSubclassExec); |
| 280 | 267 |
| 281 | 268 |
| 282 // One-element cache for the simplified test regexp. | |
| 283 var regexp_key; | |
| 284 var regexp_val; | |
| 285 | |
| 286 // Legacy implementation of RegExp.prototype.test | |
| 287 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be | |
| 288 // that test is defined in terms of String.prototype.exec. However, it probably | |
| 289 // means the original value of String.prototype.exec, which is what everybody | |
| 290 // else implements. | |
| 291 function RegExpTest(string) { | |
| 292 if (!IS_REGEXP(this)) { | |
| 293 throw %make_type_error(kIncompatibleMethodReceiver, | |
| 294 'RegExp.prototype.test', this); | |
| 295 } | |
| 296 string = TO_STRING(string); | |
| 297 | |
| 298 var lastIndex = this.lastIndex; | |
| 299 | |
| 300 // Conversion is required by the ES2015 specification (RegExpBuiltinExec | |
| 301 // algorithm, step 4) even if the value is discarded for non-global RegExps. | |
| 302 var i = TO_LENGTH(lastIndex); | |
| 303 | |
| 304 if (REGEXP_GLOBAL(this) || REGEXP_STICKY(this)) { | |
| 305 if (i < 0 || i > string.length) { | |
| 306 this.lastIndex = 0; | |
| 307 return false; | |
| 308 } | |
| 309 // matchIndices is either null or the RegExpLastMatchInfo array. | |
| 310 var matchIndices = %_RegExpExec(this, string, i, RegExpLastMatchInfo); | |
| 311 if (IS_NULL(matchIndices)) { | |
| 312 this.lastIndex = 0; | |
| 313 return false; | |
| 314 } | |
| 315 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; | |
| 316 return true; | |
| 317 } else { | |
| 318 // Non-global, non-sticky regexp. | |
| 319 // Remove irrelevant preceeding '.*' in a test regexp. The expression | |
| 320 // checks whether this.source starts with '.*' and that the third char is | |
| 321 // not a '?'. But see https://code.google.com/p/v8/issues/detail?id=3560 | |
| 322 var regexp = this; | |
| 323 var source = REGEXP_SOURCE(regexp); | |
| 324 if (source.length >= 3 && | |
| 325 %_StringCharCodeAt(source, 0) == 46 && // '.' | |
| 326 %_StringCharCodeAt(source, 1) == 42 && // '*' | |
| 327 %_StringCharCodeAt(source, 2) != 63) { // '?' | |
| 328 regexp = TrimRegExp(regexp); | |
| 329 } | |
| 330 // matchIndices is either null or the RegExpLastMatchInfo array. | |
| 331 var matchIndices = %_RegExpExec(regexp, string, 0, RegExpLastMatchInfo); | |
| 332 if (IS_NULL(matchIndices)) { | |
| 333 this.lastIndex = 0; | |
| 334 return false; | |
| 335 } | |
| 336 return true; | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 | |
| 341 // ES#sec-regexp.prototype.test RegExp.prototype.test ( S ) | 269 // ES#sec-regexp.prototype.test RegExp.prototype.test ( S ) |
| 342 function RegExpSubclassTest(string) { | 270 function RegExpSubclassTest(string) { |
| 343 if (!IS_RECEIVER(this)) { | 271 if (!IS_RECEIVER(this)) { |
| 344 throw %make_type_error(kIncompatibleMethodReceiver, | 272 throw %make_type_error(kIncompatibleMethodReceiver, |
| 345 'RegExp.prototype.test', this); | 273 'RegExp.prototype.test', this); |
| 346 } | 274 } |
| 347 string = TO_STRING(string); | 275 string = TO_STRING(string); |
| 348 var match = RegExpSubclassExec(this, string); | 276 var match = RegExpSubclassExec(this, string); |
| 349 return !IS_NULL(match); | 277 return !IS_NULL(match); |
| 350 } | 278 } |
| 351 %FunctionRemovePrototype(RegExpSubclassTest); | 279 %FunctionRemovePrototype(RegExpSubclassTest); |
| 352 | 280 |
| 353 function TrimRegExp(regexp) { | |
| 354 if (regexp_key !== regexp) { | |
| 355 regexp_key = regexp; | |
| 356 regexp_val = | |
| 357 new GlobalRegExp( | |
| 358 %_SubString(REGEXP_SOURCE(regexp), 2, REGEXP_SOURCE(regexp).length), | |
| 359 (REGEXP_IGNORE_CASE(regexp) ? REGEXP_MULTILINE(regexp) ? "im" : "i" | |
| 360 : REGEXP_MULTILINE(regexp) ? "m" : "")); | |
| 361 } | |
| 362 return regexp_val; | |
| 363 } | |
| 364 | |
| 365 | 281 |
| 366 function RegExpToString() { | 282 function RegExpToString() { |
| 367 if (!IS_RECEIVER(this)) { | 283 if (!IS_RECEIVER(this)) { |
| 368 throw %make_type_error( | 284 throw %make_type_error( |
| 369 kIncompatibleMethodReceiver, 'RegExp.prototype.toString', this); | 285 kIncompatibleMethodReceiver, 'RegExp.prototype.toString', this); |
| 370 } | 286 } |
| 371 if (this === GlobalRegExpPrototype) { | 287 if (this === GlobalRegExpPrototype) { |
| 372 %IncrementUseCounter(kRegExpPrototypeToString); | 288 %IncrementUseCounter(kRegExpPrototypeToString); |
| 373 } | 289 } |
| 374 return '/' + TO_STRING(this.source) + '/' + TO_STRING(this.flags); | 290 return '/' + TO_STRING(this.source) + '/' + TO_STRING(this.flags); |
| (...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 // ------------------------------------------------------------------- | 1134 // ------------------------------------------------------------------- |
| 1219 // Exports | 1135 // Exports |
| 1220 | 1136 |
| 1221 utils.Export(function(to) { | 1137 utils.Export(function(to) { |
| 1222 to.InternalRegExpMatch = InternalRegExpMatch; | 1138 to.InternalRegExpMatch = InternalRegExpMatch; |
| 1223 to.InternalRegExpReplace = InternalRegExpReplace; | 1139 to.InternalRegExpReplace = InternalRegExpReplace; |
| 1224 to.IsRegExp = IsRegExp; | 1140 to.IsRegExp = IsRegExp; |
| 1225 to.RegExpExec = DoRegExpExec; | 1141 to.RegExpExec = DoRegExpExec; |
| 1226 to.RegExpInitialize = RegExpInitialize; | 1142 to.RegExpInitialize = RegExpInitialize; |
| 1227 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | 1143 to.RegExpLastMatchInfo = RegExpLastMatchInfo; |
| 1228 to.RegExpTest = RegExpTest; | |
| 1229 }); | 1144 }); |
| 1230 | 1145 |
| 1231 }) | 1146 }) |
| OLD | NEW |