2 * Copyright (C) 2014 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
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef JSPropertyNameEnumerator_h
27 #define JSPropertyNameEnumerator_h
30 #include "Operations.h"
31 #include "PropertyNameArray.h"
32 #include "Structure.h"
38 class JSPropertyNameEnumerator final
: public JSCell
{
41 static const unsigned StructureFlags
= Base::StructureFlags
| StructureIsImmortal
;
43 static JSPropertyNameEnumerator
* create(VM
&);
44 static JSPropertyNameEnumerator
* create(VM
&, Structure
*, uint32_t, uint32_t, PropertyNameArray
&);
46 static const bool needsDestruction
= true;
47 static void destroy(JSCell
*);
49 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue prototype
)
51 return Structure::create(vm
, globalObject
, prototype
, TypeInfo(CellType
, StructureFlags
), info());
56 JSString
* propertyNameAtIndex(uint32_t index
) const
58 if (index
>= m_propertyNames
.size())
60 return m_propertyNames
[index
].get();
63 StructureChain
* cachedPrototypeChain() const { return m_prototypeChain
.get(); }
64 void setCachedPrototypeChain(VM
& vm
, StructureChain
* prototypeChain
) { return m_prototypeChain
.set(vm
, this, prototypeChain
); }
66 Structure
* cachedStructure(VM
& vm
) const
68 if (!m_cachedStructureID
)
70 return vm
.heap
.structureIDTable().get(m_cachedStructureID
);
72 StructureID
cachedStructureID() const { return m_cachedStructureID
; }
73 uint32_t indexedLength() const { return m_indexedLength
; }
74 uint32_t endStructurePropertyIndex() const { return m_endStructurePropertyIndex
; }
75 uint32_t endGenericPropertyIndex() const { return m_endGenericPropertyIndex
; }
76 uint32_t cachedInlineCapacity() const { return m_cachedInlineCapacity
; }
77 static ptrdiff_t cachedStructureIDOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator
, m_cachedStructureID
); }
78 static ptrdiff_t indexedLengthOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator
, m_indexedLength
); }
79 static ptrdiff_t endStructurePropertyIndexOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator
, m_endStructurePropertyIndex
); }
80 static ptrdiff_t endGenericPropertyIndexOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator
, m_endGenericPropertyIndex
); }
81 static ptrdiff_t cachedInlineCapacityOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator
, m_cachedInlineCapacity
); }
82 static ptrdiff_t cachedPropertyNamesVectorOffset()
84 return OBJECT_OFFSETOF(JSPropertyNameEnumerator
, m_propertyNames
) + Vector
<WriteBarrier
<JSString
>>::dataMemoryOffset();
87 static void visitChildren(JSCell
*, SlotVisitor
&);
90 JSPropertyNameEnumerator(VM
&, StructureID
, uint32_t);
91 void finishCreation(VM
&, uint32_t, uint32_t, PassRefPtr
<PropertyNameArrayData
>);
93 Vector
<WriteBarrier
<JSString
>> m_propertyNames
;
94 StructureID m_cachedStructureID
;
95 WriteBarrier
<StructureChain
> m_prototypeChain
;
96 uint32_t m_indexedLength
;
97 uint32_t m_endStructurePropertyIndex
;
98 uint32_t m_endGenericPropertyIndex
;
99 uint32_t m_cachedInlineCapacity
;
102 inline JSPropertyNameEnumerator
* propertyNameEnumerator(ExecState
* exec
, JSObject
* base
)
106 uint32_t indexedLength
= base
->methodTable(vm
)->getEnumerableLength(exec
, base
);
108 JSPropertyNameEnumerator
* enumerator
= nullptr;
110 Structure
* structure
= base
->structure(vm
);
112 && (enumerator
= structure
->cachedPropertyNameEnumerator())
113 && enumerator
->cachedPrototypeChain() == structure
->prototypeChain(exec
))
116 uint32_t numberStructureProperties
= 0;
118 PropertyNameArray
propertyNames(exec
);
120 if (structure
->canAccessPropertiesQuickly() && indexedLength
== base
->getArrayLength()) {
121 base
->methodTable(vm
)->getStructurePropertyNames(base
, exec
, propertyNames
, EnumerationMode());
123 numberStructureProperties
= propertyNames
.size();
125 base
->methodTable(vm
)->getGenericPropertyNames(base
, exec
, propertyNames
, EnumerationMode());
127 base
->methodTable(vm
)->getPropertyNames(base
, exec
, propertyNames
, EnumerationMode());
129 ASSERT(propertyNames
.size() < UINT32_MAX
);
131 normalizePrototypeChain(exec
, structure
);
133 enumerator
= JSPropertyNameEnumerator::create(vm
, structure
, indexedLength
, numberStructureProperties
, propertyNames
);
134 enumerator
->setCachedPrototypeChain(vm
, structure
->prototypeChain(exec
));
135 if (!indexedLength
&& structure
->canCachePropertyNameEnumerator())
136 structure
->setCachedPropertyNameEnumerator(vm
, enumerator
);
142 #endif // JSPropertyNameEnumerator_h