V8DOMWrapper.cpp revision 643ca7872b450ea4efacab6188849e5aac2ba161
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#if PLATFORM(CHROMIUM) 36#include "ChromiumBridge.h" 37#endif 38#include "DOMObjectsInclude.h" 39#include "DocumentLoader.h" 40#include "FrameLoaderClient.h" 41#include "Notification.h" 42#if PLATFORM(ANDROID) 43// TODO: Upstream SVG guard. 44#if ENABLE(SVG) 45#include "SVGElementInstance.h" 46#endif 47#endif 48#include "ScriptController.h" 49#include "V8AbstractEventListener.h" 50#include "V8Binding.h" 51#include "V8Collection.h" 52#include "V8CustomBinding.h" 53#include "V8CustomEventListener.h" 54#include "V8DOMMap.h" 55#include "V8DOMWindow.h" 56#include "V8EventListenerList.h" 57#include "V8Index.h" 58#include "V8IsolatedWorld.h" 59#include "V8Proxy.h" 60#include "WebGLArray.h" 61#include "WebGLUniformLocation.h" 62#include "WorkerContextExecutionProxy.h" 63 64#include <algorithm> 65#include <utility> 66#include <v8.h> 67#include <v8-debug.h> 68#include <wtf/Assertions.h> 69#include <wtf/OwnArrayPtr.h> 70#include <wtf/StdLibExtras.h> 71#include <wtf/UnusedParam.h> 72 73namespace WebCore { 74 75typedef HashMap<Node*, v8::Object*> DOMNodeMap; 76typedef HashMap<void*, v8::Object*> DOMObjectMap; 77 78// Get the string 'toString'. 79static v8::Persistent<v8::String> GetToStringName() 80{ 81 DEFINE_STATIC_LOCAL(v8::Persistent<v8::String>, value, ()); 82 if (value.IsEmpty()) 83 value = v8::Persistent<v8::String>::New(v8::String::New("toString")); 84 return value; 85} 86 87static v8::Handle<v8::Value> ConstructorToString(const v8::Arguments& args) 88{ 89 // The DOM constructors' toString functions grab the current toString 90 // for Functions by taking the toString function of itself and then 91 // calling it with the constructor as its receiver. This means that 92 // changes to the Function prototype chain or toString function are 93 // reflected when printing DOM constructors. The only wart is that 94 // changes to a DOM constructor's toString's toString will cause the 95 // toString of the DOM constructor itself to change. This is extremely 96 // obscure and unlikely to be a problem. 97 v8::Handle<v8::Value> value = args.Callee()->Get(GetToStringName()); 98 if (!value->IsFunction()) 99 return v8::String::New(""); 100 return v8::Handle<v8::Function>::Cast(value)->Call(args.This(), 0, 0); 101} 102 103#if ENABLE(SVG) 104v8::Handle<v8::Value> V8DOMWrapper::convertSVGElementInstanceToV8Object(SVGElementInstance* instance) 105{ 106 if (!instance) 107 return v8::Null(); 108 109 v8::Handle<v8::Object> existingInstance = getDOMSVGElementInstanceMap().get(instance); 110 if (!existingInstance.IsEmpty()) 111 return existingInstance; 112 113 instance->ref(); 114 115 // Instantiate the V8 object and remember it 116 v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::SVGELEMENTINSTANCE, V8ClassIndex::SVGELEMENTINSTANCE, instance); 117 if (!result.IsEmpty()) { 118 // Only update the DOM SVG element map if the result is non-empty. 119 getDOMSVGElementInstanceMap().set(instance, v8::Persistent<v8::Object>::New(result)); 120 } 121 return result; 122} 123 124v8::Handle<v8::Value> V8DOMWrapper::convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType type, void* object) 125{ 126 if (!object) 127 return v8::Null(); 128 129 v8::Persistent<v8::Object> result = getDOMSVGObjectWithContextMap().get(object); 130 if (!result.IsEmpty()) 131 return result; 132 133 // Special case: SVGPathSegs need to be downcast to their real type 134 if (type == V8ClassIndex::SVGPATHSEG) 135 type = V8Custom::DowncastSVGPathSeg(object); 136 137 v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, object); 138 if (!v8Object.IsEmpty()) { 139 result = v8::Persistent<v8::Object>::New(v8Object); 140 switch (type) { 141#define MAKE_CASE(TYPE, NAME) \ 142 case V8ClassIndex::TYPE: static_cast<NAME*>(object)->ref(); break; 143 SVG_OBJECT_TYPES(MAKE_CASE) 144#undef MAKE_CASE 145#define MAKE_CASE(TYPE, NAME) \ 146 case V8ClassIndex::TYPE: \ 147 static_cast<V8SVGPODTypeWrapper<NAME>*>(object)->ref(); break; 148 SVG_POD_NATIVE_TYPES(MAKE_CASE) 149#undef MAKE_CASE 150 default: 151 ASSERT_NOT_REACHED(); 152 } 153 getDOMSVGObjectWithContextMap().set(object, result); 154 } 155 156 return result; 157} 158 159#endif 160 161#if ENABLE(3D_CANVAS) 162void V8DOMWrapper::setIndexedPropertiesToExternalArray(v8::Handle<v8::Object> wrapper, 163 int index, 164 void* address, 165 int length) 166{ 167 v8::ExternalArrayType array_type = v8::kExternalByteArray; 168 V8ClassIndex::V8WrapperType classIndex = V8ClassIndex::FromInt(index); 169 switch (classIndex) { 170 case V8ClassIndex::WEBGLBYTEARRAY: 171 array_type = v8::kExternalByteArray; 172 break; 173 case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY: 174 array_type = v8::kExternalUnsignedByteArray; 175 break; 176 case V8ClassIndex::WEBGLSHORTARRAY: 177 array_type = v8::kExternalShortArray; 178 break; 179 case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY: 180 array_type = v8::kExternalUnsignedShortArray; 181 break; 182 case V8ClassIndex::WEBGLINTARRAY: 183 array_type = v8::kExternalIntArray; 184 break; 185 case V8ClassIndex::WEBGLUNSIGNEDINTARRAY: 186 array_type = v8::kExternalUnsignedIntArray; 187 break; 188 case V8ClassIndex::WEBGLFLOATARRAY: 189 array_type = v8::kExternalFloatArray; 190 break; 191 default: 192 ASSERT_NOT_REACHED(); 193 } 194 wrapper->SetIndexedPropertiesToExternalArrayData(address, 195 array_type, 196 length); 197} 198#endif 199 200bool V8DOMWrapper::domObjectHasJSWrapper(void* object) 201{ 202 return getDOMObjectMap().contains(object) || getActiveDOMObjectMap().contains(object); 203} 204 205v8::Persistent<v8::Object> V8DOMWrapper::jsWrapperForDOMObject(void* object) 206{ 207 v8::Persistent<v8::Object> wrapper = getDOMObjectMap().get(object); 208 ASSERT(!wrapper.IsEmpty()); 209 return wrapper; 210} 211 212v8::Persistent<v8::Object> V8DOMWrapper::jsWrapperForActiveDOMObject(void* object) 213{ 214 v8::Persistent<v8::Object> wrapper = getActiveDOMObjectMap().get(object); 215 ASSERT(!wrapper.IsEmpty()); 216 return wrapper; 217} 218 219// The caller must have increased obj's ref count. 220void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper) 221{ 222 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); 223#ifndef NDEBUG 224 V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); 225 switch (type) { 226#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: 227 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) 228 ASSERT_NOT_REACHED(); 229#undef MAKE_CASE 230 default: 231 break; 232 } 233#endif 234 getDOMObjectMap().set(object, wrapper); 235} 236 237// The caller must have increased obj's ref count. 238void V8DOMWrapper::setJSWrapperForActiveDOMObject(void* object, v8::Persistent<v8::Object> wrapper) 239{ 240 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); 241#ifndef NDEBUG 242 V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); 243 switch (type) { 244#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break; 245 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) 246 default: 247 ASSERT_NOT_REACHED(); 248#undef MAKE_CASE 249 } 250#endif 251 getActiveDOMObjectMap().set(object, wrapper); 252} 253 254// The caller must have increased node's ref count. 255void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper) 256{ 257 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); 258 getDOMNodeMap().set(node, wrapper); 259} 260 261v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8WrapperType type) 262{ 263 v8::Persistent<v8::FunctionTemplate>* cacheCell = V8ClassIndex::GetCache(type); 264 if (!cacheCell->IsEmpty()) 265 return *cacheCell; 266 267 // Not in the cache. 268 FunctionTemplateFactory factory = V8ClassIndex::GetFactory(type); 269 v8::Persistent<v8::FunctionTemplate> descriptor = factory(); 270 // DOM constructors are functions and should print themselves as such. 271 // However, we will later replace their prototypes with Object 272 // prototypes so we need to explicitly override toString on the 273 // instance itself. If we later make DOM constructors full objects 274 // we can give them class names instead and Object.prototype.toString 275 // will work so we can remove this code. 276 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, toStringTemplate, ()); 277 if (toStringTemplate.IsEmpty()) 278 toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(ConstructorToString)); 279 descriptor->Set(GetToStringName(), toStringTemplate); 280 switch (type) { 281 case V8ClassIndex::CSSSTYLEDECLARATION: 282 // The named property handler for style declarations has a 283 // setter. Therefore, the interceptor has to be on the object 284 // itself and not on the prototype object. 285 descriptor->InstanceTemplate()->SetNamedPropertyHandler( USE_NAMED_PROPERTY_GETTER(CSSStyleDeclaration), USE_NAMED_PROPERTY_SETTER(CSSStyleDeclaration)); 286 setCollectionStringIndexedGetter<CSSStyleDeclaration>(descriptor); 287 break; 288 case V8ClassIndex::CSSRULELIST: 289 setCollectionIndexedGetter<CSSRuleList, CSSRule>(descriptor, V8ClassIndex::CSSRULE); 290 break; 291 case V8ClassIndex::CSSVALUELIST: 292 setCollectionIndexedGetter<CSSValueList, CSSValue>(descriptor, V8ClassIndex::CSSVALUE); 293 break; 294 case V8ClassIndex::CSSVARIABLESDECLARATION: 295 setCollectionStringIndexedGetter<CSSVariablesDeclaration>(descriptor); 296 break; 297 case V8ClassIndex::WEBKITCSSTRANSFORMVALUE: 298 setCollectionIndexedGetter<WebKitCSSTransformValue, CSSValue>(descriptor, V8ClassIndex::CSSVALUE); 299 break; 300 case V8ClassIndex::HTMLALLCOLLECTION: 301 descriptor->InstanceTemplate()->MarkAsUndetectable(); // fall through 302 case V8ClassIndex::HTMLCOLLECTION: 303 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLCollection)); 304 descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLCollectionCallAsFunction)); 305 setCollectionIndexedGetter<HTMLCollection, Node>(descriptor, V8ClassIndex::NODE); 306 break; 307 case V8ClassIndex::HTMLOPTIONSCOLLECTION: 308 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLCollection)); 309 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLOptionsCollection), USE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection)); 310 descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLCollectionCallAsFunction)); 311 break; 312 case V8ClassIndex::HTMLSELECTELEMENT: 313 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLSelectElementCollection)); 314 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(nodeCollectionIndexedPropertyGetter<HTMLSelectElement>, USE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection), 315 0, 0, nodeCollectionIndexedPropertyEnumerator<HTMLSelectElement>, v8::Integer::New(V8ClassIndex::NODE)); 316 break; 317 case V8ClassIndex::HTMLDOCUMENT: { 318 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLDocument), 0, 0, USE_NAMED_PROPERTY_DELETER(HTMLDocument)); 319 320 // We add an extra internal field to all Document wrappers for 321 // storing a per document DOMImplementation wrapper. 322 // 323 // Additionally, we add two extra internal fields for 324 // HTMLDocuments to implement temporary shadowing of 325 // document.all. One field holds an object that is used as a 326 // marker. The other field holds the marker object if 327 // document.all is not shadowed and some other value if 328 // document.all is shadowed. 329 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 330 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kNodeMinimumInternalFieldCount); 331 instanceTemplate->SetInternalFieldCount(V8Custom::kHTMLDocumentInternalFieldCount); 332 break; 333 } 334#if ENABLE(SVG) 335 case V8ClassIndex::SVGDOCUMENT: // fall through 336#endif 337 case V8ClassIndex::DOCUMENT: { 338 // We add an extra internal field to all Document wrappers for 339 // storing a per document DOMImplementation wrapper. 340 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 341 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kNodeMinimumInternalFieldCount); 342 instanceTemplate->SetInternalFieldCount( V8Custom::kDocumentMinimumInternalFieldCount); 343 break; 344 } 345 case V8ClassIndex::HTMLAPPLETELEMENT: // fall through 346 case V8ClassIndex::HTMLEMBEDELEMENT: // fall through 347 case V8ClassIndex::HTMLOBJECTELEMENT: 348 // HTMLAppletElement, HTMLEmbedElement and HTMLObjectElement are 349 // inherited from HTMLPlugInElement, and they share the same property 350 // handling code. 351 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLPlugInElement), USE_NAMED_PROPERTY_SETTER(HTMLPlugInElement)); 352 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLPlugInElement), USE_INDEXED_PROPERTY_SETTER(HTMLPlugInElement)); 353 descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLPlugInElement)); 354 break; 355 case V8ClassIndex::HTMLFRAMESETELEMENT: 356 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFrameSetElement)); 357 break; 358 case V8ClassIndex::HTMLFORMELEMENT: 359 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFormElement)); 360 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLFormElement), 0, 0, 0, nodeCollectionIndexedPropertyEnumerator<HTMLFormElement>, v8::Integer::New(V8ClassIndex::NODE)); 361 break; 362 case V8ClassIndex::STYLESHEET: // fall through 363 case V8ClassIndex::CSSSTYLESHEET: { 364 // We add an extra internal field to hold a reference to 365 // the owner node. 366 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 367 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); 368 instanceTemplate->SetInternalFieldCount(V8Custom::kStyleSheetInternalFieldCount); 369 break; 370 } 371 case V8ClassIndex::MEDIALIST: 372 setCollectionStringOrNullIndexedGetter<MediaList>(descriptor); 373 break; 374 case V8ClassIndex::MIMETYPEARRAY: 375 setCollectionIndexedAndNamedGetters<MimeTypeArray, MimeType>(descriptor, V8ClassIndex::MIMETYPE); 376 break; 377 case V8ClassIndex::NAMEDNODEMAP: { 378 // We add an extra internal field to hold a reference to the owner node. 379 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 380 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); 381 instanceTemplate->SetInternalFieldCount(V8Custom::kNamedNodeMapInternalFieldCount); 382 instanceTemplate->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NamedNodeMap)); 383 instanceTemplate->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(NamedNodeMap), 0, 0, 0, collectionIndexedPropertyEnumerator<NamedNodeMap>, v8::Integer::New(V8ClassIndex::NODE)); 384 break; 385 } 386#if ENABLE(DOM_STORAGE) 387 case V8ClassIndex::STORAGE: 388 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(Storage), USE_NAMED_PROPERTY_SETTER(Storage), 0, USE_NAMED_PROPERTY_DELETER(Storage), V8Custom::v8StorageNamedPropertyEnumerator); 389 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(Storage), USE_INDEXED_PROPERTY_SETTER(Storage), 0, USE_INDEXED_PROPERTY_DELETER(Storage)); 390 break; 391#endif 392 case V8ClassIndex::NODELIST: 393 setCollectionIndexedGetter<NodeList, Node>(descriptor, V8ClassIndex::NODE); 394 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NodeList)); 395 break; 396 case V8ClassIndex::PLUGIN: 397 setCollectionIndexedAndNamedGetters<Plugin, MimeType>(descriptor, V8ClassIndex::MIMETYPE); 398 break; 399 case V8ClassIndex::PLUGINARRAY: 400 setCollectionIndexedAndNamedGetters<PluginArray, Plugin>(descriptor, V8ClassIndex::PLUGIN); 401 break; 402 case V8ClassIndex::STYLESHEETLIST: 403 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(StyleSheetList)); 404 setCollectionIndexedGetter<StyleSheetList, StyleSheet>(descriptor, V8ClassIndex::STYLESHEET); 405 break; 406 case V8ClassIndex::DOMWINDOW: { 407 v8::Local<v8::Signature> defaultSignature = v8::Signature::New(descriptor); 408 409 descriptor->PrototypeTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DOMWindow)); 410 descriptor->PrototypeTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DOMWindow)); 411 descriptor->PrototypeTemplate()->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount); 412 413 descriptor->SetHiddenPrototype(true); 414 415 // Reserve spaces for references to location, history and 416 // navigator objects. 417 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 418 instanceTemplate->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount); 419 420 // Set access check callbacks, but turned off initially. 421 // When a context is detached from a frame, turn on the access check. 422 // Turning on checks also invalidates inline caches of the object. 423 instanceTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW), false); 424 break; 425 } 426 case V8ClassIndex::LOCATION: { 427 // For security reasons, these functions are on the instance 428 // instead of on the prototype object to insure that they cannot 429 // be overwritten. 430 v8::Local<v8::ObjectTemplate> instance = descriptor->InstanceTemplate(); 431 instance->SetAccessor(v8::String::New("reload"), V8Custom::v8LocationReloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); 432 instance->SetAccessor(v8::String::New("replace"), V8Custom::v8LocationReplaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); 433 instance->SetAccessor(v8::String::New("assign"), V8Custom::v8LocationAssignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); 434 break; 435 } 436 case V8ClassIndex::HISTORY: 437 break; 438 439 case V8ClassIndex::MESSAGECHANNEL: { 440 // Reserve two more internal fields for referencing the port1 441 // and port2 wrappers. This ensures that the port wrappers are 442 // kept alive when the channel wrapper is. 443 descriptor->SetCallHandler(USE_CALLBACK(MessageChannelConstructor)); 444 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 445 instanceTemplate->SetInternalFieldCount(V8Custom::kMessageChannelInternalFieldCount); 446 break; 447 } 448 449 case V8ClassIndex::MESSAGEPORT: { 450 // Reserve one more internal field for keeping event listeners. 451 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 452 instanceTemplate->SetInternalFieldCount(V8Custom::kMessagePortInternalFieldCount); 453 break; 454 } 455 456#if ENABLE(NOTIFICATIONS) 457 case V8ClassIndex::NOTIFICATION: { 458 // Reserve one more internal field for keeping event listeners. 459 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 460 instanceTemplate->SetInternalFieldCount(V8Custom::kNotificationInternalFieldCount); 461 break; 462 } 463#endif // NOTIFICATIONS 464 465#if ENABLE(SVG) 466 case V8ClassIndex::SVGELEMENTINSTANCE: { 467 // Reserve one more internal field for keeping event listeners. 468 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 469 instanceTemplate->SetInternalFieldCount(V8Custom::kSVGElementInstanceInternalFieldCount); 470 break; 471 } 472#endif 473 474#if ENABLE(WORKERS) 475 case V8ClassIndex::ABSTRACTWORKER: { 476 // Reserve one more internal field for keeping event listeners. 477 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 478 instanceTemplate->SetInternalFieldCount(V8Custom::kAbstractWorkerInternalFieldCount); 479 break; 480 } 481 482 case V8ClassIndex::DEDICATEDWORKERCONTEXT: { 483 // Reserve internal fields for keeping event listeners. 484 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 485 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); 486 instanceTemplate->SetInternalFieldCount(V8Custom::kDedicatedWorkerContextInternalFieldCount); 487 break; 488 } 489 490 case V8ClassIndex::WORKER: { 491 // Reserve one more internal field for keeping event listeners. 492 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 493 instanceTemplate->SetInternalFieldCount(V8Custom::kWorkerInternalFieldCount); 494 descriptor->SetCallHandler(USE_CALLBACK(WorkerConstructor)); 495 break; 496 } 497 498 case V8ClassIndex::WORKERCONTEXT: { 499 // Reserve one more internal field for keeping event listeners. 500 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 501 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); 502 instanceTemplate->SetInternalFieldCount(V8Custom::kWorkerContextMinimumInternalFieldCount); 503 break; 504 } 505 506#endif // WORKERS 507 508#if ENABLE(SHARED_WORKERS) 509 case V8ClassIndex::SHAREDWORKER: { 510 // Reserve one more internal field for keeping event listeners. 511 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 512 instanceTemplate->SetInternalFieldCount(V8Custom::kSharedWorkerInternalFieldCount); 513 descriptor->SetCallHandler(USE_CALLBACK(SharedWorkerConstructor)); 514 break; 515 } 516 517 case V8ClassIndex::SHAREDWORKERCONTEXT: { 518 // Reserve internal fields for keeping event listeners. 519 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 520 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); 521 instanceTemplate->SetInternalFieldCount(V8Custom::kSharedWorkerContextInternalFieldCount); 522 break; 523 } 524#endif // SHARED_WORKERS 525 526#if ENABLE(OFFLINE_WEB_APPLICATIONS) 527 case V8ClassIndex::DOMAPPLICATIONCACHE: { 528 // Reserve one more internal field for keeping event listeners. 529 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 530 instanceTemplate->SetInternalFieldCount(V8Custom::kDOMApplicationCacheFieldCount); 531 break; 532 } 533#endif 534 535#if ENABLE(3D_CANVAS) 536 // The following objects are created from JavaScript. 537 case V8ClassIndex::WEBGLARRAYBUFFER: 538 descriptor->SetCallHandler(USE_CALLBACK(WebGLArrayBufferConstructor)); 539 break; 540 case V8ClassIndex::WEBGLBYTEARRAY: 541 descriptor->SetCallHandler(USE_CALLBACK(WebGLByteArrayConstructor)); 542 break; 543 case V8ClassIndex::WEBGLFLOATARRAY: 544 descriptor->SetCallHandler(USE_CALLBACK(WebGLFloatArrayConstructor)); 545 break; 546 case V8ClassIndex::WEBGLINTARRAY: 547 descriptor->SetCallHandler(USE_CALLBACK(WebGLIntArrayConstructor)); 548 break; 549 case V8ClassIndex::WEBGLSHORTARRAY: 550 descriptor->SetCallHandler(USE_CALLBACK(WebGLShortArrayConstructor)); 551 break; 552 case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY: 553 descriptor->SetCallHandler(USE_CALLBACK(WebGLUnsignedByteArrayConstructor)); 554 break; 555 case V8ClassIndex::WEBGLUNSIGNEDINTARRAY: 556 descriptor->SetCallHandler(USE_CALLBACK(WebGLUnsignedIntArrayConstructor)); 557 break; 558 case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY: 559 descriptor->SetCallHandler(USE_CALLBACK(WebGLUnsignedShortArrayConstructor)); 560 break; 561#endif 562 case V8ClassIndex::DOMPARSER: 563 descriptor->SetCallHandler(USE_CALLBACK(DOMParserConstructor)); 564 break; 565 case V8ClassIndex::WEBKITCSSMATRIX: 566 descriptor->SetCallHandler(USE_CALLBACK(WebKitCSSMatrixConstructor)); 567 break; 568 case V8ClassIndex::WEBKITPOINT: 569 descriptor->SetCallHandler(USE_CALLBACK(WebKitPointConstructor)); 570 break; 571#if ENABLE(WEB_SOCKETS) 572 case V8ClassIndex::WEBSOCKET: { 573 // Reserve one more internal field for keeping event listeners. 574 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 575 instanceTemplate->SetInternalFieldCount(V8Custom::kWebSocketInternalFieldCount); 576 descriptor->SetCallHandler(USE_CALLBACK(WebSocketConstructor)); 577 break; 578 } 579#endif 580 case V8ClassIndex::XMLSERIALIZER: 581 descriptor->SetCallHandler(USE_CALLBACK(XMLSerializerConstructor)); 582 break; 583 case V8ClassIndex::XMLHTTPREQUEST: { 584 // Reserve one more internal field for keeping event listeners. 585 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 586 instanceTemplate->SetInternalFieldCount(V8Custom::kXMLHttpRequestInternalFieldCount); 587 descriptor->SetCallHandler(USE_CALLBACK(XMLHttpRequestConstructor)); 588 break; 589 } 590 case V8ClassIndex::XMLHTTPREQUESTUPLOAD: { 591 // Reserve one more internal field for keeping event listeners. 592 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 593 instanceTemplate->SetInternalFieldCount(V8Custom::kXMLHttpRequestInternalFieldCount); 594 break; 595 } 596#if ENABLE(XPATH) 597 case V8ClassIndex::XPATHEVALUATOR: 598 descriptor->SetCallHandler(USE_CALLBACK(XPathEvaluatorConstructor)); 599 break; 600#endif 601#if ENABLE(XSLT) 602 case V8ClassIndex::XSLTPROCESSOR: 603 descriptor->SetCallHandler(USE_CALLBACK(XSLTProcessorConstructor)); 604 break; 605#endif 606#if ENABLE(TOUCH_EVENTS) 607 // TODO(andreip): upstream touch related changes to Chromium 608 case V8ClassIndex::TOUCHLIST: { 609 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); 610 instanceTemplate->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(TouchList)); 611 break; 612 } 613#endif 614 case V8ClassIndex::CLIENTRECTLIST: 615 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(ClientRectList)); 616 break; 617 case V8ClassIndex::FILELIST: 618 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(FileList)); 619 break; 620#if ENABLE(DATAGRID) 621 case V8ClassIndex::DATAGRIDCOLUMNLIST: 622 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DataGridColumnList)); 623 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DataGridColumnList)); 624 break; 625#endif 626 default: 627 break; 628 } 629 630 *cacheCell = descriptor; 631 return descriptor; 632} 633 634v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> objectPrototype) 635{ 636 // A DOM constructor is a function instance created from a DOM constructor 637 // template. There is one instance per context. A DOM constructor is 638 // different from a normal function in two ways: 639 // 1) it cannot be called as constructor (aka, used to create a DOM object) 640 // 2) its __proto__ points to Object.prototype rather than 641 // Function.prototype. 642 // The reason for 2) is that, in Safari, a DOM constructor is a normal JS 643 // object, but not a function. Hotmail relies on the fact that, in Safari, 644 // HTMLElement.__proto__ == Object.prototype. 645 v8::Handle<v8::FunctionTemplate> functionTemplate = getTemplate(type); 646 // Getting the function might fail if we're running out of 647 // stack or memory. 648 v8::TryCatch tryCatch; 649 v8::Local<v8::Function> value = functionTemplate->GetFunction(); 650 if (value.IsEmpty()) 651 return v8::Local<v8::Function>(); 652 // Hotmail fix, see comments above. 653 if (!objectPrototype.IsEmpty()) 654 value->Set(v8::String::New("__proto__"), objectPrototype); 655 return value; 656} 657 658v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Context> context) 659{ 660 // Enter the scope for this context to get the correct constructor. 661 v8::Context::Scope scope(context); 662 663 return getConstructor(type, V8Proxy::getHiddenObjectPrototype(context)); 664} 665 666v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window) 667{ 668 Frame* frame = window->frame(); 669 if (!frame) 670 return v8::Local<v8::Function>(); 671 672 v8::Handle<v8::Context> context = V8Proxy::context(frame); 673 if (context.IsEmpty()) 674 return v8::Local<v8::Function>(); 675 676 return getConstructorForContext(type, context); 677} 678 679v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, WorkerContext*) 680{ 681 WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); 682 if (!proxy) 683 return v8::Local<v8::Function>(); 684 685 v8::Handle<v8::Context> context = proxy->context(); 686 if (context.IsEmpty()) 687 return v8::Local<v8::Function>(); 688 689 return getConstructorForContext(type, context); 690} 691 692v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl) 693{ 694 ASSERT(type != V8ClassIndex::EVENTLISTENER); 695 ASSERT(type != V8ClassIndex::EVENTTARGET); 696 ASSERT(type != V8ClassIndex::EVENT); 697 698 // These objects can be constructed under WorkerContextExecutionProxy. They need special 699 // handling, since if we proceed below V8Proxy::retrieve() will get called and will crash. 700 // TODO(ukai): websocket? 701 if ((type == V8ClassIndex::DOMCOREEXCEPTION 702 || type == V8ClassIndex::RANGEEXCEPTION 703 || type == V8ClassIndex::EVENTEXCEPTION 704 || type == V8ClassIndex::XMLHTTPREQUESTEXCEPTION 705 || type == V8ClassIndex::MESSAGEPORT) 706 && WorkerContextExecutionProxy::retrieve()) { 707 return WorkerContextExecutionProxy::convertToV8Object(type, impl); 708 } 709 710 bool isActiveDomObject = false; 711 switch (type) { 712#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: 713 DOM_NODE_TYPES(MAKE_CASE) 714#if ENABLE(SVG) 715 SVG_NODE_TYPES(MAKE_CASE) 716#endif 717 return convertNodeToV8Object(static_cast<Node*>(impl)); 718 case V8ClassIndex::CSSVALUE: 719 return convertCSSValueToV8Object(static_cast<CSSValue*>(impl)); 720 case V8ClassIndex::CSSRULE: 721 return convertCSSRuleToV8Object(static_cast<CSSRule*>(impl)); 722 case V8ClassIndex::STYLESHEET: 723 return convertStyleSheetToV8Object(static_cast<StyleSheet*>(impl)); 724 case V8ClassIndex::DOMWINDOW: 725 return convertWindowToV8Object(static_cast<DOMWindow*>(impl)); 726 case V8ClassIndex::NAMEDNODEMAP: 727 return convertNamedNodeMapToV8Object(static_cast<NamedNodeMap*>(impl)); 728#if ENABLE(SVG) 729 SVG_NONNODE_TYPES(MAKE_CASE) 730 if (type == V8ClassIndex::SVGELEMENTINSTANCE) 731 return convertSVGElementInstanceToV8Object(static_cast<SVGElementInstance*>(impl)); 732 return convertSVGObjectWithContextToV8Object(type, impl); 733#endif 734 735 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) 736 isActiveDomObject = true; 737 break; 738 default: 739 break; 740 } 741 742#undef MAKE_CASE 743 744 if (!impl) 745 return v8::Null(); 746 747 // Non DOM node 748 v8::Persistent<v8::Object> result = isActiveDomObject ? getActiveDOMObjectMap().get(impl) : getDOMObjectMap().get(impl); 749 if (result.IsEmpty()) { 750#if ENABLE(3D_CANVAS) 751 if (type == V8ClassIndex::WEBGLARRAY && impl) { 752 // Determine which subclass we are wrapping. 753 WebGLArray* array = reinterpret_cast<WebGLArray*>(impl); 754 if (array->isByteArray()) 755 type = V8ClassIndex::WEBGLBYTEARRAY; 756 else if (array->isFloatArray()) 757 type = V8ClassIndex::WEBGLFLOATARRAY; 758 else if (array->isIntArray()) 759 type = V8ClassIndex::WEBGLINTARRAY; 760 else if (array->isShortArray()) 761 type = V8ClassIndex::WEBGLSHORTARRAY; 762 else if (array->isUnsignedByteArray()) 763 type = V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY; 764 else if (array->isUnsignedIntArray()) 765 type = V8ClassIndex::WEBGLUNSIGNEDINTARRAY; 766 else if (array->isUnsignedShortArray()) 767 type = V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY; 768 } 769#endif 770 771 v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, impl); 772 if (!v8Object.IsEmpty()) { 773 // Go through big switch statement, it has some duplications 774 // that were handled by code above (such as CSSVALUE, CSSRULE, etc). 775 switch (type) { 776#define MAKE_CASE(TYPE, NAME) \ 777 case V8ClassIndex::TYPE: static_cast<NAME*>(impl)->ref(); break; 778 DOM_OBJECT_TYPES(MAKE_CASE) 779#undef MAKE_CASE 780 default: 781 ASSERT_NOT_REACHED(); 782 } 783 result = v8::Persistent<v8::Object>::New(v8Object); 784 if (isActiveDomObject) 785 setJSWrapperForActiveDOMObject(impl, result); 786 else 787 setJSWrapperForDOMObject(impl, result); 788 789 if (type == V8ClassIndex::CANVASPIXELARRAY) { 790 CanvasPixelArray* pixels = reinterpret_cast<CanvasPixelArray*>(impl); 791 result->SetIndexedPropertiesToPixelData(pixels->data()->data(), pixels->length()); 792 } 793 794#if ENABLE(3D_CANVAS) 795 // Set up WebGLArray subclasses' accesses similarly. 796 switch (type) { 797 case V8ClassIndex::WEBGLBYTEARRAY: 798 case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY: 799 case V8ClassIndex::WEBGLSHORTARRAY: 800 case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY: 801 case V8ClassIndex::WEBGLINTARRAY: 802 case V8ClassIndex::WEBGLUNSIGNEDINTARRAY: 803 case V8ClassIndex::WEBGLFLOATARRAY: { 804 WebGLArray* array = reinterpret_cast<WebGLArray*>(impl); 805 setIndexedPropertiesToExternalArray(result, 806 V8ClassIndex::ToInt(type), 807 array->baseAddress(), 808 array->length()); 809 break; 810 } 811 default: 812 break; 813 } 814#endif 815 816 // Special case for non-node objects associated with a 817 // DOMWindow. Both Safari and FF let the JS wrappers for these 818 // objects survive GC. To mimic their behavior, V8 creates 819 // hidden references from the DOMWindow to these wrapper 820 // objects. These references get cleared when the DOMWindow is 821 // reused by a new page. 822 switch (type) { 823 case V8ClassIndex::CONSOLE: 824 setHiddenWindowReference(static_cast<Console*>(impl)->frame(), V8Custom::kDOMWindowConsoleIndex, result); 825 break; 826 case V8ClassIndex::HISTORY: 827 setHiddenWindowReference(static_cast<History*>(impl)->frame(), V8Custom::kDOMWindowHistoryIndex, result); 828 break; 829 case V8ClassIndex::NAVIGATOR: 830 setHiddenWindowReference(static_cast<Navigator*>(impl)->frame(), V8Custom::kDOMWindowNavigatorIndex, result); 831 break; 832 case V8ClassIndex::SCREEN: 833 setHiddenWindowReference(static_cast<Screen*>(impl)->frame(), V8Custom::kDOMWindowScreenIndex, result); 834 break; 835 case V8ClassIndex::LOCATION: 836 setHiddenWindowReference(static_cast<Location*>(impl)->frame(), V8Custom::kDOMWindowLocationIndex, result); 837 break; 838 case V8ClassIndex::DOMSELECTION: 839 setHiddenWindowReference(static_cast<DOMSelection*>(impl)->frame(), V8Custom::kDOMWindowDOMSelectionIndex, result); 840 break; 841 case V8ClassIndex::BARINFO: { 842 BarInfo* barInfo = static_cast<BarInfo*>(impl); 843 Frame* frame = barInfo->frame(); 844 switch (barInfo->type()) { 845 case BarInfo::Locationbar: 846 setHiddenWindowReference(frame, V8Custom::kDOMWindowLocationbarIndex, result); 847 break; 848 case BarInfo::Menubar: 849 setHiddenWindowReference(frame, V8Custom::kDOMWindowMenubarIndex, result); 850 break; 851 case BarInfo::Personalbar: 852 setHiddenWindowReference(frame, V8Custom::kDOMWindowPersonalbarIndex, result); 853 break; 854 case BarInfo::Scrollbars: 855 setHiddenWindowReference(frame, V8Custom::kDOMWindowScrollbarsIndex, result); 856 break; 857 case BarInfo::Statusbar: 858 setHiddenWindowReference(frame, V8Custom::kDOMWindowStatusbarIndex, result); 859 break; 860 case BarInfo::Toolbar: 861 setHiddenWindowReference(frame, V8Custom::kDOMWindowToolbarIndex, result); 862 break; 863 } 864 break; 865 } 866 default: 867 break; 868 } 869 } 870 } 871 return result; 872} 873 874void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalIndex, v8::Handle<v8::Object> jsObject) 875{ 876 // Get DOMWindow 877 if (!frame) 878 return; // Object might be detached from window 879 v8::Handle<v8::Context> context = V8Proxy::context(frame); 880 if (context.IsEmpty()) 881 return; 882 883 ASSERT(internalIndex < V8Custom::kDOMWindowInternalFieldCount); 884 885 v8::Handle<v8::Object> global = context->Global(); 886 // Look for real DOM wrapper. 887 global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, global); 888 ASSERT(!global.IsEmpty()); 889 ASSERT(global->GetInternalField(internalIndex)->IsUndefined()); 890 global->SetInternalField(internalIndex, jsObject); 891} 892 893V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object) 894{ 895 ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); 896 v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); 897 return V8ClassIndex::FromInt(type->Int32Value()); 898} 899 900void* V8DOMWrapper::convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object) 901{ 902 return isWrapperOfType(object, type) ? convertDOMWrapperToNative<void>(v8::Handle<v8::Object>::Cast(object)) : 0; 903} 904 905PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter) 906{ 907 // A NodeFilter is used when walking through a DOM tree or iterating tree 908 // nodes. 909 // FIXME: we may want to cache NodeFilterCondition and NodeFilter 910 // object, but it is minor. 911 // NodeFilter is passed to NodeIterator that has a ref counted pointer 912 // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition. 913 // In NodeFilterCondition, filter object is persisted in its constructor, 914 // and disposed in its destructor. 915 if (!filter->IsFunction()) 916 return 0; 917 918 NodeFilterCondition* condition = new V8NodeFilterCondition(filter); 919 return NodeFilter::create(condition); 920} 921 922v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl) 923{ 924 // Make a special case for document.all 925 if (descriptorType == V8ClassIndex::HTMLCOLLECTION && static_cast<HTMLCollection*>(impl)->type() == DocAll) 926 descriptorType = V8ClassIndex::HTMLALLCOLLECTION; 927 928 if (V8IsolatedWorld::getEntered()) { 929 // This effectively disables the wrapper cache for isolated worlds. 930 proxy = 0; 931 // FIXME: Do we need a wrapper cache for the isolated world? We should 932 // see if the performance gains are worth while. 933 } else if (!proxy) 934 proxy = V8Proxy::retrieve(); 935 936 v8::Local<v8::Object> instance; 937 if (proxy) 938 instance = proxy->createWrapperFromCache(descriptorType); 939 else { 940 v8::Local<v8::Function> function = getTemplate(descriptorType)->GetFunction(); 941 instance = SafeAllocation::newInstance(function); 942 } 943 if (!instance.IsEmpty()) { 944 // Avoid setting the DOM wrapper for failed allocations. 945 setDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl); 946 } 947 return instance; 948} 949 950#ifndef NDEBUG 951bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) 952{ 953 if (value.IsEmpty() || !value->IsObject()) 954 return false; 955 956 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); 957 if (!object->InternalFieldCount()) 958 return false; 959 960 ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount); 961 962 v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); 963 ASSERT(type->IsInt32()); 964 ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); 965 966 v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex); 967 ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); 968 969 return true; 970} 971#endif 972 973bool V8DOMWrapper::isDOMEventWrapper(v8::Handle<v8::Value> value) 974{ 975 // All kinds of events use EVENT as dom type in JS wrappers. 976 // See EventToV8Object 977 return isWrapperOfType(value, V8ClassIndex::EVENT); 978} 979 980bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType) 981{ 982 if (value.IsEmpty() || !value->IsObject()) 983 return false; 984 985 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); 986 if (!object->InternalFieldCount()) 987 return false; 988 989 ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount); 990 991 v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex); 992 ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); 993 994 v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); 995 ASSERT(type->IsInt32()); 996 ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); 997 998 return V8ClassIndex::FromInt(type->Int32Value()) == classType; 999} 1000 1001#if ENABLE(VIDEO) 1002#define FOR_EACH_VIDEO_TAG(macro) \ 1003 macro(audio, AUDIO) \ 1004 macro(source, SOURCE) \ 1005 macro(video, VIDEO) 1006#else 1007#define FOR_EACH_VIDEO_TAG(macro) 1008#endif 1009 1010#if ENABLE(DATAGRID) 1011#define FOR_EACH_DATAGRID_TAG(macro) \ 1012 macro(datagrid, DATAGRID) \ 1013 macro(dcell, DATAGRIDCELL) \ 1014 macro(dcol, DATAGRIDCOL) \ 1015 macro(drow, DATAGRIDROW) 1016#else 1017#define FOR_EACH_DATAGRID_TAG(macro) 1018#endif 1019 1020#define FOR_EACH_TAG(macro) \ 1021 FOR_EACH_DATAGRID_TAG(macro) \ 1022 macro(a, ANCHOR) \ 1023 macro(applet, APPLET) \ 1024 macro(area, AREA) \ 1025 macro(base, BASE) \ 1026 macro(basefont, BASEFONT) \ 1027 macro(blockquote, BLOCKQUOTE) \ 1028 macro(body, BODY) \ 1029 macro(br, BR) \ 1030 macro(button, BUTTON) \ 1031 macro(caption, TABLECAPTION) \ 1032 macro(col, TABLECOL) \ 1033 macro(colgroup, TABLECOL) \ 1034 macro(del, MOD) \ 1035 macro(canvas, CANVAS) \ 1036 macro(dir, DIRECTORY) \ 1037 macro(div, DIV) \ 1038 macro(dl, DLIST) \ 1039 macro(embed, EMBED) \ 1040 macro(fieldset, FIELDSET) \ 1041 macro(font, FONT) \ 1042 macro(form, FORM) \ 1043 macro(frame, FRAME) \ 1044 macro(frameset, FRAMESET) \ 1045 macro(h1, HEADING) \ 1046 macro(h2, HEADING) \ 1047 macro(h3, HEADING) \ 1048 macro(h4, HEADING) \ 1049 macro(h5, HEADING) \ 1050 macro(h6, HEADING) \ 1051 macro(head, HEAD) \ 1052 macro(hr, HR) \ 1053 macro(html, HTML) \ 1054 macro(img, IMAGE) \ 1055 macro(iframe, IFRAME) \ 1056 macro(image, IMAGE) \ 1057 macro(input, INPUT) \ 1058 macro(ins, MOD) \ 1059 macro(isindex, ISINDEX) \ 1060 macro(keygen, SELECT) \ 1061 macro(label, LABEL) \ 1062 macro(legend, LEGEND) \ 1063 macro(li, LI) \ 1064 macro(link, LINK) \ 1065 macro(listing, PRE) \ 1066 macro(map, MAP) \ 1067 macro(marquee, MARQUEE) \ 1068 macro(menu, MENU) \ 1069 macro(meta, META) \ 1070 macro(object, OBJECT) \ 1071 macro(ol, OLIST) \ 1072 macro(optgroup, OPTGROUP) \ 1073 macro(option, OPTION) \ 1074 macro(p, PARAGRAPH) \ 1075 macro(param, PARAM) \ 1076 macro(pre, PRE) \ 1077 macro(q, QUOTE) \ 1078 macro(script, SCRIPT) \ 1079 macro(select, SELECT) \ 1080 macro(style, STYLE) \ 1081 macro(table, TABLE) \ 1082 macro(thead, TABLESECTION) \ 1083 macro(tbody, TABLESECTION) \ 1084 macro(tfoot, TABLESECTION) \ 1085 macro(td, TABLECELL) \ 1086 macro(th, TABLECELL) \ 1087 macro(tr, TABLEROW) \ 1088 macro(textarea, TEXTAREA) \ 1089 macro(title, TITLE) \ 1090 macro(ul, ULIST) \ 1091 macro(xmp, PRE) 1092 1093V8ClassIndex::V8WrapperType V8DOMWrapper::htmlElementType(HTMLElement* element) 1094{ 1095 typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap; 1096 DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ()); 1097 if (wrapperTypeMap.isEmpty()) { 1098#define ADD_TO_HASH_MAP(tag, name) \ 1099 wrapperTypeMap.set(#tag, V8ClassIndex::HTML##name##ELEMENT); 1100 FOR_EACH_TAG(ADD_TO_HASH_MAP) 1101#if ENABLE(VIDEO) 1102 if (MediaPlayer::isAvailable()) { 1103 FOR_EACH_VIDEO_TAG(ADD_TO_HASH_MAP) 1104 } 1105#endif 1106#undef ADD_TO_HASH_MAP 1107 } 1108 1109 V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl()); 1110 if (!type) 1111 return V8ClassIndex::HTMLELEMENT; 1112 return type; 1113} 1114#undef FOR_EACH_TAG 1115 1116#if ENABLE(SVG) 1117 1118#if ENABLE(SVG_ANIMATION) 1119#define FOR_EACH_ANIMATION_TAG(macro) \ 1120 macro(animateColor, ANIMATECOLOR) \ 1121 macro(animate, ANIMATE) \ 1122 macro(animateTransform, ANIMATETRANSFORM) \ 1123 macro(set, SET) 1124#else 1125#define FOR_EACH_ANIMATION_TAG(macro) 1126#endif 1127 1128#if ENABLE(SVG) && ENABLE(FILTERS) 1129#define FOR_EACH_FILTERS_TAG(macro) \ 1130 macro(feBlend, FEBLEND) \ 1131 macro(feColorMatrix, FECOLORMATRIX) \ 1132 macro(feComponentTransfer, FECOMPONENTTRANSFER) \ 1133 macro(feComposite, FECOMPOSITE) \ 1134 macro(feDiffuseLighting, FEDIFFUSELIGHTING) \ 1135 macro(feDisplacementMap, FEDISPLACEMENTMAP) \ 1136 macro(feDistantLight, FEDISTANTLIGHT) \ 1137 macro(feFlood, FEFLOOD) \ 1138 macro(feFuncA, FEFUNCA) \ 1139 macro(feFuncB, FEFUNCB) \ 1140 macro(feFuncG, FEFUNCG) \ 1141 macro(feFuncR, FEFUNCR) \ 1142 macro(feGaussianBlur, FEGAUSSIANBLUR) \ 1143 macro(feImage, FEIMAGE) \ 1144 macro(feMerge, FEMERGE) \ 1145 macro(feMergeNode, FEMERGENODE) \ 1146 macro(feOffset, FEOFFSET) \ 1147 macro(fePointLight, FEPOINTLIGHT) \ 1148 macro(feSpecularLighting, FESPECULARLIGHTING) \ 1149 macro(feSpotLight, FESPOTLIGHT) \ 1150 macro(feTile, FETILE) \ 1151 macro(feTurbulence, FETURBULENCE) \ 1152 macro(filter, FILTER) 1153#else 1154#define FOR_EACH_FILTERS_TAG(macro) 1155#endif 1156 1157#if ENABLE(SVG_FONTS) 1158#define FOR_EACH_FONTS_TAG(macro) \ 1159 macro(font-face, FONTFACE) \ 1160 macro(font-face-format, FONTFACEFORMAT) \ 1161 macro(font-face-name, FONTFACENAME) \ 1162 macro(font-face-src, FONTFACESRC) \ 1163 macro(font-face-uri, FONTFACEURI) 1164#else 1165#define FOR_EACH_FONTS_TAG(marco) 1166#endif 1167 1168#if ENABLE(SVG_FOREIGN_OBJECT) 1169#define FOR_EACH_FOREIGN_OBJECT_TAG(macro) \ 1170 macro(foreignObject, FOREIGNOBJECT) 1171#else 1172#define FOR_EACH_FOREIGN_OBJECT_TAG(macro) 1173#endif 1174 1175#if ENABLE(SVG_USE) 1176#define FOR_EACH_USE_TAG(macro) \ 1177 macro(use, USE) 1178#else 1179#define FOR_EACH_USE_TAG(macro) 1180#endif 1181 1182#define FOR_EACH_TAG(macro) \ 1183 FOR_EACH_ANIMATION_TAG(macro) \ 1184 FOR_EACH_FILTERS_TAG(macro) \ 1185 FOR_EACH_FONTS_TAG(macro) \ 1186 FOR_EACH_FOREIGN_OBJECT_TAG(macro) \ 1187 FOR_EACH_USE_TAG(macro) \ 1188 macro(a, A) \ 1189 macro(altGlyph, ALTGLYPH) \ 1190 macro(circle, CIRCLE) \ 1191 macro(clipPath, CLIPPATH) \ 1192 macro(cursor, CURSOR) \ 1193 macro(defs, DEFS) \ 1194 macro(desc, DESC) \ 1195 macro(ellipse, ELLIPSE) \ 1196 macro(g, G) \ 1197 macro(glyph, GLYPH) \ 1198 macro(image, IMAGE) \ 1199 macro(linearGradient, LINEARGRADIENT) \ 1200 macro(line, LINE) \ 1201 macro(marker, MARKER) \ 1202 macro(mask, MASK) \ 1203 macro(metadata, METADATA) \ 1204 macro(path, PATH) \ 1205 macro(pattern, PATTERN) \ 1206 macro(polyline, POLYLINE) \ 1207 macro(polygon, POLYGON) \ 1208 macro(radialGradient, RADIALGRADIENT) \ 1209 macro(rect, RECT) \ 1210 macro(script, SCRIPT) \ 1211 macro(stop, STOP) \ 1212 macro(style, STYLE) \ 1213 macro(svg, SVG) \ 1214 macro(switch, SWITCH) \ 1215 macro(symbol, SYMBOL) \ 1216 macro(text, TEXT) \ 1217 macro(textPath, TEXTPATH) \ 1218 macro(title, TITLE) \ 1219 macro(tref, TREF) \ 1220 macro(tspan, TSPAN) \ 1221 macro(view, VIEW) \ 1222 // end of macro 1223 1224V8ClassIndex::V8WrapperType V8DOMWrapper::svgElementType(SVGElement* element) 1225{ 1226 typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap; 1227 DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ()); 1228 if (wrapperTypeMap.isEmpty()) { 1229#define ADD_TO_HASH_MAP(tag, name) \ 1230 wrapperTypeMap.set(#tag, V8ClassIndex::SVG##name##ELEMENT); 1231 FOR_EACH_TAG(ADD_TO_HASH_MAP) 1232#undef ADD_TO_HASH_MAP 1233 } 1234 1235 V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl()); 1236 if (!type) 1237 return V8ClassIndex::SVGELEMENT; 1238 return type; 1239} 1240#undef FOR_EACH_TAG 1241 1242#endif // ENABLE(SVG) 1243 1244v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event) 1245{ 1246 if (!event) 1247 return v8::Null(); 1248 1249 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event); 1250 if (!wrapper.IsEmpty()) 1251 return wrapper; 1252 1253 V8ClassIndex::V8WrapperType type = V8ClassIndex::EVENT; 1254 1255 if (event->isUIEvent()) { 1256 if (event->isKeyboardEvent()) 1257 type = V8ClassIndex::KEYBOARDEVENT; 1258 else if (event->isTextEvent()) 1259 type = V8ClassIndex::TEXTEVENT; 1260 else if (event->isMouseEvent()) 1261 type = V8ClassIndex::MOUSEEVENT; 1262 else if (event->isWheelEvent()) 1263 type = V8ClassIndex::WHEELEVENT; 1264#if ENABLE(TOUCH_EVENTS) 1265 // TODO(andreip): upstream touch related changes to WebKit 1266 else if (event->isTouchEvent()) 1267 type = V8ClassIndex::TOUCHEVENT; 1268#endif 1269#if ENABLE(SVG) 1270 else if (event->isSVGZoomEvent()) 1271 type = V8ClassIndex::SVGZOOMEVENT; 1272#endif 1273 else if (event->isCompositionEvent()) 1274 type = V8ClassIndex::COMPOSITIONEVENT; 1275 else 1276 type = V8ClassIndex::UIEVENT; 1277 } else if (event->isMutationEvent()) 1278 type = V8ClassIndex::MUTATIONEVENT; 1279 else if (event->isOverflowEvent()) 1280 type = V8ClassIndex::OVERFLOWEVENT; 1281 else if (event->isMessageEvent()) 1282 type = V8ClassIndex::MESSAGEEVENT; 1283 else if (event->isPageTransitionEvent()) 1284 type = V8ClassIndex::PAGETRANSITIONEVENT; 1285 else if (event->isProgressEvent()) { 1286 if (event->isXMLHttpRequestProgressEvent()) 1287 type = V8ClassIndex::XMLHTTPREQUESTPROGRESSEVENT; 1288 else 1289 type = V8ClassIndex::PROGRESSEVENT; 1290 } else if (event->isWebKitAnimationEvent()) 1291 type = V8ClassIndex::WEBKITANIMATIONEVENT; 1292 else if (event->isWebKitTransitionEvent()) 1293 type = V8ClassIndex::WEBKITTRANSITIONEVENT; 1294#if ENABLE(WORKERS) 1295 else if (event->isErrorEvent()) 1296 type = V8ClassIndex::ERROREVENT; 1297#endif 1298#if ENABLE(DOM_STORAGE) 1299 else if (event->isStorageEvent()) 1300 type = V8ClassIndex::STORAGEEVENT; 1301#endif 1302 else if (event->isBeforeLoadEvent()) 1303 type = V8ClassIndex::BEFORELOADEVENT; 1304 1305 1306 v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::EVENT, event); 1307 if (result.IsEmpty()) { 1308 // Instantiation failed. Avoid updating the DOM object map and 1309 // return null which is already handled by callers of this function 1310 // in case the event is NULL. 1311 return v8::Null(); 1312 } 1313 1314 event->ref(); // fast ref 1315 setJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result)); 1316 1317 return result; 1318} 1319 1320static const V8ClassIndex::V8WrapperType mapping[] = { 1321 V8ClassIndex::INVALID_CLASS_INDEX, // NONE 1322 V8ClassIndex::INVALID_CLASS_INDEX, // ELEMENT_NODE needs special treatment 1323 V8ClassIndex::ATTR, // ATTRIBUTE_NODE 1324 V8ClassIndex::TEXT, // TEXT_NODE 1325 V8ClassIndex::CDATASECTION, // CDATA_SECTION_NODE 1326 V8ClassIndex::ENTITYREFERENCE, // ENTITY_REFERENCE_NODE 1327 V8ClassIndex::ENTITY, // ENTITY_NODE 1328 V8ClassIndex::PROCESSINGINSTRUCTION, // PROCESSING_INSTRUCTION_NODE 1329 V8ClassIndex::COMMENT, // COMMENT_NODE 1330 V8ClassIndex::INVALID_CLASS_INDEX, // DOCUMENT_NODE needs special treatment 1331 V8ClassIndex::DOCUMENTTYPE, // DOCUMENT_TYPE_NODE 1332 V8ClassIndex::DOCUMENTFRAGMENT, // DOCUMENT_FRAGMENT_NODE 1333 V8ClassIndex::NOTATION, // NOTATION_NODE 1334 V8ClassIndex::NODE, // XPATH_NAMESPACE_NODE 1335}; 1336 1337v8::Handle<v8::Value> V8DOMWrapper::convertDocumentToV8Object(Document* document) 1338{ 1339 // Find a proxy for this node. 1340 // 1341 // Note that if proxy is found, we might initialize the context which can 1342 // instantiate a document wrapper. Therefore, we get the proxy before 1343 // checking if the node already has a wrapper. 1344 V8Proxy* proxy = V8Proxy::retrieve(document->frame()); 1345 if (proxy) 1346 proxy->initContextIfNeeded(); 1347 1348 DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap(); 1349 v8::Handle<v8::Object> wrapper = domNodeMap.get(document); 1350 if (wrapper.IsEmpty()) 1351 return convertNewNodeToV8Object(document, proxy, domNodeMap); 1352 1353 return wrapper; 1354} 1355 1356v8::Handle<v8::Value> V8DOMWrapper::convertNodeToV8Object(Node* node) 1357{ 1358 if (!node) 1359 return v8::Null(); 1360 1361 Document* document = node->document(); 1362 if (node == document) 1363 return convertDocumentToV8Object(document); 1364 1365 DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap(); 1366 v8::Handle<v8::Object> wrapper = domNodeMap.get(node); 1367 if (wrapper.IsEmpty()) 1368 return convertNewNodeToV8Object(node, 0, domNodeMap); 1369 1370 return wrapper; 1371} 1372 1373// Caller checks node is not null. 1374v8::Handle<v8::Value> V8DOMWrapper::convertNewNodeToV8Object(Node* node, V8Proxy* proxy, DOMWrapperMap<Node>& domNodeMap) 1375{ 1376 if (!proxy && node->document()) 1377 proxy = V8Proxy::retrieve(node->document()->frame()); 1378 1379 bool isDocument = false; // document type node has special handling 1380 V8ClassIndex::V8WrapperType type; 1381 1382 Node::NodeType nodeType = node->nodeType(); 1383 if (nodeType == Node::ELEMENT_NODE) { 1384 if (node->isHTMLElement()) 1385 type = htmlElementType(static_cast<HTMLElement*>(node)); 1386#if ENABLE(SVG) 1387 else if (node->isSVGElement()) 1388 type = svgElementType(static_cast<SVGElement*>(node)); 1389#endif 1390 else 1391 type = V8ClassIndex::ELEMENT; 1392 } else if (nodeType == Node::DOCUMENT_NODE) { 1393 isDocument = true; 1394 Document* document = static_cast<Document*>(node); 1395 if (document->isHTMLDocument()) 1396 type = V8ClassIndex::HTMLDOCUMENT; 1397#if ENABLE(SVG) 1398 else if (document->isSVGDocument()) 1399 type = V8ClassIndex::SVGDOCUMENT; 1400#endif 1401 else 1402 type = V8ClassIndex::DOCUMENT; 1403 } else { 1404 ASSERT(nodeType < static_cast<int>(sizeof(mapping)/sizeof(mapping[0]))); 1405 type = mapping[nodeType]; 1406 ASSERT(type != V8ClassIndex::INVALID_CLASS_INDEX); 1407 } 1408 1409 v8::Handle<v8::Context> context; 1410 if (proxy) 1411 context = proxy->context(); 1412 1413 // Enter the node's context and create the wrapper in that context. 1414 if (!context.IsEmpty()) 1415 context->Enter(); 1416 1417 v8::Local<v8::Object> result = instantiateV8Object(proxy, type, V8ClassIndex::NODE, node); 1418 1419 // Exit the node's context if it was entered. 1420 if (!context.IsEmpty()) 1421 context->Exit(); 1422 1423 if (result.IsEmpty()) { 1424 // If instantiation failed it's important not to add the result 1425 // to the DOM node map. Instead we return an empty handle, which 1426 // should already be handled by callers of this function in case 1427 // the node is NULL. 1428 return result; 1429 } 1430 1431 node->ref(); 1432 domNodeMap.set(node, v8::Persistent<v8::Object>::New(result)); 1433 1434 if (isDocument) { 1435 if (proxy) 1436 proxy->updateDocumentWrapper(result); 1437 1438 if (type == V8ClassIndex::HTMLDOCUMENT) { 1439 // Create marker object and insert it in two internal fields. 1440 // This is used to implement temporary shadowing of 1441 // document.all. 1442 ASSERT(result->InternalFieldCount() == V8Custom::kHTMLDocumentInternalFieldCount); 1443 v8::Local<v8::Object> marker = v8::Object::New(); 1444 result->SetInternalField(V8Custom::kHTMLDocumentMarkerIndex, marker); 1445 result->SetInternalField(V8Custom::kHTMLDocumentShadowIndex, marker); 1446 } 1447 } 1448 1449 return result; 1450} 1451 1452// A JS object of type EventTarget is limited to a small number of possible classes. 1453// Check EventTarget.h for new type conversion methods 1454v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* target) 1455{ 1456 if (!target) 1457 return v8::Null(); 1458 1459#if ENABLE(SVG) 1460 SVGElementInstance* instance = target->toSVGElementInstance(); 1461 if (instance) 1462 return convertToV8Object(V8ClassIndex::SVGELEMENTINSTANCE, instance); 1463#endif 1464 1465#if ENABLE(WORKERS) 1466 Worker* worker = target->toWorker(); 1467 if (worker) 1468 return convertToV8Object(V8ClassIndex::WORKER, worker); 1469#endif // WORKERS 1470 1471#if ENABLE(SHARED_WORKERS) 1472 SharedWorker* sharedWorker = target->toSharedWorker(); 1473 if (sharedWorker) 1474 return convertToV8Object(V8ClassIndex::SHAREDWORKER, sharedWorker); 1475#endif // SHARED_WORKERS 1476 1477#if ENABLE(NOTIFICATIONS) 1478 Notification* notification = target->toNotification(); 1479 if (notification) 1480 return convertToV8Object(V8ClassIndex::NOTIFICATION, notification); 1481#endif 1482 1483#if ENABLE(WEB_SOCKETS) 1484 WebSocket* webSocket = target->toWebSocket(); 1485 if (webSocket) 1486 return convertToV8Object(V8ClassIndex::WEBSOCKET, webSocket); 1487#endif 1488 1489 Node* node = target->toNode(); 1490 if (node) 1491 return convertNodeToV8Object(node); 1492 1493 if (DOMWindow* domWindow = target->toDOMWindow()) 1494 return convertToV8Object(V8ClassIndex::DOMWINDOW, domWindow); 1495 1496 // XMLHttpRequest is created within its JS counterpart. 1497 XMLHttpRequest* xmlHttpRequest = target->toXMLHttpRequest(); 1498 if (xmlHttpRequest) { 1499 v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xmlHttpRequest); 1500 ASSERT(!wrapper.IsEmpty()); 1501 return wrapper; 1502 } 1503 1504 // MessagePort is created within its JS counterpart 1505 MessagePort* port = target->toMessagePort(); 1506 if (port) { 1507 v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port); 1508 ASSERT(!wrapper.IsEmpty()); 1509 return wrapper; 1510 } 1511 1512 XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload(); 1513 if (upload) { 1514 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload); 1515 ASSERT(!wrapper.IsEmpty()); 1516 return wrapper; 1517 } 1518 1519#if ENABLE(OFFLINE_WEB_APPLICATIONS) 1520 DOMApplicationCache* domAppCache = target->toDOMApplicationCache(); 1521 if (domAppCache) 1522 return convertToV8Object(V8ClassIndex::DOMAPPLICATIONCACHE, domAppCache); 1523#endif 1524 1525 ASSERT(0); 1526 return notHandledByInterceptor(); 1527} 1528 1529v8::Handle<v8::Value> V8DOMWrapper::convertEventListenerToV8Object(ScriptExecutionContext* context, EventListener* listener) 1530{ 1531 if (!listener) 1532 return v8::Null(); 1533 1534 // FIXME: can a user take a lazy event listener and set to other places? 1535 V8AbstractEventListener* v8listener = static_cast<V8AbstractEventListener*>(listener); 1536 return v8listener->getListenerObject(context); 1537} 1538 1539PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 1540{ 1541 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 1542} 1543 1544<<<<<<< HEAD:WebCore/bindings/v8/V8DOMWrapper.cpp 1545#if PLATFORM(ANDROID) 1546======= 1547>>>>>>> webkit.org at r51976:WebCore/bindings/v8/V8DOMWrapper.cpp 1548#if ENABLE(SVG) 1549PassRefPtr<EventListener> V8DOMWrapper::getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 1550{ 1551 return getEventListener(element->correspondingElement(), value, isAttribute, lookup); 1552} 1553#endif 1554<<<<<<< HEAD:WebCore/bindings/v8/V8DOMWrapper.cpp 1555#endif 1556======= 1557>>>>>>> webkit.org at r51976:WebCore/bindings/v8/V8DOMWrapper.cpp 1558 1559PassRefPtr<EventListener> V8DOMWrapper::getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 1560{ 1561 if (worker->scriptExecutionContext()->isWorkerContext()) { 1562 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 1563 ASSERT(workerContextProxy); 1564 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 1565 } 1566 1567 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 1568} 1569 1570#if ENABLE(NOTIFICATIONS) 1571PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 1572{ 1573 if (notification->scriptExecutionContext()->isWorkerContext()) { 1574 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 1575 ASSERT(workerContextProxy); 1576 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 1577 } 1578 1579 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 1580} 1581#endif 1582 1583PassRefPtr<EventListener> V8DOMWrapper::getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 1584{ 1585 WorkerContextExecutionProxy* workerContextProxy = workerContext->script()->proxy(); 1586 if (workerContextProxy) 1587 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 1588 1589 return 0; 1590} 1591 1592PassRefPtr<EventListener> V8DOMWrapper::getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 1593{ 1594 return getEventListener(upload->associatedXMLHttpRequest(), value, isAttribute, lookup); 1595} 1596 1597PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 1598{ 1599 if (V8Proxy::retrieve(eventTarget->scriptExecutionContext())) 1600 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 1601 1602#if ENABLE(WORKERS) 1603 WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); 1604 if (workerContextProxy) 1605 return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); 1606#endif 1607 1608 return 0; 1609} 1610 1611PassRefPtr<EventListener> V8DOMWrapper::getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) 1612{ 1613 return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); 1614} 1615 1616v8::Handle<v8::Value> V8DOMWrapper::convertDOMImplementationToV8Object(DOMImplementation* impl) 1617{ 1618 v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::DOMIMPLEMENTATION, V8ClassIndex::DOMIMPLEMENTATION, impl); 1619 if (result.IsEmpty()) { 1620 // If the instantiation failed, we ignore it and return null instead 1621 // of returning an empty handle. 1622 return v8::Null(); 1623 } 1624 return result; 1625} 1626 1627v8::Handle<v8::Value> V8DOMWrapper::convertStyleSheetToV8Object(StyleSheet* sheet) 1628{ 1629 if (!sheet) 1630 return v8::Null(); 1631 1632 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(sheet); 1633 if (!wrapper.IsEmpty()) 1634 return wrapper; 1635 1636 V8ClassIndex::V8WrapperType type = V8ClassIndex::STYLESHEET; 1637 if (sheet->isCSSStyleSheet()) 1638 type = V8ClassIndex::CSSSTYLESHEET; 1639 1640 v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::STYLESHEET, sheet); 1641 if (!result.IsEmpty()) { 1642 // Only update the DOM object map if the result is non-empty. 1643 sheet->ref(); 1644 setJSWrapperForDOMObject(sheet, v8::Persistent<v8::Object>::New(result)); 1645 } 1646 1647 // Add a hidden reference from stylesheet object to its owner node. 1648 Node* ownerNode = sheet->ownerNode(); 1649 if (ownerNode) { 1650 v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(convertNodeToV8Object(ownerNode)); 1651 result->SetInternalField(V8Custom::kStyleSheetOwnerNodeIndex, owner); 1652 } 1653 1654 return result; 1655} 1656 1657v8::Handle<v8::Value> V8DOMWrapper::convertCSSValueToV8Object(CSSValue* value) 1658{ 1659 if (!value) 1660 return v8::Null(); 1661 1662 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(value); 1663 if (!wrapper.IsEmpty()) 1664 return wrapper; 1665 1666 V8ClassIndex::V8WrapperType type; 1667 1668 if (value->isWebKitCSSTransformValue()) 1669 type = V8ClassIndex::WEBKITCSSTRANSFORMVALUE; 1670 else if (value->isValueList()) 1671 type = V8ClassIndex::CSSVALUELIST; 1672 else if (value->isPrimitiveValue()) 1673 type = V8ClassIndex::CSSPRIMITIVEVALUE; 1674#if ENABLE(SVG) 1675 else if (value->isSVGPaint()) 1676 type = V8ClassIndex::SVGPAINT; 1677 else if (value->isSVGColor()) 1678 type = V8ClassIndex::SVGCOLOR; 1679#endif 1680 else 1681 type = V8ClassIndex::CSSVALUE; 1682 1683 v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSVALUE, value); 1684 if (!result.IsEmpty()) { 1685 // Only update the DOM object map if the result is non-empty. 1686 value->ref(); 1687 setJSWrapperForDOMObject(value, v8::Persistent<v8::Object>::New(result)); 1688 } 1689 1690 return result; 1691} 1692 1693v8::Handle<v8::Value> V8DOMWrapper::convertCSSRuleToV8Object(CSSRule* rule) 1694{ 1695 if (!rule) 1696 return v8::Null(); 1697 1698 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(rule); 1699 if (!wrapper.IsEmpty()) 1700 return wrapper; 1701 1702 V8ClassIndex::V8WrapperType type; 1703 1704 switch (rule->type()) { 1705 case CSSRule::STYLE_RULE: 1706 type = V8ClassIndex::CSSSTYLERULE; 1707 break; 1708 case CSSRule::CHARSET_RULE: 1709 type = V8ClassIndex::CSSCHARSETRULE; 1710 break; 1711 case CSSRule::IMPORT_RULE: 1712 type = V8ClassIndex::CSSIMPORTRULE; 1713 break; 1714 case CSSRule::MEDIA_RULE: 1715 type = V8ClassIndex::CSSMEDIARULE; 1716 break; 1717 case CSSRule::FONT_FACE_RULE: 1718 type = V8ClassIndex::CSSFONTFACERULE; 1719 break; 1720 case CSSRule::PAGE_RULE: 1721 type = V8ClassIndex::CSSPAGERULE; 1722 break; 1723 case CSSRule::VARIABLES_RULE: 1724 type = V8ClassIndex::CSSVARIABLESRULE; 1725 break; 1726 case CSSRule::WEBKIT_KEYFRAME_RULE: 1727 type = V8ClassIndex::WEBKITCSSKEYFRAMERULE; 1728 break; 1729 case CSSRule::WEBKIT_KEYFRAMES_RULE: 1730 type = V8ClassIndex::WEBKITCSSKEYFRAMESRULE; 1731 break; 1732 default: // CSSRule::UNKNOWN_RULE 1733 type = V8ClassIndex::CSSRULE; 1734 break; 1735 } 1736 1737 v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSRULE, rule); 1738 if (!result.IsEmpty()) { 1739 // Only update the DOM object map if the result is non-empty. 1740 rule->ref(); 1741 setJSWrapperForDOMObject(rule, v8::Persistent<v8::Object>::New(result)); 1742 } 1743 return result; 1744} 1745 1746v8::Handle<v8::Value> V8DOMWrapper::convertWindowToV8Object(DOMWindow* window) 1747{ 1748 if (!window) 1749 return v8::Null(); 1750 // Initializes environment of a frame, and return the global object 1751 // of the frame. 1752 Frame* frame = window->frame(); 1753 if (!frame) 1754 return v8::Handle<v8::Object>(); 1755 1756 // Special case: Because of evaluateInNewContext() one DOMWindow can have 1757 // multiple contexts and multiple global objects associated with it. When 1758 // code running in one of those contexts accesses the window object, we 1759 // want to return the global object associated with that context, not 1760 // necessarily the first global object associated with that DOMWindow. 1761 v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent(); 1762 v8::Handle<v8::Object> currentGlobal = currentContext->Global(); 1763 v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, currentGlobal); 1764 if (!windowWrapper.IsEmpty()) { 1765 if (convertDOMWrapperToNative<DOMWindow>(windowWrapper) == window) 1766 return currentGlobal; 1767 } 1768 1769 // Otherwise, return the global object associated with this frame. 1770 v8::Handle<v8::Context> context = V8Proxy::context(frame); 1771 if (context.IsEmpty()) 1772 return v8::Handle<v8::Object>(); 1773 1774 v8::Handle<v8::Object> global = context->Global(); 1775 ASSERT(!global.IsEmpty()); 1776 return global; 1777} 1778 1779v8::Handle<v8::Value> V8DOMWrapper::convertNamedNodeMapToV8Object(NamedNodeMap* map) 1780{ 1781 if (!map) 1782 return v8::Null(); 1783 1784 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(map); 1785 if (!wrapper.IsEmpty()) 1786 return wrapper; 1787 1788 v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::NAMEDNODEMAP, V8ClassIndex::NAMEDNODEMAP, map); 1789 if (result.IsEmpty()) 1790 return result; 1791 1792 // Only update the DOM object map if the result is non-empty. 1793 map->ref(); 1794 setJSWrapperForDOMObject(map, v8::Persistent<v8::Object>::New(result)); 1795 1796 // Add a hidden reference from named node map to its owner node. 1797 if (Element* element = map->element()) { 1798 v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(convertNodeToV8Object(element)); 1799 result->SetInternalField(V8Custom::kNamedNodeMapOwnerNodeIndex, owner); 1800 } 1801 1802 return result; 1803} 1804 1805} // namespace WebCore 1806