mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 14:54:25 +00:00
Issue #2305 Part 2: Support .indices in match result template objects
Before match indices, all match results had the same shape. (If there are no named capture groups, `.groups` exists but is undefined.) Match results with `.indices` have a distinct shape, so we need a distinct template object. We also need a template object for `.indices` itself.
This commit is contained in:
@@ -198,6 +198,7 @@
|
||||
macro(includes, includes, "includes") \
|
||||
macro(incumbentGlobal, incumbentGlobal, "incumbentGlobal") \
|
||||
macro(index, index, "index") \
|
||||
macro(indices, indices, "indices") \
|
||||
macro(infinity, infinity, "infinity") \
|
||||
macro(Infinity, Infinity, "Infinity") \
|
||||
macro(InitializeCollator, InitializeCollator, "InitializeCollator") \
|
||||
|
||||
+43
-29
@@ -1297,10 +1297,13 @@ RegExpShared::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
|
||||
RegExpCompartment::RegExpCompartment(Zone* zone)
|
||||
: set_(zone, Set(zone->runtimeFromMainThread())),
|
||||
matchResultTemplateObject_(nullptr),
|
||||
optimizableRegExpPrototypeShape_(nullptr),
|
||||
optimizableRegExpInstanceShape_(nullptr)
|
||||
{}
|
||||
{
|
||||
for (auto& templateObj : matchResultTemplateObjects_) {
|
||||
templateObj = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RegExpCompartment::~RegExpCompartment()
|
||||
{
|
||||
@@ -1308,38 +1311,53 @@ RegExpCompartment::~RegExpCompartment()
|
||||
}
|
||||
|
||||
ArrayObject*
|
||||
RegExpCompartment::createMatchResultTemplateObject(JSContext* cx)
|
||||
RegExpCompartment::createMatchResultTemplateObject(JSContext* cx, ResultTemplateKind kind)
|
||||
{
|
||||
MOZ_ASSERT(!matchResultTemplateObject_);
|
||||
MOZ_ASSERT(!matchResultTemplateObjects_[kind]);
|
||||
|
||||
/* Create template array object */
|
||||
RootedArrayObject templateObject(cx, NewDenseUnallocatedArray(cx, RegExpObject::MaxPairCount,
|
||||
nullptr, TenuredObject));
|
||||
if (!templateObject)
|
||||
return matchResultTemplateObject_; // = nullptr
|
||||
if (!templateObject) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create a new group for the template.
|
||||
Rooted<TaggedProto> proto(cx, templateObject->taggedProto());
|
||||
ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto);
|
||||
if (!group)
|
||||
return matchResultTemplateObject_; // = nullptr
|
||||
return nullptr;
|
||||
templateObject->setGroup(group);
|
||||
|
||||
if (kind == ResultTemplateKind::Indices) {
|
||||
/* The |indices| array only has a |groups| property. */
|
||||
RootedValue groupsVal(cx, UndefinedValue());
|
||||
if (!NativeDefineProperty(cx, templateObject, cx->names().groups,
|
||||
groupsVal, nullptr, nullptr, JSPROP_ENUMERATE)) {
|
||||
return nullptr;
|
||||
}
|
||||
AddTypePropertyId(cx, templateObject, NameToId(cx->names().groups), TypeSet::AnyObjectType());
|
||||
matchResultTemplateObjects_[kind].set(templateObject);
|
||||
return matchResultTemplateObjects_[kind];
|
||||
}
|
||||
|
||||
/* Set dummy index property */
|
||||
RootedValue index(cx, Int32Value(0));
|
||||
if (!NativeDefineProperty(cx, templateObject, cx->names().index, index, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE))
|
||||
{
|
||||
return matchResultTemplateObject_; // = nullptr
|
||||
return nullptr;
|
||||
}
|
||||
AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::UndefinedType());
|
||||
|
||||
/* Set dummy input property */
|
||||
RootedValue inputVal(cx, StringValue(cx->runtime()->emptyString));
|
||||
if (!NativeDefineProperty(cx, templateObject, cx->names().input, inputVal, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE))
|
||||
{
|
||||
return matchResultTemplateObject_; // = nullptr
|
||||
return nullptr;
|
||||
}
|
||||
AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::StringType());
|
||||
|
||||
/* Set dummy groups property */
|
||||
RootedValue groupsVal(cx, UndefinedValue());
|
||||
@@ -1347,25 +1365,21 @@ RegExpCompartment::createMatchResultTemplateObject(JSContext* cx)
|
||||
cx, templateObject, cx->names().groups, groupsVal, nullptr, nullptr, JSPROP_ENUMERATE)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Make sure that the properties are in the right slots.
|
||||
DebugOnly<Shape*> shape = templateObject->lastProperty();
|
||||
MOZ_ASSERT(shape->slot() == 2 &&
|
||||
shape->propidRef() == NameToId(cx->names().groups));
|
||||
MOZ_ASSERT(shape->previous()->slot() == 1 &&
|
||||
shape->previous()->propidRef() == NameToId(cx->names().input));
|
||||
MOZ_ASSERT(shape->previous()->previous()->slot() == 0 &&
|
||||
shape->previous()->previous()->propidRef() == NameToId(cx->names().index));
|
||||
|
||||
// Make sure type information reflects the indexed properties which might
|
||||
// be added.
|
||||
AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::StringType());
|
||||
AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::UndefinedType());
|
||||
AddTypePropertyId(cx, templateObject, NameToId(cx->names().groups), TypeSet::AnyObjectType());
|
||||
|
||||
matchResultTemplateObject_.set(templateObject);
|
||||
if (kind == ResultTemplateKind::WithIndices) {
|
||||
/* Set dummy indices property */
|
||||
RootedValue indicesVal(cx, UndefinedValue());
|
||||
if (!NativeDefineProperty(cx, templateObject, cx->names().indices,
|
||||
indicesVal, nullptr, nullptr, JSPROP_ENUMERATE)) {
|
||||
return nullptr;
|
||||
}
|
||||
AddTypePropertyId(cx, templateObject, NameToId(cx->names().indices), TypeSet::AnyObjectType());
|
||||
}
|
||||
|
||||
return matchResultTemplateObject_;
|
||||
matchResultTemplateObjects_[kind].set(templateObject);
|
||||
|
||||
return matchResultTemplateObjects_[kind];
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1383,10 +1397,10 @@ RegExpCompartment::init(JSContext* cx)
|
||||
void
|
||||
RegExpCompartment::sweep(JSRuntime* rt)
|
||||
{
|
||||
if (matchResultTemplateObject_ &&
|
||||
IsAboutToBeFinalized(&matchResultTemplateObject_))
|
||||
{
|
||||
matchResultTemplateObject_.set(nullptr);
|
||||
for (auto& templateObject : matchResultTemplateObjects_) {
|
||||
if (templateObject && IsAboutToBeFinalized(&templateObject)) {
|
||||
templateObject.set(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (optimizableRegExpPrototypeShape_ &&
|
||||
|
||||
@@ -298,12 +298,27 @@ class RegExpCompartment
|
||||
using Set = GCHashSet<ReadBarriered<RegExpShared*>, Key, RuntimeAllocPolicy>;
|
||||
JS::WeakCache<Set> set_;
|
||||
|
||||
public:
|
||||
enum ResultTemplateKind { Normal, WithIndices, Indices, NumKinds };
|
||||
|
||||
private:
|
||||
/*
|
||||
* This is the template object where the result of re.exec() is based on,
|
||||
* if there is a result. This is used in CreateRegExpMatchResult to set
|
||||
* the input/index properties faster.
|
||||
* The template objects that the result of re.exec() is based on, if
|
||||
* there is a result. These are used in CreateRegExpMatchResult.
|
||||
* There are three template objects, each of which is an ArrayObject
|
||||
* with some additional properties. We decide which to use based on
|
||||
* the |hasIndices| (/d) flag.
|
||||
*
|
||||
* Normal: Has |index|, |input|, and |groups| properties.
|
||||
* Used for the result object if |hasIndices| is not set.
|
||||
*
|
||||
* WithIndices: Has |index|, |input|, |groups|, and |indices| properties.
|
||||
* Used for the result object if |hasIndices| is set.
|
||||
*
|
||||
* Indices: Has a |groups| property. If |hasIndices| is set, used
|
||||
* for the |.indices| property of the result object.
|
||||
*/
|
||||
ReadBarriered<ArrayObject*> matchResultTemplateObject_;
|
||||
ReadBarriered<ArrayObject*> matchResultTemplateObjects_[ResultTemplateKind::NumKinds];
|
||||
|
||||
/*
|
||||
* The shape of RegExp.prototype object that satisfies following:
|
||||
@@ -326,7 +341,7 @@ class RegExpCompartment
|
||||
*/
|
||||
ReadBarriered<Shape*> optimizableRegExpInstanceShape_;
|
||||
|
||||
ArrayObject* createMatchResultTemplateObject(JSContext* cx);
|
||||
ArrayObject* createMatchResultTemplateObject(JSContext* cx, ResultTemplateKind kind);
|
||||
|
||||
public:
|
||||
explicit RegExpCompartment(Zone* zone);
|
||||
@@ -344,10 +359,10 @@ class RegExpCompartment
|
||||
MutableHandleRegExpShared shared);
|
||||
|
||||
/* Get or create template object used to base the result of .exec() on. */
|
||||
ArrayObject* getOrCreateMatchResultTemplateObject(JSContext* cx) {
|
||||
if (matchResultTemplateObject_)
|
||||
return matchResultTemplateObject_;
|
||||
return createMatchResultTemplateObject(cx);
|
||||
ArrayObject* getOrCreateMatchResultTemplateObject(JSContext* cx, ResultTemplateKind kind = ResultTemplateKind::Normal) {
|
||||
if (matchResultTemplateObjects_[kind])
|
||||
return matchResultTemplateObjects_[kind];
|
||||
return createMatchResultTemplateObject(cx, kind);
|
||||
}
|
||||
|
||||
Shape* getOptimizableRegExpPrototypeShape() {
|
||||
|
||||
Reference in New Issue
Block a user