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