2 * Copyright (C) 2009 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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"
48 #include "V8DOMWindow.h"
49 #include "V8EventListenerList.h"
51 #include "V8IsolatedWorld.h"
53 #include "WebGLArray.h"
54 #include "WebGLUniformLocation.h"
55 #include "WorkerContextExecutionProxy.h"
61 #include <wtf/Assertions.h>
62 #include <wtf/OwnArrayPtr.h>
63 #include <wtf/StdLibExtras.h>
64 #include <wtf/UnusedParam.h>
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
, ());
76 value
= v8::Persistent
<v8::String
>::New(v8::String::New("toString"));
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);
97 v8::Handle
<v8::Value
> V8DOMWrapper::convertSVGElementInstanceToV8Object(SVGElementInstance
* instance
)
102 v8::Handle
<v8::Object
> existingInstance
= getDOMSVGElementInstanceMap().get(instance
);
103 if (!existingInstance
.IsEmpty())
104 return existingInstance
;
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
));
117 v8::Handle
<v8::Value
> V8DOMWrapper::convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType type
, void* object
)
122 v8::Persistent
<v8::Object
> result
= getDOMSVGObjectWithContextMap().get(object
);
123 if (!result
.IsEmpty())
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
);
134 #define MAKE_CASE(TYPE, NAME) \
135 case V8ClassIndex::TYPE: static_cast<NAME*>(object)->ref(); break;
136 SVG_OBJECT_TYPES(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
)
144 ASSERT_NOT_REACHED();
146 getDOMSVGObjectWithContextMap().set(object
, result
);
154 #if ENABLE(3D_CANVAS)
155 void V8DOMWrapper::setIndexedPropertiesToExternalArray(v8::Handle
<v8::Object
> wrapper
,
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
;
166 case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY
:
167 array_type
= v8::kExternalUnsignedByteArray
;
169 case V8ClassIndex::WEBGLSHORTARRAY
:
170 array_type
= v8::kExternalShortArray
;
172 case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY
:
173 array_type
= v8::kExternalUnsignedShortArray
;
175 case V8ClassIndex::WEBGLINTARRAY
:
176 array_type
= v8::kExternalIntArray
;
178 case V8ClassIndex::WEBGLUNSIGNEDINTARRAY
:
179 array_type
= v8::kExternalUnsignedIntArray
;
181 case V8ClassIndex::WEBGLFLOATARRAY
:
182 array_type
= v8::kExternalFloatArray
;
185 ASSERT_NOT_REACHED();
187 wrapper
->SetIndexedPropertiesToExternalArrayData(address
,
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());
205 v8::Persistent
<v8::Object
> V8DOMWrapper::jsWrapperForActiveDOMObject(void* object
)
207 v8::Persistent
<v8::Object
> wrapper
= getActiveDOMObjectMap().get(object
);
208 ASSERT(!wrapper
.IsEmpty());
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
));
217 V8ClassIndex::V8WrapperType type
= V8DOMWrapper::domWrapperType(wrapper
);
219 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
220 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE
)
221 ASSERT_NOT_REACHED();
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
));
235 V8ClassIndex::V8WrapperType type
= V8DOMWrapper::domWrapperType(wrapper
);
237 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break;
238 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE
)
240 ASSERT_NOT_REACHED();
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())
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
);
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
));
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
));
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
));
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
));
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
);
314 case V8ClassIndex::SVGDOCUMENT
: // fall through
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
);
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
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
));
334 case V8ClassIndex::HTMLFRAMESETELEMENT
:
335 descriptor
->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFrameSetElement
));
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
));
341 case V8ClassIndex::STYLESHEET
: // fall through
342 case V8ClassIndex::CSSSTYLESHEET
: {
343 // We add an extra internal field to hold a reference to
345 v8::Local
<v8::ObjectTemplate
> instanceTemplate
= descriptor
->InstanceTemplate();
346 ASSERT(instanceTemplate
->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount
);
347 instanceTemplate
->SetInternalFieldCount(V8Custom::kStyleSheetInternalFieldCount
);
350 case V8ClassIndex::MIMETYPEARRAY
:
351 setCollectionNamedGetter
<MimeTypeArray
, MimeType
>(descriptor
, V8ClassIndex::MIMETYPE
);
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
));
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
));
368 case V8ClassIndex::NODELIST
:
369 descriptor
->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NodeList
));
371 case V8ClassIndex::PLUGIN
:
372 setCollectionNamedGetter
<Plugin
, MimeType
>(descriptor
, V8ClassIndex::MIMETYPE
);
374 case V8ClassIndex::PLUGINARRAY
:
375 setCollectionNamedGetter
<PluginArray
, Plugin
>(descriptor
, V8ClassIndex::PLUGIN
);
377 case V8ClassIndex::STYLESHEETLIST
:
378 descriptor
->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(StyleSheetList
));
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);
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
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
));
410 case V8ClassIndex::HISTORY
:
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
);
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
);
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
);
437 #endif // NOTIFICATIONS
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
);
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
);
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
);
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
));
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
);
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
));
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
);
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
);
509 #if ENABLE(3D_CANVAS)
510 // The following objects are created from JavaScript.
511 case V8ClassIndex::WEBGLARRAYBUFFER
:
512 descriptor
->SetCallHandler(USE_CALLBACK(WebGLArrayBufferConstructor
));
514 case V8ClassIndex::WEBGLBYTEARRAY
:
515 descriptor
->SetCallHandler(USE_CALLBACK(WebGLByteArrayConstructor
));
517 case V8ClassIndex::WEBGLFLOATARRAY
:
518 descriptor
->SetCallHandler(USE_CALLBACK(WebGLFloatArrayConstructor
));
520 case V8ClassIndex::WEBGLINTARRAY
:
521 descriptor
->SetCallHandler(USE_CALLBACK(WebGLIntArrayConstructor
));
523 case V8ClassIndex::WEBGLSHORTARRAY
:
524 descriptor
->SetCallHandler(USE_CALLBACK(WebGLShortArrayConstructor
));
526 case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY
:
527 descriptor
->SetCallHandler(USE_CALLBACK(WebGLUnsignedByteArrayConstructor
));
529 case V8ClassIndex::WEBGLUNSIGNEDINTARRAY
:
530 descriptor
->SetCallHandler(USE_CALLBACK(WebGLUnsignedIntArrayConstructor
));
532 case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY
:
533 descriptor
->SetCallHandler(USE_CALLBACK(WebGLUnsignedShortArrayConstructor
));
536 case V8ClassIndex::DOMPARSER
:
537 descriptor
->SetCallHandler(USE_CALLBACK(DOMParserConstructor
));
539 case V8ClassIndex::WEBKITCSSMATRIX
:
540 descriptor
->SetCallHandler(USE_CALLBACK(WebKitCSSMatrixConstructor
));
542 case V8ClassIndex::WEBKITPOINT
:
543 descriptor
->SetCallHandler(USE_CALLBACK(WebKitPointConstructor
));
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
));
554 case V8ClassIndex::XMLSERIALIZER
:
555 descriptor
->SetCallHandler(USE_CALLBACK(XMLSerializerConstructor
));
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
));
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
);
570 case V8ClassIndex::XPATHEVALUATOR
:
571 descriptor
->SetCallHandler(USE_CALLBACK(XPathEvaluatorConstructor
));
573 case V8ClassIndex::XSLTPROCESSOR
:
574 descriptor
->SetCallHandler(USE_CALLBACK(XSLTProcessorConstructor
));
576 case V8ClassIndex::CLIENTRECTLIST
:
577 descriptor
->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(ClientRectList
));
579 case V8ClassIndex::FILELIST
:
580 descriptor
->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(FileList
));
583 case V8ClassIndex::DATAGRIDCOLUMNLIST
:
584 descriptor
->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DataGridColumnList
));
585 descriptor
->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DataGridColumnList
));
592 *cacheCell
= 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
610 v8::TryCatch tryCatch
;
611 v8::Local
<v8::Function
> value
= functionTemplate
->GetFunction();
613 return v8::Local
<v8::Function
>();
614 // Hotmail fix, see comments above.
615 if (!objectPrototype
.IsEmpty())
616 value
->Set(v8::String::New("__proto__"), objectPrototype
);
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();
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();
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;
674 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
675 DOM_NODE_TYPES(MAKE_CASE
)
677 SVG_NODE_TYPES(MAKE_CASE
)
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
));
691 SVG_NONNODE_TYPES(MAKE_CASE
)
692 if (type
== V8ClassIndex::SVGELEMENTINSTANCE
)
693 return convertSVGElementInstanceToV8Object(static_cast<SVGElementInstance
*>(impl
));
694 return convertSVGObjectWithContextToV8Object(type
, impl
);
697 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE
)
698 isActiveDomObject
= true;
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
;
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).
738 #define MAKE_CASE(TYPE, NAME) \
739 case V8ClassIndex::TYPE: static_cast<NAME*>(impl)->ref(); break;
740 DOM_OBJECT_TYPES(MAKE_CASE
)
743 ASSERT_NOT_REACHED();
745 result
= v8::Persistent
<v8::Object
>::New(v8Object
);
746 if (isActiveDomObject
)
747 setJSWrapperForActiveDOMObject(impl
, result
);
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.
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(),
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.
785 case V8ClassIndex::CONSOLE
:
786 setHiddenWindowReference(static_cast<Console
*>(impl
)->frame(), V8Custom::kDOMWindowConsoleIndex
, result
);
788 case V8ClassIndex::HISTORY
:
789 setHiddenWindowReference(static_cast<History
*>(impl
)->frame(), V8Custom::kDOMWindowHistoryIndex
, result
);
791 case V8ClassIndex::NAVIGATOR
:
792 setHiddenWindowReference(static_cast<Navigator
*>(impl
)->frame(), V8Custom::kDOMWindowNavigatorIndex
, result
);
794 case V8ClassIndex::SCREEN
:
795 setHiddenWindowReference(static_cast<Screen
*>(impl
)->frame(), V8Custom::kDOMWindowScreenIndex
, result
);
797 case V8ClassIndex::LOCATION
:
798 setHiddenWindowReference(static_cast<Location
*>(impl
)->frame(), V8Custom::kDOMWindowLocationIndex
, result
);
800 case V8ClassIndex::DOMSELECTION
:
801 setHiddenWindowReference(static_cast<DOMSelection
*>(impl
)->frame(), V8Custom::kDOMWindowDOMSelectionIndex
, result
);
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
);
810 case BarInfo::Menubar
:
811 setHiddenWindowReference(frame
, V8Custom::kDOMWindowMenubarIndex
, result
);
813 case BarInfo::Personalbar
:
814 setHiddenWindowReference(frame
, V8Custom::kDOMWindowPersonalbarIndex
, result
);
816 case BarInfo::Scrollbars
:
817 setHiddenWindowReference(frame
, V8Custom::kDOMWindowScrollbarsIndex
, result
);
819 case BarInfo::Statusbar
:
820 setHiddenWindowReference(frame
, V8Custom::kDOMWindowStatusbarIndex
, result
);
822 case BarInfo::Toolbar
:
823 setHiddenWindowReference(frame
, V8Custom::kDOMWindowToolbarIndex
, result
);
836 void V8DOMWrapper::setHiddenWindowReference(Frame
* frame
, const int internalIndex
, v8::Handle
<v8::Object
> jsObject
)
840 return; // Object might be detached from window
841 v8::Handle
<v8::Context
> context
= V8Proxy::context(frame
);
842 if (context
.IsEmpty())
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
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())
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.
893 // FIXME: Do we need a wrapper cache for the isolated world? We should
894 // see if the performance gains are worth while.
896 proxy
= V8Proxy::retrieve();
898 v8::Local
<v8::Object
> instance
;
900 instance
= proxy
->createWrapperFromCache(descriptorType
);
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
);
913 bool V8DOMWrapper::maybeDOMWrapper(v8::Handle
<v8::Value
> value
)
915 if (value
.IsEmpty() || !value
->IsObject())
918 v8::Handle
<v8::Object
> object
= v8::Handle
<v8::Object
>::Cast(value
);
919 if (!object
->InternalFieldCount())
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());
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())
947 v8::Handle
<v8::Object
> object
= v8::Handle
<v8::Object
>::Cast(value
);
948 if (!object
->InternalFieldCount())
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
;
964 #define FOR_EACH_VIDEO_TAG(macro) \
965 macro(audio, AUDIO) \
966 macro(source, SOURCE) \
969 #define FOR_EACH_VIDEO_TAG(macro)
973 #define FOR_EACH_DATAGRID_TAG(macro) \
974 macro(datagrid, DATAGRID) \
975 macro(dcell, DATAGRIDCELL) \
976 macro(dcol, DATAGRIDCOL) \
977 macro(drow, DATAGRIDROW)
979 #define FOR_EACH_DATAGRID_TAG(macro)
982 #define FOR_EACH_TAG(macro) \
983 FOR_EACH_DATAGRID_TAG(macro) \
985 macro(applet, APPLET) \
988 macro(basefont, BASEFONT) \
989 macro(blockquote, BLOCKQUOTE) \
992 macro(button, BUTTON) \
993 macro(caption, TABLECAPTION) \
994 macro(col, TABLECOL) \
995 macro(colgroup, TABLECOL) \
997 macro(canvas, CANVAS) \
998 macro(dir, DIRECTORY) \
1001 macro(embed, EMBED) \
1002 macro(fieldset, FIELDSET) \
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) \
1017 macro(iframe, IFRAME) \
1018 macro(image, IMAGE) \
1019 macro(input, INPUT) \
1021 macro(isindex, ISINDEX) \
1022 macro(keygen, SELECT) \
1023 macro(label, LABEL) \
1024 macro(legend, LEGEND) \
1027 macro(listing, PRE) \
1029 macro(marquee, MARQUEE) \
1032 macro(object, OBJECT) \
1034 macro(optgroup, OPTGROUP) \
1035 macro(option, OPTION) \
1036 macro(p, PARAGRAPH) \
1037 macro(param, PARAM) \
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) \
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
)
1064 if (MediaPlayer::isAvailable()) {
1065 FOR_EACH_VIDEO_TAG(ADD_TO_HASH_MAP
)
1068 #undef ADD_TO_HASH_MAP
1071 V8ClassIndex::V8WrapperType type
= wrapperTypeMap
.get(element
->localName().impl());
1073 return V8ClassIndex::HTMLELEMENT
;
1080 #if ENABLE(SVG_ANIMATION)
1081 #define FOR_EACH_ANIMATION_TAG(macro) \
1082 macro(animateColor, ANIMATECOLOR) \
1083 macro(animate, ANIMATE) \
1084 macro(animateTransform, ANIMATETRANSFORM) \
1087 #define FOR_EACH_ANIMATION_TAG(macro)
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)
1116 #define FOR_EACH_FILTERS_TAG(macro)
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)
1127 #define FOR_EACH_FONTS_TAG(marco)
1130 #if ENABLE(SVG_FOREIGN_OBJECT)
1131 #define FOR_EACH_FOREIGN_OBJECT_TAG(macro) \
1132 macro(foreignObject, FOREIGNOBJECT)
1134 #define FOR_EACH_FOREIGN_OBJECT_TAG(macro)
1138 #define FOR_EACH_USE_TAG(macro) \
1141 #define FOR_EACH_USE_TAG(macro)
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) \
1151 macro(altGlyph, ALTGLYPH) \
1152 macro(circle, CIRCLE) \
1153 macro(clipPath, CLIPPATH) \
1154 macro(cursor, CURSOR) \
1157 macro(ellipse, ELLIPSE) \
1159 macro(glyph, GLYPH) \
1160 macro(image, IMAGE) \
1161 macro(linearGradient, LINEARGRADIENT) \
1163 macro(marker, MARKER) \
1165 macro(metadata, METADATA) \
1167 macro(pattern, PATTERN) \
1168 macro(polyline, POLYLINE) \
1169 macro(polygon, POLYGON) \
1170 macro(radialGradient, RADIALGRADIENT) \
1172 macro(script, SCRIPT) \
1174 macro(style, STYLE) \
1176 macro(switch, SWITCH) \
1177 macro(symbol, SYMBOL) \
1179 macro(textPath, TEXTPATH) \
1180 macro(title, TITLE) \
1182 macro(tspan, TSPAN) \
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());
1199 return V8ClassIndex::SVGELEMENT
;
1204 #endif // ENABLE(SVG)
1206 v8::Handle
<v8::Value
> V8DOMWrapper::convertEventToV8Object(Event
* event
)
1211 v8::Handle
<v8::Object
> wrapper
= getDOMObjectMap().get(event
);
1212 if (!wrapper
.IsEmpty())
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
;
1227 else if (event
->isSVGZoomEvent())
1228 type
= V8ClassIndex::SVGZOOMEVENT
;
1230 else if (event
->isCompositionEvent())
1231 type
= V8ClassIndex::COMPOSITIONEVENT
;
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
;
1246 type
= V8ClassIndex::PROGRESSEVENT
;
1247 } else if (event
->isWebKitAnimationEvent())
1248 type
= V8ClassIndex::WEBKITANIMATIONEVENT
;
1249 else if (event
->isWebKitTransitionEvent())
1250 type
= V8ClassIndex::WEBKITTRANSITIONEVENT
;
1252 else if (event
->isErrorEvent())
1253 type
= V8ClassIndex::ERROREVENT
;
1255 #if ENABLE(DOM_STORAGE)
1256 else if (event
->isStorageEvent())
1257 type
= V8ClassIndex::STORAGEEVENT
;
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.
1271 event
->ref(); // fast ref
1272 setJSWrapperForDOMObject(event
, v8::Persistent
<v8::Object
>::New(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());
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
);
1313 v8::Handle
<v8::Value
> V8DOMWrapper::convertNodeToV8Object(Node
* node
)
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
);
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
));
1344 else if (node
->isSVGElement())
1345 type
= svgElementType(static_cast<SVGElement
*>(node
));
1348 type
= V8ClassIndex::ELEMENT
;
1349 } else if (nodeType
== Node::DOCUMENT_NODE
) {
1351 Document
* document
= static_cast<Document
*>(node
);
1352 if (document
->isHTMLDocument())
1353 type
= V8ClassIndex::HTMLDOCUMENT
;
1355 else if (document
->isSVGDocument())
1356 type
= V8ClassIndex::SVGDOCUMENT
;
1359 type
= V8ClassIndex::DOCUMENT
;
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
;
1368 context
= proxy
->context();
1370 // Enter the node's context and create the wrapper in that context.
1371 if (!context
.IsEmpty())
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())
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.
1389 domNodeMap
.set(node
, v8::Persistent
<v8::Object
>::New(result
));
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
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
);
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
)
1417 SVGElementInstance
* instance
= target
->toSVGElementInstance();
1419 return convertToV8Object(V8ClassIndex::SVGELEMENTINSTANCE
, instance
);
1423 Worker
* worker
= target
->toWorker();
1425 return convertToV8Object(V8ClassIndex::WORKER
, worker
);
1428 #if ENABLE(SHARED_WORKERS)
1429 SharedWorker
* sharedWorker
= target
->toSharedWorker();
1431 return convertToV8Object(V8ClassIndex::SHAREDWORKER
, sharedWorker
);
1432 #endif // SHARED_WORKERS
1434 #if ENABLE(NOTIFICATIONS)
1435 Notification
* notification
= target
->toNotification();
1437 return convertToV8Object(V8ClassIndex::NOTIFICATION
, notification
);
1440 #if ENABLE(WEB_SOCKETS)
1441 WebSocket
* webSocket
= target
->toWebSocket();
1443 return convertToV8Object(V8ClassIndex::WEBSOCKET
, webSocket
);
1446 Node
* node
= target
->toNode();
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());
1461 // MessagePort is created within its JS counterpart
1462 MessagePort
* port
= target
->toMessagePort();
1464 v8::Handle
<v8::Object
> wrapper
= getActiveDOMObjectMap().get(port
);
1465 ASSERT(!wrapper
.IsEmpty());
1469 XMLHttpRequestUpload
* upload
= target
->toXMLHttpRequestUpload();
1471 v8::Handle
<v8::Object
> wrapper
= getDOMObjectMap().get(upload
);
1472 ASSERT(!wrapper
.IsEmpty());
1476 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
1477 DOMApplicationCache
* domAppCache
= target
->toDOMApplicationCache();
1479 return convertToV8Object(V8ClassIndex::DOMAPPLICATIONCACHE
, domAppCache
);
1483 return notHandledByInterceptor();
1486 v8::Handle
<v8::Value
> V8DOMWrapper::convertEventListenerToV8Object(ScriptExecutionContext
* context
, EventListener
* listener
)
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
);
1502 PassRefPtr
<EventListener
> V8DOMWrapper::getEventListener(SVGElementInstance
* element
, v8::Local
<v8::Value
> value
, bool isAttribute
, ListenerLookupType lookup
)
1504 return getEventListener(element
->correspondingElement(), value
, isAttribute
, lookup
);
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
);
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
);
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
);
1552 WorkerContextExecutionProxy
* workerContextProxy
= WorkerContextExecutionProxy::retrieve();
1553 if (workerContextProxy
)
1554 return workerContextProxy
->findOrCreateEventListener(value
, isAttribute
, lookup
== ListenerFindOnly
);
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.
1576 v8::Handle
<v8::Value
> V8DOMWrapper::convertStyleSheetToV8Object(StyleSheet
* sheet
)
1581 v8::Handle
<v8::Object
> wrapper
= getDOMObjectMap().get(sheet
);
1582 if (!wrapper
.IsEmpty())
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.
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();
1599 v8::Handle
<v8::Object
> owner
= v8::Handle
<v8::Object
>::Cast(convertNodeToV8Object(ownerNode
));
1600 result
->SetInternalField(V8Custom::kStyleSheetOwnerNodeIndex
, owner
);
1606 v8::Handle
<v8::Value
> V8DOMWrapper::convertCSSValueToV8Object(CSSValue
* value
)
1611 v8::Handle
<v8::Object
> wrapper
= getDOMObjectMap().get(value
);
1612 if (!wrapper
.IsEmpty())
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
;
1624 else if (value
->isSVGPaint())
1625 type
= V8ClassIndex::SVGPAINT
;
1626 else if (value
->isSVGColor())
1627 type
= V8ClassIndex::SVGCOLOR
;
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.
1636 setJSWrapperForDOMObject(value
, v8::Persistent
<v8::Object
>::New(result
));
1642 v8::Handle
<v8::Value
> V8DOMWrapper::convertCSSRuleToV8Object(CSSRule
* rule
)
1647 v8::Handle
<v8::Object
> wrapper
= getDOMObjectMap().get(rule
);
1648 if (!wrapper
.IsEmpty())
1651 V8ClassIndex::V8WrapperType type
;
1653 switch (rule
->type()) {
1654 case CSSRule::STYLE_RULE
:
1655 type
= V8ClassIndex::CSSSTYLERULE
;
1657 case CSSRule::CHARSET_RULE
:
1658 type
= V8ClassIndex::CSSCHARSETRULE
;
1660 case CSSRule::IMPORT_RULE
:
1661 type
= V8ClassIndex::CSSIMPORTRULE
;
1663 case CSSRule::MEDIA_RULE
:
1664 type
= V8ClassIndex::CSSMEDIARULE
;
1666 case CSSRule::FONT_FACE_RULE
:
1667 type
= V8ClassIndex::CSSFONTFACERULE
;
1669 case CSSRule::PAGE_RULE
:
1670 type
= V8ClassIndex::CSSPAGERULE
;
1672 case CSSRule::VARIABLES_RULE
:
1673 type
= V8ClassIndex::CSSVARIABLESRULE
;
1675 case CSSRule::WEBKIT_KEYFRAME_RULE
:
1676 type
= V8ClassIndex::WEBKITCSSKEYFRAMERULE
;
1678 case CSSRule::WEBKIT_KEYFRAMES_RULE
:
1679 type
= V8ClassIndex::WEBKITCSSKEYFRAMESRULE
;
1681 default: // CSSRule::UNKNOWN_RULE
1682 type
= V8ClassIndex::CSSRULE
;
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.
1690 setJSWrapperForDOMObject(rule
, v8::Persistent
<v8::Object
>::New(result
));
1695 v8::Handle
<v8::Value
> V8DOMWrapper::convertWindowToV8Object(DOMWindow
* window
)
1699 // Initializes environment of a frame, and return the global object
1701 Frame
* frame
= window
->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());
1728 v8::Handle
<v8::Value
> V8DOMWrapper::convertNamedNodeMapToV8Object(NamedNodeMap
* map
)
1733 v8::Handle
<v8::Object
> wrapper
= getDOMObjectMap().get(map
);
1734 if (!wrapper
.IsEmpty())
1737 v8::Handle
<v8::Object
> result
= instantiateV8Object(V8ClassIndex::NAMEDNODEMAP
, V8ClassIndex::NAMEDNODEMAP
, map
);
1738 if (result
.IsEmpty())
1741 // Only update the DOM object map if the result is non-empty.
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
);
1754 } // namespace WebCore