mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-22 07:07:30 +09:00
Issue #2305 Part 3b: Create .indices and .indices.groups
This commit is contained in:
parent
2d8696c4fe
commit
6dbe2de6db
2 changed files with 109 additions and 18 deletions
|
|
@ -31,6 +31,28 @@ using mozilla::Maybe;
|
||||||
|
|
||||||
using CapturesVector = GCVector<Value, 4>;
|
using CapturesVector = GCVector<Value, 4>;
|
||||||
|
|
||||||
|
|
||||||
|
// Allocate an object for the |.groups| or |.indices.groups| property
|
||||||
|
// of a regexp match result.
|
||||||
|
static PlainObject* CreateGroupsObject(JSContext* cx,
|
||||||
|
HandlePlainObject groupsTemplate)
|
||||||
|
{
|
||||||
|
PlainObject* result = NewObjectWithGivenProto<PlainObject>(cx, nullptr);
|
||||||
|
result->setGroup(groupsTemplate->group());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch a group index corresponding to a |key| from the template object
|
||||||
|
static uint32_t GetNamedCaptureIndex(JSContext* cx, HandlePlainObject groupsTemplate, HandleId key)
|
||||||
|
{
|
||||||
|
RootedValue ival(cx);
|
||||||
|
|
||||||
|
if (!NativeGetProperty(cx, groupsTemplate, key, &ival))
|
||||||
|
return -1;
|
||||||
|
return ival.toInt32();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implements RegExpBuiltinExec: Steps 18-35
|
* Implements RegExpBuiltinExec: Steps 18-35
|
||||||
* https://tc39.es/ecma262/#sec-regexpbuiltinexec
|
* https://tc39.es/ecma262/#sec-regexpbuiltinexec
|
||||||
|
|
@ -64,17 +86,17 @@ js::CreateRegExpMatchResult(JSContext* cx, RegExpShared& re,
|
||||||
if (!templateObject)
|
if (!templateObject)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Step 16
|
// Steps 18-19
|
||||||
size_t numPairs = matches.length();
|
size_t numPairs = matches.length();
|
||||||
MOZ_ASSERT(numPairs > 0);
|
MOZ_ASSERT(numPairs > 0);
|
||||||
|
|
||||||
/* Step 18-19. */
|
// Steps 20-21: Allocate the match result object.
|
||||||
RootedArrayObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject));
|
RootedArrayObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject));
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Steps 22-23 and 27 a-e
|
// Steps 28-29 and 33 a-d: Initialize the elements of the match result.
|
||||||
* Store a Value for each pair. */
|
// Store a Value for each match pair.
|
||||||
for (size_t i = 0; i < numPairs; i++) {
|
for (size_t i = 0; i < numPairs; i++) {
|
||||||
const MatchPair& pair = matches[i];
|
const MatchPair& pair = matches[i];
|
||||||
|
|
||||||
|
|
@ -91,15 +113,66 @@ js::CreateRegExpMatchResult(JSContext* cx, RegExpShared& re,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 24 (reordered)
|
// Step 34a (reordered): Allocate and initialize the indices object if needed.
|
||||||
|
// This is an inlined implementation of MakeIndicesArray:
|
||||||
|
// https://tc39.es/ecma262/#sec-makeindicesarray
|
||||||
|
RootedArrayObject indices(cx);
|
||||||
|
RootedPlainObject indicesGroups(cx);
|
||||||
|
if (hasIndices) {
|
||||||
|
// MakeIndicesArray: step 8
|
||||||
|
ArrayObject* indicesTemplate =
|
||||||
|
cx->compartment()->regExps.getOrCreateMatchResultTemplateObject(cx, RegExpCompartment::ResultTemplateKind::Indices);
|
||||||
|
indices = NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, indicesTemplate);
|
||||||
|
if (!indices) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeIndicesArray: steps 10-12
|
||||||
|
if (re.numNamedCaptures() > 0) {
|
||||||
|
RootedPlainObject groupsTemplate(cx, re.getGroupsTemplate());
|
||||||
|
indicesGroups = CreateGroupsObject(cx, groupsTemplate);
|
||||||
|
if (!indicesGroups) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
indices->setSlot(0, ObjectValue(*indicesGroups));
|
||||||
|
} else {
|
||||||
|
indices->setSlot(0, UndefinedValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: can we merge this with step 28-29 and 33 a-d above??
|
||||||
|
// MakeIndicesArray: step 13 a-d. (Step 13.e is implemented below.)
|
||||||
|
for (size_t i = 0; i < numPairs; i++) {
|
||||||
|
const MatchPair& pair = matches[i];
|
||||||
|
|
||||||
|
if (pair.isUndefined()) {
|
||||||
|
// Since we had a match, first pair must be present.
|
||||||
|
MOZ_ASSERT(i != 0);
|
||||||
|
indices->setDenseInitializedLength(i + 1);
|
||||||
|
indices->initDenseElement(i, UndefinedValue());
|
||||||
|
} else {
|
||||||
|
RootedArrayObject indexPair(cx, NewDenseFullyAllocatedArray(cx, 2));
|
||||||
|
if (!indexPair) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
indexPair->setDenseInitializedLength(2);
|
||||||
|
indexPair->initDenseElement(0, Int32Value(pair.start));
|
||||||
|
indexPair->initDenseElement(1, Int32Value(pair.limit));
|
||||||
|
|
||||||
|
indices->setDenseInitializedLength(i + 1);
|
||||||
|
indices->initDenseElement(i, ObjectValue(*indexPair));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// /FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steps 30-31 (reordered): Allocate the groups object (if needed).
|
||||||
RootedPlainObject groups(cx);
|
RootedPlainObject groups(cx);
|
||||||
if (re.numNamedCaptures() > 0) {
|
if (re.numNamedCaptures() > 0) {
|
||||||
// construct a new object from the template saved on RegExpShared
|
// construct a new object from the template saved on RegExpShared
|
||||||
RootedPlainObject groupsTemplate(cx, re.getGroupsTemplate());
|
RootedPlainObject groupsTemplate(cx, re.getGroupsTemplate());
|
||||||
groups = NewObjectWithGivenProto<PlainObject>(cx, nullptr);
|
groups = CreateGroupsObject(cx, groupsTemplate);
|
||||||
groups->setGroup(groupsTemplate->group());
|
|
||||||
|
|
||||||
// Step 27 f.
|
// Step 33 e-f
|
||||||
// The groups template object stores the names of the named captures in the
|
// The groups template object stores the names of the named captures in the
|
||||||
// the order in which they are defined.
|
// the order in which they are defined.
|
||||||
// Grab the index into the match vector from the template object and define the
|
// Grab the index into the match vector from the template object and define the
|
||||||
|
|
@ -110,33 +183,46 @@ js::CreateRegExpMatchResult(JSContext* cx, RegExpShared& re,
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(keys.length() == re.numNamedCaptures());
|
MOZ_ASSERT(keys.length() == re.numNamedCaptures());
|
||||||
RootedId key(cx);
|
RootedId key(cx);
|
||||||
RootedValue ival(cx);
|
|
||||||
RootedValue val(cx);
|
RootedValue val(cx);
|
||||||
for (size_t i = 0; i < keys.length(); i++) {
|
for (size_t i = 0; i < keys.length(); i++) {
|
||||||
key = keys[i];
|
key = keys[i];
|
||||||
// fetch the group's match index...
|
uint32_t idx = GetNamedCaptureIndex(cx, groupsTemplate, key);
|
||||||
if (!NativeGetProperty(cx, groupsTemplate, key, &ival))
|
MOZ_ASSERT(idx >= 0);
|
||||||
return false;
|
// Copy the matched string to |.groups|
|
||||||
// ... and set it on groups
|
val = arr->getDenseElement(idx);
|
||||||
val = arr->getDenseElement(ival.toInt32());
|
|
||||||
if (!NativeDefineProperty(cx, groups, key, val, nullptr, nullptr, JSPROP_ENUMERATE)) {
|
if (!NativeDefineProperty(cx, groups, key, val, nullptr, nullptr, JSPROP_ENUMERATE)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// MakeIndicesArray: Step 13.e (reordered)
|
||||||
|
// If we have an |.indices|, copy the information to |.indices.groups|
|
||||||
|
if (hasIndices) {
|
||||||
|
val = indices->getDenseElement(idx);
|
||||||
|
if (!NativeDefineDataProperty(cx, indicesGroups, key, val,
|
||||||
|
JSPROP_ENUMERATE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 20 (reordered).
|
/* Step 22 (reordered).
|
||||||
* Set the |index| property. (TemplateObject positions it in slot 0) */
|
* Set the |index| property. (TemplateObject positions it in slot 0) */
|
||||||
arr->setSlot(0, Int32Value(matches[0].start));
|
arr->setSlot(0, Int32Value(matches[0].start));
|
||||||
|
|
||||||
/* Step 21 (reordered).
|
/* Step 23 (reordered).
|
||||||
* Set the |input| property. (TemplateObject positions it in slot 1) */
|
* Set the |input| property. (TemplateObject positions it in slot 1) */
|
||||||
arr->setSlot(1, StringValue(input));
|
arr->setSlot(1, StringValue(input));
|
||||||
|
|
||||||
// Steps 25-26 (reordered)
|
// Step 32 (reordered)
|
||||||
// Set the |groups| property.
|
// Set the |groups| property.
|
||||||
arr->setSlot(2, groups ? ObjectValue(*groups) : UndefinedValue());
|
arr->setSlot(2, groups ? ObjectValue(*groups) : UndefinedValue());
|
||||||
|
|
||||||
|
// Step 34b (reordered)
|
||||||
|
// Set the |indices| property.
|
||||||
|
if (hasIndices) {
|
||||||
|
arr->setSlot(3, ObjectValue(*indices));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
RootedValue test(cx);
|
RootedValue test(cx);
|
||||||
RootedId id(cx, NameToId(cx->names().index));
|
RootedId id(cx, NameToId(cx->names().index));
|
||||||
|
|
@ -149,7 +235,7 @@ js::CreateRegExpMatchResult(JSContext* cx, RegExpShared& re,
|
||||||
MOZ_ASSERT(test == arr->getSlot(1));
|
MOZ_ASSERT(test == arr->getSlot(1));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Step 25. */
|
/* Step 35. */
|
||||||
rval.setObject(*arr);
|
rval.setObject(*arr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1545,6 +1545,11 @@ JitCompartment::generateRegExpMatcherStub(JSContext* cx)
|
||||||
ImmWord(0),
|
ImmWord(0),
|
||||||
&oolEntry);
|
&oolEntry);
|
||||||
|
|
||||||
|
// Similarly, if the |hasIndices| flag is set, fall back to the OOL stub.
|
||||||
|
masm.branchTest32(Assembler::NonZero,
|
||||||
|
Address(shared, RegExpShared::offsetOfFlags()),
|
||||||
|
Imm32(int32_t(HasIndicesFlag)), &oolEntry);
|
||||||
|
|
||||||
// Construct the result.
|
// Construct the result.
|
||||||
Register object = temp1;
|
Register object = temp1;
|
||||||
Label matchResultFallback, matchResultJoin;
|
Label matchResultFallback, matchResultJoin;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue