Changeset 232092 in webkit
- Timestamp:
- May 22, 2018 5:16:57 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r232089 r232092 1 2018-05-22 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Fix CachedCall's argument count if RegExp has named captures 4 https://bugs.webkit.org/show_bug.cgi?id=185587 5 6 Reviewed by Mark Lam. 7 8 * test262/expectations.yaml: 9 1 10 2018-05-22 Mark Lam <mark.lam@apple.com> 2 11 -
trunk/JSTests/test262/expectations.yaml
r231768 r232092 1304 1304 default: 'SyntaxError: Invalid regular expression: invalid group specifier name' 1305 1305 strict mode: 'SyntaxError: Invalid regular expression: invalid group specifier name' 1306 test/built-ins/RegExp/named-groups/functional-replace-global.js:1307 default: "TypeError: undefined is not an object (evaluating 'groups.fst')"1308 strict mode: "TypeError: undefined is not an object (evaluating 'groups.fst')"1309 1306 test/built-ins/RegExp/named-groups/groups-object-subclass-sans.js: 1310 1307 default: 'Test262Error: Expected SameValue(«b», «$<a>») to be true' -
trunk/Source/JavaScriptCore/ChangeLog
r232089 r232092 1 2018-05-22 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Fix CachedCall's argument count if RegExp has named captures 4 https://bugs.webkit.org/show_bug.cgi?id=185587 5 6 Reviewed by Mark Lam. 7 8 If the given RegExp has named captures, the argument count of CachedCall in String#replace 9 should be increased by one. This causes crash with assertion in test262. This patch corrects 10 the argument count. 11 12 This patch also unifies source.is8Bit()/!source.is8Bit() code since they are now completely 13 the same. 14 15 * runtime/StringPrototype.cpp: 16 (JSC::replaceUsingRegExpSearch): 17 1 18 2018-05-22 Mark Lam <mark.lam@apple.com> 2 19 -
trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp
r231741 r232092 566 566 // regExp->numSubpatterns() + 1 for pattern args, + 2 for match start and string 567 567 int argCount = regExp->numSubpatterns() + 1 + 2; 568 if (hasNamedCaptures) 569 ++argCount; 568 570 JSFunction* func = jsCast<JSFunction*>(replaceValue); 569 571 CachedCall cachedCall(exec, func, argCount); 570 572 RETURN_IF_EXCEPTION(scope, nullptr); 571 if (source.is8Bit()) { 572 while (true) { 573 int* ovector; 574 MatchResult result = regExpConstructor->performMatch(vm, regExp, string, source, startPosition, &ovector); 575 if (!result) 576 break; 577 578 if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, result.start - lastIndex))) 579 OUT_OF_MEMORY(exec, scope); 580 581 unsigned i = 0; 582 cachedCall.clearArguments(); 583 584 JSObject* groups = nullptr; 585 586 if (hasNamedCaptures) { 587 JSGlobalObject* globalObject = exec->lexicalGlobalObject(); 588 groups = JSFinalObject::create(vm, JSFinalObject::createStructure(vm, globalObject, globalObject->objectPrototype(), 0)); 589 } 590 591 for (; i < regExp->numSubpatterns() + 1; ++i) { 592 int matchStart = ovector[i * 2]; 593 int matchLen = ovector[i * 2 + 1] - matchStart; 594 595 JSValue patternValue; 596 597 if (matchStart < 0) 598 patternValue = jsUndefined(); 599 else 600 patternValue = jsSubstring(&vm, source, matchStart, matchLen); 601 602 cachedCall.appendArgument(patternValue); 603 604 if (i && hasNamedCaptures) { 605 String groupName = regExp->getCaptureGroupName(i); 606 if (!groupName.isEmpty()) 607 groups->putDirect(vm, Identifier::fromString(&vm, groupName), patternValue); 608 } 609 } 610 611 cachedCall.appendArgument(jsNumber(result.start)); 612 cachedCall.appendArgument(string); 613 if (hasNamedCaptures) 614 cachedCall.appendArgument(groups); 615 616 cachedCall.setThis(jsUndefined()); 617 if (UNLIKELY(cachedCall.hasOverflowedArguments())) { 618 throwOutOfMemoryError(exec, scope); 619 return nullptr; 620 } 621 622 JSValue jsResult = cachedCall.call(); 623 RETURN_IF_EXCEPTION(scope, nullptr); 624 replacements.append(jsResult.toWTFString(exec)); 625 RETURN_IF_EXCEPTION(scope, nullptr); 626 627 lastIndex = result.end; 628 startPosition = lastIndex; 629 630 // special case of empty match 631 if (result.empty()) { 632 startPosition++; 633 if (startPosition > sourceLen) 634 break; 573 while (true) { 574 int* ovector; 575 MatchResult result = regExpConstructor->performMatch(vm, regExp, string, source, startPosition, &ovector); 576 if (!result) 577 break; 578 579 if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, result.start - lastIndex))) 580 OUT_OF_MEMORY(exec, scope); 581 582 cachedCall.clearArguments(); 583 584 JSObject* groups = nullptr; 585 586 if (hasNamedCaptures) { 587 JSGlobalObject* globalObject = exec->lexicalGlobalObject(); 588 groups = JSFinalObject::create(vm, JSFinalObject::createStructure(vm, globalObject, globalObject->objectPrototype(), 0)); 589 } 590 591 for (unsigned i = 0; i < regExp->numSubpatterns() + 1; ++i) { 592 int matchStart = ovector[i * 2]; 593 int matchLen = ovector[i * 2 + 1] - matchStart; 594 595 JSValue patternValue; 596 597 if (matchStart < 0) 598 patternValue = jsUndefined(); 599 else 600 patternValue = jsSubstring(&vm, source, matchStart, matchLen); 601 602 cachedCall.appendArgument(patternValue); 603 604 if (i && hasNamedCaptures) { 605 String groupName = regExp->getCaptureGroupName(i); 606 if (!groupName.isEmpty()) 607 groups->putDirect(vm, Identifier::fromString(&vm, groupName), patternValue); 635 608 } 636 609 } 637 } else { 638 while (true) { 639 int* ovector; 640 MatchResult result = regExpConstructor->performMatch(vm, regExp, string, source, startPosition, &ovector); 641 if (!result) 610 611 cachedCall.appendArgument(jsNumber(result.start)); 612 cachedCall.appendArgument(string); 613 if (hasNamedCaptures) 614 cachedCall.appendArgument(groups); 615 616 cachedCall.setThis(jsUndefined()); 617 if (UNLIKELY(cachedCall.hasOverflowedArguments())) { 618 throwOutOfMemoryError(exec, scope); 619 return nullptr; 620 } 621 622 JSValue jsResult = cachedCall.call(); 623 RETURN_IF_EXCEPTION(scope, nullptr); 624 replacements.append(jsResult.toWTFString(exec)); 625 RETURN_IF_EXCEPTION(scope, nullptr); 626 627 lastIndex = result.end; 628 startPosition = lastIndex; 629 630 // special case of empty match 631 if (result.empty()) { 632 startPosition++; 633 if (startPosition > sourceLen) 642 634 break; 643 644 if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, result.start - lastIndex)))645 OUT_OF_MEMORY(exec, scope);646 647 unsigned i = 0;648 cachedCall.clearArguments();649 650 JSObject* groups = nullptr;651 652 if (hasNamedCaptures) {653 JSGlobalObject* globalObject = exec->lexicalGlobalObject();654 groups = JSFinalObject::create(vm, JSFinalObject::createStructure(vm, globalObject, globalObject->objectPrototype(), 0));655 }656 657 for (; i < regExp->numSubpatterns() + 1; ++i) {658 int matchStart = ovector[i * 2];659 int matchLen = ovector[i * 2 + 1] - matchStart;660 661 JSValue patternValue;662 663 if (matchStart < 0)664 patternValue = jsUndefined();665 else666 patternValue = jsSubstring(&vm, source, matchStart, matchLen);667 668 cachedCall.appendArgument(patternValue);669 670 if (i && hasNamedCaptures) {671 String groupName = regExp->getCaptureGroupName(i);672 if (!groupName.isEmpty())673 groups->putDirect(vm, Identifier::fromString(&vm, groupName), patternValue);674 }675 }676 677 cachedCall.appendArgument(jsNumber(result.start));678 cachedCall.appendArgument(string);679 if (hasNamedCaptures)680 cachedCall.appendArgument(groups);681 682 cachedCall.setThis(jsUndefined());683 if (UNLIKELY(cachedCall.hasOverflowedArguments())) {684 throwOutOfMemoryError(exec, scope);685 return nullptr;686 }687 688 JSValue jsResult = cachedCall.call();689 RETURN_IF_EXCEPTION(scope, nullptr);690 replacements.append(jsResult.toWTFString(exec));691 RETURN_IF_EXCEPTION(scope, nullptr);692 693 lastIndex = result.end;694 startPosition = lastIndex;695 696 // special case of empty match697 if (result.empty()) {698 startPosition++;699 if (startPosition > sourceLen)700 break;701 }702 635 } 703 636 }
Note: See TracChangeset
for help on using the changeset viewer.