summaryrefslogtreecommitdiffstats
path: root/js/src/vm/UbiNodeCensus.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/UbiNodeCensus.cpp')
-rw-r--r--js/src/vm/UbiNodeCensus.cpp66
1 files changed, 47 insertions, 19 deletions
diff --git a/js/src/vm/UbiNodeCensus.cpp b/js/src/vm/UbiNodeCensus.cpp
index ba3ccd0898..7e33341d30 100644
--- a/js/src/vm/UbiNodeCensus.cpp
+++ b/js/src/vm/UbiNodeCensus.cpp
@@ -6,6 +6,8 @@
#include "js/UbiNodeCensus.h"
+#include "mozilla/ScopeExit.h"
+
#include "builtin/MapObject.h"
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
#include "js/Printer.h"
@@ -1062,17 +1064,19 @@ JS_PUBLIC_API bool CensusHandler::operator()(
/*** Parsing Breakdowns *****************************************************/
-static CountTypePtr ParseChildBreakdown(JSContext* cx, HandleObject breakdown,
- PropertyName* prop) {
+static CountTypePtr ParseChildBreakdown(
+ JSContext* cx, HandleObject breakdown, PropertyName* prop,
+ MutableHandle<GCVector<JSLinearString*>> seen) {
RootedValue v(cx);
if (!GetProperty(cx, breakdown, breakdown, prop, &v)) {
return nullptr;
}
- return ParseBreakdown(cx, v);
+ return ParseBreakdown(cx, v, seen);
}
-JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx,
- HandleValue breakdownValue) {
+JS_PUBLIC_API CountTypePtr
+ParseBreakdown(JSContext* cx, HandleValue breakdownValue,
+ MutableHandle<GCVector<JSLinearString*>> seen) {
if (breakdownValue.isUndefined()) {
// Construct the default type, { by: 'count' }
CountTypePtr simple(cx->new_<SimpleCount>());
@@ -1097,6 +1101,24 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx,
return nullptr;
}
+ for (auto candidate : seen.get()) {
+ if (EqualStrings(by, candidate)) {
+ UniqueChars byBytes = QuoteString(cx, by, '"');
+ if (!byBytes) {
+ return nullptr;
+ }
+
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+ JSMSG_DEBUG_CENSUS_BREAKDOWN_NESTED,
+ byBytes.get());
+ return nullptr;
+ }
+ }
+ if (!seen.append(by)) {
+ return nullptr;
+ }
+ auto popper = mozilla::MakeScopeExit([&]() { seen.popBack(); });
+
if (StringEqualsLiteral(by, "count")) {
RootedValue countValue(cx), bytesValue(cx);
if (!GetProperty(cx, breakdown, breakdown, cx->names().count,
@@ -1140,13 +1162,14 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx,
}
if (StringEqualsLiteral(by, "objectClass")) {
- CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
+ CountTypePtr thenType(
+ ParseChildBreakdown(cx, breakdown, cx->names().then, seen));
if (!thenType) {
return nullptr;
}
CountTypePtr otherType(
- ParseChildBreakdown(cx, breakdown, cx->names().other));
+ ParseChildBreakdown(cx, breakdown, cx->names().other, seen));
if (!otherType) {
return nullptr;
}
@@ -1156,27 +1179,27 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx,
if (StringEqualsLiteral(by, "coarseType")) {
CountTypePtr objectsType(
- ParseChildBreakdown(cx, breakdown, cx->names().objects));
+ ParseChildBreakdown(cx, breakdown, cx->names().objects, seen));
if (!objectsType) {
return nullptr;
}
CountTypePtr scriptsType(
- ParseChildBreakdown(cx, breakdown, cx->names().scripts));
+ ParseChildBreakdown(cx, breakdown, cx->names().scripts, seen));
if (!scriptsType) {
return nullptr;
}
CountTypePtr stringsType(
- ParseChildBreakdown(cx, breakdown, cx->names().strings));
+ ParseChildBreakdown(cx, breakdown, cx->names().strings, seen));
if (!stringsType) {
return nullptr;
}
CountTypePtr otherType(
- ParseChildBreakdown(cx, breakdown, cx->names().other));
+ ParseChildBreakdown(cx, breakdown, cx->names().other, seen));
if (!otherType) {
return nullptr;
}
CountTypePtr domNodeType(
- ParseChildBreakdown(cx, breakdown, cx->names().domNode));
+ ParseChildBreakdown(cx, breakdown, cx->names().domNode, seen));
if (!domNodeType) {
return nullptr;
}
@@ -1186,7 +1209,8 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx,
}
if (StringEqualsLiteral(by, "internalType")) {
- CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
+ CountTypePtr thenType(
+ ParseChildBreakdown(cx, breakdown, cx->names().then, seen));
if (!thenType) {
return nullptr;
}
@@ -1195,7 +1219,8 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx,
}
if (StringEqualsLiteral(by, "descriptiveType")) {
- CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
+ CountTypePtr thenType(
+ ParseChildBreakdown(cx, breakdown, cx->names().then, seen));
if (!thenType) {
return nullptr;
}
@@ -1203,12 +1228,13 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx,
}
if (StringEqualsLiteral(by, "allocationStack")) {
- CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
+ CountTypePtr thenType(
+ ParseChildBreakdown(cx, breakdown, cx->names().then, seen));
if (!thenType) {
return nullptr;
}
CountTypePtr noStackType(
- ParseChildBreakdown(cx, breakdown, cx->names().noStack));
+ ParseChildBreakdown(cx, breakdown, cx->names().noStack, seen));
if (!noStackType) {
return nullptr;
}
@@ -1217,13 +1243,14 @@ JS_PUBLIC_API CountTypePtr ParseBreakdown(JSContext* cx,
}
if (StringEqualsLiteral(by, "filename")) {
- CountTypePtr thenType(ParseChildBreakdown(cx, breakdown, cx->names().then));
+ CountTypePtr thenType(
+ ParseChildBreakdown(cx, breakdown, cx->names().then, seen));
if (!thenType) {
return nullptr;
}
CountTypePtr noFilenameType(
- ParseChildBreakdown(cx, breakdown, cx->names().noFilename));
+ ParseChildBreakdown(cx, breakdown, cx->names().noFilename, seen));
if (!noFilenameType) {
return nullptr;
}
@@ -1307,8 +1334,9 @@ JS_PUBLIC_API bool ParseCensusOptions(JSContext* cx, Census& census,
return false;
}
+ Rooted<GCVector<JSLinearString*>> seen(cx, cx);
outResult = breakdown.isUndefined() ? GetDefaultBreakdown(cx)
- : ParseBreakdown(cx, breakdown);
+ : ParseBreakdown(cx, breakdown, &seen);
return !!outResult;
}