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 "SVGElementInstance.h"
40 #include "ScriptController.h"
41 #include "V8AbstractEventListener.h"
42 #include "V8Binding.h"
43 #include "V8Collection.h"
44 #include "V8CustomBinding.h"
46 #include "V8DOMWindow.h"
47 #include "V8EventListenerList.h"
49 #include "V8IsolatedWorld.h"
50 #include "V8ObjectEventListener.h"
52 #include "WorkerContextExecutionProxy.h"
58 #include <wtf/Assertions.h>
59 #include <wtf/OwnArrayPtr.h>
60 #include <wtf/StdLibExtras.h>
61 #include <wtf/UnusedParam.h>
65 typedef HashMap<Node*, v8::Object*> DOMNodeMap;
66 typedef HashMap<void*, v8::Object*> DOMObjectMap;
68 // Get the string 'toString'.
69 static v8::Persistent<v8::String> GetToStringName()
71 DEFINE_STATIC_LOCAL(v8::Persistent<v8::String>, value, ());
73 value = v8::Persistent<v8::String>::New(v8::String::New("toString"));
77 static v8::Handle<v8::Value> ConstructorToString(const v8::Arguments& args)
79 // The DOM constructors' toString functions grab the current toString
80 // for Functions by taking the toString function of itself and then
81 // calling it with the constructor as its receiver. This means that
82 // changes to the Function prototype chain or toString function are
83 // reflected when printing DOM constructors. The only wart is that
84 // changes to a DOM constructor's toString's toString will cause the
85 // toString of the DOM constructor itself to change. This is extremely
86 // obscure and unlikely to be a problem.
87 v8::Handle<v8::Value> value = args.Callee()->Get(GetToStringName());
88 if (!value->IsFunction())
89 return v8::String::New("");
90 return v8::Handle<v8::Function>::Cast(value)->Call(args.This(), 0, 0);
94 v8::Handle<v8::Value> V8DOMWrapper::convertSVGElementInstanceToV8Object(SVGElementInstance* instance)
99 v8::Handle<v8::Object> existingInstance = getDOMSVGElementInstanceMap().get(instance);
100 if (!existingInstance.IsEmpty())
101 return existingInstance;
105 // Instantiate the V8 object and remember it
106 v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::SVGELEMENTINSTANCE, V8ClassIndex::SVGELEMENTINSTANCE, instance);
107 if (!result.IsEmpty()) {
108 // Only update the DOM SVG element map if the result is non-empty.
109 getDOMSVGElementInstanceMap().set(instance, v8::Persistent<v8::Object>::New(result));
114 v8::Handle<v8::Value> V8DOMWrapper::convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType type, void* object)
119 v8::Persistent<v8::Object> result = getDOMSVGObjectWithContextMap().get(object);
120 if (!result.IsEmpty())
123 // Special case: SVGPathSegs need to be downcast to their real type
124 if (type == V8ClassIndex::SVGPATHSEG)
125 type = V8Custom::DowncastSVGPathSeg(object);
127 v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, object);
128 if (!v8Object.IsEmpty()) {
129 result = v8::Persistent<v8::Object>::New(v8Object);
131 #define MAKE_CASE(TYPE, NAME) \
132 case V8ClassIndex::TYPE: static_cast<NAME*>(object)->ref(); break;
133 SVG_OBJECT_TYPES(MAKE_CASE)
135 #define MAKE_CASE(TYPE, NAME) \
136 case V8ClassIndex::TYPE: \
137 static_cast<V8SVGPODTypeWrapper<NAME>*>(object)->ref(); break;
138 SVG_POD_NATIVE_TYPES(MAKE_CASE)
141 ASSERT_NOT_REACHED();
143 getDOMSVGObjectWithContextMap().set(object, result);
151 bool V8DOMWrapper::domObjectHasJSWrapper(void* object)
153 return getDOMObjectMap().contains(object) || getActiveDOMObjectMap().contains(object);
156 // The caller must have increased obj's ref count.
157 void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper)
159 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper));
161 V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper);
163 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
164 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
165 ASSERT_NOT_REACHED();
171 getDOMObjectMap().set(object, wrapper);
174 // The caller must have increased obj's ref count.
175 void V8DOMWrapper::setJSWrapperForActiveDOMObject(void* object, v8::Persistent<v8::Object> wrapper)
177 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper));
179 V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper);
181 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break;
182 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
184 ASSERT_NOT_REACHED();
188 getActiveDOMObjectMap().set(object, wrapper);
191 // The caller must have increased node's ref count.
192 void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper)
194 ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper));
195 getDOMNodeMap().set(node, wrapper);
198 v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8WrapperType type)
200 v8::Persistent<v8::FunctionTemplate>* cacheCell = V8ClassIndex::GetCache(type);
201 if (!cacheCell->IsEmpty())
205 FunctionTemplateFactory factory = V8ClassIndex::GetFactory(type);
206 v8::Persistent<v8::FunctionTemplate> descriptor = factory();
207 // DOM constructors are functions and should print themselves as such.
208 // However, we will later replace their prototypes with Object
209 // prototypes so we need to explicitly override toString on the
210 // instance itself. If we later make DOM constructors full objects
211 // we can give them class names instead and Object.prototype.toString
212 // will work so we can remove this code.
213 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, toStringTemplate, ());
214 if (toStringTemplate.IsEmpty())
215 toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(ConstructorToString));
216 descriptor->Set(GetToStringName(), toStringTemplate);
218 case V8ClassIndex::CSSSTYLEDECLARATION:
219 // The named property handler for style declarations has a
220 // setter. Therefore, the interceptor has to be on the object
221 // itself and not on the prototype object.
222 descriptor->InstanceTemplate()->SetNamedPropertyHandler( USE_NAMED_PROPERTY_GETTER(CSSStyleDeclaration), USE_NAMED_PROPERTY_SETTER(CSSStyleDeclaration));
223 setCollectionStringOrNullIndexedGetter<CSSStyleDeclaration>(descriptor);
225 case V8ClassIndex::CSSRULELIST:
226 setCollectionIndexedGetter<CSSRuleList, CSSRule>(descriptor, V8ClassIndex::CSSRULE);
228 case V8ClassIndex::CSSVALUELIST:
229 setCollectionIndexedGetter<CSSValueList, CSSValue>(descriptor, V8ClassIndex::CSSVALUE);
231 case V8ClassIndex::CSSVARIABLESDECLARATION:
232 setCollectionStringOrNullIndexedGetter<CSSVariablesDeclaration>(descriptor);
234 case V8ClassIndex::WEBKITCSSTRANSFORMVALUE:
235 setCollectionIndexedGetter<WebKitCSSTransformValue, CSSValue>(descriptor, V8ClassIndex::CSSVALUE);
237 case V8ClassIndex::HTMLALLCOLLECTION:
238 descriptor->InstanceTemplate()->MarkAsUndetectable(); // fall through
239 case V8ClassIndex::HTMLCOLLECTION:
240 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLCollection));
241 descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLCollectionCallAsFunction));
242 setCollectionIndexedGetter<HTMLCollection, Node>(descriptor, V8ClassIndex::NODE);
244 case V8ClassIndex::HTMLOPTIONSCOLLECTION:
245 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLCollection));
246 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLOptionsCollection), USE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection));
247 descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLCollectionCallAsFunction));
249 case V8ClassIndex::HTMLSELECTELEMENT:
250 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLSelectElementCollection));
251 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(nodeCollectionIndexedPropertyGetter<HTMLSelectElement>, USE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection),
252 0, 0, nodeCollectionIndexedPropertyEnumerator<HTMLSelectElement>, v8::Integer::New(V8ClassIndex::NODE));
254 case V8ClassIndex::HTMLDOCUMENT: {
255 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLDocument), 0, 0, USE_NAMED_PROPERTY_DELETER(HTMLDocument));
257 // We add an extra internal field to all Document wrappers for
258 // storing a per document DOMImplementation wrapper.
260 // Additionally, we add two extra internal fields for
261 // HTMLDocuments to implement temporary shadowing of
262 // document.all. One field holds an object that is used as a
263 // marker. The other field holds the marker object if
264 // document.all is not shadowed and some other value if
265 // document.all is shadowed.
266 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
267 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kNodeMinimumInternalFieldCount);
268 instanceTemplate->SetInternalFieldCount(V8Custom::kHTMLDocumentInternalFieldCount);
272 case V8ClassIndex::SVGDOCUMENT: // fall through
274 case V8ClassIndex::DOCUMENT: {
275 // We add an extra internal field to all Document wrappers for
276 // storing a per document DOMImplementation wrapper.
277 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
278 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kNodeMinimumInternalFieldCount);
279 instanceTemplate->SetInternalFieldCount( V8Custom::kDocumentMinimumInternalFieldCount);
282 case V8ClassIndex::HTMLAPPLETELEMENT: // fall through
283 case V8ClassIndex::HTMLEMBEDELEMENT: // fall through
284 case V8ClassIndex::HTMLOBJECTELEMENT:
285 // HTMLAppletElement, HTMLEmbedElement and HTMLObjectElement are
286 // inherited from HTMLPlugInElement, and they share the same property
288 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLPlugInElement), USE_NAMED_PROPERTY_SETTER(HTMLPlugInElement));
289 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLPlugInElement), USE_INDEXED_PROPERTY_SETTER(HTMLPlugInElement));
290 descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLPlugInElement));
292 case V8ClassIndex::HTMLFRAMESETELEMENT:
293 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFrameSetElement));
295 case V8ClassIndex::HTMLFORMELEMENT:
296 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFormElement));
297 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLFormElement), 0, 0, 0, nodeCollectionIndexedPropertyEnumerator<HTMLFormElement>, v8::Integer::New(V8ClassIndex::NODE));
299 case V8ClassIndex::STYLESHEET: // fall through
300 case V8ClassIndex::CSSSTYLESHEET: {
301 // We add an extra internal field to hold a reference to
303 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
304 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount);
305 instanceTemplate->SetInternalFieldCount(V8Custom::kStyleSheetInternalFieldCount);
308 case V8ClassIndex::MEDIALIST:
309 setCollectionStringOrNullIndexedGetter<MediaList>(descriptor);
311 case V8ClassIndex::MIMETYPEARRAY:
312 setCollectionIndexedAndNamedGetters<MimeTypeArray, MimeType>(descriptor, V8ClassIndex::MIMETYPE);
314 case V8ClassIndex::NAMEDNODEMAP:
315 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NamedNodeMap));
316 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(NamedNodeMap), 0, 0, 0, collectionIndexedPropertyEnumerator<NamedNodeMap>, v8::Integer::New(V8ClassIndex::NODE));
318 #if ENABLE(DOM_STORAGE)
319 case V8ClassIndex::STORAGE:
320 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(Storage), USE_NAMED_PROPERTY_SETTER(Storage), 0, USE_NAMED_PROPERTY_DELETER(Storage), V8Custom::v8StorageNamedPropertyEnumerator);
321 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(Storage), USE_INDEXED_PROPERTY_SETTER(Storage), 0, USE_INDEXED_PROPERTY_DELETER(Storage));
324 case V8ClassIndex::NODELIST:
325 setCollectionIndexedGetter<NodeList, Node>(descriptor, V8ClassIndex::NODE);
326 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NodeList));
328 case V8ClassIndex::PLUGIN:
329 setCollectionIndexedAndNamedGetters<Plugin, MimeType>(descriptor, V8ClassIndex::MIMETYPE);
331 case V8ClassIndex::PLUGINARRAY:
332 setCollectionIndexedAndNamedGetters<PluginArray, Plugin>(descriptor, V8ClassIndex::PLUGIN);
334 case V8ClassIndex::STYLESHEETLIST:
335 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(StyleSheetList));
336 setCollectionIndexedGetter<StyleSheetList, StyleSheet>(descriptor, V8ClassIndex::STYLESHEET);
338 case V8ClassIndex::DOMWINDOW: {
339 v8::Local<v8::Signature> defaultSignature = v8::Signature::New(descriptor);
341 descriptor->PrototypeTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DOMWindow));
342 descriptor->PrototypeTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DOMWindow));
344 descriptor->SetHiddenPrototype(true);
346 // Reserve spaces for references to location, history and
347 // navigator objects.
348 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
349 instanceTemplate->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount);
351 // Set access check callbacks, but turned off initially.
352 // When a context is detached from a frame, turn on the access check.
353 // Turning on checks also invalidates inline caches of the object.
354 instanceTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW), false);
357 case V8ClassIndex::LOCATION: {
358 // For security reasons, these functions are on the instance
359 // instead of on the prototype object to insure that they cannot
361 v8::Local<v8::ObjectTemplate> instance = descriptor->InstanceTemplate();
362 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));
363 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));
364 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));
367 case V8ClassIndex::HISTORY:
370 case V8ClassIndex::MESSAGECHANNEL: {
371 // Reserve two more internal fields for referencing the port1
372 // and port2 wrappers. This ensures that the port wrappers are
373 // kept alive when the channel wrapper is.
374 descriptor->SetCallHandler(USE_CALLBACK(MessageChannelConstructor));
375 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
376 instanceTemplate->SetInternalFieldCount(V8Custom::kMessageChannelInternalFieldCount);
380 case V8ClassIndex::MESSAGEPORT: {
381 // Reserve one more internal field for keeping event listeners.
382 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
383 instanceTemplate->SetInternalFieldCount(V8Custom::kMessagePortInternalFieldCount);
387 #if ENABLE(NOTIFICATIONS)
388 case V8ClassIndex::NOTIFICATION: {
389 // Reserve one more internal field for keeping event listeners.
390 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
391 instanceTemplate->SetInternalFieldCount(V8Custom::kNotificationInternalFieldCount);
394 #endif // NOTIFICATIONS
397 case V8ClassIndex::ABSTRACTWORKER: {
398 // Reserve one more internal field for keeping event listeners.
399 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
400 instanceTemplate->SetInternalFieldCount(V8Custom::kAbstractWorkerInternalFieldCount);
404 case V8ClassIndex::DEDICATEDWORKERCONTEXT: {
405 // Reserve internal fields for keeping event listeners.
406 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
407 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount);
408 instanceTemplate->SetInternalFieldCount(V8Custom::kDedicatedWorkerContextInternalFieldCount);
412 case V8ClassIndex::WORKER: {
413 // Reserve one more internal field for keeping event listeners.
414 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
415 instanceTemplate->SetInternalFieldCount(V8Custom::kWorkerInternalFieldCount);
416 descriptor->SetCallHandler(USE_CALLBACK(WorkerConstructor));
420 case V8ClassIndex::WORKERCONTEXT: {
421 // Reserve one more internal field for keeping event listeners.
422 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
423 ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount);
424 instanceTemplate->SetInternalFieldCount(V8Custom::kWorkerContextMinimumInternalFieldCount);
430 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
431 case V8ClassIndex::DOMAPPLICATIONCACHE: {
432 // Reserve one more internal field for keeping event listeners.
433 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
434 instanceTemplate->SetInternalFieldCount(V8Custom::kDOMApplicationCacheFieldCount);
439 // The following objects are created from JavaScript.
440 case V8ClassIndex::DOMPARSER:
441 descriptor->SetCallHandler(USE_CALLBACK(DOMParserConstructor));
444 case V8ClassIndex::HTMLAUDIOELEMENT:
445 descriptor->SetCallHandler(USE_CALLBACK(HTMLAudioElementConstructor));
448 case V8ClassIndex::HTMLIMAGEELEMENT:
449 descriptor->SetCallHandler(USE_CALLBACK(HTMLImageElementConstructor));
451 case V8ClassIndex::HTMLOPTIONELEMENT:
452 descriptor->SetCallHandler(USE_CALLBACK(HTMLOptionElementConstructor));
454 case V8ClassIndex::WEBKITCSSMATRIX:
455 descriptor->SetCallHandler(USE_CALLBACK(WebKitCSSMatrixConstructor));
457 case V8ClassIndex::WEBKITPOINT:
458 descriptor->SetCallHandler(USE_CALLBACK(WebKitPointConstructor));
460 #if ENABLE(WEB_SOCKETS)
461 case V8ClassIndex::WEBSOCKET: {
462 // Reserve one more internal field for keeping event listeners.
463 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
464 instanceTemplate->SetInternalFieldCount(V8Custom::kWebSocketInternalFieldCount);
465 descriptor->SetCallHandler(USE_CALLBACK(WebSocketConstructor));
469 case V8ClassIndex::XMLSERIALIZER:
470 descriptor->SetCallHandler(USE_CALLBACK(XMLSerializerConstructor));
472 case V8ClassIndex::XMLHTTPREQUEST: {
473 // Reserve one more internal field for keeping event listeners.
474 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
475 instanceTemplate->SetInternalFieldCount(V8Custom::kXMLHttpRequestInternalFieldCount);
476 descriptor->SetCallHandler(USE_CALLBACK(XMLHttpRequestConstructor));
479 case V8ClassIndex::XMLHTTPREQUESTUPLOAD: {
480 // Reserve one more internal field for keeping event listeners.
481 v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
482 instanceTemplate->SetInternalFieldCount(V8Custom::kXMLHttpRequestInternalFieldCount);
485 case V8ClassIndex::XPATHEVALUATOR:
486 descriptor->SetCallHandler(USE_CALLBACK(XPathEvaluatorConstructor));
488 case V8ClassIndex::XSLTPROCESSOR:
489 descriptor->SetCallHandler(USE_CALLBACK(XSLTProcessorConstructor));
491 case V8ClassIndex::CLIENTRECTLIST:
492 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(ClientRectList));
495 case V8ClassIndex::DATAGRIDCOLUMNLIST:
496 descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DataGridColumnList));
497 descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DataGridColumnList));
504 *cacheCell = descriptor;
508 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> objectPrototype)
510 // A DOM constructor is a function instance created from a DOM constructor
511 // template. There is one instance per context. A DOM constructor is
512 // different from a normal function in two ways:
513 // 1) it cannot be called as constructor (aka, used to create a DOM object)
514 // 2) its __proto__ points to Object.prototype rather than
515 // Function.prototype.
516 // The reason for 2) is that, in Safari, a DOM constructor is a normal JS
517 // object, but not a function. Hotmail relies on the fact that, in Safari,
518 // HTMLElement.__proto__ == Object.prototype.
519 v8::Handle<v8::FunctionTemplate> functionTemplate = getTemplate(type);
520 // Getting the function might fail if we're running out of
522 v8::TryCatch tryCatch;
523 v8::Local<v8::Function> value = functionTemplate->GetFunction();
525 return v8::Local<v8::Function>();
526 // Hotmail fix, see comments above.
527 if (!objectPrototype.IsEmpty())
528 value->Set(v8::String::New("__proto__"), objectPrototype);
532 v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Context> context)
534 // Enter the scope for this context to get the correct constructor.
535 v8::Context::Scope scope(context);
537 return getConstructor(type, V8Proxy::getHiddenObjectPrototype(context));
540 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window)
542 Frame* frame = window->frame();
544 return v8::Local<v8::Function>();
546 v8::Handle<v8::Context> context = V8Proxy::context(frame);
547 if (context.IsEmpty())
548 return v8::Local<v8::Function>();
550 return getConstructorForContext(type, context);
553 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, WorkerContext*)
555 WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
557 return v8::Local<v8::Function>();
559 v8::Handle<v8::Context> context = proxy->context();
560 if (context.IsEmpty())
561 return v8::Local<v8::Function>();
563 return getConstructorForContext(type, context);
566 v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl)
568 ASSERT(type != V8ClassIndex::EVENTLISTENER);
569 ASSERT(type != V8ClassIndex::EVENTTARGET);
570 ASSERT(type != V8ClassIndex::EVENT);
572 // These objects can be constructed under WorkerContextExecutionProxy. They need special
573 // handling, since if we proceed below V8Proxy::retrieve() will get called and will crash.
574 // TODO(ukai): websocket?
575 if ((type == V8ClassIndex::DOMCOREEXCEPTION
576 || type == V8ClassIndex::RANGEEXCEPTION
577 || type == V8ClassIndex::EVENTEXCEPTION
578 || type == V8ClassIndex::XMLHTTPREQUESTEXCEPTION
579 || type == V8ClassIndex::MESSAGEPORT)
580 && WorkerContextExecutionProxy::retrieve()) {
581 return WorkerContextExecutionProxy::convertToV8Object(type, impl);
584 bool isActiveDomObject = false;
586 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
587 DOM_NODE_TYPES(MAKE_CASE)
589 SVG_NODE_TYPES(MAKE_CASE)
591 return convertNodeToV8Object(static_cast<Node*>(impl));
592 case V8ClassIndex::CSSVALUE:
593 return convertCSSValueToV8Object(static_cast<CSSValue*>(impl));
594 case V8ClassIndex::CSSRULE:
595 return convertCSSRuleToV8Object(static_cast<CSSRule*>(impl));
596 case V8ClassIndex::STYLESHEET:
597 return convertStyleSheetToV8Object(static_cast<StyleSheet*>(impl));
598 case V8ClassIndex::DOMWINDOW:
599 return convertWindowToV8Object(static_cast<DOMWindow*>(impl));
601 SVG_NONNODE_TYPES(MAKE_CASE)
602 if (type == V8ClassIndex::SVGELEMENTINSTANCE)
603 return convertSVGElementInstanceToV8Object(static_cast<SVGElementInstance*>(impl));
604 return convertSVGObjectWithContextToV8Object(type, impl);
607 ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
608 isActiveDomObject = true;
620 v8::Persistent<v8::Object> result = isActiveDomObject ? getActiveDOMObjectMap().get(impl) : getDOMObjectMap().get(impl);
621 if (result.IsEmpty()) {
622 v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, impl);
623 if (!v8Object.IsEmpty()) {
624 // Go through big switch statement, it has some duplications
625 // that were handled by code above (such as CSSVALUE, CSSRULE, etc).
627 #define MAKE_CASE(TYPE, NAME) \
628 case V8ClassIndex::TYPE: static_cast<NAME*>(impl)->ref(); break;
629 DOM_OBJECT_TYPES(MAKE_CASE)
632 ASSERT_NOT_REACHED();
634 result = v8::Persistent<v8::Object>::New(v8Object);
635 if (isActiveDomObject)
636 setJSWrapperForActiveDOMObject(impl, result);
638 setJSWrapperForDOMObject(impl, result);
640 if (type == V8ClassIndex::CANVASPIXELARRAY) {
641 CanvasPixelArray* pixels = reinterpret_cast<CanvasPixelArray*>(impl);
642 result->SetIndexedPropertiesToPixelData(pixels->data()->data(), pixels->length());
645 // Special case for non-node objects associated with a
646 // DOMWindow. Both Safari and FF let the JS wrappers for these
647 // objects survive GC. To mimic their behavior, V8 creates
648 // hidden references from the DOMWindow to these wrapper
649 // objects. These references get cleared when the DOMWindow is
650 // reused by a new page.
652 case V8ClassIndex::CONSOLE:
653 setHiddenWindowReference(static_cast<Console*>(impl)->frame(), V8Custom::kDOMWindowConsoleIndex, result);
655 case V8ClassIndex::HISTORY:
656 setHiddenWindowReference(static_cast<History*>(impl)->frame(), V8Custom::kDOMWindowHistoryIndex, result);
658 case V8ClassIndex::NAVIGATOR:
659 setHiddenWindowReference(static_cast<Navigator*>(impl)->frame(), V8Custom::kDOMWindowNavigatorIndex, result);
661 case V8ClassIndex::SCREEN:
662 setHiddenWindowReference(static_cast<Screen*>(impl)->frame(), V8Custom::kDOMWindowScreenIndex, result);
664 case V8ClassIndex::LOCATION:
665 setHiddenWindowReference(static_cast<Location*>(impl)->frame(), V8Custom::kDOMWindowLocationIndex, result);
667 case V8ClassIndex::DOMSELECTION:
668 setHiddenWindowReference(static_cast<DOMSelection*>(impl)->frame(), V8Custom::kDOMWindowDOMSelectionIndex, result);
670 case V8ClassIndex::BARINFO: {
671 BarInfo* barInfo = static_cast<BarInfo*>(impl);
672 Frame* frame = barInfo->frame();
673 switch (barInfo->type()) {
674 case BarInfo::Locationbar:
675 setHiddenWindowReference(frame, V8Custom::kDOMWindowLocationbarIndex, result);
677 case BarInfo::Menubar:
678 setHiddenWindowReference(frame, V8Custom::kDOMWindowMenubarIndex, result);
680 case BarInfo::Personalbar:
681 setHiddenWindowReference(frame, V8Custom::kDOMWindowPersonalbarIndex, result);
683 case BarInfo::Scrollbars:
684 setHiddenWindowReference(frame, V8Custom::kDOMWindowScrollbarsIndex, result);
686 case BarInfo::Statusbar:
687 setHiddenWindowReference(frame, V8Custom::kDOMWindowStatusbarIndex, result);
689 case BarInfo::Toolbar:
690 setHiddenWindowReference(frame, V8Custom::kDOMWindowToolbarIndex, result);
703 void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalIndex, v8::Handle<v8::Object> jsObject)
707 return; // Object might be detached from window
708 v8::Handle<v8::Context> context = V8Proxy::context(frame);
709 if (context.IsEmpty())
712 ASSERT(internalIndex < V8Custom::kDOMWindowInternalFieldCount);
714 v8::Handle<v8::Object> global = context->Global();
715 // Look for real DOM wrapper.
716 global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, global);
717 ASSERT(!global.IsEmpty());
718 ASSERT(global->GetInternalField(internalIndex)->IsUndefined());
719 global->SetInternalField(internalIndex, jsObject);
722 V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object)
724 ASSERT(V8DOMWrapper::maybeDOMWrapper(object));
725 v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex);
726 return V8ClassIndex::FromInt(type->Int32Value());
729 void* V8DOMWrapper::convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object)
731 return isWrapperOfType(object, type) ? convertDOMWrapperToNative<void>(v8::Handle<v8::Object>::Cast(object)) : 0;
734 PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter)
736 // A NodeFilter is used when walking through a DOM tree or iterating tree
738 // FIXME: we may want to cache NodeFilterCondition and NodeFilter
739 // object, but it is minor.
740 // NodeFilter is passed to NodeIterator that has a ref counted pointer
741 // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition.
742 // In NodeFilterCondition, filter object is persisted in its constructor,
743 // and disposed in its destructor.
744 if (!filter->IsFunction())
747 NodeFilterCondition* condition = new V8NodeFilterCondition(filter);
748 return NodeFilter::create(condition);
751 v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl)
753 // Make a special case for document.all
754 if (descriptorType == V8ClassIndex::HTMLCOLLECTION && static_cast<HTMLCollection*>(impl)->type() == DocAll)
755 descriptorType = V8ClassIndex::HTMLALLCOLLECTION;
757 if (V8IsolatedWorld::getEntered()) {
758 // This effectively disables the wrapper cache for isolated worlds.
760 // FIXME: Do we need a wrapper cache for the isolated world? We should
761 // see if the performance gains are worth while.
763 proxy = V8Proxy::retrieve();
765 v8::Local<v8::Object> instance;
767 instance = proxy->createWrapperFromCache(descriptorType);
769 v8::Local<v8::Function> function = getTemplate(descriptorType)->GetFunction();
770 instance = SafeAllocation::newInstance(function);
772 if (!instance.IsEmpty()) {
773 // Avoid setting the DOM wrapper for failed allocations.
774 setDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl);
779 void V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object> object, int type, void* cptr)
781 ASSERT(object->InternalFieldCount() >= 2);
782 object->SetPointerInInternalField(V8Custom::kDOMWrapperObjectIndex, cptr);
783 object->SetInternalField(V8Custom::kDOMWrapperTypeIndex, v8::Integer::New(type));
787 bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value)
789 if (value.IsEmpty() || !value->IsObject())
792 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
793 if (!object->InternalFieldCount())
796 ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount);
798 v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex);
799 ASSERT(type->IsInt32());
800 ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END);
802 v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex);
803 ASSERT(wrapper->IsNumber() || wrapper->IsExternal());
809 bool V8DOMWrapper::isDOMEventWrapper(v8::Handle<v8::Value> value)
811 // All kinds of events use EVENT as dom type in JS wrappers.
812 // See EventToV8Object
813 return isWrapperOfType(value, V8ClassIndex::EVENT);
816 bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType)
818 if (value.IsEmpty() || !value->IsObject())
821 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
822 if (!object->InternalFieldCount())
825 ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount);
827 v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex);
828 ASSERT(wrapper->IsNumber() || wrapper->IsExternal());
830 v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex);
831 ASSERT(type->IsInt32());
832 ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END);
834 return V8ClassIndex::FromInt(type->Int32Value()) == classType;
838 #define FOR_EACH_VIDEO_TAG(macro) \
839 macro(audio, AUDIO) \
840 macro(source, SOURCE) \
843 #define FOR_EACH_VIDEO_TAG(macro)
847 #define FOR_EACH_DATAGRID_TAG(macro) \
848 macro(datagrid, DATAGRID) \
849 macro(dcell, DATAGRIDCELL) \
850 macro(dcol, DATAGRIDCOL) \
851 macro(drow, DATAGRIDROW)
853 #define FOR_EACH_DATAGRID_TAG(macro)
856 #define FOR_EACH_TAG(macro) \
857 FOR_EACH_DATAGRID_TAG(macro) \
859 macro(applet, APPLET) \
862 macro(basefont, BASEFONT) \
863 macro(blockquote, BLOCKQUOTE) \
866 macro(button, BUTTON) \
867 macro(caption, TABLECAPTION) \
868 macro(col, TABLECOL) \
869 macro(colgroup, TABLECOL) \
871 macro(canvas, CANVAS) \
872 macro(dir, DIRECTORY) \
875 macro(embed, EMBED) \
876 macro(fieldset, FIELDSET) \
879 macro(frame, FRAME) \
880 macro(frameset, FRAMESET) \
891 macro(iframe, IFRAME) \
892 macro(image, IMAGE) \
893 macro(input, INPUT) \
895 macro(isindex, ISINDEX) \
896 macro(keygen, SELECT) \
897 macro(label, LABEL) \
898 macro(legend, LEGEND) \
901 macro(listing, PRE) \
903 macro(marquee, MARQUEE) \
906 macro(object, OBJECT) \
908 macro(optgroup, OPTGROUP) \
909 macro(option, OPTION) \
910 macro(p, PARAGRAPH) \
911 macro(param, PARAM) \
914 macro(script, SCRIPT) \
915 macro(select, SELECT) \
916 macro(style, STYLE) \
917 macro(table, TABLE) \
918 macro(thead, TABLESECTION) \
919 macro(tbody, TABLESECTION) \
920 macro(tfoot, TABLESECTION) \
921 macro(td, TABLECELL) \
922 macro(th, TABLECELL) \
923 macro(tr, TABLEROW) \
924 macro(textarea, TEXTAREA) \
925 macro(title, TITLE) \
929 V8ClassIndex::V8WrapperType V8DOMWrapper::htmlElementType(HTMLElement* element)
931 typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap;
932 DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ());
933 if (wrapperTypeMap.isEmpty()) {
934 #define ADD_TO_HASH_MAP(tag, name) \
935 wrapperTypeMap.set(#tag, V8ClassIndex::HTML##name##ELEMENT);
936 FOR_EACH_TAG(ADD_TO_HASH_MAP)
938 if (MediaPlayer::isAvailable()) {
939 FOR_EACH_VIDEO_TAG(ADD_TO_HASH_MAP)
942 #undef ADD_TO_HASH_MAP
945 V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl());
947 return V8ClassIndex::HTMLELEMENT;
954 #if ENABLE(SVG_ANIMATION)
955 #define FOR_EACH_ANIMATION_TAG(macro) \
956 macro(animateColor, ANIMATECOLOR) \
957 macro(animate, ANIMATE) \
958 macro(animateTransform, ANIMATETRANSFORM) \
961 #define FOR_EACH_ANIMATION_TAG(macro)
964 #if ENABLE(SVG_FILTERS)
965 #define FOR_EACH_FILTERS_TAG(macro) \
966 macro(feBlend, FEBLEND) \
967 macro(feColorMatrix, FECOLORMATRIX) \
968 macro(feComponentTransfer, FECOMPONENTTRANSFER) \
969 macro(feComposite, FECOMPOSITE) \
970 macro(feDiffuseLighting, FEDIFFUSELIGHTING) \
971 macro(feDisplacementMap, FEDISPLACEMENTMAP) \
972 macro(feDistantLight, FEDISTANTLIGHT) \
973 macro(feFlood, FEFLOOD) \
974 macro(feFuncA, FEFUNCA) \
975 macro(feFuncB, FEFUNCB) \
976 macro(feFuncG, FEFUNCG) \
977 macro(feFuncR, FEFUNCR) \
978 macro(feGaussianBlur, FEGAUSSIANBLUR) \
979 macro(feImage, FEIMAGE) \
980 macro(feMerge, FEMERGE) \
981 macro(feMergeNode, FEMERGENODE) \
982 macro(feOffset, FEOFFSET) \
983 macro(fePointLight, FEPOINTLIGHT) \
984 macro(feSpecularLighting, FESPECULARLIGHTING) \
985 macro(feSpotLight, FESPOTLIGHT) \
986 macro(feTile, FETILE) \
987 macro(feTurbulence, FETURBULENCE) \
988 macro(filter, FILTER)
990 #define FOR_EACH_FILTERS_TAG(macro)
993 #if ENABLE(SVG_FONTS)
994 #define FOR_EACH_FONTS_TAG(macro) \
995 macro(definition-src, DEFINITIONSRC) \
996 macro(font-face, FONTFACE) \
997 macro(font-face-format, FONTFACEFORMAT) \
998 macro(font-face-name, FONTFACENAME) \
999 macro(font-face-src, FONTFACESRC) \
1000 macro(font-face-uri, FONTFACEURI)
1002 #define FOR_EACH_FONTS_TAG(marco)
1005 #if ENABLE(SVG_FOREIGN_OBJECT)
1006 #define FOR_EACH_FOREIGN_OBJECT_TAG(macro) \
1007 macro(foreignObject, FOREIGNOBJECT)
1009 #define FOR_EACH_FOREIGN_OBJECT_TAG(macro)
1013 #define FOR_EACH_USE_TAG(macro) \
1016 #define FOR_EACH_USE_TAG(macro)
1019 #define FOR_EACH_TAG(macro) \
1020 FOR_EACH_ANIMATION_TAG(macro) \
1021 FOR_EACH_FILTERS_TAG(macro) \
1022 FOR_EACH_FONTS_TAG(macro) \
1023 FOR_EACH_FOREIGN_OBJECT_TAG(macro) \
1024 FOR_EACH_USE_TAG(macro) \
1026 macro(altGlyph, ALTGLYPH) \
1027 macro(circle, CIRCLE) \
1028 macro(clipPath, CLIPPATH) \
1029 macro(cursor, CURSOR) \
1032 macro(ellipse, ELLIPSE) \
1034 macro(glyph, GLYPH) \
1035 macro(image, IMAGE) \
1036 macro(linearGradient, LINEARGRADIENT) \
1038 macro(marker, MARKER) \
1040 macro(metadata, METADATA) \
1042 macro(pattern, PATTERN) \
1043 macro(polyline, POLYLINE) \
1044 macro(polygon, POLYGON) \
1045 macro(radialGradient, RADIALGRADIENT) \
1047 macro(script, SCRIPT) \
1049 macro(style, STYLE) \
1051 macro(switch, SWITCH) \
1052 macro(symbol, SYMBOL) \
1054 macro(textPath, TEXTPATH) \
1055 macro(title, TITLE) \
1057 macro(tspan, TSPAN) \
1061 V8ClassIndex::V8WrapperType V8DOMWrapper::svgElementType(SVGElement* element)
1063 typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap;
1064 DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ());
1065 if (wrapperTypeMap.isEmpty()) {
1066 #define ADD_TO_HASH_MAP(tag, name) \
1067 wrapperTypeMap.set(#tag, V8ClassIndex::SVG##name##ELEMENT);
1068 FOR_EACH_TAG(ADD_TO_HASH_MAP)
1069 #undef ADD_TO_HASH_MAP
1072 V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl());
1074 return V8ClassIndex::SVGELEMENT;
1079 #endif // ENABLE(SVG)
1081 v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event)
1086 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event);
1087 if (!wrapper.IsEmpty())
1090 V8ClassIndex::V8WrapperType type = V8ClassIndex::EVENT;
1092 if (event->isUIEvent()) {
1093 if (event->isKeyboardEvent())
1094 type = V8ClassIndex::KEYBOARDEVENT;
1095 else if (event->isTextEvent())
1096 type = V8ClassIndex::TEXTEVENT;
1097 else if (event->isMouseEvent())
1098 type = V8ClassIndex::MOUSEEVENT;
1099 else if (event->isWheelEvent())
1100 type = V8ClassIndex::WHEELEVENT;
1102 else if (event->isSVGZoomEvent())
1103 type = V8ClassIndex::SVGZOOMEVENT;
1106 type = V8ClassIndex::UIEVENT;
1107 } else if (event->isMutationEvent())
1108 type = V8ClassIndex::MUTATIONEVENT;
1109 else if (event->isOverflowEvent())
1110 type = V8ClassIndex::OVERFLOWEVENT;
1111 else if (event->isMessageEvent())
1112 type = V8ClassIndex::MESSAGEEVENT;
1113 else if (event->isProgressEvent()) {
1114 if (event->isXMLHttpRequestProgressEvent())
1115 type = V8ClassIndex::XMLHTTPREQUESTPROGRESSEVENT;
1117 type = V8ClassIndex::PROGRESSEVENT;
1118 } else if (event->isWebKitAnimationEvent())
1119 type = V8ClassIndex::WEBKITANIMATIONEVENT;
1120 else if (event->isWebKitTransitionEvent())
1121 type = V8ClassIndex::WEBKITTRANSITIONEVENT;
1123 else if (event->isErrorEvent())
1124 type = V8ClassIndex::ERROREVENT;
1128 v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::EVENT, event);
1129 if (result.IsEmpty()) {
1130 // Instantiation failed. Avoid updating the DOM object map and
1131 // return null which is already handled by callers of this function
1132 // in case the event is NULL.
1136 event->ref(); // fast ref
1137 setJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result));
1142 static const V8ClassIndex::V8WrapperType mapping[] = {
1143 V8ClassIndex::INVALID_CLASS_INDEX, // NONE
1144 V8ClassIndex::INVALID_CLASS_INDEX, // ELEMENT_NODE needs special treatment
1145 V8ClassIndex::ATTR, // ATTRIBUTE_NODE
1146 V8ClassIndex::TEXT, // TEXT_NODE
1147 V8ClassIndex::CDATASECTION, // CDATA_SECTION_NODE
1148 V8ClassIndex::ENTITYREFERENCE, // ENTITY_REFERENCE_NODE
1149 V8ClassIndex::ENTITY, // ENTITY_NODE
1150 V8ClassIndex::PROCESSINGINSTRUCTION, // PROCESSING_INSTRUCTION_NODE
1151 V8ClassIndex::COMMENT, // COMMENT_NODE
1152 V8ClassIndex::INVALID_CLASS_INDEX, // DOCUMENT_NODE needs special treatment
1153 V8ClassIndex::DOCUMENTTYPE, // DOCUMENT_TYPE_NODE
1154 V8ClassIndex::DOCUMENTFRAGMENT, // DOCUMENT_FRAGMENT_NODE
1155 V8ClassIndex::NOTATION, // NOTATION_NODE
1156 V8ClassIndex::NODE, // XPATH_NAMESPACE_NODE
1159 v8::Handle<v8::Value> V8DOMWrapper::convertDocumentToV8Object(Document* document)
1161 // Find a proxy for this node.
1163 // Note that if proxy is found, we might initialize the context which can
1164 // instantiate a document wrapper. Therefore, we get the proxy before
1165 // checking if the node already has a wrapper.
1166 V8Proxy* proxy = V8Proxy::retrieve(document->frame());
1168 proxy->initContextIfNeeded();
1170 DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap();
1171 v8::Handle<v8::Object> wrapper = domNodeMap.get(document);
1172 if (wrapper.IsEmpty())
1173 return convertNewNodeToV8Object(document, proxy, domNodeMap);
1178 // Caller checks node is not null.
1179 v8::Handle<v8::Value> V8DOMWrapper::convertNewNodeToV8Object(Node* node, V8Proxy* proxy, DOMWrapperMap<Node>& domNodeMap)
1181 if (!proxy && node->document())
1182 proxy = V8Proxy::retrieve(node->document()->frame());
1184 bool isDocument = false; // document type node has special handling
1185 V8ClassIndex::V8WrapperType type;
1187 Node::NodeType nodeType = node->nodeType();
1188 if (nodeType == Node::ELEMENT_NODE) {
1189 if (node->isHTMLElement())
1190 type = htmlElementType(static_cast<HTMLElement*>(node));
1192 else if (node->isSVGElement())
1193 type = svgElementType(static_cast<SVGElement*>(node));
1196 type = V8ClassIndex::ELEMENT;
1197 } else if (nodeType == Node::DOCUMENT_NODE) {
1199 Document* document = static_cast<Document*>(node);
1200 if (document->isHTMLDocument())
1201 type = V8ClassIndex::HTMLDOCUMENT;
1203 else if (document->isSVGDocument())
1204 type = V8ClassIndex::SVGDOCUMENT;
1207 type = V8ClassIndex::DOCUMENT;
1209 ASSERT(nodeType < sizeof(mapping)/sizeof(mapping[0]));
1210 type = mapping[nodeType];
1211 ASSERT(type != V8ClassIndex::INVALID_CLASS_INDEX);
1214 v8::Handle<v8::Context> context;
1216 context = V8Proxy::context(proxy->frame());
1218 // Enter the node's context and create the wrapper in that context.
1219 if (!context.IsEmpty())
1222 v8::Local<v8::Object> result = instantiateV8Object(proxy, type, V8ClassIndex::NODE, node);
1224 // Exit the node's context if it was entered.
1225 if (!context.IsEmpty())
1228 if (result.IsEmpty()) {
1229 // If instantiation failed it's important not to add the result
1230 // to the DOM node map. Instead we return an empty handle, which
1231 // should already be handled by callers of this function in case
1232 // the node is NULL.
1237 domNodeMap.set(node, v8::Persistent<v8::Object>::New(result));
1241 proxy->updateDocumentWrapper(result);
1243 if (type == V8ClassIndex::HTMLDOCUMENT) {
1244 // Create marker object and insert it in two internal fields.
1245 // This is used to implement temporary shadowing of
1247 ASSERT(result->InternalFieldCount() == V8Custom::kHTMLDocumentInternalFieldCount);
1248 v8::Local<v8::Object> marker = v8::Object::New();
1249 result->SetInternalField(V8Custom::kHTMLDocumentMarkerIndex, marker);
1250 result->SetInternalField(V8Custom::kHTMLDocumentShadowIndex, marker);
1257 // A JS object of type EventTarget is limited to a small number of possible classes.
1258 // Check EventTarget.h for new type conversion methods
1259 v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* target)
1265 SVGElementInstance* instance = target->toSVGElementInstance();
1267 return convertToV8Object(V8ClassIndex::SVGELEMENTINSTANCE, instance);
1271 Worker* worker = target->toWorker();
1273 return convertToV8Object(V8ClassIndex::WORKER, worker);
1276 #if ENABLE(NOTIFICATIONS)
1277 Notification* notification = target->toNotification();
1279 return convertToV8Object(V8ClassIndex::NOTIFICATION, notification);
1282 #if ENABLE(WEB_SOCKETS)
1283 WebSocket* webSocket = target->toWebSocket();
1285 return convertToV8Object(V8ClassIndex::WEBSOCKET, webSocket);
1288 Node* node = target->toNode();
1290 return convertNodeToV8Object(node);
1292 if (DOMWindow* domWindow = target->toDOMWindow())
1293 return convertToV8Object(V8ClassIndex::DOMWINDOW, domWindow);
1295 // XMLHttpRequest is created within its JS counterpart.
1296 XMLHttpRequest* xmlHttpRequest = target->toXMLHttpRequest();
1297 if (xmlHttpRequest) {
1298 v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xmlHttpRequest);
1299 ASSERT(!wrapper.IsEmpty());
1303 // MessagePort is created within its JS counterpart
1304 MessagePort* port = target->toMessagePort();
1306 v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port);
1307 ASSERT(!wrapper.IsEmpty());
1311 XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload();
1313 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload);
1314 ASSERT(!wrapper.IsEmpty());
1318 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
1319 DOMApplicationCache* domAppCache = target->toDOMApplicationCache();
1321 return convertToV8Object(V8ClassIndex::DOMAPPLICATIONCACHE, domAppCache);
1325 return notHandledByInterceptor();
1328 v8::Handle<v8::Value> V8DOMWrapper::convertEventListenerToV8Object(EventListener* listener)
1333 // FIXME: can a user take a lazy event listener and set to other places?
1334 V8AbstractEventListener* v8listener = static_cast<V8AbstractEventListener*>(listener);
1335 return v8listener->getListenerObject();
1338 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, bool findOnly)
1340 V8Proxy* proxy = V8Proxy::retrieve(node->scriptExecutionContext());
1341 // The document might be created using createDocument, which does
1342 // not have a frame, use the active frame.
1344 proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext());
1347 V8EventListenerList* list = proxy->objectListeners();
1348 return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute);
1354 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, bool findOnly)
1356 return getEventListener(element->correspondingElement(), value, isAttribute, findOnly);
1360 v8::Handle<v8::Value> V8DOMWrapper::convertDOMImplementationToV8Object(DOMImplementation* impl)
1362 v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::DOMIMPLEMENTATION, V8ClassIndex::DOMIMPLEMENTATION, impl);
1363 if (result.IsEmpty()) {
1364 // If the instantiation failed, we ignore it and return null instead
1365 // of returning an empty handle.
1371 v8::Handle<v8::Value> V8DOMWrapper::convertStyleSheetToV8Object(StyleSheet* sheet)
1376 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(sheet);
1377 if (!wrapper.IsEmpty())
1380 V8ClassIndex::V8WrapperType type = V8ClassIndex::STYLESHEET;
1381 if (sheet->isCSSStyleSheet())
1382 type = V8ClassIndex::CSSSTYLESHEET;
1384 v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::STYLESHEET, sheet);
1385 if (!result.IsEmpty()) {
1386 // Only update the DOM object map if the result is non-empty.
1388 setJSWrapperForDOMObject(sheet, v8::Persistent<v8::Object>::New(result));
1391 // Add a hidden reference from stylesheet object to its owner node.
1392 Node* ownerNode = sheet->ownerNode();
1394 v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(convertNodeToV8Object(ownerNode));
1395 result->SetInternalField(V8Custom::kStyleSheetOwnerNodeIndex, owner);
1401 v8::Handle<v8::Value> V8DOMWrapper::convertCSSValueToV8Object(CSSValue* value)
1406 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(value);
1407 if (!wrapper.IsEmpty())
1410 V8ClassIndex::V8WrapperType type;
1412 if (value->isWebKitCSSTransformValue())
1413 type = V8ClassIndex::WEBKITCSSTRANSFORMVALUE;
1414 else if (value->isValueList())
1415 type = V8ClassIndex::CSSVALUELIST;
1416 else if (value->isPrimitiveValue())
1417 type = V8ClassIndex::CSSPRIMITIVEVALUE;
1419 else if (value->isSVGPaint())
1420 type = V8ClassIndex::SVGPAINT;
1421 else if (value->isSVGColor())
1422 type = V8ClassIndex::SVGCOLOR;
1425 type = V8ClassIndex::CSSVALUE;
1427 v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSVALUE, value);
1428 if (!result.IsEmpty()) {
1429 // Only update the DOM object map if the result is non-empty.
1431 setJSWrapperForDOMObject(value, v8::Persistent<v8::Object>::New(result));
1437 v8::Handle<v8::Value> V8DOMWrapper::convertCSSRuleToV8Object(CSSRule* rule)
1442 v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(rule);
1443 if (!wrapper.IsEmpty())
1446 V8ClassIndex::V8WrapperType type;
1448 switch (rule->type()) {
1449 case CSSRule::STYLE_RULE:
1450 type = V8ClassIndex::CSSSTYLERULE;
1452 case CSSRule::CHARSET_RULE:
1453 type = V8ClassIndex::CSSCHARSETRULE;
1455 case CSSRule::IMPORT_RULE:
1456 type = V8ClassIndex::CSSIMPORTRULE;
1458 case CSSRule::MEDIA_RULE:
1459 type = V8ClassIndex::CSSMEDIARULE;
1461 case CSSRule::FONT_FACE_RULE:
1462 type = V8ClassIndex::CSSFONTFACERULE;
1464 case CSSRule::PAGE_RULE:
1465 type = V8ClassIndex::CSSPAGERULE;
1467 case CSSRule::VARIABLES_RULE:
1468 type = V8ClassIndex::CSSVARIABLESRULE;
1470 case CSSRule::WEBKIT_KEYFRAME_RULE:
1471 type = V8ClassIndex::WEBKITCSSKEYFRAMERULE;
1473 case CSSRule::WEBKIT_KEYFRAMES_RULE:
1474 type = V8ClassIndex::WEBKITCSSKEYFRAMESRULE;
1476 default: // CSSRule::UNKNOWN_RULE
1477 type = V8ClassIndex::CSSRULE;
1481 v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSRULE, rule);
1482 if (!result.IsEmpty()) {
1483 // Only update the DOM object map if the result is non-empty.
1485 setJSWrapperForDOMObject(rule, v8::Persistent<v8::Object>::New(result));
1490 v8::Handle<v8::Value> V8DOMWrapper::convertWindowToV8Object(DOMWindow* window)
1494 // Initializes environment of a frame, and return the global object
1496 Frame* frame = window->frame();
1498 return v8::Handle<v8::Object>();
1500 // Special case: Because of evaluateInNewContext() one DOMWindow can have
1501 // multiple contexts and multiple global objects associated with it. When
1502 // code running in one of those contexts accesses the window object, we
1503 // want to return the global object associated with that context, not
1504 // necessarily the first global object associated with that DOMWindow.
1505 v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent();
1506 v8::Handle<v8::Object> currentGlobal = currentContext->Global();
1507 v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, currentGlobal);
1508 if (!windowWrapper.IsEmpty()) {
1509 if (convertDOMWrapperToNative<DOMWindow>(windowWrapper) == window)
1510 return currentGlobal;
1513 // Otherwise, return the global object associated with this frame.
1514 v8::Handle<v8::Context> context = V8Proxy::context(frame);
1515 if (context.IsEmpty())
1516 return v8::Handle<v8::Object>();
1518 v8::Handle<v8::Object> global = context->Global();
1519 ASSERT(!global.IsEmpty());
1523 } // namespace WebCore