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