summaryrefslogtreecommitdiffstats
path: root/js/src/jsiter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsiter.cpp')
-rw-r--r--js/src/jsiter.cpp42
1 files changed, 32 insertions, 10 deletions
diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp
index c58f32382..8b1436b68 100644
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -158,11 +158,8 @@ SortComparatorIntegerIds(jsid a, jsid b, bool* lessOrEqualp)
}
static bool
-EnumerateNativeProperties(JSContext* cx,
- HandleNativeObject pobj,
- unsigned flags,
- Maybe<IdSet>& ht,
- AutoIdVector* props)
+EnumerateNativeProperties(JSContext* cx, HandleNativeObject pobj, unsigned flags, Maybe<IdSet>& ht,
+ AutoIdVector* props, Handle<UnboxedPlainObject*> unboxed = nullptr)
{
bool enumerateSymbols;
if (flags & JSITER_SYMBOLSONLY) {
@@ -224,6 +221,16 @@ EnumerateNativeProperties(JSContext* cx,
return false;
}
+ if (unboxed) {
+ // If |unboxed| is set then |pobj| is the expando for an unboxed
+ // plain object we are enumerating. Add the unboxed properties
+ // themselves here since they are all property names that were
+ // given to the object before any of the expando's properties.
+ MOZ_ASSERT(pobj->is<UnboxedExpandoObject>());
+ if (!EnumerateExtraProperties(cx, unboxed, flags, ht, props))
+ return false;
+ }
+
size_t initialLength = props->length();
/* Collect all unique property names from this object's shape. */
@@ -349,12 +356,22 @@ Snapshot(JSContext* cx, HandleObject pobj_, unsigned flags, AutoIdVector* props)
do {
if (pobj->getOpsEnumerate()) {
- if (!EnumerateExtraProperties(cx, pobj, flags, ht, props))
- return false;
-
- if (pobj->isNative()) {
- if (!EnumerateNativeProperties(cx, pobj.as<NativeObject>(), flags, ht, props))
+ if (pobj->is<UnboxedPlainObject>() && pobj->as<UnboxedPlainObject>().maybeExpando()) {
+ // Special case unboxed objects with an expando object.
+ RootedNativeObject expando(cx, pobj->as<UnboxedPlainObject>().maybeExpando());
+ if (!EnumerateNativeProperties(cx, expando, flags, ht, props,
+ pobj.as<UnboxedPlainObject>()))
+ {
+ return false;
+ }
+ } else {
+ if (!EnumerateExtraProperties(cx, pobj, flags, ht, props))
return false;
+
+ if (pobj->isNative()) {
+ if (!EnumerateNativeProperties(cx, pobj.as<NativeObject>(), flags, ht, props))
+ return false;
+ }
}
} else if (pobj->isNative()) {
// Give the object a chance to resolve all lazy properties
@@ -769,6 +786,11 @@ CanCompareIterableObjectToCache(JSObject* obj)
{
if (obj->isNative())
return obj->as<NativeObject>().hasEmptyElements();
+ if (obj->is<UnboxedPlainObject>()) {
+ if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando())
+ return expando->hasEmptyElements();
+ return true;
+ }
return false;
}