[V8] FileList cannot be accessed via index in Chromium.
[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 "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"
45 #include "V8DOMMap.h"
46 #include "V8DOMWindow.h"
47 #include "V8EventListenerList.h"
48 #include "V8Index.h"
49 #include "V8IsolatedWorld.h"
50 #include "V8ObjectEventListener.h"
51 #include "V8Proxy.h"
52 #include "WorkerContextExecutionProxy.h"
53
54 #include <algorithm>
55 #include <utility>
56 #include <v8.h>
57 #include <v8-debug.h>
58 #include <wtf/Assertions.h>
59 #include <wtf/OwnArrayPtr.h>
60 #include <wtf/StdLibExtras.h>
61 #include <wtf/UnusedParam.h>
62
63 namespace WebCore {
64
65 typedef HashMap<Node*, v8::Object*> DOMNodeMap;
66 typedef HashMap<void*, v8::Object*> DOMObjectMap;
67
68 // Get the string 'toString'.
69 static v8::Persistent<v8::String> GetToStringName()
70 {
71     DEFINE_STATIC_LOCAL(v8::Persistent<v8::String>, value, ());
72     if (value.IsEmpty())
73         value = v8::Persistent<v8::String>::New(v8::String::New("toString"));
74     return value;
75 }
76
77 static v8::Handle<v8::Value> ConstructorToString(const v8::Arguments& args)
78 {
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);
91 }
92
93 #if ENABLE(SVG)
94 v8::Handle<v8::Value> V8DOMWrapper::convertSVGElementInstanceToV8Object(SVGElementInstance* instance)
95 {
96     if (!instance)
97         return v8::Null();
98
99     v8::Handle<v8::Object> existingInstance = getDOMSVGElementInstanceMap().get(instance);
100     if (!existingInstance.IsEmpty())
101         return existingInstance;
102
103     instance->ref();
104
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));
110     }
111     return result;
112 }
113
114 v8::Handle<v8::Value> V8DOMWrapper::convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType type, void* object)
115 {
116     if (!object)
117         return v8::Null();
118
119     v8::Persistent<v8::Object> result = getDOMSVGObjectWithContextMap().get(object);
120     if (!result.IsEmpty())
121         return result;
122
123     // Special case: SVGPathSegs need to be downcast to their real type
124     if (type == V8ClassIndex::SVGPATHSEG)
125         type = V8Custom::DowncastSVGPathSeg(object);
126
127     v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, object);
128     if (!v8Object.IsEmpty()) {
129         result = v8::Persistent<v8::Object>::New(v8Object);
130         switch (type) {
131 #define MAKE_CASE(TYPE, NAME)     \
132         case V8ClassIndex::TYPE: static_cast<NAME*>(object)->ref(); break;
133         SVG_OBJECT_TYPES(MAKE_CASE)
134 #undef 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)
139 #undef MAKE_CASE
140         default:
141             ASSERT_NOT_REACHED();
142         }
143         getDOMSVGObjectWithContextMap().set(object, result);
144     }
145
146     return result;
147 }
148
149 #endif
150
151 bool V8DOMWrapper::domObjectHasJSWrapper(void* object)
152 {
153     return getDOMObjectMap().contains(object) || getActiveDOMObjectMap().contains(object);
154 }
155
156 // The caller must have increased obj's ref count.
157 void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper)
158 {
159     ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper));
160 #ifndef NDEBUG
161     V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper);
162     switch (type) {
163 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
164         ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
165         ASSERT_NOT_REACHED();
166 #undef MAKE_CASE
167     default:
168         break;
169     }
170 #endif
171     getDOMObjectMap().set(object, wrapper);
172 }
173
174 // The caller must have increased obj's ref count.
175 void V8DOMWrapper::setJSWrapperForActiveDOMObject(void* object, v8::Persistent<v8::Object> wrapper)
176 {
177     ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper));
178 #ifndef NDEBUG
179     V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper);
180     switch (type) {
181 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break;
182         ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
183     default: 
184         ASSERT_NOT_REACHED();
185 #undef MAKE_CASE
186     }
187 #endif
188     getActiveDOMObjectMap().set(object, wrapper);
189 }
190
191 // The caller must have increased node's ref count.
192 void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper)
193 {
194     ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper));
195     getDOMNodeMap().set(node, wrapper);
196 }
197
198 v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8WrapperType type)
199 {
200     v8::Persistent<v8::FunctionTemplate>* cacheCell = V8ClassIndex::GetCache(type);
201     if (!cacheCell->IsEmpty())
202         return *cacheCell;
203
204     // Not in the cache.
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);
217     switch (type) {
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);
224         break;
225     case V8ClassIndex::CSSRULELIST:
226         setCollectionIndexedGetter<CSSRuleList, CSSRule>(descriptor,  V8ClassIndex::CSSRULE);
227         break;
228     case V8ClassIndex::CSSVALUELIST:
229         setCollectionIndexedGetter<CSSValueList, CSSValue>(descriptor, V8ClassIndex::CSSVALUE);
230         break;
231     case V8ClassIndex::CSSVARIABLESDECLARATION:
232         setCollectionStringOrNullIndexedGetter<CSSVariablesDeclaration>(descriptor);
233         break;
234     case V8ClassIndex::WEBKITCSSTRANSFORMVALUE:
235         setCollectionIndexedGetter<WebKitCSSTransformValue, CSSValue>(descriptor, V8ClassIndex::CSSVALUE);
236         break;
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);
243         break;
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));
248         break;
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));
253         break;
254     case V8ClassIndex::HTMLDOCUMENT: {
255         descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLDocument), 0, 0, USE_NAMED_PROPERTY_DELETER(HTMLDocument));
256
257         // We add an extra internal field to all Document wrappers for
258         // storing a per document DOMImplementation wrapper.
259         //
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);
269         break;
270     }
271 #if ENABLE(SVG)
272     case V8ClassIndex::SVGDOCUMENT:  // fall through
273 #endif
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);
280         break;
281     }
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
287         // handling code.
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));
291         break;
292     case V8ClassIndex::HTMLFRAMESETELEMENT:
293         descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFrameSetElement));
294         break;
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));
298         break;
299     case V8ClassIndex::STYLESHEET:  // fall through
300     case V8ClassIndex::CSSSTYLESHEET: {
301         // We add an extra internal field to hold a reference to
302         // the owner node.
303         v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
304         ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount);
305         instanceTemplate->SetInternalFieldCount(V8Custom::kStyleSheetInternalFieldCount);
306         break;
307     }
308     case V8ClassIndex::MEDIALIST:
309         setCollectionStringOrNullIndexedGetter<MediaList>(descriptor);
310         break;
311     case V8ClassIndex::MIMETYPEARRAY:
312         setCollectionIndexedAndNamedGetters<MimeTypeArray, MimeType>(descriptor, V8ClassIndex::MIMETYPE);
313         break;
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));
317         break;
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));
322         break;
323 #endif
324     case V8ClassIndex::NODELIST:
325         setCollectionIndexedGetter<NodeList, Node>(descriptor, V8ClassIndex::NODE);
326         descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NodeList));
327         break;
328     case V8ClassIndex::PLUGIN:
329         setCollectionIndexedAndNamedGetters<Plugin, MimeType>(descriptor, V8ClassIndex::MIMETYPE);
330         break;
331     case V8ClassIndex::PLUGINARRAY:
332         setCollectionIndexedAndNamedGetters<PluginArray, Plugin>(descriptor, V8ClassIndex::PLUGIN);
333         break;
334     case V8ClassIndex::STYLESHEETLIST:
335         descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(StyleSheetList));
336         setCollectionIndexedGetter<StyleSheetList, StyleSheet>(descriptor, V8ClassIndex::STYLESHEET);
337         break;
338     case V8ClassIndex::DOMWINDOW: {
339         v8::Local<v8::Signature> defaultSignature = v8::Signature::New(descriptor);
340
341         descriptor->PrototypeTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DOMWindow));
342         descriptor->PrototypeTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DOMWindow));
343
344         descriptor->SetHiddenPrototype(true);
345
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);
350
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);
355         break;
356     }
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
360         // be overwritten.
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));
365         break;
366     }
367     case V8ClassIndex::HISTORY:
368         break;
369
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);
377         break;
378     }
379
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);
384         break;
385     }
386
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);
392         break;
393     }
394 #endif // NOTIFICATIONS
395
396 #if ENABLE(WORKERS)
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);
401         break;
402     }
403
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);
409         break;
410     }
411
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));
417         break;
418     }
419
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);
425         break;
426     }
427
428 #endif // WORKERS
429
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);
435         break;
436     }
437 #endif
438
439     // The following objects are created from JavaScript.
440     case V8ClassIndex::DOMPARSER:
441         descriptor->SetCallHandler(USE_CALLBACK(DOMParserConstructor));
442         break;
443 #if ENABLE(VIDEO)
444     case V8ClassIndex::HTMLAUDIOELEMENT:
445         descriptor->SetCallHandler(USE_CALLBACK(HTMLAudioElementConstructor));
446         break;
447 #endif
448     case V8ClassIndex::HTMLIMAGEELEMENT:
449         descriptor->SetCallHandler(USE_CALLBACK(HTMLImageElementConstructor));
450         break;
451     case V8ClassIndex::HTMLOPTIONELEMENT:
452         descriptor->SetCallHandler(USE_CALLBACK(HTMLOptionElementConstructor));
453         break;
454     case V8ClassIndex::WEBKITCSSMATRIX:
455         descriptor->SetCallHandler(USE_CALLBACK(WebKitCSSMatrixConstructor));
456         break;
457     case V8ClassIndex::WEBKITPOINT:
458         descriptor->SetCallHandler(USE_CALLBACK(WebKitPointConstructor));
459         break;
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));
466         break;
467     }
468 #endif
469     case V8ClassIndex::XMLSERIALIZER:
470         descriptor->SetCallHandler(USE_CALLBACK(XMLSerializerConstructor));
471         break;
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));
477         break;
478     }
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);
483         break;
484     }
485     case V8ClassIndex::XPATHEVALUATOR:
486         descriptor->SetCallHandler(USE_CALLBACK(XPathEvaluatorConstructor));
487         break;
488     case V8ClassIndex::XSLTPROCESSOR:
489         descriptor->SetCallHandler(USE_CALLBACK(XSLTProcessorConstructor));
490         break;
491     case V8ClassIndex::CLIENTRECTLIST:
492         descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(ClientRectList));
493         break;
494     case V8ClassIndex::FILELIST:
495         descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(FileList));
496         break;
497 #if ENABLE(DATAGRID)
498     case V8ClassIndex::DATAGRIDCOLUMNLIST:
499         descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DataGridColumnList));
500         descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DataGridColumnList));
501         break;
502 #endif
503     default:
504         break;
505     }
506
507     *cacheCell = descriptor;
508     return descriptor;
509 }
510
511 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> objectPrototype)
512 {
513     // A DOM constructor is a function instance created from a DOM constructor
514     // template. There is one instance per context. A DOM constructor is
515     // different from a normal function in two ways:
516     //   1) it cannot be called as constructor (aka, used to create a DOM object)
517     //   2) its __proto__ points to Object.prototype rather than
518     //      Function.prototype.
519     // The reason for 2) is that, in Safari, a DOM constructor is a normal JS
520     // object, but not a function. Hotmail relies on the fact that, in Safari,
521     // HTMLElement.__proto__ == Object.prototype.
522     v8::Handle<v8::FunctionTemplate> functionTemplate = getTemplate(type);
523     // Getting the function might fail if we're running out of
524     // stack or memory.
525     v8::TryCatch tryCatch;
526     v8::Local<v8::Function> value = functionTemplate->GetFunction();
527     if (value.IsEmpty())
528         return v8::Local<v8::Function>();
529     // Hotmail fix, see comments above.
530     if (!objectPrototype.IsEmpty())
531         value->Set(v8::String::New("__proto__"), objectPrototype);
532     return value;
533 }
534
535 v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Context> context)
536 {
537     // Enter the scope for this context to get the correct constructor.
538     v8::Context::Scope scope(context);
539
540     return getConstructor(type, V8Proxy::getHiddenObjectPrototype(context));
541 }
542
543 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window)
544 {
545     Frame* frame = window->frame();
546     if (!frame)
547         return v8::Local<v8::Function>();
548
549     v8::Handle<v8::Context> context = V8Proxy::context(frame);
550     if (context.IsEmpty())
551         return v8::Local<v8::Function>();
552
553     return getConstructorForContext(type, context);
554 }
555
556 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, WorkerContext*)
557 {
558     WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
559     if (!proxy)
560         return v8::Local<v8::Function>();
561
562     v8::Handle<v8::Context> context = proxy->context();
563     if (context.IsEmpty())
564         return v8::Local<v8::Function>();
565
566     return getConstructorForContext(type, context);
567 }
568
569 v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl)
570 {
571     ASSERT(type != V8ClassIndex::EVENTLISTENER);
572     ASSERT(type != V8ClassIndex::EVENTTARGET);
573     ASSERT(type != V8ClassIndex::EVENT);
574
575     // These objects can be constructed under WorkerContextExecutionProxy.  They need special
576     // handling, since if we proceed below V8Proxy::retrieve() will get called and will crash.
577     // TODO(ukai): websocket?
578     if ((type == V8ClassIndex::DOMCOREEXCEPTION
579          || type == V8ClassIndex::RANGEEXCEPTION
580          || type == V8ClassIndex::EVENTEXCEPTION
581          || type == V8ClassIndex::XMLHTTPREQUESTEXCEPTION
582          || type == V8ClassIndex::MESSAGEPORT)
583         && WorkerContextExecutionProxy::retrieve()) {
584         return WorkerContextExecutionProxy::convertToV8Object(type, impl);
585     }
586
587     bool isActiveDomObject = false;
588     switch (type) {
589 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
590         DOM_NODE_TYPES(MAKE_CASE)
591 #if ENABLE(SVG)
592         SVG_NODE_TYPES(MAKE_CASE)
593 #endif
594         return convertNodeToV8Object(static_cast<Node*>(impl));
595     case V8ClassIndex::CSSVALUE:
596         return convertCSSValueToV8Object(static_cast<CSSValue*>(impl));
597     case V8ClassIndex::CSSRULE:
598         return convertCSSRuleToV8Object(static_cast<CSSRule*>(impl));
599     case V8ClassIndex::STYLESHEET:
600         return convertStyleSheetToV8Object(static_cast<StyleSheet*>(impl));
601     case V8ClassIndex::DOMWINDOW:
602         return convertWindowToV8Object(static_cast<DOMWindow*>(impl));
603 #if ENABLE(SVG)
604         SVG_NONNODE_TYPES(MAKE_CASE)
605         if (type == V8ClassIndex::SVGELEMENTINSTANCE)
606             return convertSVGElementInstanceToV8Object(static_cast<SVGElementInstance*>(impl));
607         return convertSVGObjectWithContextToV8Object(type, impl);
608 #endif
609
610         ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
611         isActiveDomObject = true;
612         break;
613     default:
614         break;
615   }
616
617 #undef MAKE_CASE
618
619     if (!impl)
620         return v8::Null();
621
622     // Non DOM node
623     v8::Persistent<v8::Object> result = isActiveDomObject ? getActiveDOMObjectMap().get(impl) : getDOMObjectMap().get(impl);
624     if (result.IsEmpty()) {
625         v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, impl);
626         if (!v8Object.IsEmpty()) {
627             // Go through big switch statement, it has some duplications
628             // that were handled by code above (such as CSSVALUE, CSSRULE, etc).
629             switch (type) {
630 #define MAKE_CASE(TYPE, NAME) \
631             case V8ClassIndex::TYPE: static_cast<NAME*>(impl)->ref(); break;
632                 DOM_OBJECT_TYPES(MAKE_CASE)
633 #undef MAKE_CASE
634             default:
635                 ASSERT_NOT_REACHED();
636             }
637             result = v8::Persistent<v8::Object>::New(v8Object);
638             if (isActiveDomObject)
639                 setJSWrapperForActiveDOMObject(impl, result);
640             else
641                 setJSWrapperForDOMObject(impl, result);
642
643             if (type == V8ClassIndex::CANVASPIXELARRAY) {
644                 CanvasPixelArray* pixels = reinterpret_cast<CanvasPixelArray*>(impl);
645                 result->SetIndexedPropertiesToPixelData(pixels->data()->data(), pixels->length());
646             }
647
648             // Special case for non-node objects associated with a
649             // DOMWindow. Both Safari and FF let the JS wrappers for these
650             // objects survive GC. To mimic their behavior, V8 creates
651             // hidden references from the DOMWindow to these wrapper
652             // objects. These references get cleared when the DOMWindow is
653             // reused by a new page.
654             switch (type) {
655             case V8ClassIndex::CONSOLE:
656                 setHiddenWindowReference(static_cast<Console*>(impl)->frame(), V8Custom::kDOMWindowConsoleIndex, result);
657                 break;
658             case V8ClassIndex::HISTORY:
659                 setHiddenWindowReference(static_cast<History*>(impl)->frame(), V8Custom::kDOMWindowHistoryIndex, result);
660                 break;
661             case V8ClassIndex::NAVIGATOR:
662                 setHiddenWindowReference(static_cast<Navigator*>(impl)->frame(), V8Custom::kDOMWindowNavigatorIndex, result);
663                 break;
664             case V8ClassIndex::SCREEN:
665                 setHiddenWindowReference(static_cast<Screen*>(impl)->frame(), V8Custom::kDOMWindowScreenIndex, result);
666                 break;
667             case V8ClassIndex::LOCATION:
668                 setHiddenWindowReference(static_cast<Location*>(impl)->frame(), V8Custom::kDOMWindowLocationIndex, result);
669                 break;
670             case V8ClassIndex::DOMSELECTION:
671                 setHiddenWindowReference(static_cast<DOMSelection*>(impl)->frame(), V8Custom::kDOMWindowDOMSelectionIndex, result);
672                 break;
673             case V8ClassIndex::BARINFO: {
674                 BarInfo* barInfo = static_cast<BarInfo*>(impl);
675                 Frame* frame = barInfo->frame();
676                 switch (barInfo->type()) {
677                 case BarInfo::Locationbar:
678                     setHiddenWindowReference(frame, V8Custom::kDOMWindowLocationbarIndex, result);
679                     break;
680                 case BarInfo::Menubar:
681                     setHiddenWindowReference(frame, V8Custom::kDOMWindowMenubarIndex, result);
682                     break;
683                 case BarInfo::Personalbar:
684                     setHiddenWindowReference(frame, V8Custom::kDOMWindowPersonalbarIndex, result);
685                     break;
686                 case BarInfo::Scrollbars:
687                     setHiddenWindowReference(frame, V8Custom::kDOMWindowScrollbarsIndex, result);
688                     break;
689                 case BarInfo::Statusbar:
690                     setHiddenWindowReference(frame, V8Custom::kDOMWindowStatusbarIndex, result);
691                     break;
692                 case BarInfo::Toolbar:
693                     setHiddenWindowReference(frame, V8Custom::kDOMWindowToolbarIndex, result);
694                     break;
695                 }
696                 break;
697             }
698             default:
699                 break;
700             }
701         }
702     }
703     return result;
704 }
705
706 void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalIndex, v8::Handle<v8::Object> jsObject)
707 {
708     // Get DOMWindow
709     if (!frame)
710         return; // Object might be detached from window
711     v8::Handle<v8::Context> context = V8Proxy::context(frame);
712     if (context.IsEmpty())
713         return;
714
715     ASSERT(internalIndex < V8Custom::kDOMWindowInternalFieldCount);
716
717     v8::Handle<v8::Object> global = context->Global();
718     // Look for real DOM wrapper.
719     global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, global);
720     ASSERT(!global.IsEmpty());
721     ASSERT(global->GetInternalField(internalIndex)->IsUndefined());
722     global->SetInternalField(internalIndex, jsObject);
723 }
724
725 V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object)
726 {
727     ASSERT(V8DOMWrapper::maybeDOMWrapper(object));
728     v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex);
729     return V8ClassIndex::FromInt(type->Int32Value());
730 }
731
732 void* V8DOMWrapper::convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object)
733 {
734     return isWrapperOfType(object, type) ? convertDOMWrapperToNative<void>(v8::Handle<v8::Object>::Cast(object)) : 0;
735 }
736
737 PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter)
738 {
739     // A NodeFilter is used when walking through a DOM tree or iterating tree
740     // nodes.
741     // FIXME: we may want to cache NodeFilterCondition and NodeFilter
742     // object, but it is minor.
743     // NodeFilter is passed to NodeIterator that has a ref counted pointer
744     // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition.
745     // In NodeFilterCondition, filter object is persisted in its constructor,
746     // and disposed in its destructor.
747     if (!filter->IsFunction())
748         return 0;
749
750     NodeFilterCondition* condition = new V8NodeFilterCondition(filter);
751     return NodeFilter::create(condition);
752 }
753
754 v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl)
755 {
756     // Make a special case for document.all
757     if (descriptorType == V8ClassIndex::HTMLCOLLECTION && static_cast<HTMLCollection*>(impl)->type() == DocAll)
758         descriptorType = V8ClassIndex::HTMLALLCOLLECTION;
759
760     if (V8IsolatedWorld::getEntered()) {
761         // This effectively disables the wrapper cache for isolated worlds.
762         proxy = 0;
763         // FIXME: Do we need a wrapper cache for the isolated world?  We should
764         // see if the performance gains are worth while.
765     } else if (!proxy)
766         proxy = V8Proxy::retrieve();
767
768     v8::Local<v8::Object> instance;
769     if (proxy)
770         instance = proxy->createWrapperFromCache(descriptorType);
771     else {
772         v8::Local<v8::Function> function = getTemplate(descriptorType)->GetFunction();
773         instance = SafeAllocation::newInstance(function);
774     }
775     if (!instance.IsEmpty()) {
776         // Avoid setting the DOM wrapper for failed allocations.
777         setDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl);
778     }
779     return instance;
780 }
781
782 void V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object> object, int type, void* cptr)
783 {
784     ASSERT(object->InternalFieldCount() >= 2);
785     object->SetPointerInInternalField(V8Custom::kDOMWrapperObjectIndex, cptr);
786     object->SetInternalField(V8Custom::kDOMWrapperTypeIndex, v8::Integer::New(type));
787 }
788
789 #ifndef NDEBUG
790 bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value)
791 {
792     if (value.IsEmpty() || !value->IsObject())
793         return false;
794
795     v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
796     if (!object->InternalFieldCount())
797         return false;
798
799     ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount);
800
801     v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex);
802     ASSERT(type->IsInt32());
803     ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END);
804
805     v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex);
806     ASSERT(wrapper->IsNumber() || wrapper->IsExternal());
807
808     return true;
809 }
810 #endif
811
812 bool V8DOMWrapper::isDOMEventWrapper(v8::Handle<v8::Value> value)
813 {
814     // All kinds of events use EVENT as dom type in JS wrappers.
815     // See EventToV8Object
816     return isWrapperOfType(value, V8ClassIndex::EVENT);
817 }
818
819 bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType)
820 {
821     if (value.IsEmpty() || !value->IsObject())
822         return false;
823
824     v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
825     if (!object->InternalFieldCount())
826         return false;
827
828     ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount);
829
830     v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex);
831     ASSERT(wrapper->IsNumber() || wrapper->IsExternal());
832
833     v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex);
834     ASSERT(type->IsInt32());
835     ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END);
836
837     return V8ClassIndex::FromInt(type->Int32Value()) == classType;
838 }
839
840 #if ENABLE(VIDEO)
841 #define FOR_EACH_VIDEO_TAG(macro)                  \
842     macro(audio, AUDIO)                            \
843     macro(source, SOURCE)                          \
844     macro(video, VIDEO)
845 #else
846 #define FOR_EACH_VIDEO_TAG(macro)
847 #endif
848
849 #if ENABLE(DATAGRID)
850 #define FOR_EACH_DATAGRID_TAG(macro)               \
851     macro(datagrid, DATAGRID)                        \
852     macro(dcell, DATAGRIDCELL)                       \
853     macro(dcol, DATAGRIDCOL)                         \
854     macro(drow, DATAGRIDROW)
855 #else
856 #define FOR_EACH_DATAGRID_TAG(macro)
857 #endif
858
859 #define FOR_EACH_TAG(macro)                        \
860     FOR_EACH_DATAGRID_TAG(macro)                   \
861     macro(a, ANCHOR)                               \
862     macro(applet, APPLET)                          \
863     macro(area, AREA)                              \
864     macro(base, BASE)                              \
865     macro(basefont, BASEFONT)                      \
866     macro(blockquote, BLOCKQUOTE)                  \
867     macro(body, BODY)                              \
868     macro(br, BR)                                  \
869     macro(button, BUTTON)                          \
870     macro(caption, TABLECAPTION)                   \
871     macro(col, TABLECOL)                           \
872     macro(colgroup, TABLECOL)                      \
873     macro(del, MOD)                                \
874     macro(canvas, CANVAS)                          \
875     macro(dir, DIRECTORY)                          \
876     macro(div, DIV)                                \
877     macro(dl, DLIST)                               \
878     macro(embed, EMBED)                            \
879     macro(fieldset, FIELDSET)                      \
880     macro(font, FONT)                              \
881     macro(form, FORM)                              \
882     macro(frame, FRAME)                            \
883     macro(frameset, FRAMESET)                      \
884     macro(h1, HEADING)                             \
885     macro(h2, HEADING)                             \
886     macro(h3, HEADING)                             \
887     macro(h4, HEADING)                             \
888     macro(h5, HEADING)                             \
889     macro(h6, HEADING)                             \
890     macro(head, HEAD)                              \
891     macro(hr, HR)                                  \
892     macro(html, HTML)                              \
893     macro(img, IMAGE)                              \
894     macro(iframe, IFRAME)                          \
895     macro(image, IMAGE)                            \
896     macro(input, INPUT)                            \
897     macro(ins, MOD)                                \
898     macro(isindex, ISINDEX)                        \
899     macro(keygen, SELECT)                          \
900     macro(label, LABEL)                            \
901     macro(legend, LEGEND)                          \
902     macro(li, LI)                                  \
903     macro(link, LINK)                              \
904     macro(listing, PRE)                            \
905     macro(map, MAP)                                \
906     macro(marquee, MARQUEE)                        \
907     macro(menu, MENU)                              \
908     macro(meta, META)                              \
909     macro(object, OBJECT)                          \
910     macro(ol, OLIST)                               \
911     macro(optgroup, OPTGROUP)                      \
912     macro(option, OPTION)                          \
913     macro(p, PARAGRAPH)                            \
914     macro(param, PARAM)                            \
915     macro(pre, PRE)                                \
916     macro(q, QUOTE)                                \
917     macro(script, SCRIPT)                          \
918     macro(select, SELECT)                          \
919     macro(style, STYLE)                            \
920     macro(table, TABLE)                            \
921     macro(thead, TABLESECTION)                     \
922     macro(tbody, TABLESECTION)                     \
923     macro(tfoot, TABLESECTION)                     \
924     macro(td, TABLECELL)                           \
925     macro(th, TABLECELL)                           \
926     macro(tr, TABLEROW)                            \
927     macro(textarea, TEXTAREA)                      \
928     macro(title, TITLE)                            \
929     macro(ul, ULIST)                               \
930     macro(xmp, PRE)
931
932 V8ClassIndex::V8WrapperType V8DOMWrapper::htmlElementType(HTMLElement* element)
933 {
934     typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap;
935     DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ());
936     if (wrapperTypeMap.isEmpty()) {
937 #define ADD_TO_HASH_MAP(tag, name) \
938         wrapperTypeMap.set(#tag, V8ClassIndex::HTML##name##ELEMENT);
939         FOR_EACH_TAG(ADD_TO_HASH_MAP)
940 #if ENABLE(VIDEO)
941         if (MediaPlayer::isAvailable()) {
942             FOR_EACH_VIDEO_TAG(ADD_TO_HASH_MAP)
943         }
944 #endif
945 #undef ADD_TO_HASH_MAP
946     }
947
948     V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl());
949     if (!type)
950         return V8ClassIndex::HTMLELEMENT;
951     return type;
952 }
953 #undef FOR_EACH_TAG
954
955 #if ENABLE(SVG)
956
957 #if ENABLE(SVG_ANIMATION)
958 #define FOR_EACH_ANIMATION_TAG(macro) \
959     macro(animateColor, ANIMATECOLOR) \
960     macro(animate, ANIMATE) \
961     macro(animateTransform, ANIMATETRANSFORM) \
962     macro(set, SET)
963 #else
964 #define FOR_EACH_ANIMATION_TAG(macro)
965 #endif
966
967 #if ENABLE(SVG_FILTERS)
968 #define FOR_EACH_FILTERS_TAG(macro) \
969     macro(feBlend, FEBLEND) \
970     macro(feColorMatrix, FECOLORMATRIX) \
971     macro(feComponentTransfer, FECOMPONENTTRANSFER) \
972     macro(feComposite, FECOMPOSITE) \
973     macro(feDiffuseLighting, FEDIFFUSELIGHTING) \
974     macro(feDisplacementMap, FEDISPLACEMENTMAP) \
975     macro(feDistantLight, FEDISTANTLIGHT) \
976     macro(feFlood, FEFLOOD) \
977     macro(feFuncA, FEFUNCA) \
978     macro(feFuncB, FEFUNCB) \
979     macro(feFuncG, FEFUNCG) \
980     macro(feFuncR, FEFUNCR) \
981     macro(feGaussianBlur, FEGAUSSIANBLUR) \
982     macro(feImage, FEIMAGE) \
983     macro(feMerge, FEMERGE) \
984     macro(feMergeNode, FEMERGENODE) \
985     macro(feOffset, FEOFFSET) \
986     macro(fePointLight, FEPOINTLIGHT) \
987     macro(feSpecularLighting, FESPECULARLIGHTING) \
988     macro(feSpotLight, FESPOTLIGHT) \
989     macro(feTile, FETILE) \
990     macro(feTurbulence, FETURBULENCE) \
991     macro(filter, FILTER)
992 #else
993 #define FOR_EACH_FILTERS_TAG(macro)
994 #endif
995
996 #if ENABLE(SVG_FONTS)
997 #define FOR_EACH_FONTS_TAG(macro) \
998     macro(definition-src, DEFINITIONSRC) \
999     macro(font-face, FONTFACE) \
1000     macro(font-face-format, FONTFACEFORMAT) \
1001     macro(font-face-name, FONTFACENAME) \
1002     macro(font-face-src, FONTFACESRC) \
1003     macro(font-face-uri, FONTFACEURI)
1004 #else
1005 #define FOR_EACH_FONTS_TAG(marco)
1006 #endif
1007
1008 #if ENABLE(SVG_FOREIGN_OBJECT)
1009 #define FOR_EACH_FOREIGN_OBJECT_TAG(macro) \
1010     macro(foreignObject, FOREIGNOBJECT)
1011 #else
1012 #define FOR_EACH_FOREIGN_OBJECT_TAG(macro)
1013 #endif
1014
1015 #if ENABLE(SVG_USE)
1016 #define FOR_EACH_USE_TAG(macro) \
1017     macro(use, USE)
1018 #else
1019 #define FOR_EACH_USE_TAG(macro)
1020 #endif
1021
1022 #define FOR_EACH_TAG(macro) \
1023     FOR_EACH_ANIMATION_TAG(macro) \
1024     FOR_EACH_FILTERS_TAG(macro) \
1025     FOR_EACH_FONTS_TAG(macro) \
1026     FOR_EACH_FOREIGN_OBJECT_TAG(macro) \
1027     FOR_EACH_USE_TAG(macro) \
1028     macro(a, A) \
1029     macro(altGlyph, ALTGLYPH) \
1030     macro(circle, CIRCLE) \
1031     macro(clipPath, CLIPPATH) \
1032     macro(cursor, CURSOR) \
1033     macro(defs, DEFS) \
1034     macro(desc, DESC) \
1035     macro(ellipse, ELLIPSE) \
1036     macro(g, G) \
1037     macro(glyph, GLYPH) \
1038     macro(image, IMAGE) \
1039     macro(linearGradient, LINEARGRADIENT) \
1040     macro(line, LINE) \
1041     macro(marker, MARKER) \
1042     macro(mask, MASK) \
1043     macro(metadata, METADATA) \
1044     macro(path, PATH) \
1045     macro(pattern, PATTERN) \
1046     macro(polyline, POLYLINE) \
1047     macro(polygon, POLYGON) \
1048     macro(radialGradient, RADIALGRADIENT) \
1049     macro(rect, RECT) \
1050     macro(script, SCRIPT) \
1051     macro(stop, STOP) \
1052     macro(style, STYLE) \
1053     macro(svg, SVG) \
1054     macro(switch, SWITCH) \
1055     macro(symbol, SYMBOL) \
1056     macro(text, TEXT) \
1057     macro(textPath, TEXTPATH) \
1058     macro(title, TITLE) \
1059     macro(tref, TREF) \
1060     macro(tspan, TSPAN) \
1061     macro(view, VIEW) \
1062     // end of macro
1063
1064 V8ClassIndex::V8WrapperType V8DOMWrapper::svgElementType(SVGElement* element)
1065 {
1066     typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap;
1067     DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ());
1068     if (wrapperTypeMap.isEmpty()) {
1069 #define ADD_TO_HASH_MAP(tag, name) \
1070         wrapperTypeMap.set(#tag, V8ClassIndex::SVG##name##ELEMENT);
1071         FOR_EACH_TAG(ADD_TO_HASH_MAP)
1072 #undef ADD_TO_HASH_MAP
1073     }
1074
1075     V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl());
1076     if (!type)
1077         return V8ClassIndex::SVGELEMENT;
1078     return type;
1079 }
1080 #undef FOR_EACH_TAG
1081
1082 #endif // ENABLE(SVG)
1083
1084 v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event)
1085 {
1086     if (!event)
1087         return v8::Null();
1088
1089     v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event);
1090     if (!wrapper.IsEmpty())
1091         return wrapper;
1092
1093     V8ClassIndex::V8WrapperType type = V8ClassIndex::EVENT;
1094
1095     if (event->isUIEvent()) {
1096         if (event->isKeyboardEvent())
1097             type = V8ClassIndex::KEYBOARDEVENT;
1098         else if (event->isTextEvent())
1099             type = V8ClassIndex::TEXTEVENT;
1100         else if (event->isMouseEvent())
1101             type = V8ClassIndex::MOUSEEVENT;
1102         else if (event->isWheelEvent())
1103             type = V8ClassIndex::WHEELEVENT;
1104 #if ENABLE(SVG)
1105         else if (event->isSVGZoomEvent())
1106             type = V8ClassIndex::SVGZOOMEVENT;
1107 #endif
1108         else
1109             type = V8ClassIndex::UIEVENT;
1110     } else if (event->isMutationEvent())
1111         type = V8ClassIndex::MUTATIONEVENT;
1112     else if (event->isOverflowEvent())
1113         type = V8ClassIndex::OVERFLOWEVENT;
1114     else if (event->isMessageEvent())
1115         type = V8ClassIndex::MESSAGEEVENT;
1116     else if (event->isProgressEvent()) {
1117         if (event->isXMLHttpRequestProgressEvent())
1118             type = V8ClassIndex::XMLHTTPREQUESTPROGRESSEVENT;
1119         else
1120             type = V8ClassIndex::PROGRESSEVENT;
1121     } else if (event->isWebKitAnimationEvent())
1122         type = V8ClassIndex::WEBKITANIMATIONEVENT;
1123     else if (event->isWebKitTransitionEvent())
1124         type = V8ClassIndex::WEBKITTRANSITIONEVENT;
1125 #if ENABLE(WORKERS)
1126     else if (event->isErrorEvent())
1127         type = V8ClassIndex::ERROREVENT;
1128 #endif
1129
1130
1131     v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::EVENT, event);
1132     if (result.IsEmpty()) {
1133         // Instantiation failed. Avoid updating the DOM object map and
1134         // return null which is already handled by callers of this function
1135         // in case the event is NULL.
1136         return v8::Null();
1137     }
1138
1139     event->ref(); // fast ref
1140     setJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result));
1141
1142     return result;
1143 }
1144
1145 static const V8ClassIndex::V8WrapperType mapping[] = {
1146     V8ClassIndex::INVALID_CLASS_INDEX,    // NONE
1147     V8ClassIndex::INVALID_CLASS_INDEX,    // ELEMENT_NODE needs special treatment
1148     V8ClassIndex::ATTR,                   // ATTRIBUTE_NODE
1149     V8ClassIndex::TEXT,                   // TEXT_NODE
1150     V8ClassIndex::CDATASECTION,           // CDATA_SECTION_NODE
1151     V8ClassIndex::ENTITYREFERENCE,        // ENTITY_REFERENCE_NODE
1152     V8ClassIndex::ENTITY,                 // ENTITY_NODE
1153     V8ClassIndex::PROCESSINGINSTRUCTION,  // PROCESSING_INSTRUCTION_NODE
1154     V8ClassIndex::COMMENT,                // COMMENT_NODE
1155     V8ClassIndex::INVALID_CLASS_INDEX,    // DOCUMENT_NODE needs special treatment
1156     V8ClassIndex::DOCUMENTTYPE,           // DOCUMENT_TYPE_NODE
1157     V8ClassIndex::DOCUMENTFRAGMENT,       // DOCUMENT_FRAGMENT_NODE
1158     V8ClassIndex::NOTATION,               // NOTATION_NODE
1159     V8ClassIndex::NODE,                   // XPATH_NAMESPACE_NODE
1160 };
1161
1162 v8::Handle<v8::Value> V8DOMWrapper::convertDocumentToV8Object(Document* document)
1163 {
1164     // Find a proxy for this node.
1165     //
1166     // Note that if proxy is found, we might initialize the context which can
1167     // instantiate a document wrapper.  Therefore, we get the proxy before
1168     // checking if the node already has a wrapper.
1169     V8Proxy* proxy = V8Proxy::retrieve(document->frame());
1170     if (proxy)
1171         proxy->initContextIfNeeded();
1172
1173     DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap();
1174     v8::Handle<v8::Object> wrapper = domNodeMap.get(document);
1175     if (wrapper.IsEmpty())
1176         return convertNewNodeToV8Object(document, proxy, domNodeMap);
1177
1178     return wrapper;
1179 }
1180
1181 // Caller checks node is not null.
1182 v8::Handle<v8::Value> V8DOMWrapper::convertNewNodeToV8Object(Node* node, V8Proxy* proxy, DOMWrapperMap<Node>& domNodeMap)
1183 {
1184     if (!proxy && node->document())
1185         proxy = V8Proxy::retrieve(node->document()->frame());
1186
1187     bool isDocument = false; // document type node has special handling
1188     V8ClassIndex::V8WrapperType type;
1189
1190     Node::NodeType nodeType = node->nodeType();
1191     if (nodeType == Node::ELEMENT_NODE) {
1192         if (node->isHTMLElement())
1193             type = htmlElementType(static_cast<HTMLElement*>(node));
1194 #if ENABLE(SVG)
1195         else if (node->isSVGElement())
1196             type = svgElementType(static_cast<SVGElement*>(node));
1197 #endif
1198         else
1199             type = V8ClassIndex::ELEMENT;
1200     } else if (nodeType == Node::DOCUMENT_NODE) {
1201         isDocument = true;
1202         Document* document = static_cast<Document*>(node);
1203         if (document->isHTMLDocument())
1204             type = V8ClassIndex::HTMLDOCUMENT;
1205 #if ENABLE(SVG)
1206         else if (document->isSVGDocument())
1207             type = V8ClassIndex::SVGDOCUMENT;
1208 #endif
1209         else
1210             type = V8ClassIndex::DOCUMENT;
1211     } else {
1212         ASSERT(nodeType < sizeof(mapping)/sizeof(mapping[0]));
1213         type = mapping[nodeType];
1214         ASSERT(type != V8ClassIndex::INVALID_CLASS_INDEX);
1215     }
1216
1217     v8::Handle<v8::Context> context;
1218     if (proxy)
1219         context = V8Proxy::context(proxy->frame());
1220
1221     // Enter the node's context and create the wrapper in that context.
1222     if (!context.IsEmpty())
1223         context->Enter();
1224
1225     v8::Local<v8::Object> result = instantiateV8Object(proxy, type, V8ClassIndex::NODE, node);
1226
1227     // Exit the node's context if it was entered.
1228     if (!context.IsEmpty())
1229         context->Exit();
1230
1231     if (result.IsEmpty()) {
1232         // If instantiation failed it's important not to add the result
1233         // to the DOM node map. Instead we return an empty handle, which
1234         // should already be handled by callers of this function in case
1235         // the node is NULL.
1236         return result;
1237     }
1238
1239     node->ref();
1240     domNodeMap.set(node, v8::Persistent<v8::Object>::New(result));
1241
1242     if (isDocument) {
1243         if (proxy)
1244             proxy->updateDocumentWrapper(result);
1245
1246         if (type == V8ClassIndex::HTMLDOCUMENT) {
1247             // Create marker object and insert it in two internal fields.
1248             // This is used to implement temporary shadowing of
1249             // document.all.
1250             ASSERT(result->InternalFieldCount() == V8Custom::kHTMLDocumentInternalFieldCount);
1251             v8::Local<v8::Object> marker = v8::Object::New();
1252             result->SetInternalField(V8Custom::kHTMLDocumentMarkerIndex, marker);
1253             result->SetInternalField(V8Custom::kHTMLDocumentShadowIndex, marker);
1254         }
1255     }
1256
1257     return result;
1258 }
1259
1260 // A JS object of type EventTarget is limited to a small number of possible classes.
1261 // Check EventTarget.h for new type conversion methods
1262 v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* target)
1263 {
1264     if (!target)
1265         return v8::Null();
1266
1267 #if ENABLE(SVG)
1268     SVGElementInstance* instance = target->toSVGElementInstance();
1269     if (instance)
1270         return convertToV8Object(V8ClassIndex::SVGELEMENTINSTANCE, instance);
1271 #endif
1272
1273 #if ENABLE(WORKERS)
1274     Worker* worker = target->toWorker();
1275     if (worker)
1276         return convertToV8Object(V8ClassIndex::WORKER, worker);
1277 #endif // WORKERS
1278
1279 #if ENABLE(NOTIFICATIONS)
1280     Notification* notification = target->toNotification();
1281     if (notification)
1282         return convertToV8Object(V8ClassIndex::NOTIFICATION, notification);
1283 #endif
1284
1285 #if ENABLE(WEB_SOCKETS)
1286     WebSocket* webSocket = target->toWebSocket();
1287     if (webSocket)
1288         return convertToV8Object(V8ClassIndex::WEBSOCKET, webSocket);
1289 #endif
1290
1291     Node* node = target->toNode();
1292     if (node)
1293         return convertNodeToV8Object(node);
1294
1295     if (DOMWindow* domWindow = target->toDOMWindow())
1296         return convertToV8Object(V8ClassIndex::DOMWINDOW, domWindow);
1297
1298     // XMLHttpRequest is created within its JS counterpart.
1299     XMLHttpRequest* xmlHttpRequest = target->toXMLHttpRequest();
1300     if (xmlHttpRequest) {
1301         v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xmlHttpRequest);
1302         ASSERT(!wrapper.IsEmpty());
1303         return wrapper;
1304     }
1305
1306     // MessagePort is created within its JS counterpart
1307     MessagePort* port = target->toMessagePort();
1308     if (port) {
1309         v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port);
1310         ASSERT(!wrapper.IsEmpty());
1311         return wrapper;
1312     }
1313
1314     XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload();
1315     if (upload) {
1316         v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload);
1317         ASSERT(!wrapper.IsEmpty());
1318         return wrapper;
1319     }
1320
1321 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
1322     DOMApplicationCache* domAppCache = target->toDOMApplicationCache();
1323     if (domAppCache)
1324         return convertToV8Object(V8ClassIndex::DOMAPPLICATIONCACHE, domAppCache);
1325 #endif
1326
1327     ASSERT(0);
1328     return notHandledByInterceptor();
1329 }
1330
1331 v8::Handle<v8::Value> V8DOMWrapper::convertEventListenerToV8Object(EventListener* listener)
1332 {
1333     if (!listener)
1334         return v8::Null();
1335
1336     // FIXME: can a user take a lazy event listener and set to other places?
1337     V8AbstractEventListener* v8listener = static_cast<V8AbstractEventListener*>(listener);
1338     return v8listener->getListenerObject();
1339 }
1340
1341 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, bool findOnly)
1342 {
1343     V8Proxy* proxy = V8Proxy::retrieve(node->scriptExecutionContext());
1344     // The document might be created using createDocument, which does
1345     // not have a frame, use the active frame.
1346     if (!proxy)
1347         proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext());
1348
1349     if (proxy) {
1350         V8EventListenerList* list = proxy->objectListeners();
1351         return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute);
1352     }
1353
1354     return 0;
1355 }
1356
1357 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, bool findOnly)
1358 {
1359     return getEventListener(element->correspondingElement(), value, isAttribute, findOnly);
1360 }
1361
1362
1363 v8::Handle<v8::Value> V8DOMWrapper::convertDOMImplementationToV8Object(DOMImplementation* impl)
1364 {
1365     v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::DOMIMPLEMENTATION, V8ClassIndex::DOMIMPLEMENTATION, impl);
1366     if (result.IsEmpty()) {
1367         // If the instantiation failed, we ignore it and return null instead
1368         // of returning an empty handle.
1369         return v8::Null();
1370     }
1371     return result;
1372 }
1373
1374 v8::Handle<v8::Value> V8DOMWrapper::convertStyleSheetToV8Object(StyleSheet* sheet)
1375 {
1376     if (!sheet)
1377         return v8::Null();
1378
1379     v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(sheet);
1380     if (!wrapper.IsEmpty())
1381         return wrapper;
1382
1383     V8ClassIndex::V8WrapperType type = V8ClassIndex::STYLESHEET;
1384     if (sheet->isCSSStyleSheet())
1385         type = V8ClassIndex::CSSSTYLESHEET;
1386
1387     v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::STYLESHEET, sheet);
1388     if (!result.IsEmpty()) {
1389         // Only update the DOM object map if the result is non-empty.
1390         sheet->ref();
1391         setJSWrapperForDOMObject(sheet, v8::Persistent<v8::Object>::New(result));
1392     }
1393
1394     // Add a hidden reference from stylesheet object to its owner node.
1395     Node* ownerNode = sheet->ownerNode();
1396     if (ownerNode) {
1397         v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(convertNodeToV8Object(ownerNode));
1398         result->SetInternalField(V8Custom::kStyleSheetOwnerNodeIndex, owner);
1399     }
1400
1401     return result;
1402 }
1403
1404 v8::Handle<v8::Value> V8DOMWrapper::convertCSSValueToV8Object(CSSValue* value)
1405 {
1406     if (!value)
1407         return v8::Null();
1408
1409     v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(value);
1410     if (!wrapper.IsEmpty())
1411         return wrapper;
1412
1413     V8ClassIndex::V8WrapperType type;
1414
1415     if (value->isWebKitCSSTransformValue())
1416         type = V8ClassIndex::WEBKITCSSTRANSFORMVALUE;
1417     else if (value->isValueList())
1418         type = V8ClassIndex::CSSVALUELIST;
1419     else if (value->isPrimitiveValue())
1420         type = V8ClassIndex::CSSPRIMITIVEVALUE;
1421 #if ENABLE(SVG)
1422     else if (value->isSVGPaint())
1423         type = V8ClassIndex::SVGPAINT;
1424     else if (value->isSVGColor())
1425         type = V8ClassIndex::SVGCOLOR;
1426 #endif
1427     else
1428         type = V8ClassIndex::CSSVALUE;
1429
1430     v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSVALUE, value);
1431     if (!result.IsEmpty()) {
1432         // Only update the DOM object map if the result is non-empty.
1433         value->ref();
1434         setJSWrapperForDOMObject(value, v8::Persistent<v8::Object>::New(result));
1435     }
1436
1437     return result;
1438 }
1439
1440 v8::Handle<v8::Value> V8DOMWrapper::convertCSSRuleToV8Object(CSSRule* rule)
1441 {
1442     if (!rule) 
1443         return v8::Null();
1444
1445     v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(rule);
1446     if (!wrapper.IsEmpty())
1447         return wrapper;
1448
1449     V8ClassIndex::V8WrapperType type;
1450
1451     switch (rule->type()) {
1452     case CSSRule::STYLE_RULE:
1453         type = V8ClassIndex::CSSSTYLERULE;
1454         break;
1455     case CSSRule::CHARSET_RULE:
1456         type = V8ClassIndex::CSSCHARSETRULE;
1457         break;
1458     case CSSRule::IMPORT_RULE:
1459         type = V8ClassIndex::CSSIMPORTRULE;
1460         break;
1461     case CSSRule::MEDIA_RULE:
1462         type = V8ClassIndex::CSSMEDIARULE;
1463         break;
1464     case CSSRule::FONT_FACE_RULE:
1465         type = V8ClassIndex::CSSFONTFACERULE;
1466         break;
1467     case CSSRule::PAGE_RULE:
1468         type = V8ClassIndex::CSSPAGERULE;
1469         break;
1470     case CSSRule::VARIABLES_RULE:
1471         type = V8ClassIndex::CSSVARIABLESRULE;
1472         break;
1473     case CSSRule::WEBKIT_KEYFRAME_RULE:
1474         type = V8ClassIndex::WEBKITCSSKEYFRAMERULE;
1475         break;
1476     case CSSRule::WEBKIT_KEYFRAMES_RULE:
1477         type = V8ClassIndex::WEBKITCSSKEYFRAMESRULE;
1478         break;
1479     default:  // CSSRule::UNKNOWN_RULE
1480         type = V8ClassIndex::CSSRULE;
1481         break;
1482     }
1483
1484     v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSRULE, rule);
1485     if (!result.IsEmpty()) {
1486         // Only update the DOM object map if the result is non-empty.
1487         rule->ref();
1488         setJSWrapperForDOMObject(rule, v8::Persistent<v8::Object>::New(result));
1489     }
1490     return result;
1491 }
1492
1493 v8::Handle<v8::Value> V8DOMWrapper::convertWindowToV8Object(DOMWindow* window)
1494 {
1495     if (!window)
1496         return v8::Null();
1497     // Initializes environment of a frame, and return the global object
1498     // of the frame.
1499     Frame* frame = window->frame();
1500     if (!frame)
1501         return v8::Handle<v8::Object>();
1502
1503     // Special case: Because of evaluateInNewContext() one DOMWindow can have
1504     // multiple contexts and multiple global objects associated with it. When
1505     // code running in one of those contexts accesses the window object, we
1506     // want to return the global object associated with that context, not
1507     // necessarily the first global object associated with that DOMWindow.
1508     v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent();
1509     v8::Handle<v8::Object> currentGlobal = currentContext->Global();
1510     v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, currentGlobal);
1511     if (!windowWrapper.IsEmpty()) {
1512         if (convertDOMWrapperToNative<DOMWindow>(windowWrapper) == window)
1513             return currentGlobal;
1514     }
1515
1516     // Otherwise, return the global object associated with this frame.
1517     v8::Handle<v8::Context> context = V8Proxy::context(frame);
1518     if (context.IsEmpty())
1519         return v8::Handle<v8::Object>();
1520
1521     v8::Handle<v8::Object> global = context->Global();
1522     ASSERT(!global.IsEmpty());
1523     return global;
1524 }
1525
1526 }  // namespace WebCore