mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-03 14:28:39 +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>;
|
||||
|
||||
|
||||
// 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
|
||||
* https://tc39.es/ecma262/#sec-regexpbuiltinexec
|
||||
|
|
@ -64,17 +86,17 @@ js::CreateRegExpMatchResult(JSContext* cx, RegExpShared& re,
|
|||
if (!templateObject)
|
||||
return false;
|
||||
|
||||
// Step 16
|
||||
// Steps 18-19
|
||||
size_t numPairs = matches.length();
|
||||
MOZ_ASSERT(numPairs > 0);
|
||||
|
||||
/* Step 18-19. */
|
||||
// Steps 20-21: Allocate the match result object.
|
||||
RootedArrayObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject));
|
||||
if (!arr)
|
||||
return false;
|
||||
|
||||
/* Steps 22-23 and 27 a-e
|
||||
* Store a Value for each pair. */
|
||||
// Steps 28-29 and 33 a-d: Initialize the elements of the match result.
|
||||
// Store a Value for each match pair.
|
||||
for (size_t i = 0; i < numPairs; 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);
|
||||
if (re.numNamedCaptures() > 0) {
|
||||
// construct a new object from the template saved on RegExpShared
|
||||
RootedPlainObject groupsTemplate(cx, re.getGroupsTemplate());
|
||||
groups = NewObjectWithGivenProto<PlainObject>(cx, nullptr);
|
||||
groups->setGroup(groupsTemplate->group());
|
||||
groups = CreateGroupsObject(cx, groupsTemplate);
|
||||
|
||||
// Step 27 f.
|
||||
// Step 33 e-f
|
||||
// The groups template object stores the names of the named captures in the
|
||||
// the order in which they are defined.
|
||||
// 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());
|
||||
RootedId key(cx);
|
||||
RootedValue ival(cx);
|
||||
RootedValue val(cx);
|
||||
for (size_t i = 0; i < keys.length(); i++) {
|
||||
key = keys[i];
|
||||
// fetch the group's match index...
|
||||
if (!NativeGetProperty(cx, groupsTemplate, key, &ival))
|
||||
return false;
|
||||
// ... and set it on groups
|
||||
val = arr->getDenseElement(ival.toInt32());
|
||||
uint32_t idx = GetNamedCaptureIndex(cx, groupsTemplate, key);
|
||||
MOZ_ASSERT(idx >= 0);
|
||||
// Copy the matched string to |.groups|
|
||||
val = arr->getDenseElement(idx);
|
||||
if (!NativeDefineProperty(cx, groups, key, val, nullptr, nullptr, JSPROP_ENUMERATE)) {
|
||||
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) */
|
||||
arr->setSlot(0, Int32Value(matches[0].start));
|
||||
|
||||
/* Step 21 (reordered).
|
||||
/* Step 23 (reordered).
|
||||
* Set the |input| property. (TemplateObject positions it in slot 1) */
|
||||
arr->setSlot(1, StringValue(input));
|
||||
|
||||
// Steps 25-26 (reordered)
|
||||
// Step 32 (reordered)
|
||||
// Set the |groups| property.
|
||||
arr->setSlot(2, groups ? ObjectValue(*groups) : UndefinedValue());
|
||||
|
||||
// Step 34b (reordered)
|
||||
// Set the |indices| property.
|
||||
if (hasIndices) {
|
||||
arr->setSlot(3, ObjectValue(*indices));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
RootedValue test(cx);
|
||||
RootedId id(cx, NameToId(cx->names().index));
|
||||
|
|
@ -149,7 +235,7 @@ js::CreateRegExpMatchResult(JSContext* cx, RegExpShared& re,
|
|||
MOZ_ASSERT(test == arr->getSlot(1));
|
||||
#endif
|
||||
|
||||
/* Step 25. */
|
||||
/* Step 35. */
|
||||
rval.setObject(*arr);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1545,6 +1545,11 @@ JitCompartment::generateRegExpMatcherStub(JSContext* cx)
|
|||
ImmWord(0),
|
||||
&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.
|
||||
Register object = temp1;
|
||||
Label matchResultFallback, matchResultJoin;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue