From 33f0cf5acd0b0514ceb11e108337e36b50edb018 Mon Sep 17 00:00:00 2001 From: mathiasb Date: Wed, 10 Dec 2014 12:41:00 -0800 Subject: [PATCH] Implement the `RegExp.prototype.flags` getter TEST=mjsunit/harmony BUG=v8:3751 LOG=N Review URL: https://codereview.chromium.org/770333005 Cr-Commit-Position: refs/heads/master@{#25762} --- BUILD.gn | 3 ++- src/bootstrapper.cc | 3 ++- src/harmony-regexp.js | 35 ++++++++++++++++++++++++ src/messages.js | 1 + test/mjsunit/harmony/regexp-flags.js | 40 ++++++++++++++++++++++++++++ tools/gyp/v8.gyp | 3 ++- 6 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 src/harmony-regexp.js create mode 100644 test/mjsunit/harmony/regexp-flags.js diff --git a/BUILD.gn b/BUILD.gn index 996cf078fe13..d6b6ec22aefc 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -243,7 +243,8 @@ action("js2c_experimental") { "src/harmony-typedarray.js", "src/harmony-classes.js", "src/harmony-tostring.js", - "src/harmony-templates.js" + "src/harmony-templates.js", + "src/harmony-regexp.js" ] outputs = [ diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index f13a3dab4e61..c59f9964dff7 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -2166,7 +2166,8 @@ bool Genesis::InstallExperimentalNatives() { static const char* harmony_modules_natives[] = {NULL}; static const char* harmony_scoping_natives[] = {NULL}; static const char* harmony_object_literals_natives[] = {NULL}; - static const char* harmony_regexps_natives[] = {NULL}; + static const char* harmony_regexps_natives[] = { + "native harmony-regexp.js", NULL}; static const char* harmony_arrow_functions_natives[] = {NULL}; static const char* harmony_numeric_literals_natives[] = {NULL}; static const char* harmony_tostring_natives[] = {"native harmony-tostring.js", diff --git a/src/harmony-regexp.js b/src/harmony-regexp.js new file mode 100644 index 000000000000..a2b172983ec3 --- /dev/null +++ b/src/harmony-regexp.js @@ -0,0 +1,35 @@ +// Copyright 2014 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. + +'use strict'; + +var $RegExp = global.RegExp; + +// ------------------------------------------------------------------- + +// ES6 draft 12-06-13, section 21.2.5.3 +// + https://bugs.ecmascript.org/show_bug.cgi?id=3423 +function RegExpGetFlags() { + if (!IS_SPEC_OBJECT(this)) { + throw MakeTypeError('flags_getter_non_object', + [%ToString(this)]); + } + var result = ''; + if (this.global) result += 'g'; + if (this.ignoreCase) result += 'i'; + if (this.multiline) result += 'm'; + if (this.unicode) result += 'u'; + if (this.sticky) result += 'y'; + return result; +} + +function ExtendRegExpPrototype() { + %CheckIsBootstrapping(); + + %DefineAccessorPropertyUnchecked($RegExp.prototype, 'flags', RegExpGetFlags, + null, DONT_ENUM | DONT_DELETE); + %SetNativeFlag(RegExpGetFlags); +} + +ExtendRegExpPrototype(); diff --git a/src/messages.js b/src/messages.js index bf47a45c9d21..56d4ddb504d9 100644 --- a/src/messages.js +++ b/src/messages.js @@ -52,6 +52,7 @@ var kMessages = { apply_wrong_args: ["Function.prototype.apply: Arguments list has wrong type"], toMethod_non_function: ["Function.prototype.toMethod was called on ", "%0", ", which is a ", "%1", " and not a function"], toMethod_non_object: ["Function.prototype.toMethod: home object ", "%0", " is not an object"], + flags_getter_non_object: ["RegExp.prototype.flags getter called on non-object ", "%0"], invalid_in_operator_use: ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"], instanceof_function_expected: ["Expecting a function in instanceof check, but got ", "%0"], instanceof_nonobject_proto: ["Function has non-object prototype '", "%0", "' in instanceof check"], diff --git a/test/mjsunit/harmony/regexp-flags.js b/test/mjsunit/harmony/regexp-flags.js new file mode 100644 index 000000000000..b20044343b8e --- /dev/null +++ b/test/mjsunit/harmony/regexp-flags.js @@ -0,0 +1,40 @@ +// Copyright 2014 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-regexps + +delete RegExp.prototype.flags; +RegExp.prototype.flags = 'setter should be undefined'; + +assertEquals('', RegExp('').flags); +assertEquals('', /./.flags); +assertEquals('gimy', RegExp('', 'ygmi').flags); +assertEquals('gimy', /foo/ymig.flags); + +// TODO(dslomov): When support for the `u` flag is added, uncomment the first +// line below and remove the second line. +//assertEquals(RegExp('', 'yumig').flags, 'gimuy'); +assertThrows(function() { RegExp('', 'yumig').flags; }, SyntaxError); + +var descriptor = Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags'); +assertFalse(descriptor.configurable); +assertFalse(descriptor.enumerable); +assertInstanceof(descriptor.get, Function); +assertEquals(undefined, descriptor.set); + +function testGenericFlags(object) { + return descriptor.get.call(object); +} + +assertEquals('', testGenericFlags({})); +assertEquals('i', testGenericFlags({ ignoreCase: true })); +assertEquals('uy', testGenericFlags({ global: 0, sticky: 1, unicode: 1 })); +assertEquals('m', testGenericFlags({ __proto__: { multiline: true } })); +assertThrows(function() { testGenericFlags(); }, TypeError); +assertThrows(function() { testGenericFlags(undefined); }, TypeError); +assertThrows(function() { testGenericFlags(null); }, TypeError); +assertThrows(function() { testGenericFlags(true); }, TypeError); +assertThrows(function() { testGenericFlags(false); }, TypeError); +assertThrows(function() { testGenericFlags(''); }, TypeError); +assertThrows(function() { testGenericFlags(42); }, TypeError); diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 2a91b1cecfa6..e306effdc5aa 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -1637,7 +1637,8 @@ '../../src/harmony-tostring.js', '../../src/harmony-typedarray.js', '../../src/harmony-classes.js', - '../../src/harmony-templates.js' + '../../src/harmony-templates.js', + '../../src/harmony-regexp.js' ], 'libraries_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries.bin', 'libraries_experimental_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental.bin',