| Index: third_party/WebKit/WebCore/bindings/v8/V8EventListenerList.cpp
|
| ===================================================================
|
| --- third_party/WebKit/WebCore/bindings/v8/V8EventListenerList.cpp (revision 14992)
|
| +++ third_party/WebKit/WebCore/bindings/v8/V8EventListenerList.cpp (working copy)
|
| @@ -35,96 +35,149 @@
|
|
|
| namespace WebCore {
|
|
|
| -V8EventListenerList::V8EventListenerList(const char* name)
|
| +V8EventListenerListIterator::V8EventListenerListIterator(V8EventListenerList* list)
|
| + : m_list(list)
|
| + , m_vectorIndex(0)
|
| + , m_iter(list->m_table.begin())
|
| {
|
| - ASSERT(strlen(name) <= maxKeyNameLength);
|
| - v8::HandleScope handleScope;
|
| +}
|
|
|
| - // Write the name into a temporary buffer, leaving 1 space at the beginning
|
| - // for a prefix we'll vary between the inline and non-inline keys.
|
| - char keyBuffer[maxKeyNameLength + 2] = { 0 };
|
| - strncpy(keyBuffer + 1, name, maxKeyNameLength);
|
| - keyBuffer[0] = '1';
|
| - m_inlineKey = v8::Persistent<v8::String>::New(v8::String::New(keyBuffer));
|
| - keyBuffer[0] = '2';
|
| - m_nonInlineKey = v8::Persistent<v8::String>::New(v8::String::New(keyBuffer));
|
| +V8EventListenerListIterator::V8EventListenerListIterator(V8EventListenerList* list, bool shouldSeekToEnd)
|
| + : m_list(list)
|
| + , m_vectorIndex(0)
|
| + , m_iter(list->m_table.begin())
|
| +{
|
| + if (shouldSeekToEnd)
|
| + seekToEnd();
|
| }
|
|
|
| +V8EventListenerListIterator::~V8EventListenerListIterator() { }
|
| +
|
| +void V8EventListenerListIterator::operator++()
|
| +{
|
| + if (m_iter != m_list->m_table.end()) {
|
| + Vector<V8EventListener*>* vector = m_iter->second;
|
| + if (m_vectorIndex + 1 < vector->size()) {
|
| + m_vectorIndex++;
|
| + return;
|
| + }
|
| + m_vectorIndex = 0;
|
| + ++m_iter;
|
| + }
|
| +}
|
| +
|
| +bool V8EventListenerListIterator::operator==(const V8EventListenerListIterator& other)
|
| +{
|
| + return other.m_iter == m_iter && other.m_vectorIndex == m_vectorIndex && other.m_list == m_list;
|
| +}
|
| +
|
| +bool V8EventListenerListIterator::operator!=(const V8EventListenerListIterator& other)
|
| +{
|
| + return !operator==(other);
|
| +}
|
| +
|
| +V8EventListener* V8EventListenerListIterator::operator*()
|
| +{
|
| + if (m_iter != m_list->m_table.end()) {
|
| + Vector<V8EventListener*>* vector = m_iter->second;
|
| + if (m_vectorIndex < vector->size())
|
| + return vector->at(m_vectorIndex);
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +void V8EventListenerListIterator::seekToEnd()
|
| +{
|
| + m_iter = m_list->m_table.end();
|
| + m_vectorIndex = 0;
|
| +}
|
| +
|
| +
|
| +V8EventListenerList::V8EventListenerList()
|
| +{
|
| +}
|
| +
|
| V8EventListenerList::~V8EventListenerList()
|
| {
|
| - m_inlineKey.Dispose();
|
| - m_nonInlineKey.Dispose();
|
| }
|
|
|
| -V8EventListenerList::iterator V8EventListenerList::begin()
|
| +V8EventListenerListIterator V8EventListenerList::begin()
|
| {
|
| - return m_list.begin();
|
| + return iterator(this);
|
| }
|
|
|
| -V8EventListenerList::iterator V8EventListenerList::end()
|
| +V8EventListenerListIterator V8EventListenerList::end()
|
| {
|
| - return m_list.end();
|
| + return iterator(this, true);
|
| }
|
|
|
| -v8::Handle<v8::String> V8EventListenerList::getKey(bool isInline)
|
| +
|
| +int getKey(v8::Local<v8::Object> object)
|
| {
|
| - return isInline ? m_inlineKey : m_nonInlineKey;
|
| + // 0 is a sentinel value for the HashMap key, so we map it to 1.
|
| + int hash = object->GetIdentityHash();
|
| + if (!hash)
|
| + return 1;
|
| + return hash;
|
| }
|
|
|
| -// See comment in .h file for this function, and update accordingly if implementation details change here.
|
| void V8EventListenerList::add(V8EventListener* listener)
|
| {
|
| - // FIXME: http://crbug.com/10562
|
| - //ASSERT(v8::Context::InContext());
|
| - m_list.append(listener);
|
| + ASSERT(v8::Context::InContext());
|
| + v8::HandleScope handleScope;
|
|
|
| - v8::HandleScope handleScope;
|
| v8::Local<v8::Object> object = listener->getListenerObject();
|
| - v8::Local<v8::Value> value = v8::External::Wrap(listener);
|
| - object->SetHiddenValue(getKey(listener->isAttribute()), value);
|
| + int key = getKey(object);
|
| + Vector<V8EventListener*>* vector = m_table.get(key);
|
| + if (!vector) {
|
| + vector = new Vector<V8EventListener*>();
|
| + m_table.set(key, vector);
|
| + }
|
| + vector->append(listener);
|
| + m_reverseTable.set(listener, key);
|
| }
|
|
|
| void V8EventListenerList::remove(V8EventListener* listener)
|
| {
|
| - // FIXME: http://crbug.com/10562
|
| - //ASSERT(v8::Context::InContext());
|
| - v8::HandleScope handleScope;
|
| - v8::Handle<v8::String> key = getKey(listener->isAttribute());
|
| - for (size_t i = 0; i < m_list.size(); i++) {
|
| - V8EventListener* element = m_list.at(i);
|
| - if (element->isAttribute() == listener->isAttribute() && element == listener) {
|
| - v8::Local<v8::Object> object = listener->getListenerObject();
|
| + if (m_reverseTable.contains(listener)) {
|
| + int key = m_reverseTable.get(listener);
|
| + Vector<V8EventListener*>* vector = m_table.get(key);
|
| + if (!vector)
|
| + return;
|
| + for (size_t j = 0; j < vector->size(); j++) {
|
| + if (vector->at(j) == listener) {
|
| + vector->remove(j);
|
| + if (!vector->size())
|
| + m_table.remove(key);
|
|
|
| - // FIXME(asargent) this check for hidden value being !empty is a workaround for
|
| - // http://code.google.com/p/v8/issues/detail?id=300
|
| - // Once the fix for that is pulled into chromium we can remove the check here.
|
| - if (!object->GetHiddenValue(key).IsEmpty())
|
| - object->DeleteHiddenValue(getKey(listener->isAttribute()));
|
| - m_list.remove(i);
|
| - break;
|
| + m_reverseTable.remove(listener);
|
| + return;
|
| + }
|
| }
|
| }
|
| }
|
|
|
| void V8EventListenerList::clear()
|
| {
|
| - // FIXME: http://crbug.com/10562
|
| - //ASSERT(v8::Context::InContext());
|
| - v8::HandleScope handleScope;
|
| - for (size_t i = 0; i < m_list.size(); i++) {
|
| - V8EventListener* element = m_list.at(i);
|
| - v8::Local<v8::Object> object = element->getListenerObject();
|
| - object->DeleteHiddenValue(getKey(element->isAttribute()));
|
| - }
|
| - m_list.clear();
|
| + m_table.clear();
|
| + m_reverseTable.clear();
|
| }
|
|
|
| -V8EventListener* V8EventListenerList::find(v8::Local<v8::Object> object, bool isInline)
|
| +V8EventListener* V8EventListenerList::find(v8::Local<v8::Object> object, bool isAttribute)
|
| {
|
| - v8::Local<v8::Value> value = object->GetHiddenValue(getKey(isInline));
|
| - if (value.IsEmpty())
|
| + ASSERT(v8::Context::InContext());
|
| + int key = getKey(object);
|
| +
|
| + Vector<V8EventListener*>* vector = m_table.get(key);
|
| + if (!vector)
|
| return 0;
|
| - return reinterpret_cast<V8EventListener*>(v8::External::Unwrap(value));
|
| +
|
| + for (size_t i = 0; i < vector->size(); i++) {
|
| + V8EventListener* element = vector->at(i);
|
| + if (isAttribute == element->isAttribute() && object == element->getListenerObject())
|
| + return element;
|
| + }
|
| + return 0;
|
| }
|
|
|
| } // namespace WebCore
|
|
|