summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-03-19 10:42:58 +0100
committerjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-03-19 10:42:58 +0100
commitdf313c5b777daf119385beb8b12c60c33b35a2d0 (patch)
tree774103d300333a82fb02dd3eb928c5583670bcb4
parentcf70142093eb145b8e349bd7a95e22a55662a6d3 (diff)
downloaduxp-df313c5b777daf119385beb8b12c60c33b35a2d0.tar.gz
Use ordinary object for RegExp prototype
Issue #77
-rw-r--r--js/src/builtin/RegExp.cpp140
-rw-r--r--js/src/vm/RegExpObject.cpp13
-rw-r--r--js/src/vm/RegExpObject.h4
3 files changed, 98 insertions, 59 deletions
diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp
index 80a4bb5bde..b20f41c53e 100644
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -577,14 +577,29 @@ js::regexp_clone(JSContext* cx, unsigned argc, Value* vp)
return true;
}
-/* ES6 draft rev32 21.2.5.4. */
+MOZ_ALWAYS_INLINE bool
+IsRegExpInstanceOrPrototype(HandleValue v)
+{
+ if (!v.isObject())
+ return false;
+
+ return StandardProtoKeyOrNull(&v.toObject()) == JSProto_RegExp;
+}
+
+// ES 2017 draft 21.2.5.4.
MOZ_ALWAYS_INLINE bool
regexp_global_impl(JSContext* cx, const CallArgs& args)
{
- MOZ_ASSERT(IsRegExpObject(args.thisv()));
- Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
+ MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv()));
- /* Steps 4-6. */
+ // Step 3.a.
+ if (!IsRegExpObject(args.thisv())) {
+ args.rval().setUndefined();
+ return true;
+ }
+
+ // Steps 4-6.
+ Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
args.rval().setBoolean(reObj->global());
return true;
}
@@ -592,19 +607,25 @@ regexp_global_impl(JSContext* cx, const CallArgs& args)
bool
js::regexp_global(JSContext* cx, unsigned argc, JS::Value* vp)
{
- /* Steps 1-3. */
+ // Steps 1-3.
CallArgs args = CallArgsFromVp(argc, vp);
- return CallNonGenericMethod<IsRegExpObject, regexp_global_impl>(cx, args);
+ return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_global_impl>(cx, args);
}
-/* ES6 draft rev32 21.2.5.5. */
+// ES 2017 draft 21.2.5.5.
MOZ_ALWAYS_INLINE bool
regexp_ignoreCase_impl(JSContext* cx, const CallArgs& args)
{
- MOZ_ASSERT(IsRegExpObject(args.thisv()));
- Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
+ MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv()));
- /* Steps 4-6. */
+ // Step 3.a
+ if (!IsRegExpObject(args.thisv())) {
+ args.rval().setUndefined();
+ return true;
+ }
+
+ // Steps 4-6.
+ Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
args.rval().setBoolean(reObj->ignoreCase());
return true;
}
@@ -612,19 +633,25 @@ regexp_ignoreCase_impl(JSContext* cx, const CallArgs& args)
bool
js::regexp_ignoreCase(JSContext* cx, unsigned argc, JS::Value* vp)
{
- /* Steps 1-3. */
+ // Steps 1-3.
CallArgs args = CallArgsFromVp(argc, vp);
- return CallNonGenericMethod<IsRegExpObject, regexp_ignoreCase_impl>(cx, args);
+ return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_ignoreCase_impl>(cx, args);
}
-/* ES6 draft rev32 21.2.5.7. */
+// ES 2017 draft 21.2.5.7.
MOZ_ALWAYS_INLINE bool
regexp_multiline_impl(JSContext* cx, const CallArgs& args)
{
- MOZ_ASSERT(IsRegExpObject(args.thisv()));
- Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
+ MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv()));
- /* Steps 4-6. */
+ // Step 3.a.
+ if (!IsRegExpObject(args.thisv())) {
+ args.rval().setUndefined();
+ return true;
+ }
+
+ // Steps 4-6.
+ Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
args.rval().setBoolean(reObj->multiline());
return true;
}
@@ -632,24 +659,30 @@ regexp_multiline_impl(JSContext* cx, const CallArgs& args)
bool
js::regexp_multiline(JSContext* cx, unsigned argc, JS::Value* vp)
{
- /* Steps 1-3. */
+ // Steps 1-3.
CallArgs args = CallArgsFromVp(argc, vp);
- return CallNonGenericMethod<IsRegExpObject, regexp_multiline_impl>(cx, args);
+ return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_multiline_impl>(cx, args);
}
-/* ES6 draft rev32 21.2.5.10. */
+// ES 2017 draft rev32 21.2.5.10.
MOZ_ALWAYS_INLINE bool
regexp_source_impl(JSContext* cx, const CallArgs& args)
{
- MOZ_ASSERT(IsRegExpObject(args.thisv()));
- Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
+ MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv()));
+
+ // Step 3.a.
+ if (!IsRegExpObject(args.thisv())) {
+ args.rval().setString(cx->names().emptyRegExp);
+ return true;
+ }
- /* Step 5. */
+ // Step 5.
+ Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
RootedAtom src(cx, reObj->getSource());
if (!src)
return false;
- /* Step 7. */
+ // Step 7.
RootedString str(cx, EscapeRegExpPattern(cx, src));
if (!str)
return false;
@@ -661,19 +694,25 @@ regexp_source_impl(JSContext* cx, const CallArgs& args)
static bool
regexp_source(JSContext* cx, unsigned argc, JS::Value* vp)
{
- /* Steps 1-4. */
+ // Steps 1-4.
CallArgs args = CallArgsFromVp(argc, vp);
- return CallNonGenericMethod<IsRegExpObject, regexp_source_impl>(cx, args);
+ return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_source_impl>(cx, args);
}
-/* ES6 draft rev32 21.2.5.12. */
+// ES 2017 draft 21.2.5.12.
MOZ_ALWAYS_INLINE bool
regexp_sticky_impl(JSContext* cx, const CallArgs& args)
{
- MOZ_ASSERT(IsRegExpObject(args.thisv()));
- Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
+ MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv()));
- /* Steps 4-6. */
+ // Step 3.a.
+ if (!IsRegExpObject(args.thisv())) {
+ args.rval().setUndefined();
+ return true;
+ }
+
+ // Steps 4-6.
+ Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
args.rval().setBoolean(reObj->sticky());
return true;
}
@@ -681,27 +720,35 @@ regexp_sticky_impl(JSContext* cx, const CallArgs& args)
bool
js::regexp_sticky(JSContext* cx, unsigned argc, JS::Value* vp)
{
- /* Steps 1-3. */
+ // Steps 1-3.
CallArgs args = CallArgsFromVp(argc, vp);
- return CallNonGenericMethod<IsRegExpObject, regexp_sticky_impl>(cx, args);
+ return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_sticky_impl>(cx, args);
}
-/* ES6 21.2.5.15. */
+// ES 2017 draft 21.2.5.15.
MOZ_ALWAYS_INLINE bool
regexp_unicode_impl(JSContext* cx, const CallArgs& args)
{
- MOZ_ASSERT(IsRegExpObject(args.thisv()));
- /* Steps 4-6. */
- args.rval().setBoolean(args.thisv().toObject().as<RegExpObject>().unicode());
+ MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv()));
+
+ // Step 3.a.
+ if (!IsRegExpObject(args.thisv())) {
+ args.rval().setUndefined();
+ return true;
+ }
+
+ // Steps 4-6.
+ Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>());
+ args.rval().setBoolean(reObj->unicode());
return true;
}
bool
js::regexp_unicode(JSContext* cx, unsigned argc, JS::Value* vp)
{
- /* Steps 1-3. */
+ // Steps 1-3.
CallArgs args = CallArgsFromVp(argc, vp);
- return CallNonGenericMethod<IsRegExpObject, regexp_unicode_impl>(cx, args);
+ return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_unicode_impl>(cx, args);
}
const JSPropertySpec js::regexp_properties[] = {
@@ -829,25 +876,6 @@ const JSPropertySpec js::regexp_static_props[] = {
JS_PS_END
};
-JSObject*
-js::CreateRegExpPrototype(JSContext* cx, JSProtoKey key)
-{
- MOZ_ASSERT(key == JSProto_RegExp);
-
- Rooted<RegExpObject*> proto(cx, cx->global()->createBlankPrototype<RegExpObject>(cx));
- if (!proto)
- return nullptr;
- proto->NativeObject::setPrivate(nullptr);
-
- if (!RegExpObject::assignInitialShape(cx, proto))
- return nullptr;
-
- RootedAtom source(cx, cx->names().empty);
- proto->initAndZeroLastIndex(source, RegExpFlag(0), cx);
-
- return proto;
-}
-
template <typename CharT>
static bool
IsTrailSurrogateWithLeadSurrogateImpl(JSContext* cx, HandleLinearString input, size_t index)
diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
index 97f1163aa8..e0b44e1eb7 100644
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -196,6 +196,12 @@ RegExpObject::trace(JSTracer* trc, JSObject* obj)
}
}
+static JSObject*
+CreateRegExpPrototype(JSContext* cx, JSProtoKey key)
+{
+ return cx->global()->createBlankPrototype(cx, &RegExpObject::protoClass_);
+}
+
static const ClassOps RegExpObjectClassOps = {
nullptr, /* addProperty */
nullptr, /* delProperty */
@@ -229,6 +235,13 @@ const Class RegExpObject::class_ = {
&RegExpObjectClassSpec
};
+const Class RegExpObject::protoClass_ = {
+ js_Object_str,
+ JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
+ JS_NULL_CLASS_OPS,
+ &RegExpObjectClassSpec
+};
+
RegExpObject*
RegExpObject::create(ExclusiveContext* cx, const char16_t* chars, size_t length, RegExpFlag flags,
TokenStream* tokenStream, LifoAlloc& alloc)
diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h
index d6dde16684..dc428a9735 100644
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -79,9 +79,6 @@ RegExpAlloc(ExclusiveContext* cx, HandleObject proto = nullptr);
extern JSObject*
CloneRegExpObject(JSContext* cx, JSObject* regexp);
-extern JSObject*
-CreateRegExpPrototype(JSContext* cx, JSProtoKey key);
-
/*
* A RegExpShared is the compiled representation of a regexp. A RegExpShared is
* potentially pointed to by multiple RegExpObjects. Additionally, C++ code may
@@ -411,6 +408,7 @@ class RegExpObject : public NativeObject
static const unsigned PRIVATE_SLOT = 3;
static const Class class_;
+ static const Class protoClass_;
// The maximum number of pairs a MatchResult can have, without having to
// allocate a bigger MatchResult.