Bug 1120170 - part 2 - Self-host RegExp.prototype.flags. r=till
authorziyunfei <446240525@qq.com>
Sun, 22 Feb 2015 07:23:00 +0100
changeset 230334 f2dcbff898a1b8aa37041fc6b32b4c9defde5f8d
parent 230333 b66941d0e3288e486c2d9c88547b9765abc4d6b5
child 230335 0408a35f9cd71a6c913bddb79737a88aaf6ce659
push id28322
push userkwierso@gmail.com
push dateTue, 24 Feb 2015 00:05:31 +0000
treeherdermozilla-central@368c62292249 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs1120170
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1120170 - part 2 - Self-host RegExp.prototype.flags. r=till
js/src/Makefile.in
js/src/builtin/RegExp.cpp
js/src/builtin/RegExp.js
js/src/jsapi.h
js/src/tests/ecma_6/RegExp/flags.js
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -306,16 +306,17 @@ selfhosting_srcs := \
   $(srcdir)/builtin/Error.js \
   $(srcdir)/builtin/Generator.js \
   $(srcdir)/builtin/Intl.js \
   $(srcdir)/builtin/IntlData.js \
   $(srcdir)/builtin/Iterator.js \
   $(srcdir)/builtin/Map.js \
   $(srcdir)/builtin/Number.js \
   $(srcdir)/builtin/Object.js \
+  $(srcdir)/builtin/RegExp.js \
   $(srcdir)/builtin/String.js \
   $(srcdir)/builtin/Set.js \
   $(srcdir)/builtin/TypedArray.js \
   $(srcdir)/builtin/TypedObject.js \
   $(srcdir)/builtin/WeakSet.js \
   $(NULL)
 
 selfhosted_out_h_deps := \
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -323,77 +323,16 @@ regexp_toString_impl(JSContext *cx, Call
 
 static bool
 regexp_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsRegExp, regexp_toString_impl>(cx, args);
 }
 
-/* ES6 draft rev29 21.2.5.3 RegExp.prototype.flags */
-bool
-regexp_flags(JSContext *cx, unsigned argc, JS::Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-
-    /* Steps 1-2. */
-    if (!args.thisv().isObject()) {
-        char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, args.thisv(), NullPtr());
-        if (!bytes)
-            return false;
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
-                             bytes, "not an object");
-        js_free(bytes);
-        return false;
-    }
-    RootedObject thisObj(cx, &args.thisv().toObject());
-
-    /* Step 3. */
-    StringBuffer sb(cx);
-
-    /* Steps 4-6. */
-    RootedValue global(cx);
-    if (!GetProperty(cx, thisObj, thisObj, cx->names().global, &global))
-        return false;
-    if (ToBoolean(global) && !sb.append('g'))
-        return false;
-
-    /* Steps 7-9. */
-    RootedValue ignoreCase(cx);
-    if (!GetProperty(cx, thisObj, thisObj, cx->names().ignoreCase, &ignoreCase))
-        return false;
-    if (ToBoolean(ignoreCase) && !sb.append('i'))
-        return false;
-
-    /* Steps 10-12. */
-    RootedValue multiline(cx);
-    if (!GetProperty(cx, thisObj, thisObj, cx->names().multiline, &multiline))
-        return false;
-    if (ToBoolean(multiline) && !sb.append('m'))
-        return false;
-
-    /* Steps 13-15. */
-    RootedValue unicode(cx);
-    if (!GetProperty(cx, thisObj, thisObj, cx->names().unicode, &unicode))
-        return false;
-    if (ToBoolean(unicode) && !sb.append('u'))
-        return false;
-
-    /* Steps 16-18. */
-    RootedValue sticky(cx);
-    if (!GetProperty(cx, thisObj, thisObj, cx->names().sticky, &sticky))
-        return false;
-    if (ToBoolean(sticky) && !sb.append('y'))
-        return false;
-
-    /* Step 19. */
-    args.rval().setString(sb.finishString());
-    return true;
-}
-
 /* ES6 draft rev32 21.2.5.4. */
 MOZ_ALWAYS_INLINE bool
 regexp_global_impl(JSContext *cx, CallArgs args)
 {
     MOZ_ASSERT(IsRegExp(args.thisv()));
     Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
 
     /* Steps 4-6. */
@@ -494,17 +433,17 @@ static bool
 regexp_sticky(JSContext *cx, unsigned argc, JS::Value *vp)
 {
     /* Steps 1-3. */
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsRegExp, regexp_sticky_impl>(cx, args);
 }
 
 static const JSPropertySpec regexp_properties[] = {
-    JS_PSG("flags", regexp_flags, 0),
+    JS_SELF_HOSTED_GET("flags", "RegExpFlagsGetter", 0),
     JS_PSG("global", regexp_global, 0),
     JS_PSG("ignoreCase", regexp_ignoreCase, 0),
     JS_PSG("multiline", regexp_multiline, 0),
     JS_PSG("source", regexp_source, 0),
     JS_PSG("sticky", regexp_sticky, 0),
     JS_PS_END
 };
 
new file mode 100644
--- /dev/null
+++ b/js/src/builtin/RegExp.js
@@ -0,0 +1,38 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// ES6 draft rev34 (2015/02/20) 21.2.5.3 get RegExp.prototype.flags
+function RegExpFlagsGetter() {
+    // Steps 1-2.
+    var R = this;
+    if (!IsObject(R))
+        ThrowError(JSMSG_NOT_NONNULL_OBJECT, R === null ? "null" : typeof R);
+
+    // Step 3.
+    var result = "";
+
+    // Steps 4-6.
+    if (R.global)
+        result += "g";
+
+    // Steps 7-9.
+    if (R.ignoreCase)
+        result += "i";
+
+    // Steps 10-12.
+    if (R.multiline)
+        result += "m";
+
+    // Steps 13-15.
+    // TODO: Uncomment these steps when bug 1135377 is fixed.
+    // if (R.unicode)
+    //     result += "u";
+
+    // Steps 16-18.
+    if (R.sticky)
+        result += "y";
+
+    // Step 19.
+    return result;
+}
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2140,17 +2140,17 @@ inline int CheckIsStrictPropertyOp(JSStr
 #define JS_PSGS(name, getter, setter, flags) \
     {name, \
      uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \
      JSNATIVE_WRAPPER(getter), \
      JSNATIVE_WRAPPER(setter)}
 #define JS_SELF_HOSTED_GET(name, getterName, flags) \
     {name, \
      uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
-     { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo *) }, \
+     { { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo *) } }, \
      JSNATIVE_WRAPPER(nullptr) }
 #define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \
     {name, \
      uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER), \
      { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo *) },  \
      { nullptr, JS_CAST_STRING_TO(setterName, const JSJitInfo *) } }
 #define JS_PS_END { nullptr, 0, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr) }
 
--- a/js/src/tests/ecma_6/RegExp/flags.js
+++ b/js/src/tests/ecma_6/RegExp/flags.js
@@ -2,24 +2,26 @@ var BUGNUMBER = 1108467;
 var summary = "Implement RegExp.prototype.flags";
 
 print(BUGNUMBER + ": " + summary);
 
 assertEq(RegExp.prototype.flags, "");
 assertEq(/foo/iymg.flags, "gimy");
 assertEq(RegExp("").flags, "");
 assertEq(RegExp("", "mygi").flags, "gimy");
+// TODO: Uncomment lines 12, 16, 19 and remove lines 11, 15, 18 when bug 1135377 is fixed.
 assertThrowsInstanceOf(() => RegExp("", "mygui").flags, SyntaxError);
-// When the /u flag is supported, uncomment the line below and remove the line above
 // assertEq(RegExp("", "mygui").flags, "gimuy");
 assertEq(genericFlags({}), "");
 assertEq(genericFlags({ignoreCase: true}), "i");
-assertEq(genericFlags({sticky:1, unicode:1, global: 0}), "uy");
+assertEq(genericFlags({sticky:1, unicode:1, global: 0}), "y");
+// assertEq(genericFlags({sticky:1, unicode:1, global: 0}), "uy");
 assertEq(genericFlags({__proto__: {multiline: true}}), "m");
-assertEq(genericFlags(new Proxy({}, {get(){return true}})), "gimuy");
+assertEq(genericFlags(new Proxy({}, {get(){return true}})), "gimy");
+// assertEq(genericFlags(new Proxy({}, {get(){return true}})), "gimuy");
 
 assertThrowsInstanceOf(() => genericFlags(), TypeError);
 assertThrowsInstanceOf(() => genericFlags(1), TypeError);
 assertThrowsInstanceOf(() => genericFlags(""), TypeError);
 
 function genericFlags(obj) {
     return Object.getOwnPropertyDescriptor(RegExp.prototype,"flags").get.call(obj);
 }