ES2015 web compat workaround: RegExp.prototype.flags => ""

It turns out that some old polyfill library uses
RegExp.prototype.flags as a way of feature testing. It's not clear
how widespread this is. For now, as a minimal workaround, we can
return undefined from getters like RegExp.prototype.global when
the receiver is RegExp.prototype. This patch implements that strategy
but omits a UseCounter to make backports easier.

R=adamk
CC=yangguo@chromium.org
BUG=chromium:581577
LOG=Y
CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_chromium_rel_ng;tryserver.blink:linux_blink_rel

Review URL: https://codereview.chromium.org/1640803003

Cr-Commit-Position: refs/heads/master@{#34201}
This commit is contained in:
littledan 2016-02-22 17:48:31 -08:00 committed by Commit bot
parent 579c01072d
commit b22b258874
6 changed files with 33 additions and 6 deletions

View File

@ -24,8 +24,10 @@ utils.Import(function(from) {
// ES6 21.2.5.15.
function RegExpGetUnicode() {
if (!IS_REGEXP(this)) {
// TODO(littledan): Remove this RegExp compat workaround
if (this === GlobalRegExpPrototype) {
%IncrementUseCounter(kRegExpPrototypeUnicodeGetter);
return UNDEFINED;
}
throw MakeTypeError(kRegExpNonRegExp, "RegExp.prototype.unicode");
}

View File

@ -642,6 +642,10 @@ function RegExpMakeCaptureGetter(n) {
// ES6 21.2.5.4.
function RegExpGetGlobal() {
if (!IS_REGEXP(this)) {
// TODO(littledan): Remove this RegExp compat workaround
if (this === GlobalRegExpPrototype) {
return UNDEFINED;
}
throw MakeTypeError(kRegExpNonRegExp, "RegExp.prototype.global");
}
return !!REGEXP_GLOBAL(this);
@ -653,6 +657,10 @@ function RegExpGetGlobal() {
// ES6 21.2.5.5.
function RegExpGetIgnoreCase() {
if (!IS_REGEXP(this)) {
// TODO(littledan): Remove this RegExp compat workaround
if (this === GlobalRegExpPrototype) {
return UNDEFINED;
}
throw MakeTypeError(kRegExpNonRegExp, "RegExp.prototype.ignoreCase");
}
return !!REGEXP_IGNORE_CASE(this);
@ -664,6 +672,10 @@ function RegExpGetIgnoreCase() {
// ES6 21.2.5.7.
function RegExpGetMultiline() {
if (!IS_REGEXP(this)) {
// TODO(littledan): Remove this RegExp compat workaround
if (this === GlobalRegExpPrototype) {
return UNDEFINED;
}
throw MakeTypeError(kRegExpNonRegExp, "RegExp.prototype.multiline");
}
return !!REGEXP_MULTILINE(this);
@ -675,6 +687,10 @@ function RegExpGetMultiline() {
// ES6 21.2.5.10.
function RegExpGetSource() {
if (!IS_REGEXP(this)) {
// TODO(littledan): Remove this RegExp compat workaround
if (this === GlobalRegExpPrototype) {
return UNDEFINED;
}
throw MakeTypeError(kRegExpNonRegExp, "RegExp.prototype.source");
}
return REGEXP_SOURCE(this);

View File

@ -50,11 +50,9 @@ assertEquals(4, get_count);
function testName(name) {
if (name === "sticky") {
assertEquals(undefined, RegExp.prototype[name]);
} else {
assertThrows(() => RegExp.prototype[name], TypeError);
}
// TODO(littledan): For web compatibility, we don't throw an exception,
// but ES2015 expects an exception to be thrown from this getter.
assertEquals(undefined, RegExp.prototype[name]);
assertEquals(
"get " + name,
Object.getOwnPropertyDescriptor(RegExp.prototype, name).get.name);

View File

@ -0,0 +1,5 @@
// Copyright 2015 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.
assertEquals("", RegExp.prototype.flags);

View File

@ -252,6 +252,12 @@
'built-ins/Object/entries/*': [SKIP],
'built-ins/Object/values/*': [SKIP],
# https://code.google.com/p/chromium/issues/detail?id=581577
'built-ins/RegExp/prototype/source/15.10.7.1-1': [FAIL],
'built-ins/RegExp/prototype/global/15.10.7.2-1': [FAIL],
'built-ins/RegExp/prototype/ignoreCase/15.10.7.3-1': [FAIL],
'built-ins/RegExp/prototype/multiline/15.10.7.4-1': [FAIL],
######################## NEEDS INVESTIGATION ###########################
# These test failures are specific to the intl402 suite and need investigation

View File

@ -28,7 +28,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
PASS RegExp('/').source is "\\/"
PASS RegExp('').source is "(?:)"
FAIL RegExp.prototype.source should be (?:). Threw exception TypeError: RegExp.prototype.source getter called on non-RegExp object
FAIL RegExp.prototype.source should be (?:) (of type string). Was undefined (of type undefined).
PASS RegExp('/').toString() is "/\\//"
PASS RegExp('').toString() is "/(?:)/"
PASS RegExp.prototype.toString() is "/(?:)/"