Commit c6341230 authored by Joshua Litt's avatar Joshua Litt Committed by Commit Bot

[regexp] Modify matchAll to throw on non-globals.

This cl modifies RegExp.prototype.matchAll to throw on
non-global regexps.

Relevant pull request: https://github.com/tc39/ecma262/pull/1716

Bug: v8:9800
Change-Id: Ie963c1c00441f1c4e2b975c3bab77cca902c7ebc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1846067Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Joshua Litt <joshualitt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64318}
parent 0b9f1053
......@@ -1529,7 +1529,51 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) {
// 1. Let O be ? RequireObjectCoercible(this value).
RequireObjectCoercible(context, receiver, method_name);
// 2. If regexp is neither undefined nor null, then
RegExpMatchAllAssembler regexp_asm(state());
{
Label fast(this), slow(this, Label::kDeferred),
throw_exception(this, Label::kDeferred), next(this);
// 2. If regexp is neither undefined nor null, then
// a. Let isRegExp be ? IsRegExp(regexp).
// b. If isRegExp is true, then
// i. Let flags be ? Get(regexp, "flags").
// ii. Perform ? RequireObjectCoercible(flags).
// iii. If ? ToString(flags) does not contain "g", throw a
// TypeError exception.
GotoIf(TaggedIsSmi(maybe_regexp), &next);
TNode<HeapObject> heap_maybe_regexp = CAST(maybe_regexp);
regexp_asm.BranchIfFastRegExp_Strict(context, heap_maybe_regexp, &fast,
&slow);
BIND(&fast);
{
TNode<BoolT> is_global = regexp_asm.FlagGetter(context, heap_maybe_regexp,
JSRegExp::kGlobal, true);
Branch(is_global, &next, &throw_exception);
}
BIND(&slow);
{
GotoIfNot(regexp_asm.IsRegExp(native_context, heap_maybe_regexp), &next);
TNode<Object> flags = GetProperty(context, heap_maybe_regexp,
isolate()->factory()->flags_string());
RequireObjectCoercible(context, flags, method_name);
TNode<String> flags_string = ToString_Inline(context, flags);
TNode<String> global_char_string = StringConstant("g");
TNode<Smi> global_ix =
CAST(CallBuiltin(Builtins::kStringIndexOf, context, flags_string,
global_char_string, SmiConstant(0)));
Branch(SmiEqual(global_ix, SmiConstant(-1)), &throw_exception, &next);
}
BIND(&throw_exception);
ThrowTypeError(context, MessageTemplate::kRegExpGlobalInvokedOnNonGlobal);
BIND(&next);
}
// a. Let matcher be ? GetMethod(regexp, @@matchAll).
// b. If matcher is not undefined, then
// i. Return ? Call(matcher, regexp, « O »).
......@@ -1552,8 +1596,6 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) {
Context::REGEXP_MATCH_ALL_FUNCTION_INDEX},
if_regexp_call, if_generic_call);
RegExpMatchAllAssembler regexp_asm(state());
// 3. Let S be ? ToString(O).
TNode<String> s = ToString_Inline(context, receiver);
......
......@@ -270,6 +270,8 @@ namespace internal {
"Cannot supply flags when constructing one RegExp from another") \
T(RegExpNonObject, "% getter called on non-object %") \
T(RegExpNonRegExp, "% getter called on non-RegExp object") \
T(RegExpGlobalInvokedOnNonGlobal, \
"%s called with a non-global RegExp argument") \
T(RelativeDateTimeFormatterBadParameters, \
"Incorrect RelativeDateTimeFormatter provided") \
T(ResolverNotAFunction, "Promise resolver % is not a function") \
......
......@@ -296,7 +296,7 @@ bytecodes: [
B(Mov), R(context), R(16),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(17),
B(LdaConstant), U8(11),
B(Star), R(18),
......
......@@ -61,7 +61,7 @@ bytecodes: [
B(Mov), R(context), R(11),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(12),
B(LdaConstant), U8(5),
B(Star), R(13),
......@@ -191,7 +191,7 @@ bytecodes: [
B(Mov), R(context), R(12),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(13),
B(LdaConstant), U8(5),
B(Star), R(14),
......@@ -308,7 +308,7 @@ bytecodes: [
B(Mov), R(context), R(13),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(14),
B(LdaConstant), U8(6),
B(Star), R(15),
......
......@@ -93,7 +93,7 @@ bytecodes: [
B(Mov), R(context), R(15),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(16),
B(LdaConstant), U8(9),
B(Star), R(17),
......@@ -260,7 +260,7 @@ bytecodes: [
B(Mov), R(context), R(15),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(16),
B(LdaConstant), U8(9),
B(Star), R(17),
......@@ -443,7 +443,7 @@ bytecodes: [
B(Mov), R(context), R(15),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(16),
B(LdaConstant), U8(9),
B(Star), R(17),
......@@ -590,7 +590,7 @@ bytecodes: [
B(Mov), R(context), R(12),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(13),
B(LdaConstant), U8(7),
B(Star), R(14),
......
......@@ -58,7 +58,7 @@ bytecodes: [
B(Mov), R(context), R(10),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(11),
B(LdaConstant), U8(5),
B(Star), R(12),
......@@ -154,7 +154,7 @@ bytecodes: [
B(Mov), R(context), R(11),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(12),
B(LdaConstant), U8(5),
B(Star), R(13),
......@@ -261,7 +261,7 @@ bytecodes: [
B(Mov), R(context), R(10),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(11),
B(LdaConstant), U8(5),
B(Star), R(12),
......@@ -361,7 +361,7 @@ bytecodes: [
B(Mov), R(context), R(10),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(11),
B(LdaConstant), U8(7),
B(Star), R(12),
......
......@@ -61,7 +61,7 @@ bytecodes: [
B(Mov), R(context), R(12),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(13),
B(LdaConstant), U8(4),
B(Star), R(14),
......@@ -192,7 +192,7 @@ bytecodes: [
B(Mov), R(context), R(13),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(14),
B(LdaConstant), U8(9),
B(Star), R(15),
......@@ -300,7 +300,7 @@ bytecodes: [
B(Mov), R(context), R(11),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(12),
B(LdaConstant), U8(6),
B(Star), R(13),
......@@ -400,7 +400,7 @@ bytecodes: [
B(Mov), R(context), R(14),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(15),
B(LdaConstant), U8(6),
B(Star), R(16),
......@@ -510,7 +510,7 @@ bytecodes: [
B(Mov), R(context), R(13),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(14),
B(LdaConstant), U8(7),
B(Star), R(15),
......@@ -635,7 +635,7 @@ bytecodes: [
B(Mov), R(context), R(12),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(13),
B(LdaConstant), U8(10),
B(Star), R(14),
......@@ -744,7 +744,7 @@ bytecodes: [
B(Mov), R(context), R(14),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(15),
B(LdaConstant), U8(4),
B(Star), R(16),
......@@ -877,7 +877,7 @@ bytecodes: [
B(Mov), R(context), R(13),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(14),
B(LdaConstant), U8(5),
B(Star), R(15),
......
......@@ -176,7 +176,7 @@ bytecodes: [
B(Mov), R(context), R(12),
B(TestTypeOf), U8(6),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(159),
B(Wide), B(LdaSmi), I16(160),
B(Star), R(13),
B(LdaConstant), U8(11),
B(Star), R(14),
......
......@@ -84,7 +84,7 @@ bytecodes: [
B(Star), R(1),
B(Mov), R(this), R(0),
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
/* 53 S> */ B(Wide), B(LdaSmi), I16(263),
/* 53 S> */ B(Wide), B(LdaSmi), I16(264),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -115,7 +115,7 @@ bytecodes: [
B(Star), R(1),
B(Mov), R(this), R(0),
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
/* 46 S> */ B(Wide), B(LdaSmi), I16(262),
/* 46 S> */ B(Wide), B(LdaSmi), I16(263),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -146,7 +146,7 @@ bytecodes: [
B(Star), R(1),
B(Mov), R(this), R(0),
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
/* 53 S> */ B(Wide), B(LdaSmi), I16(263),
/* 53 S> */ B(Wide), B(LdaSmi), I16(264),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -177,7 +177,7 @@ bytecodes: [
B(Star), R(1),
B(Mov), R(this), R(0),
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
/* 46 S> */ B(Wide), B(LdaSmi), I16(262),
/* 46 S> */ B(Wide), B(LdaSmi), I16(263),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
......
......@@ -57,7 +57,7 @@ bytecodes: [
B(Star), R(1),
B(Mov), R(this), R(0),
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
/* 49 S> */ B(Wide), B(LdaSmi), I16(261),
/* 49 S> */ B(Wide), B(LdaSmi), I16(262),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -89,7 +89,7 @@ bytecodes: [
B(Star), R(1),
B(Mov), R(this), R(0),
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
/* 49 S> */ B(Wide), B(LdaSmi), I16(261),
/* 49 S> */ B(Wide), B(LdaSmi), I16(262),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......
......@@ -26,7 +26,7 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(1),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(259),
B(Wide), B(LdaSmi), I16(260),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -58,7 +58,7 @@ parameter count: 1
bytecode array length: 17
bytecodes: [
/* 51 E> */ B(StackCheck),
/* 56 S> */ B(Wide), B(LdaSmi), I16(261),
/* 56 S> */ B(Wide), B(LdaSmi), I16(262),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -86,7 +86,7 @@ parameter count: 1
bytecode array length: 17
bytecodes: [
/* 51 E> */ B(StackCheck),
/* 56 S> */ B(Wide), B(LdaSmi), I16(261),
/* 56 S> */ B(Wide), B(LdaSmi), I16(262),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -126,7 +126,7 @@ bytecodes: [
/* 94 E> */ B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(259),
B(Wide), B(LdaSmi), I16(260),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -148,7 +148,7 @@ bytecodes: [
/* 109 E> */ B(TestReferenceEqual), R(this),
B(Mov), R(this), R(1),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(260),
B(Wide), B(LdaSmi), I16(261),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
......@@ -163,7 +163,7 @@ bytecodes: [
/* 133 E> */ B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(259),
B(Wide), B(LdaSmi), I16(260),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -194,7 +194,7 @@ parameter count: 1
bytecode array length: 17
bytecodes: [
/* 55 E> */ B(StackCheck),
/* 60 S> */ B(Wide), B(LdaSmi), I16(263),
/* 60 S> */ B(Wide), B(LdaSmi), I16(264),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -221,7 +221,7 @@ parameter count: 1
bytecode array length: 17
bytecodes: [
/* 48 E> */ B(StackCheck),
/* 53 S> */ B(Wide), B(LdaSmi), I16(262),
/* 53 S> */ B(Wide), B(LdaSmi), I16(263),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -248,7 +248,7 @@ parameter count: 1
bytecode array length: 17
bytecodes: [
/* 55 E> */ B(StackCheck),
/* 60 S> */ B(Wide), B(LdaSmi), I16(263),
/* 60 S> */ B(Wide), B(LdaSmi), I16(264),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -275,7 +275,7 @@ parameter count: 1
bytecode array length: 17
bytecodes: [
/* 41 E> */ B(StackCheck),
/* 46 S> */ B(Wide), B(LdaSmi), I16(262),
/* 46 S> */ B(Wide), B(LdaSmi), I16(263),
B(Star), R(1),
B(LdaConstant), U8(0),
B(Star), R(2),
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
(function TestReceiverNonString() {
const iter = 'a'.matchAll(/./);
const iter = 'a'.matchAll(/./g);
assertThrows(
() => iter.next.call(0),
TypeError
......@@ -12,7 +12,7 @@
(function TestAncestry() {
const iterProto = Object.getPrototypeOf('a'.matchAll(/./));
const iterProto = Object.getPrototypeOf('a'.matchAll(/./g));
const arrProto = Object.getPrototypeOf([][Symbol.iterator]());
assertSame(Object.getPrototypeOf(iterProto), Object.getPrototypeOf(arrProto));
......@@ -24,20 +24,14 @@ function TestNoMatch(string, regex_or_string) {
assertSame(undefined, next_result.value);
assertTrue(next_result.done);
}
TestNoMatch('a', /b/);
TestNoMatch('a', /b/g);
TestNoMatch('a', 'b');
(function NonGlobalRegex() {
const iter = 'ab'.matchAll(/./);
let next_result = iter.next();
assertEquals(['a'], next_result.value);
assertFalse(next_result.done);
next_result = iter.next();
assertEquals(undefined, next_result.value);
assertTrue(next_result.done);
assertThrows(
() => { const iter = 'ab'.matchAll(/./); },
TypeError);
})();
......
......@@ -4,7 +4,7 @@
var s = "baa";
assertEquals([["b"]], [...s.matchAll(/./)]);
assertEquals([["b"], ["a"], ["a"]], [...s.matchAll(/./g)]);
RegExp.prototype[Symbol.matchAll] = () => 42;
assertEquals(42, s.matchAll(/a./));
assertEquals(42, s.matchAll(/a./g));
......@@ -8,7 +8,7 @@ class MyRegExp {
exec() { return null; }
}
var r = /c/;
var r = /c/g;
assertEquals(["ab", ""], "abc".split(r));
assertEquals([["c"]], [..."c".matchAll(r)]);
......@@ -18,10 +18,10 @@ r.constructor = { [Symbol.species] : MyRegExp };
assertEquals(["abc"], "abc".split(r));
assertEquals([], [..."c".matchAll(r)]);
assertEquals(["ab", ""], "abc".split(/c/));
assertEquals([["c"]], [..."c".matchAll(/c/)]);
assertEquals(["ab", ""], "abc".split(/c/g));
assertEquals([["c"]], [..."c".matchAll(/c/g)]);
RegExp.prototype.constructor = { [Symbol.species] : MyRegExp };
assertEquals(["abc"], "abc".split(/c/));
assertEquals([], [..."c".matchAll(/c/)]);
assertEquals(["abc"], "abc".split(/c/g));
assertEquals([], [..."c".matchAll(/c/g)]);
......@@ -8,10 +8,10 @@ class MyRegExp {
exec() { return null; }
}
assertEquals(["ab", ""], "abc".split(/c/));
assertEquals([["a"]], [..."a".matchAll(/a/)]);
assertEquals(["ab", ""], "abc".split(/c/g));
assertEquals([["a"]], [..."a".matchAll(/a/g)]);
Object.defineProperty(RegExp, Symbol.species, { get() { return MyRegExp; }});
assertEquals(["abc"], "abc".split(/c/));
assertEquals([], [..."a".matchAll(/a/)]);
assertEquals(["abc"], "abc".split(/c/g));
assertEquals([], [..."a".matchAll(/a/g)]);
......@@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
''.matchAll(/./u);
''.matchAll(/./ug);
......@@ -550,7 +550,12 @@
# https://bugs.chromium.org/p/v8/issues/detail?id=9800
'built-ins/String/prototype/matchAll/flags-undefined-throws': [FAIL],
'built-ins/String/prototype/matchAll/flags-nonglobal-throws': [FAIL],
'built-ins/String/prototype/matchAll/regexp-get-matchAll-throws': [FAIL],
'built-ins/String/prototype/matchAll/regexp-matchAll-is-undefined-or-null': [FAIL],
'built-ins/String/prototype/matchAll/regexp-prototype-matchAll-throws': [FAIL],
'built-ins/String/prototype/matchAll/regexp-matchAll-throws': [FAIL],
'built-ins/String/prototype/matchAll/regexp-prototype-matchAll-invocation': [FAIL],
'built-ins/String/prototype/matchAll/regexp-prototype-get-matchAll-throws': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=9818
'built-ins/AsyncFunction/proto-from-ctor-realm': [FAIL],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment