Implement the `RegExp.prototype.flags` getter
authormathiasb <mathiasb@opera.com>
Wed, 10 Dec 2014 20:41:00 +0000 (12:41 -0800)
committerCommit bot <commit-bot@chromium.org>
Wed, 10 Dec 2014 20:41:10 +0000 (20:41 +0000)
TEST=mjsunit/harmony
BUG=v8:3751
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#25762}

BUILD.gn
src/bootstrapper.cc
src/harmony-regexp.js [new file with mode: 0644]
src/messages.js
test/mjsunit/harmony/regexp-flags.js [new file with mode: 0644]
tools/gyp/v8.gyp

index 996cf07..d6b6ec2 100644 (file)
--- 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 = [
index f13a3da..c59f996 100644 (file)
@@ -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 (file)
index 0000000..a2b1729
--- /dev/null
@@ -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();
index bf47a45..56d4ddb 100644 (file)
@@ -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 (file)
index 0000000..b200443
--- /dev/null
@@ -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);
index 2a91b1c..e306eff 100644 (file)
           '../../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',