| Index: src/runtime/runtime-regexp.cc
|
| diff --git a/src/runtime/runtime-regexp.cc b/src/runtime/runtime-regexp.cc
|
| index df9f52aa59e937c9e25908ad02baae5cb2662c8c..4a89b92396df7259e1ffd47f79fab99e57a36b22 100644
|
| --- a/src/runtime/runtime-regexp.cc
|
| +++ b/src/runtime/runtime-regexp.cc
|
| @@ -75,7 +75,6 @@ class CompiledReplacement {
|
| SUBJECT_CAPTURE,
|
| REPLACEMENT_SUBSTRING,
|
| REPLACEMENT_STRING,
|
| - EMPTY,
|
| NUMBER_OF_PART_TYPES
|
| };
|
|
|
| @@ -100,7 +99,6 @@ class CompiledReplacement {
|
| DCHECK(to > from);
|
| return ReplacementPart(-from, to);
|
| }
|
| - static inline ReplacementPart Empty() { return ReplacementPart(EMPTY, 0); }
|
|
|
| // If tag <= 0 then it is the negation of a start index of a substring of
|
| // the replacement pattern, otherwise it's a value from PartType.
|
| @@ -113,8 +111,7 @@ class CompiledReplacement {
|
| int tag;
|
| // The data value's interpretation depends on the value of tag:
|
| // tag == SUBJECT_PREFIX ||
|
| - // tag == SUBJECT_SUFFIX ||
|
| - // tag == EMPTY: data is unused.
|
| + // tag == SUBJECT_SUFFIX: data is unused.
|
| // tag == SUBJECT_CAPTURE: data is the number of the capture.
|
| // tag == REPLACEMENT_SUBSTRING ||
|
| // tag == REPLACEMENT_STRING: data is index into array of substrings
|
| @@ -251,30 +248,27 @@ class CompiledReplacement {
|
|
|
| // Let capture be ? Get(namedCaptures, groupName).
|
|
|
| - int capture_index = LookupNamedCapture(
|
| + const int capture_index = LookupNamedCapture(
|
| [=](String* capture_name) {
|
| return capture_name->IsEqualTo(requested_name);
|
| },
|
| capture_name_map);
|
|
|
| + // If ? HasProperty(_namedCaptures_, _groupName_) is *false*, throw
|
| + // a *SyntaxError* exception.
|
| + if (capture_index == -1) return Nothing<bool>();
|
| +
|
| // If capture is undefined, replace the text through the following
|
| // '>' with the empty string.
|
| // Otherwise, replace the text through the following '>' with
|
| // ? ToString(capture).
|
|
|
| - DCHECK_IMPLIES(
|
| - capture_index != -1,
|
| - 1 <= capture_index && capture_index <= capture_count);
|
| -
|
| - ReplacementPart replacement =
|
| - (capture_index == -1)
|
| - ? ReplacementPart::Empty()
|
| - : ReplacementPart::SubjectCapture(capture_index);
|
| + DCHECK(1 <= capture_index && capture_index <= capture_count);
|
|
|
| if (i > last) {
|
| parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
|
| }
|
| - parts->Add(replacement, zone);
|
| + parts->Add(ReplacementPart::SubjectCapture(capture_index), zone);
|
| last = closing_bracket_index + 1;
|
| i = closing_bracket_index;
|
| break;
|
| @@ -386,8 +380,6 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
|
| case REPLACEMENT_STRING:
|
| builder->AddString(replacement_substrings_[part.data]);
|
| break;
|
| - case EMPTY:
|
| - break;
|
| default:
|
| UNREACHABLE();
|
| }
|
| @@ -1018,19 +1010,32 @@ class MatchInfoBackedMatch : public String::Match {
|
| }
|
|
|
| MaybeHandle<String> GetNamedCapture(Handle<String> name,
|
| - bool* capture_exists) override {
|
| + CaptureState* state) override {
|
| DCHECK(has_named_captures_);
|
| const int capture_index = LookupNamedCapture(
|
| [=](String* capture_name) { return capture_name->Equals(*name); },
|
| *capture_name_map_);
|
|
|
| if (capture_index == -1) {
|
| - *capture_exists = false;
|
| + *state = INVALID;
|
| return name; // Arbitrary string handle.
|
| }
|
|
|
| DCHECK(1 <= capture_index && capture_index <= CaptureCount());
|
| - return GetCapture(capture_index, capture_exists);
|
| +
|
| + bool capture_exists;
|
| + Handle<String> capture_value;
|
| + ASSIGN_RETURN_ON_EXCEPTION(isolate_, capture_value,
|
| + GetCapture(capture_index, &capture_exists),
|
| + String);
|
| +
|
| + if (!capture_exists) {
|
| + *state = UNMATCHED;
|
| + return isolate_->factory()->empty_string();
|
| + } else {
|
| + *state = MATCHED;
|
| + return capture_value;
|
| + }
|
| }
|
|
|
| private:
|
| @@ -1086,16 +1091,26 @@ class VectorBackedMatch : public String::Match {
|
| }
|
|
|
| MaybeHandle<String> GetNamedCapture(Handle<String> name,
|
| - bool* capture_exists) override {
|
| + CaptureState* state) override {
|
| DCHECK(has_named_captures_);
|
| +
|
| + Maybe<bool> maybe_capture_exists =
|
| + JSReceiver::HasProperty(groups_obj_, name);
|
| + if (maybe_capture_exists.IsNothing()) return MaybeHandle<String>();
|
| +
|
| + if (!maybe_capture_exists.FromJust()) {
|
| + *state = INVALID;
|
| + return name; // Arbitrary string handle.
|
| + }
|
| +
|
| Handle<Object> capture_obj;
|
| ASSIGN_RETURN_ON_EXCEPTION(isolate_, capture_obj,
|
| Object::GetProperty(groups_obj_, name), String);
|
| if (capture_obj->IsUndefined(isolate_)) {
|
| - *capture_exists = false;
|
| - return name;
|
| + *state = UNMATCHED;
|
| + return isolate_->factory()->empty_string();
|
| } else {
|
| - *capture_exists = true;
|
| + *state = MATCHED;
|
| return Object::ToString(isolate_, capture_obj);
|
| }
|
| }
|
| @@ -1892,7 +1907,6 @@ RUNTIME_FUNCTION(Runtime_RegExpReplace) {
|
| } else {
|
| DCHECK(!functional_replace);
|
| if (!groups_obj->IsUndefined(isolate)) {
|
| - // TODO(jgruber): Behavior in this case is not yet specced.
|
| ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| isolate, groups_obj, JSReceiver::ToObject(isolate, groups_obj));
|
| }
|
|
|