Skip to content

Commit

Permalink
[esnext] Update String.p.matchAll as per spec changes
Browse files Browse the repository at this point in the history
As per (tc39/proposal-string-matchall#41), String.p.matchAll's fallback was removed.
Additionally, removed a IsNullOrUndefined check that was already covered by MaybeCallFunctionAtSymbol.
Updates to Test262 has been submitted: tc39/test262#1990

Bug: v8:6890
Change-Id: I246cbbcb4641ebded704c5f772809f182deaa30e
Reviewed-on: https://chromium-review.googlesource.com/c/1369091
Commit-Queue: Peter Wong <peter.wm.wong@gmail.com>
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Mathias Bynens <mathias@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58172}
  • Loading branch information
peterwmwong authored and Commit Bot committed Dec 11, 2018
1 parent 63d6b75 commit 29a970a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 49 deletions.
82 changes: 33 additions & 49 deletions src/builtins/builtins-string-gen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1521,57 +1521,41 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) {
RequireObjectCoercible(context, receiver, method_name);

// 2. If regexp is neither undefined nor null, then
Label tostring_and_create_regexp_string_iterator(this, Label::kDeferred);
TVARIABLE(String, var_receiver_string);
GotoIf(IsNullOrUndefined(maybe_regexp),
&tostring_and_create_regexp_string_iterator);
{
// a. Let matcher be ? GetMethod(regexp, @@matchAll).
// b. If matcher is not undefined, then
// i. Return ? Call(matcher, regexp, « O »).
auto if_regexp_call = [&] {
// MaybeCallFunctionAtSymbol guarantees fast path is chosen only if
// maybe_regexp is a fast regexp and receiver is a string.
var_receiver_string = CAST(receiver);
CSA_ASSERT(this, IsString(var_receiver_string.value()));

RegExpMatchAllAssembler regexp_asm(state());
regexp_asm.Generate(context, native_context, maybe_regexp,
var_receiver_string.value());
};
auto if_generic_call = [=](Node* fn) {
Callable call_callable = CodeFactory::Call(isolate());
Return(CallJS(call_callable, context, fn, maybe_regexp, receiver));
};
MaybeCallFunctionAtSymbol(
context, maybe_regexp, receiver,
isolate()->factory()->match_all_symbol(),
DescriptorIndexAndName{JSRegExp::kSymbolMatchAllFunctionDescriptorIndex,
RootIndex::kmatch_all_symbol},
if_regexp_call, if_generic_call);
Goto(&tostring_and_create_regexp_string_iterator);
}
BIND(&tostring_and_create_regexp_string_iterator);
{
// a. Let matcher be ? GetMethod(regexp, @@matchAll).
// b. If matcher is not undefined, then
// i. Return ? Call(matcher, regexp, « O »).
auto if_regexp_call = [&] {
// MaybeCallFunctionAtSymbol guarantees fast path is chosen only if
// maybe_regexp is a fast regexp and receiver is a string.
TNode<String> s = CAST(receiver);

RegExpMatchAllAssembler regexp_asm(state());
regexp_asm.Generate(context, native_context, maybe_regexp, s);
};
auto if_generic_call = [=](Node* fn) {
Callable call_callable = CodeFactory::Call(isolate());
Return(CallJS(call_callable, context, fn, maybe_regexp, receiver));
};
MaybeCallFunctionAtSymbol(
context, maybe_regexp, receiver, isolate()->factory()->match_all_symbol(),
DescriptorIndexAndName{JSRegExp::kSymbolMatchAllFunctionDescriptorIndex,
RootIndex::kmatch_all_symbol},
if_regexp_call, if_generic_call);

// 3. Let S be ? ToString(O).
var_receiver_string = ToString_Inline(context, receiver);

// 4. Let matcher be ? RegExpCreate(R, "g").
TNode<Object> regexp = regexp_asm.RegExpCreate(
context, native_context, maybe_regexp, StringConstant("g"));

// 5. Let global be true.
// 6. Let fullUnicode be false.
// 7. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode).
TNode<Int32T> global = Int32Constant(1);
TNode<Int32T> full_unicode = Int32Constant(0);
TNode<Object> iterator = regexp_asm.CreateRegExpStringIterator(
native_context, regexp, var_receiver_string.value(), global,
full_unicode);
Return(iterator);
}
RegExpMatchAllAssembler regexp_asm(state());

// 3. Let S be ? ToString(O).
TNode<String> s = ToString_Inline(context, receiver);

// 4. Let rx be ? RegExpCreate(R, "g").
TNode<Object> rx = regexp_asm.RegExpCreate(context, native_context,
maybe_regexp, StringConstant("g"));

// 5. Return ? Invoke(rx, @@matchAll, « S »).
Callable callable = CodeFactory::Call(isolate());
TNode<Object> match_all_func =
GetProperty(context, rx, isolate()->factory()->match_all_symbol());
Return(CallJS(callable, context, match_all_func, rx, s));
}

class StringPadAssembler : public StringBuiltinsAssembler {
Expand Down
9 changes: 9 additions & 0 deletions test/mjsunit/harmony/string-matchAll-deleted-matchAll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --harmony-string-matchall

delete RegExp.prototype[Symbol.matchAll];
const str = 'a';
assertThrows(() => str.matchAll(/\w/g), TypeError);
4 changes: 4 additions & 0 deletions test/test262/test262.status
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,10 @@
'harness/detachArrayBuffer': [SKIP],
'harness/detachArrayBuffer-host-detachArrayBuffer': [SKIP],

# Test needs to be updated to spec changes.
# https://github.com/tc39/test262/pull/1990
'built-ins/String/prototype/matchAll/regexp-prototype-has-no-matchAll': [FAIL],

############################ SKIPPED TESTS #############################

# These tests take a looong time to run.
Expand Down

0 comments on commit 29a970a

Please sign in to comment.