2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "JSPropertyNameIterator.h"
32 #include "JSCInlines.h"
33 #include "JSGlobalObject.h"
34 #include <wtf/StdLibExtras.h>
38 const ClassInfo
JSPropertyNameIterator::s_info
= { "JSPropertyNameIterator", 0, 0, 0, CREATE_METHOD_TABLE(JSPropertyNameIterator
) };
40 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState
* exec
, PropertyNameArrayData
* propertyNameArrayData
, size_t numCacheableSlots
)
41 : JSCell(exec
->vm(), exec
->vm().propertyNameIteratorStructure
.get())
42 , m_numCacheableSlots(numCacheableSlots
)
43 , m_jsStringsSize(propertyNameArrayData
->propertyNameVector().size())
44 , m_jsStrings(m_jsStringsSize
? std::make_unique
<WriteBarrier
<Unknown
>[]>(m_jsStringsSize
) : nullptr)
48 JSPropertyNameIterator
* JSPropertyNameIterator::create(ExecState
* exec
, JSObject
* o
)
50 ASSERT(!o
->structure()->enumerationCache() ||
51 o
->structure()->enumerationCache()->cachedStructure() != o
->structure() ||
52 o
->structure()->enumerationCache()->cachedPrototypeChain() != o
->structure()->prototypeChain(exec
));
56 PropertyNameArray
propertyNames(exec
);
57 o
->methodTable()->getPropertyNames(o
, exec
, propertyNames
, ExcludeDontEnumProperties
);
58 size_t numCacheableSlots
= 0;
59 if (!o
->structure()->hasNonEnumerableProperties() && !o
->structure()->hasGetterSetterProperties()
60 && !o
->structure()->isUncacheableDictionary() && !o
->structure()->typeInfo().overridesGetPropertyNames())
61 numCacheableSlots
= propertyNames
.numCacheableSlots();
63 JSPropertyNameIterator
* jsPropertyNameIterator
= new (NotNull
, allocateCell
<JSPropertyNameIterator
>(vm
.heap
)) JSPropertyNameIterator(exec
, propertyNames
.data(), numCacheableSlots
);
64 jsPropertyNameIterator
->finishCreation(vm
, propertyNames
.data(), o
);
66 if (o
->structure()->isDictionary())
67 return jsPropertyNameIterator
;
69 if (o
->structure()->typeInfo().overridesGetPropertyNames())
70 return jsPropertyNameIterator
;
72 if (hasIndexedProperties(o
->indexingType()))
73 return jsPropertyNameIterator
;
75 size_t count
= normalizePrototypeChain(exec
, o
);
76 StructureChain
* structureChain
= o
->structure()->prototypeChain(exec
);
77 WriteBarrier
<Structure
>* structure
= structureChain
->head();
78 for (size_t i
= 0; i
< count
; ++i
) {
79 if (structure
[i
]->typeInfo().overridesGetPropertyNames())
80 return jsPropertyNameIterator
;
83 jsPropertyNameIterator
->setCachedPrototypeChain(vm
, structureChain
);
84 jsPropertyNameIterator
->setCachedStructure(vm
, o
->structure());
85 o
->structure()->setEnumerationCache(vm
, jsPropertyNameIterator
);
86 return jsPropertyNameIterator
;
89 void JSPropertyNameIterator::destroy(JSCell
* cell
)
91 static_cast<JSPropertyNameIterator
*>(cell
)->JSPropertyNameIterator::~JSPropertyNameIterator();
94 JSValue
JSPropertyNameIterator::get(ExecState
* exec
, JSObject
* base
, size_t i
)
96 JSValue identifier
= m_jsStrings
[i
].get();
97 if (m_cachedStructure
.get() == base
->structure() && m_cachedPrototypeChain
.get() == base
->structure()->prototypeChain(exec
))
100 if (!base
->hasProperty(exec
, Identifier(exec
, asString(identifier
)->value(exec
))))
105 void JSPropertyNameIterator::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
107 JSPropertyNameIterator
* thisObject
= jsCast
<JSPropertyNameIterator
*>(cell
);
108 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
109 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
110 visitor
.appendValues(thisObject
->m_jsStrings
.get(), thisObject
->m_jsStringsSize
);
111 visitor
.append(&thisObject
->m_cachedPrototypeChain
);