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