summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp196
1 files changed, 78 insertions, 118 deletions
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
index a9749a524..68a8bd87d 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -1,153 +1,113 @@
/*
- * Copyright (C) 2015 Apple, Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "JSPropertyNameIterator.h"
-#include "IdentifierInlines.h"
-#include "IteratorOperations.h"
-#include "JSCJSValueInlines.h"
-#include "JSCellInlines.h"
-#include "JSPropertyNameEnumerator.h"
-#include "SlotVisitorInlines.h"
-#include "StructureInlines.h"
+#include "JSGlobalObject.h"
+#include <wtf/StdLibExtras.h>
namespace JSC {
-static EncodedJSValue JSC_HOST_CALL propertyNameIteratorFuncNext(ExecState*);
-
-const ClassInfo JSPropertyNameIterator::s_info = { "PropertyName Iterator", &Base::s_info, 0, CREATE_METHOD_TABLE(JSPropertyNameIterator) };
-
-JSPropertyNameIterator::JSPropertyNameIterator(VM& vm, Structure* structure, JSObject* object, JSPropertyNameEnumerator* enumerator)
- : Base(vm, structure)
- , m_iteratedObject(vm, this, object)
- , m_propertyNameEnumerator(vm, this, enumerator)
- , m_enumerationPhase(EnumerationPhase::IndexedNames)
- , m_cursor(0)
-{
-}
+const ClassInfo JSPropertyNameIterator::s_info = { "JSPropertyNameIterator", 0, 0, 0, CREATE_METHOD_TABLE(JSPropertyNameIterator) };
-JSPropertyNameIterator* JSPropertyNameIterator::clone(ExecState* exec)
+inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
+ : JSCell(exec->vm(), exec->vm().propertyNameIteratorStructure.get())
+ , m_numCacheableSlots(numCacheableSlots)
+ , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
+ , m_jsStrings(m_jsStringsSize ? std::make_unique<WriteBarrier<Unknown>[]>(m_jsStringsSize) : nullptr)
{
- auto iterator = JSPropertyNameIterator::create(exec, exec->callee()->globalObject()->propertyNameIteratorStructure(), m_iteratedObject.get(), m_propertyNameEnumerator.get());
- iterator->m_enumerationPhase = m_enumerationPhase;
- iterator->m_cursor = m_cursor;
- return iterator;
}
-JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, Structure* structure, JSObject* iteratedObject)
+JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
{
- return JSPropertyNameIterator::create(exec, structure, iteratedObject, propertyNameEnumerator(exec, iteratedObject));
-}
+ ASSERT(!o->structure()->enumerationCache() ||
+ o->structure()->enumerationCache()->cachedStructure() != o->structure() ||
+ o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec));
-JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, Structure* structure, JSObject* iteratedObject, JSPropertyNameEnumerator* enumerator)
-{
VM& vm = exec->vm();
- JSPropertyNameIterator* instance = new (NotNull, allocateCell<JSPropertyNameIterator>(vm.heap)) JSPropertyNameIterator(vm, structure, iteratedObject, enumerator);
- instance->finishCreation(vm, structure->globalObject());
- return instance;
-}
-void JSPropertyNameIterator::finishCreation(VM& vm, JSGlobalObject* globalObject)
-{
- Base::finishCreation(vm);
- ASSERT(inherits(info()));
- JSC_NATIVE_FUNCTION(vm.propertyNames->next, propertyNameIteratorFuncNext, DontEnum, 0);
+ PropertyNameArray propertyNames(exec);
+ o->methodTable()->getPropertyNames(o, exec, propertyNames, ExcludeDontEnumProperties);
+ size_t numCacheableSlots = 0;
+ if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasGetterSetterProperties()
+ && !o->structure()->isUncacheableDictionary() && !o->structure()->typeInfo().overridesGetPropertyNames())
+ numCacheableSlots = propertyNames.numCacheableSlots();
+
+ JSPropertyNameIterator* jsPropertyNameIterator = new (NotNull, allocateCell<JSPropertyNameIterator>(vm.heap)) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots);
+ jsPropertyNameIterator->finishCreation(vm, propertyNames.data(), o);
+
+ if (o->structure()->isDictionary())
+ return jsPropertyNameIterator;
+
+ if (o->structure()->typeInfo().overridesGetPropertyNames())
+ return jsPropertyNameIterator;
+
+ if (hasIndexedProperties(o->structure()->indexingType()))
+ return jsPropertyNameIterator;
+
+ size_t count = normalizePrototypeChain(exec, o);
+ StructureChain* structureChain = o->structure()->prototypeChain(exec);
+ WriteBarrier<Structure>* structure = structureChain->head();
+ for (size_t i = 0; i < count; ++i) {
+ if (structure[i]->typeInfo().overridesGetPropertyNames())
+ return jsPropertyNameIterator;
+ }
+
+ jsPropertyNameIterator->setCachedPrototypeChain(vm, structureChain);
+ jsPropertyNameIterator->setCachedStructure(vm, o->structure());
+ o->structure()->setEnumerationCache(vm, jsPropertyNameIterator);
+ return jsPropertyNameIterator;
}
-void JSPropertyNameIterator::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSPropertyNameIterator::destroy(JSCell* cell)
{
- JSPropertyNameIterator* thisObject = jsCast<JSPropertyNameIterator*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- Base::visitChildren(thisObject, visitor);
- visitor.append(&thisObject->m_iteratedObject);
- visitor.append(&thisObject->m_propertyNameEnumerator);
+ static_cast<JSPropertyNameIterator*>(cell)->JSPropertyNameIterator::~JSPropertyNameIterator();
}
-bool JSPropertyNameIterator::next(ExecState* exec, JSValue& output)
+JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
{
- if (m_enumerationPhase == EnumerationPhase::IndexedNames) {
- for (; m_cursor < m_propertyNameEnumerator->indexedLength();) {
- uint32_t index = m_cursor++;
- if (m_iteratedObject->hasProperty(exec, index)) {
- output = jsString(exec, Identifier::from(exec, index).string());
- return true;
- }
- }
- m_cursor = 0;
- m_enumerationPhase = EnumerationPhase::StructureNames;
- }
+ JSValue identifier = m_jsStrings[i].get();
+ if (m_cachedStructure.get() == base->structure() && m_cachedPrototypeChain.get() == base->structure()->prototypeChain(exec))
+ return identifier;
- if (m_enumerationPhase == EnumerationPhase::StructureNames) {
- for (; m_cursor < m_propertyNameEnumerator->endStructurePropertyIndex();) {
- uint32_t index = m_cursor++;
- JSString* propertyName = m_propertyNameEnumerator->propertyNameAtIndex(index);
- ASSERT(propertyName);
- if (m_iteratedObject->structure(exec->vm())->id() == m_propertyNameEnumerator->cachedStructureID()) {
- output = propertyName;
- return true;
- }
-
- if (m_iteratedObject->hasProperty(exec, propertyName->toIdentifier(exec))) {
- output = propertyName;
- return true;
- }
- }
- ASSERT(m_cursor >= m_propertyNameEnumerator->endStructurePropertyIndex());
- // Use the same m_cursor in the GenericNames phase.
- m_enumerationPhase = EnumerationPhase::GenericNames;
- }
-
- if (m_enumerationPhase == EnumerationPhase::GenericNames) {
- for (; m_cursor < m_propertyNameEnumerator->endGenericPropertyIndex();) {
- uint32_t index = m_cursor++;
- JSString* propertyName = m_propertyNameEnumerator->propertyNameAtIndex(index);
- ASSERT(propertyName);
- if (m_iteratedObject->hasProperty(exec, propertyName->toIdentifier(exec))) {
- output = propertyName;
- return true;
- }
- }
- m_enumerationPhase = EnumerationPhase::Done;
- }
-
- return false;
+ if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec))))
+ return JSValue();
+ return identifier;
}
-// ------------------------------ PropertyNameIterator Functions ----------------------------
-
-EncodedJSValue JSC_HOST_CALL propertyNameIteratorFuncNext(ExecState* exec)
+void JSPropertyNameIterator::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
- JSPropertyNameIterator* iterator = jsDynamicCast<JSPropertyNameIterator*>(exec->thisValue());
- if (!iterator)
- return JSValue::encode(throwTypeError(exec, ASCIILiteral("Cannot call PropertyNameIterator.next() on a non-PropertyNameIterator object")));
-
- JSValue result;
- if (iterator->next(exec, result))
- return JSValue::encode(createIteratorResultObject(exec, result, false));
- return JSValue::encode(createIteratorResultObject(exec, jsUndefined(), true));
+ JSPropertyNameIterator* thisObject = jsCast<JSPropertyNameIterator*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+ visitor.appendValues(thisObject->m_jsStrings.get(), thisObject->m_jsStringsSize);
+ visitor.append(&thisObject->m_cachedPrototypeChain);
}
} // namespace JSC