Use ordinary object for RegExp prototype

Issue #77
This commit is contained in:
janekptacijarabaci 2018-03-19 10:42:58 +01:00 committed by Roy Tam
commit d275a63a71
3 changed files with 98 additions and 59 deletions

View file

@ -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 5. */
// Step 3.a.
if (!IsRegExpObject(args.thisv())) {
args.rval().setString(cx->names().emptyRegExp);
return true;
}
// 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)

View file

@ -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)

View file

@ -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.