OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/conversions-inl.h" | 8 #include "src/conversions-inl.h" |
9 #include "src/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
(...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1262 DCHECK(args.length() == 3); | 1262 DCHECK(args.length() == 3); |
1263 | 1263 |
1264 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | 1264 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
1265 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); | 1265 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); |
1266 CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2); | 1266 CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2); |
1267 | 1267 |
1268 RETURN_RESULT_OR_FAILURE(isolate, StringReplaceNonGlobalRegExpWithFunction( | 1268 RETURN_RESULT_OR_FAILURE(isolate, StringReplaceNonGlobalRegExpWithFunction( |
1269 isolate, subject, regexp, replace)); | 1269 isolate, subject, regexp, replace)); |
1270 } | 1270 } |
1271 | 1271 |
| 1272 namespace { |
| 1273 |
| 1274 // ES##sec-speciesconstructor |
| 1275 // SpeciesConstructor ( O, defaultConstructor ) |
| 1276 MUST_USE_RESULT MaybeHandle<Object> SpeciesConstructor( |
| 1277 Isolate* isolate, Handle<JSReceiver> recv, |
| 1278 Handle<JSFunction> default_ctor) { |
| 1279 Handle<Object> ctor_obj; |
| 1280 ASSIGN_RETURN_ON_EXCEPTION( |
| 1281 isolate, ctor_obj, |
| 1282 JSObject::GetProperty(recv, isolate->factory()->constructor_string()), |
| 1283 Object); |
| 1284 |
| 1285 if (ctor_obj->IsUndefined(isolate)) return default_ctor; |
| 1286 |
| 1287 if (!ctor_obj->IsJSReceiver()) { |
| 1288 THROW_NEW_ERROR(isolate, |
| 1289 NewTypeError(MessageTemplate::kConstructorNotReceiver), |
| 1290 Object); |
| 1291 } |
| 1292 |
| 1293 Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj); |
| 1294 |
| 1295 Handle<Object> species; |
| 1296 ASSIGN_RETURN_ON_EXCEPTION( |
| 1297 isolate, species, |
| 1298 JSObject::GetProperty(ctor, isolate->factory()->species_symbol()), |
| 1299 Object); |
| 1300 |
| 1301 if (species->IsNull(isolate) || species->IsUndefined(isolate)) { |
| 1302 return default_ctor; |
| 1303 } |
| 1304 |
| 1305 if (species->IsConstructor()) return species; |
| 1306 |
| 1307 THROW_NEW_ERROR( |
| 1308 isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object); |
| 1309 } |
| 1310 |
| 1311 MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate, |
| 1312 Handle<Object> object, |
| 1313 uint32_t* out) { |
| 1314 if (object->IsUndefined(isolate)) { |
| 1315 *out = kMaxUInt32; |
| 1316 return object; |
| 1317 } |
| 1318 |
| 1319 Handle<Object> number; |
| 1320 ASSIGN_RETURN_ON_EXCEPTION(isolate, number, Object::ToNumber(object), Object); |
| 1321 *out = NumberToUint32(*number); |
| 1322 return object; |
| 1323 } |
| 1324 |
| 1325 Handle<JSArray> NewJSArrayWithElements(Isolate* isolate, |
| 1326 Handle<FixedArray> elems, |
| 1327 int num_elems) { |
| 1328 elems->Shrink(num_elems); |
| 1329 return isolate->factory()->NewJSArrayWithElements(elems); |
| 1330 } |
| 1331 |
| 1332 } // namespace |
| 1333 |
| 1334 // Slow path for: |
| 1335 // ES#sec-regexp.prototype-@@replace |
| 1336 // RegExp.prototype [ @@split ] ( string, limit ) |
| 1337 RUNTIME_FUNCTION(Runtime_RegExpSplit) { |
| 1338 HandleScope scope(isolate); |
| 1339 DCHECK(args.length() == 3); |
| 1340 |
| 1341 DCHECK(args[1]->IsString()); |
| 1342 |
| 1343 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, recv, 0); |
| 1344 CONVERT_ARG_HANDLE_CHECKED(String, string, 1); |
| 1345 CONVERT_ARG_HANDLE_CHECKED(Object, limit_obj, 2); |
| 1346 |
| 1347 Factory* factory = isolate->factory(); |
| 1348 |
| 1349 Handle<JSFunction> regexp_fun = isolate->regexp_function(); |
| 1350 Handle<Object> ctor; |
| 1351 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1352 isolate, ctor, SpeciesConstructor(isolate, recv, regexp_fun)); |
| 1353 |
| 1354 Handle<Object> flags_obj; |
| 1355 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1356 isolate, flags_obj, JSObject::GetProperty(recv, factory->flags_string())); |
| 1357 |
| 1358 Handle<String> flags; |
| 1359 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, flags, |
| 1360 Object::ToString(isolate, flags_obj)); |
| 1361 |
| 1362 Handle<String> u_str = factory->LookupSingleCharacterStringFromCode('u'); |
| 1363 const bool unicode = (String::IndexOf(isolate, flags, u_str, 0) >= 0); |
| 1364 |
| 1365 Handle<String> y_str = factory->LookupSingleCharacterStringFromCode('y'); |
| 1366 const bool sticky = (String::IndexOf(isolate, flags, y_str, 0) >= 0); |
| 1367 |
| 1368 Handle<String> new_flags = flags; |
| 1369 if (!sticky) { |
| 1370 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, new_flags, |
| 1371 factory->NewConsString(flags, y_str)); |
| 1372 } |
| 1373 |
| 1374 Handle<JSReceiver> splitter; |
| 1375 { |
| 1376 const int argc = 2; |
| 1377 |
| 1378 ScopedVector<Handle<Object>> argv(argc); |
| 1379 argv[0] = recv; |
| 1380 argv[1] = new_flags; |
| 1381 |
| 1382 Handle<JSFunction> ctor_fun = Handle<JSFunction>::cast(ctor); |
| 1383 Handle<Object> splitter_obj; |
| 1384 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1385 isolate, splitter_obj, Execution::New(ctor_fun, argc, argv.start())); |
| 1386 |
| 1387 splitter = Handle<JSReceiver>::cast(splitter_obj); |
| 1388 } |
| 1389 |
| 1390 uint32_t limit; |
| 1391 RETURN_FAILURE_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit)); |
| 1392 |
| 1393 const int length = string->length(); |
| 1394 |
| 1395 if (limit == 0) return *factory->NewJSArray(0); |
| 1396 |
| 1397 if (length == 0) { |
| 1398 Handle<Object> result; |
| 1399 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1400 isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string, |
| 1401 factory->undefined_value())); |
| 1402 |
| 1403 if (!result->IsNull(isolate)) return *factory->NewJSArray(0); |
| 1404 |
| 1405 Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1); |
| 1406 elems->set(0, *string); |
| 1407 return *factory->NewJSArrayWithElements(elems); |
| 1408 } |
| 1409 |
| 1410 static const int kInitialArraySize = 8; |
| 1411 Handle<FixedArray> elems = factory->NewFixedArrayWithHoles(kInitialArraySize); |
| 1412 int num_elems = 0; |
| 1413 |
| 1414 int string_index = 0; |
| 1415 int prev_string_index = 0; |
| 1416 while (string_index < length) { |
| 1417 RETURN_FAILURE_ON_EXCEPTION( |
| 1418 isolate, RegExpUtils::SetLastIndex(isolate, splitter, string_index)); |
| 1419 |
| 1420 Handle<Object> result; |
| 1421 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1422 isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string, |
| 1423 factory->undefined_value())); |
| 1424 |
| 1425 if (result->IsNull(isolate)) { |
| 1426 string_index = RegExpUtils::AdvanceStringIndex(isolate, string, |
| 1427 string_index, unicode); |
| 1428 continue; |
| 1429 } |
| 1430 |
| 1431 Handle<Object> last_index_obj; |
| 1432 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1433 isolate, last_index_obj, RegExpUtils::GetLastIndex(isolate, splitter)); |
| 1434 |
| 1435 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1436 isolate, last_index_obj, Object::ToLength(isolate, last_index_obj)); |
| 1437 const int last_index = Handle<Smi>::cast(last_index_obj)->value(); |
| 1438 |
| 1439 const int end = std::min(last_index, length); |
| 1440 if (end == prev_string_index) { |
| 1441 string_index = RegExpUtils::AdvanceStringIndex(isolate, string, |
| 1442 string_index, unicode); |
| 1443 continue; |
| 1444 } |
| 1445 |
| 1446 { |
| 1447 Handle<String> substr = |
| 1448 factory->NewSubString(string, prev_string_index, string_index); |
| 1449 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); |
| 1450 if (static_cast<uint32_t>(num_elems) == limit) { |
| 1451 return *NewJSArrayWithElements(isolate, elems, num_elems); |
| 1452 } |
| 1453 } |
| 1454 |
| 1455 prev_string_index = end; |
| 1456 |
| 1457 Handle<Object> num_captures_obj; |
| 1458 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1459 isolate, num_captures_obj, |
| 1460 Object::GetProperty(result, isolate->factory()->length_string())); |
| 1461 |
| 1462 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1463 isolate, num_captures_obj, Object::ToLength(isolate, num_captures_obj)); |
| 1464 const int num_captures = |
| 1465 std::max(Handle<Smi>::cast(num_captures_obj)->value(), 0); |
| 1466 |
| 1467 for (int i = 1; i < num_captures; i++) { |
| 1468 Handle<Object> capture; |
| 1469 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1470 isolate, capture, Object::GetElement(isolate, result, i)); |
| 1471 elems = FixedArray::SetAndGrow(elems, num_elems++, capture); |
| 1472 if (static_cast<uint32_t>(num_elems) == limit) { |
| 1473 return *NewJSArrayWithElements(isolate, elems, num_elems); |
| 1474 } |
| 1475 } |
| 1476 |
| 1477 string_index = prev_string_index; |
| 1478 } |
| 1479 |
| 1480 { |
| 1481 Handle<String> substr = |
| 1482 factory->NewSubString(string, prev_string_index, length); |
| 1483 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); |
| 1484 } |
| 1485 |
| 1486 return *NewJSArrayWithElements(isolate, elems, num_elems); |
| 1487 } |
| 1488 |
1272 // Slow path for: | 1489 // Slow path for: |
1273 // ES#sec-regexp.prototype-@@replace | 1490 // ES#sec-regexp.prototype-@@replace |
1274 // RegExp.prototype [ @@replace ] ( string, replaceValue ) | 1491 // RegExp.prototype [ @@replace ] ( string, replaceValue ) |
1275 RUNTIME_FUNCTION(Runtime_RegExpReplace) { | 1492 RUNTIME_FUNCTION(Runtime_RegExpReplace) { |
1276 HandleScope scope(isolate); | 1493 HandleScope scope(isolate); |
1277 DCHECK(args.length() == 3); | 1494 DCHECK(args.length() == 3); |
1278 | 1495 |
1279 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, recv, 0); | 1496 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, recv, 0); |
1280 CONVERT_ARG_HANDLE_CHECKED(String, string, 1); | 1497 CONVERT_ARG_HANDLE_CHECKED(String, string, 1); |
1281 Handle<Object> replace_obj = args.at<Object>(2); | 1498 Handle<Object> replace_obj = args.at<Object>(2); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 | 1668 |
1452 RUNTIME_FUNCTION(Runtime_IsRegExp) { | 1669 RUNTIME_FUNCTION(Runtime_IsRegExp) { |
1453 SealHandleScope shs(isolate); | 1670 SealHandleScope shs(isolate); |
1454 DCHECK(args.length() == 1); | 1671 DCHECK(args.length() == 1); |
1455 CONVERT_ARG_CHECKED(Object, obj, 0); | 1672 CONVERT_ARG_CHECKED(Object, obj, 0); |
1456 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); | 1673 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); |
1457 } | 1674 } |
1458 | 1675 |
1459 } // namespace internal | 1676 } // namespace internal |
1460 } // namespace v8 | 1677 } // namespace v8 |
OLD | NEW |