JavaScriptCore/runtime/JSPropertyNameIterator.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *
       
     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 Computer, 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.
       
    16  *
       
    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.
       
    27  */
       
    28 
       
    29 #include "config.h"
       
    30 #include "JSPropertyNameIterator.h"
       
    31 
       
    32 #include "JSGlobalObject.h"
       
    33 
       
    34 namespace JSC {
       
    35 
       
    36 ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
       
    37 
       
    38 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
       
    39     : JSCell(exec->globalData().propertyNameIteratorStructure.get())
       
    40     , m_cachedStructure(0)
       
    41     , m_numCacheableSlots(numCacheableSlots)
       
    42     , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
       
    43     , m_jsStrings(new JSValue[m_jsStringsSize])
       
    44 {
       
    45     PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
       
    46     for (size_t i = 0; i < m_jsStringsSize; ++i)
       
    47         m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring());
       
    48 }
       
    49 
       
    50 JSPropertyNameIterator::~JSPropertyNameIterator()
       
    51 {
       
    52     if (m_cachedStructure)
       
    53         m_cachedStructure->clearEnumerationCache(this);
       
    54 }
       
    55 
       
    56 JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
       
    57 {
       
    58     ASSERT(!o->structure()->enumerationCache() ||
       
    59             o->structure()->enumerationCache()->cachedStructure() != o->structure() ||
       
    60             o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec));
       
    61 
       
    62     PropertyNameArray propertyNames(exec);
       
    63     o->getPropertyNames(exec, propertyNames);
       
    64     size_t numCacheableSlots = 0;
       
    65     if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasAnonymousSlots() &&
       
    66         !o->structure()->hasGetterSetterProperties() && !o->structure()->isUncacheableDictionary() &&
       
    67         !o->structure()->typeInfo().overridesGetPropertyNames())
       
    68         numCacheableSlots = o->structure()->propertyStorageSize();
       
    69 
       
    70     JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots);
       
    71 
       
    72     if (o->structure()->isDictionary())
       
    73         return jsPropertyNameIterator;
       
    74 
       
    75     if (o->structure()->typeInfo().overridesGetPropertyNames())
       
    76         return jsPropertyNameIterator;
       
    77     
       
    78     size_t count = normalizePrototypeChain(exec, o);
       
    79     StructureChain* structureChain = o->structure()->prototypeChain(exec);
       
    80     RefPtr<Structure>* structure = structureChain->head();
       
    81     for (size_t i = 0; i < count; ++i) {
       
    82         if (structure[i]->typeInfo().overridesGetPropertyNames())
       
    83             return jsPropertyNameIterator;
       
    84     }
       
    85 
       
    86     jsPropertyNameIterator->setCachedPrototypeChain(structureChain);
       
    87     jsPropertyNameIterator->setCachedStructure(o->structure());
       
    88     o->structure()->setEnumerationCache(jsPropertyNameIterator);
       
    89     return jsPropertyNameIterator;
       
    90 }
       
    91 
       
    92 JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
       
    93 {
       
    94     JSValue& identifier = m_jsStrings[i];
       
    95     if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec))
       
    96         return identifier;
       
    97 
       
    98     if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec))))
       
    99         return JSValue();
       
   100     return identifier;
       
   101 }
       
   102 
       
   103 void JSPropertyNameIterator::markChildren(MarkStack& markStack)
       
   104 {
       
   105     markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
       
   106 }
       
   107 
       
   108 } // namespace JSC