Пример #1
0
void Structure::getPropertyNames(PropertyNameArray& propertyNames, EnumerationMode mode)
{
    materializePropertyMapIfNecessary();
    if (!m_propertyTable)
        return;

    if (m_propertyTable->keyCount < tinyMapThreshold) {
        PropertyMapEntry* a[tinyMapThreshold];
        int i = 0;
        unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
        for (unsigned k = 1; k <= entryCount; k++) {
            ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[k].attributes & DontEnum));
            if (m_propertyTable->entries()[k].key && (!(m_propertyTable->entries()[k].attributes & DontEnum) || (mode == IncludeDontEnumProperties))) {
                PropertyMapEntry* value = &m_propertyTable->entries()[k];
                int j;
                for (j = i - 1; j >= 0 && a[j]->index > value->index; --j)
                    a[j + 1] = a[j];
                a[j + 1] = value;
                ++i;
            }
        }
        if (!propertyNames.size()) {
            for (int k = 0; k < i; ++k)
                propertyNames.addKnownUnique(a[k]->key);
        } else {
            for (int k = 0; k < i; ++k)
                propertyNames.add(a[k]->key);
        }

        return;
    }

    // Allocate a buffer to use to sort the keys.
    Vector<PropertyMapEntry*, smallMapThreshold> sortedEnumerables(m_propertyTable->keyCount);

    // Get pointers to the enumerable entries in the buffer.
    PropertyMapEntry** p = sortedEnumerables.data();
    unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
    for (unsigned i = 1; i <= entryCount; i++) {
        if (m_propertyTable->entries()[i].key && (!(m_propertyTable->entries()[i].attributes & DontEnum) || (mode == IncludeDontEnumProperties)))
            *p++ = &m_propertyTable->entries()[i];
    }

    size_t enumerableCount = p - sortedEnumerables.data();
    // Sort the entries by index.
    qsort(sortedEnumerables.data(), enumerableCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices);
    sortedEnumerables.resize(enumerableCount);

    // Put the keys of the sorted entries into the list.
    if (!propertyNames.size()) {
        for (size_t i = 0; i < sortedEnumerables.size(); ++i)
            propertyNames.addKnownUnique(sortedEnumerables[i]->key);
    } else {
        for (size_t i = 0; i < sortedEnumerables.size(); ++i)
            propertyNames.add(sortedEnumerables[i]->key);
    }
}
Пример #2
0
void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
{
    bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary);

    if (shouldCache && m_cachedPropertyNameArrayData) {
        if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
            propertyNames.setData(m_cachedPropertyNameArrayData);
            return;
        }
        clearEnumerationCache();
    }

    getEnumerableNamesFromPropertyTable(propertyNames);
    getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames);

    if (m_prototype.isObject()) {
        propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
        asObject(m_prototype)->getPropertyNames(exec, propertyNames);
    }

    if (shouldCache) {
        m_cachedPropertyNameArrayData = propertyNames.data();
        m_cachedPropertyNameArrayData->setCachedPrototypeChain(prototypeChain(exec));
        m_cachedPropertyNameArrayData->setCachedStructure(this);
    }
}
Пример #3
0
bool _NPN_Enumerate(NPP, NPObject *o, NPIdentifier **identifier, uint32_t *count)
{
    if (o->_class == NPScriptObjectClass) {
        JavaScriptObject* obj = (JavaScriptObject*)o; 
        if (!_isSafeScript(obj))
            return false;
        
        RootObject* rootObject = obj->rootObject;
        if (!rootObject || !rootObject->isValid())
            return false;
        
        ExecState* exec = rootObject->interpreter()->globalExec();
        JSLock lock;
        PropertyNameArray propertyNames;

        obj->imp->getPropertyNames(exec, propertyNames);
        unsigned size = static_cast<unsigned>(propertyNames.size());
        // FIXME: This should really call NPN_MemAlloc but that's in WebKit
        NPIdentifier *identifiers = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier) * size));
        
        for (unsigned i = 0; i < size; i++)
            identifiers[i] = _NPN_GetStringIdentifier(propertyNames[i].ustring().UTF8String().c_str());

        *identifier = identifiers;
        *count = size;
        
        return true;
    }
    
    if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o->_class) && o->_class->enumerate)
        return o->_class->enumerate(o, identifier, count);
    
    return false;
}
unsigned ArrayInstance::compactForSorting()
{
    JSValue *undefined = jsUndefined();

    unsigned o = 0;
    
    for (unsigned i = 0; i != storageLength; ++i) {
        JSValue *v = storage[i];
        if (v && v != undefined) {
            if (o != i)
                storage[o] = v;
            o++;
        }
    }
   
    PropertyNameArray sparseProperties;
    _prop.getSparseArrayPropertyNames(sparseProperties);
    unsigned newLength = o + sparseProperties.size();
    
    if (newLength > storageLength)
        resizeStorage(newLength);
    
    PropertyNameArrayIterator end = sparseProperties.end();
    for (PropertyNameArrayIterator it = sparseProperties.begin(); it != end; ++it) {
        Identifier name = *it;
        storage[o] = getDirect(name);
        _prop.remove(name);
        o++;
    }
    
    if (newLength != storageLength)
        memset(storage + o, 0, sizeof(JSValue *) * (storageLength - o));
    
    return o;
}
Пример #5
0
void Structure::getPropertyNamesFromStructure(JSGlobalData& globalData, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    materializePropertyMapIfNecessary(globalData);
    if (!m_propertyTable)
        return;

    bool knownUnique = !propertyNames.size();

    PropertyTable::iterator end = m_propertyTable->end();
    for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
        ASSERT(m_hasNonEnumerableProperties || !(iter->attributes & DontEnum));
        if (iter->key->isIdentifier() && (!(iter->attributes & DontEnum) || mode == IncludeDontEnumProperties)) {
            if (knownUnique)
                propertyNames.addKnownUnique(iter->key);
            else
                propertyNames.add(iter->key);
        }
    }
}
Пример #6
0
void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
{
    bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary());

    if (shouldCache && m_cachedPropertyNameArrayData) {
        if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
            propertyNames.setData(m_cachedPropertyNameArrayData);
            return;
        }
        clearEnumerationCache();
    }

    baseObject->getOwnPropertyNames(exec, propertyNames);

    if (m_prototype.isObject()) {
        propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
        JSObject* prototype = asObject(m_prototype);
        while(1) {
            if (!prototype->structure()->typeInfo().hasDefaultGetPropertyNames()) {
                prototype->getPropertyNames(exec, propertyNames);
                break;
            }
            prototype->getOwnPropertyNames(exec, propertyNames);
            JSValue nextProto = prototype->prototype();
            if (!nextProto.isObject())
                break;
            prototype = asObject(nextProto);
        }
    }

    if (shouldCache) {
        StructureChain* protoChain = prototypeChain(exec);
        m_cachedPropertyNameArrayData = propertyNames.data();
        if (!protoChain->isCacheable())
            return;
        m_cachedPropertyNameArrayData->setCachedPrototypeChain(protoChain);
        m_cachedPropertyNameArrayData->setCachedStructure(this);
    }
}