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 84 namespace WebCore { 85 86 typedef HashMap<Node*, v8::Object*> DOMNodeMap; 87 typedef HashMap<void*, v8::Object*> DOMObjectMap; 88 89 #if ENABLE(3D_CANVAS) 90 void 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. 129 void 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. 147 void 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. 164 void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper) 165 { 166 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); 167 getDOMNodeMap().set(node, wrapper); 168 } 169 170 v8::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 194 v8::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 202 v8::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) 216 v8::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 230 void 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 249 V8ClassIndex::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 256 PassRefPtr<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 273 static 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 286 v8::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 ENABLE(WORKERS) 315 if (workerContext) 316 function = getConstructor(type, workerContext); 317 else 318 #endif 319 function = V8ClassIndex::getTemplate(type)->GetFunction(); 320 instance = SafeAllocation::newInstance(function); 321 } 322 if (!instance.IsEmpty()) { 323 // Avoid setting the DOM wrapper for failed allocations. 324 setDOMWrapper(instance, V8ClassIndex::ToInt(type), impl); 325 } 326 return instance; 327 } 328 329 #ifndef NDEBUG 330 bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) 331 { 332 if (value.IsEmpty() || !value->IsObject()) 333 return false; 334 335 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); 336 if (!object->InternalFieldCount()) 337 return false; 338 339 ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); 340 341 v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); 342 ASSERT(type->IsInt32()); 343 ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); 344 345 v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); 346 ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); 347 348 return true; 349 } 350 #endif 351 352 bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType) 353 { 354 if (value.IsEmpty() || !value->IsObject()) 355 return false; 356 357 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); 358 if (!object->InternalFieldCount()) 359 return false; 360 361 ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); 362 363 v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); 364 ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); 365 366 v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); 367 ASSERT(type->IsInt32()); 368 ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); 369 370 return V8ClassIndex::FromInt(type->Int32Value()) == classType; 371 } 372 373 v8::Handle<v8::Object> V8DOMWrapper::getWrapper(Node* node) 374 { 375 ASSERT(WTF::isMainThread()); 376 V8IsolatedContext* context = V8IsolatedContext::getEntered(); 377 if (LIKELY(!context)) { 378 v8::Persistent<v8::Object>* wrapper = node->wrapper(); 379 if (!wrapper) 380 return v8::Handle<v8::Object>(); 381 return *wrapper; 382 } 383 384 DOMNodeMapping& domNodeMap = context->world()->domDataStore()->domNodeMap(); 385 return domNodeMap.get(node); 386 } 387 388 // A JS object of type EventTarget is limited to a small number of possible classes. 389 // Check EventTarget.h for new type conversion methods 390 v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* target) 391 { 392 if (!target) 393 return v8::Null(); 394 395 #if ENABLE(SVG) 396 if (SVGElementInstance* instance = target->toSVGElementInstance()) 397 return toV8(instance); 398 #endif 399 400 #if ENABLE(WORKERS) 401 if (Worker* worker = target->toWorker()) 402 return toV8(worker); 403 404 if (DedicatedWorkerContext* workerContext = target->toDedicatedWorkerContext()) 405 return toV8(workerContext); 406 #endif // WORKERS 407 408 #if ENABLE(SHARED_WORKERS) 409 if (SharedWorker* sharedWorker = target->toSharedWorker()) 410 return toV8(sharedWorker); 411 412 if (SharedWorkerContext* sharedWorkerContext = target->toSharedWorkerContext()) 413 return toV8(sharedWorkerContext); 414 #endif // SHARED_WORKERS 415 416 #if ENABLE(NOTIFICATIONS) 417 if (Notification* notification = target->toNotification()) 418 return toV8(notification); 419 #endif 420 421 #if ENABLE(WEB_SOCKETS) 422 if (WebSocket* webSocket = target->toWebSocket()) 423 return toV8(webSocket); 424 #endif 425 426 if (Node* node = target->toNode()) 427 return toV8(node); 428 429 if (DOMWindow* domWindow = target->toDOMWindow()) 430 return toV8(domWindow); 431 432 // XMLHttpRequest is created within its JS counterpart. 433 if (XMLHttpRequest* xmlHttpRequest = target->toXMLHttpRequest()) { 434 v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xmlHttpRequest); 435 ASSERT(!wrapper.IsEmpty()); 436 return wrapper; 437 } 438 439 if (XMLHttpRequest* xhr = target->toXMLHttpRequest()) 440 return toV8(xhr); 441 442 // MessagePort is created within its JS counterpart 443 if (MessagePort* port = target->toMessagePort()) { 444 v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port); 445 ASSERT(!wrapper.IsEmpty()); 446 return wrapper; 447 } 448 449 if (XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload()) { 450 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload); 451 ASSERT(!wrapper.IsEmpty()); 452 return wrapper; 453 } 454 455 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 456 if (DOMApplicationCache* domAppCache = target->toDOMApplicationCache()) 457 return toV8(domAppCache); 458 #endif 459 460 #if ENABLE(EVENTSOURCE) 461 if (EventSource* eventSource = target->toEventSource()) 462 return toV8(eventSource); 463 #endif 464 465 ASSERT(0); 466 return notHandledByInterceptor(); 467 } 468 469 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 470 { 471 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 472 } 473 474 #if ENABLE(SVG) 475 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 476 { 477 return getEventListener(element->correspondingElement(), value, isAttribute, lookup); 478 } 479 #endif 480 481 // ANDROID 482 // Temporary fix until we merge http://trac.webkit.org/changeset/55096 483 #if ENABLE(WORKERS) 484 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 485 { 486 if (worker->scriptExecutionContext()->isWorkerContext()) { 487 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 488 ASSERT(workerContextProxy); 489 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 490 } 491 492 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 493 } 494 #endif 495 496 #if ENABLE(NOTIFICATIONS) 497 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 498 { 499 if (notification->scriptExecutionContext()->isWorkerContext()) { 500 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 501 ASSERT(workerContextProxy); 502 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 503 } 504 505 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 506 } 507 #endif 508 509 // ANDROID 510 // Temporary fix until we merge http://trac.webkit.org/changeset/55096 511 #if ENABLE(WORKERS) 512 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 513 { 514 WorkerContextExecutionProxy* workerContextProxy = workerContext->script()->proxy(); 515 if (workerContextProxy) 516 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 517 518 return 0; 519 } 520 #endif 521 522 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 523 { 524 return getEventListener(upload->associatedXMLHttpRequest(), value, isAttribute, lookup); 525 } 526 527 #if ENABLE(EVENTSOURCE) 528 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventSource* eventSource, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 529 { 530 if (V8Proxy::retrieve(eventSource->scriptExecutionContext())) 531 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 532 533 #if ENABLE(WORKERS) 534 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 535 if (workerContextProxy) 536 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 537 #endif 538 539 return 0; 540 } 541 #endif 542 543 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 544 { 545 if (V8Proxy::retrieve(eventTarget->scriptExecutionContext())) 546 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 547 548 #if ENABLE(WORKERS) 549 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 550 if (workerContextProxy) 551 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 552 #endif 553 554 return 0; 555 } 556 557 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 558 { 559 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 560 } 561 562 } // namespace WebCore 563