V8DOMWrapper.cpp revision 0a1c44c4c4b15d34cfec09cc303479df2743584b
1/* 2 * Copyright (C) 2009 Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "V8DOMWrapper.h" 33 34#include "CSSMutableStyleDeclaration.h" 35#include "DOMDataStore.h" 36#include "DOMObjectsInclude.h" 37#include "DocumentLoader.h" 38#include "FrameLoaderClient.h" 39#include "Notification.h" 40#include "SVGElementInstance.h" 41#include "SVGPathSeg.h" 42#include "ScriptController.h" 43#include "V8AbstractEventListener.h" 44#include "V8Binding.h" 45#include "V8Collection.h" 46#include "V8CustomEventListener.h" 47#include "V8DOMApplicationCache.h" 48#include "V8DOMMap.h" 49#include "V8DOMWindow.h" 50#include "V8EventListenerList.h" 51#include "V8HTMLCollection.h" 52#include "V8HTMLDocument.h" 53#include "V8Index.h" 54#include "V8IsolatedContext.h" 55#include "V8Location.h" 56#include "V8MessageChannel.h" 57#include "V8NamedNodeMap.h" 58#include "V8Node.h" 59#include "V8NodeList.h" 60#include "V8Notification.h" 61#include "V8Proxy.h" 62#include "V8SVGElementInstance.h" 63#include "V8SharedWorker.h" 64#include "V8SharedWorkerContext.h" 65#include "V8StyleSheet.h" 66#include "V8WebSocket.h" 67#include "V8Worker.h" 68#include "V8WorkerContext.h" 69#include "V8XMLHttpRequest.h" 70#include "WebGLArray.h" 71#include "WebGLContextAttributes.h" 72#include "WebGLUniformLocation.h" 73#include "WorkerContextExecutionProxy.h" 74 75#include <algorithm> 76#include <utility> 77#include <v8.h> 78#include <v8-debug.h> 79#include <wtf/Assertions.h> 80#include <wtf/OwnArrayPtr.h> 81#include <wtf/StdLibExtras.h> 82#include <wtf/UnusedParam.h> 83 84namespace WebCore { 85 86typedef HashMap<Node*, v8::Object*> DOMNodeMap; 87typedef HashMap<void*, v8::Object*> DOMObjectMap; 88 89#if ENABLE(3D_CANVAS) 90void V8DOMWrapper::setIndexedPropertiesToExternalArray(v8::Handle<v8::Object> wrapper, 91 int index, 92 void* address, 93 int length) 94{ 95 v8::ExternalArrayType array_type = v8::kExternalByteArray; 96 V8ClassIndex::V8WrapperType classIndex = V8ClassIndex::FromInt(index); 97 switch (classIndex) { 98 case V8ClassIndex::WEBGLBYTEARRAY: 99 array_type = v8::kExternalByteArray; 100 break; 101 case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY: 102 array_type = v8::kExternalUnsignedByteArray; 103 break; 104 case V8ClassIndex::WEBGLSHORTARRAY: 105 array_type = v8::kExternalShortArray; 106 break; 107 case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY: 108 array_type = v8::kExternalUnsignedShortArray; 109 break; 110 case V8ClassIndex::WEBGLINTARRAY: 111 array_type = v8::kExternalIntArray; 112 break; 113 case V8ClassIndex::WEBGLUNSIGNEDINTARRAY: 114 array_type = v8::kExternalUnsignedIntArray; 115 break; 116 case V8ClassIndex::WEBGLFLOATARRAY: 117 array_type = v8::kExternalFloatArray; 118 break; 119 default: 120 ASSERT_NOT_REACHED(); 121 } 122 wrapper->SetIndexedPropertiesToExternalArrayData(address, 123 array_type, 124 length); 125} 126#endif 127 128// The caller must have increased obj's ref count. 129void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper) 130{ 131 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); 132#ifndef NDEBUG 133 V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); 134 switch (type) { 135#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: 136 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) 137 ASSERT_NOT_REACHED(); 138#undef MAKE_CASE 139 default: 140 break; 141 } 142#endif 143 getDOMObjectMap().set(object, wrapper); 144} 145 146// The caller must have increased obj's ref count. 147void V8DOMWrapper::setJSWrapperForActiveDOMObject(void* object, v8::Persistent<v8::Object> wrapper) 148{ 149 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); 150#ifndef NDEBUG 151 V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); 152 switch (type) { 153#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break; 154 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) 155 default: 156 ASSERT_NOT_REACHED(); 157#undef MAKE_CASE 158 } 159#endif 160 getActiveDOMObjectMap().set(object, wrapper); 161} 162 163// The caller must have increased node's ref count. 164void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper) 165{ 166 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); 167 getDOMNodeMap().set(node, wrapper); 168} 169 170v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> objectPrototype) 171{ 172 // A DOM constructor is a function instance created from a DOM constructor 173 // template. There is one instance per context. A DOM constructor is 174 // different from a normal function in two ways: 175 // 1) it cannot be called as constructor (aka, used to create a DOM object) 176 // 2) its __proto__ points to Object.prototype rather than 177 // Function.prototype. 178 // The reason for 2) is that, in Safari, a DOM constructor is a normal JS 179 // object, but not a function. Hotmail relies on the fact that, in Safari, 180 // HTMLElement.__proto__ == Object.prototype. 181 v8::Handle<v8::FunctionTemplate> functionTemplate = V8ClassIndex::getTemplate(type); 182 // Getting the function might fail if we're running out of 183 // stack or memory. 184 v8::TryCatch tryCatch; 185 v8::Local<v8::Function> value = functionTemplate->GetFunction(); 186 if (value.IsEmpty()) 187 return v8::Local<v8::Function>(); 188 // Hotmail fix, see comments above. 189 if (!objectPrototype.IsEmpty()) 190 value->Set(v8::String::New("__proto__"), objectPrototype); 191 return value; 192} 193 194v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Context> context) 195{ 196 // Enter the scope for this context to get the correct constructor. 197 v8::Context::Scope scope(context); 198 199 return getConstructor(type, V8DOMWindowShell::getHiddenObjectPrototype(context)); 200} 201 202v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window) 203{ 204 Frame* frame = window->frame(); 205 if (!frame) 206 return v8::Local<v8::Function>(); 207 208 v8::Handle<v8::Context> context = V8Proxy::context(frame); 209 if (context.IsEmpty()) 210 return v8::Local<v8::Function>(); 211 212 return getConstructorForContext(type, context); 213} 214 215#if ENABLE(WORKERS) 216v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, WorkerContext*) 217{ 218 WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); 219 if (!proxy) 220 return v8::Local<v8::Function>(); 221 222 v8::Handle<v8::Context> context = proxy->context(); 223 if (context.IsEmpty()) 224 return v8::Local<v8::Function>(); 225 226 return getConstructorForContext(type, context); 227} 228#endif 229 230void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalIndex, v8::Handle<v8::Object> jsObject) 231{ 232 // Get DOMWindow 233 if (!frame) 234 return; // Object might be detached from window 235 v8::Handle<v8::Context> context = V8Proxy::context(frame); 236 if (context.IsEmpty()) 237 return; 238 239 ASSERT(internalIndex < V8DOMWindow::internalFieldCount); 240 241 v8::Handle<v8::Object> global = context->Global(); 242 // Look for real DOM wrapper. 243 global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); 244 ASSERT(!global.IsEmpty()); 245 ASSERT(global->GetInternalField(internalIndex)->IsUndefined()); 246 global->SetInternalField(internalIndex, jsObject); 247} 248 249V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object) 250{ 251 ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); 252 v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); 253 return V8ClassIndex::FromInt(type->Int32Value()); 254} 255 256PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter) 257{ 258 // A NodeFilter is used when walking through a DOM tree or iterating tree 259 // nodes. 260 // FIXME: we may want to cache NodeFilterCondition and NodeFilter 261 // object, but it is minor. 262 // NodeFilter is passed to NodeIterator that has a ref counted pointer 263 // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition. 264 // In NodeFilterCondition, filter object is persisted in its constructor, 265 // and disposed in its destructor. 266 if (!filter->IsFunction()) 267 return 0; 268 269 NodeFilterCondition* condition = new V8NodeFilterCondition(filter); 270 return NodeFilter::create(condition); 271} 272 273static bool globalObjectPrototypeIsDOMWindow(v8::Handle<v8::Object> objectPrototype) 274{ 275#if ENABLE(SHARED_WORKERS) 276 // We can identify what type of context the global object is wrapping by looking at the 277 // internal field count of its prototype. This assumes WorkerContexts and DOMWindows have different numbers 278 // of internal fields, so a COMPILE_ASSERT is included to warn if this ever changes. DOMWindow has 279 // traditionally had far more internal fields than any other class. 280 COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8WorkerContext::internalFieldCount && V8DOMWindow::internalFieldCount != V8SharedWorkerContext::internalFieldCount, 281 DOMWindowAndWorkerContextHaveUnequalFieldCounts); 282#endif 283 return objectPrototype->InternalFieldCount() == V8DOMWindow::internalFieldCount; 284} 285 286v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType type, void* impl) 287{ 288 WorkerContext* workerContext = 0; 289 if (V8IsolatedContext::getEntered()) { 290 // This effectively disables the wrapper cache for isolated worlds. 291 proxy = 0; 292 // FIXME: Do we need a wrapper cache for the isolated world? We should 293 // see if the performance gains are worth while. 294 // We'll get one once we give the isolated context a proper window shell. 295 } else if (!proxy) { 296 v8::Handle<v8::Context> context = v8::Context::GetCurrent(); 297 if (!context.IsEmpty()) { 298 v8::Handle<v8::Object> globalPrototype = v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); 299 if (globalObjectPrototypeIsDOMWindow(globalPrototype)) 300 proxy = V8Proxy::retrieve(V8DOMWindow::toNative(globalPrototype)->frame()); 301#if ENABLE(WORKERS) 302 else 303 workerContext = V8WorkerContext::toNative(globalPrototype); 304#endif 305 } 306 } 307 308 v8::Local<v8::Object> instance; 309 if (proxy) 310 // FIXME: Fix this to work properly with isolated worlds (see above). 311 instance = proxy->windowShell()->createWrapperFromCache(type); 312 else { 313 v8::Local<v8::Function> function; 314 if (workerContext) 315 function = getConstructor(type, workerContext); 316 else 317 function = V8ClassIndex::getTemplate(type)->GetFunction(); 318 instance = SafeAllocation::newInstance(function); 319 } 320 if (!instance.IsEmpty()) { 321 // Avoid setting the DOM wrapper for failed allocations. 322 setDOMWrapper(instance, V8ClassIndex::ToInt(type), impl); 323 } 324 return instance; 325} 326 327#ifndef NDEBUG 328bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) 329{ 330 if (value.IsEmpty() || !value->IsObject()) 331 return false; 332 333 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); 334 if (!object->InternalFieldCount()) 335 return false; 336 337 ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); 338 339 v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); 340 ASSERT(type->IsInt32()); 341 ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); 342 343 v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); 344 ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); 345 346 return true; 347} 348#endif 349 350bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType) 351{ 352 if (value.IsEmpty() || !value->IsObject()) 353 return false; 354 355 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); 356 if (!object->InternalFieldCount()) 357 return false; 358 359 ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); 360 361 v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); 362 ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); 363 364 v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); 365 ASSERT(type->IsInt32()); 366 ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); 367 368 return V8ClassIndex::FromInt(type->Int32Value()) == classType; 369} 370 371v8::Handle<v8::Object> V8DOMWrapper::getWrapper(Node* node) 372{ 373 ASSERT(WTF::isMainThread()); 374 V8IsolatedContext* context = V8IsolatedContext::getEntered(); 375 if (LIKELY(!context)) { 376 v8::Persistent<v8::Object>* wrapper = node->wrapper(); 377 if (!wrapper) 378 return v8::Handle<v8::Object>(); 379 return *wrapper; 380 } 381 382 DOMNodeMapping& domNodeMap = context->world()->domDataStore()->domNodeMap(); 383 return domNodeMap.get(node); 384} 385 386// A JS object of type EventTarget is limited to a small number of possible classes. 387// Check EventTarget.h for new type conversion methods 388v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* target) 389{ 390 if (!target) 391 return v8::Null(); 392 393#if ENABLE(SVG) 394 if (SVGElementInstance* instance = target->toSVGElementInstance()) 395 return toV8(instance); 396#endif 397 398#if ENABLE(WORKERS) 399 if (Worker* worker = target->toWorker()) 400 return toV8(worker); 401 402 if (DedicatedWorkerContext* workerContext = target->toDedicatedWorkerContext()) 403 return toV8(workerContext); 404#endif // WORKERS 405 406#if ENABLE(SHARED_WORKERS) 407 if (SharedWorker* sharedWorker = target->toSharedWorker()) 408 return toV8(sharedWorker); 409 410 if (SharedWorkerContext* sharedWorkerContext = target->toSharedWorkerContext()) 411 return toV8(sharedWorkerContext); 412#endif // SHARED_WORKERS 413 414#if ENABLE(NOTIFICATIONS) 415 if (Notification* notification = target->toNotification()) 416 return toV8(notification); 417#endif 418 419#if ENABLE(WEB_SOCKETS) 420 if (WebSocket* webSocket = target->toWebSocket()) 421 return toV8(webSocket); 422#endif 423 424 if (Node* node = target->toNode()) 425 return toV8(node); 426 427 if (DOMWindow* domWindow = target->toDOMWindow()) 428 return toV8(domWindow); 429 430 // XMLHttpRequest is created within its JS counterpart. 431 if (XMLHttpRequest* xmlHttpRequest = target->toXMLHttpRequest()) { 432 v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xmlHttpRequest); 433 ASSERT(!wrapper.IsEmpty()); 434 return wrapper; 435 } 436 437 if (XMLHttpRequest* xhr = target->toXMLHttpRequest()) 438 return toV8(xhr); 439 440 // MessagePort is created within its JS counterpart 441 if (MessagePort* port = target->toMessagePort()) { 442 v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port); 443 ASSERT(!wrapper.IsEmpty()); 444 return wrapper; 445 } 446 447 if (XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload()) { 448 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload); 449 ASSERT(!wrapper.IsEmpty()); 450 return wrapper; 451 } 452 453#if ENABLE(OFFLINE_WEB_APPLICATIONS) 454 if (DOMApplicationCache* domAppCache = target->toDOMApplicationCache()) 455 return toV8(domAppCache); 456#endif 457 458#if ENABLE(EVENTSOURCE) 459 if (EventSource* eventSource = target->toEventSource()) 460 return toV8(eventSource); 461#endif 462 463 ASSERT(0); 464 return notHandledByInterceptor(); 465} 466 467PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 468{ 469 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 470} 471 472#if ENABLE(SVG) 473PassRefPtr<EventListener> V8DOMWrapper::getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 474{ 475 return getEventListener(element->correspondingElement(), value, isAttribute, lookup); 476} 477#endif 478 479// ANDROID 480// Temporary fix until we merge http://trac.webkit.org/changeset/55096 481#if ENABLE(WORKERS) 482PassRefPtr<EventListener> V8DOMWrapper::getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 483{ 484 if (worker->scriptExecutionContext()->isWorkerContext()) { 485 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 486 ASSERT(workerContextProxy); 487 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 488 } 489 490 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 491} 492#endif 493 494#if ENABLE(NOTIFICATIONS) 495PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 496{ 497 if (notification->scriptExecutionContext()->isWorkerContext()) { 498 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 499 ASSERT(workerContextProxy); 500 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 501 } 502 503 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 504} 505#endif 506 507// ANDROID 508// Temporary fix until we merge http://trac.webkit.org/changeset/55096 509#if ENABLE(WORKERS) 510PassRefPtr<EventListener> V8DOMWrapper::getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 511{ 512 WorkerContextExecutionProxy* workerContextProxy = workerContext->script()->proxy(); 513 if (workerContextProxy) 514 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 515 516 return 0; 517} 518#endif 519 520PassRefPtr<EventListener> V8DOMWrapper::getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 521{ 522 return getEventListener(upload->associatedXMLHttpRequest(), value, isAttribute, lookup); 523} 524 525#if ENABLE(EVENTSOURCE) 526PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventSource* eventSource, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 527{ 528 if (V8Proxy::retrieve(eventSource->scriptExecutionContext())) 529 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 530 531#if ENABLE(WORKERS) 532 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 533 if (workerContextProxy) 534 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 535#endif 536 537 return 0; 538} 539#endif 540 541PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 542{ 543 if (V8Proxy::retrieve(eventTarget->scriptExecutionContext())) 544 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 545 546#if ENABLE(WORKERS) 547 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 548 if (workerContextProxy) 549 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 550#endif 551 552 return 0; 553} 554 555PassRefPtr<EventListener> V8DOMWrapper::getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 556{ 557 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 558} 559 560} // namespace WebCore 561