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