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