De-inline convertNodeToV8Object(), which expands to a lot of asm code and is inlined 136
[WebKit-https.git] / WebCore / bindings / v8 / V8DOMWrapper.h
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 #ifndef V8DOMWrapper_h
32 #define V8DOMWrapper_h
33
34 #include "Document.h"
35 #include "Event.h"
36 #include "Node.h"
37 #include "NodeFilter.h"
38 #include "PlatformString.h" // for WebCore::String
39 #include "V8CustomBinding.h"
40 #include "V8CustomXPathNSResolver.h"
41 #include "V8DOMMap.h"
42 #include "V8Index.h"
43 #include "V8Utilities.h"
44 #include "V8XPathNSResolver.h"
45 #include "XPathNSResolver.h"
46 #include <v8.h>
47
48 namespace WebCore {
49
50     // FIXME: This probably aren't all needed.
51     class CSSRule;
52     class CSSRuleList;
53     class CSSStyleDeclaration;
54     class CSSValue;
55     class CSSValueList;
56     class ClientRectList;
57     class DOMImplementation;
58     class DOMWindow;
59     class Document;
60     class Element;
61     class Event;
62     class EventListener;
63     class EventTarget;
64     class Frame;
65     class HTMLCollection;
66     class HTMLDocument;
67     class HTMLElement;
68     class HTMLOptionsCollection;
69     class MediaList;
70     class MimeType;
71     class MimeTypeArray;
72     class NamedNodeMap;
73     class Navigator;
74     class Node;
75     class NodeFilter;
76     class NodeList;
77     class Plugin;
78     class PluginArray;
79     class SVGElement;
80 #if ENABLE(SVG)
81     class SVGElementInstance;
82 #endif
83     class Screen;
84     class ScriptExecutionContext;
85 #if ENABLE(DOM_STORAGE)
86     class Storage;
87     class StorageEvent;
88 #endif
89     class String;
90     class StyleSheet;
91     class StyleSheetList;
92     class V8EventListener;
93     class V8ObjectEventListener;
94 #if ENABLE(WEB_SOCKETS)
95     class WebSocket;
96 #endif
97     class WorkerContext;
98
99     enum ListenerLookupType {
100         ListenerFindOnly,
101         ListenerFindOrCreate,
102     };
103
104     class V8DOMWrapper {
105     public:
106 #ifndef NDEBUG
107         // Checks if a v8 value can be a DOM wrapper
108         static bool maybeDOMWrapper(v8::Handle<v8::Value>);
109 #endif
110
111         // Sets contents of a DOM wrapper.
112         static void setDOMWrapper(v8::Handle<v8::Object>, int type, void* ptr);
113
114         static v8::Handle<v8::Object> lookupDOMWrapper(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object)
115         {
116             return object.IsEmpty() ? object : object->FindInstanceInPrototypeChain(getTemplate(type));
117         }
118
119         // A helper function extract native object pointer from a DOM wrapper
120         // and cast to the specified type.
121         template <class C>
122         static C* convertDOMWrapperToNative(v8::Handle<v8::Object> object)
123         {
124             ASSERT(maybeDOMWrapper(object));
125             return reinterpret_cast<C*>(object->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex));
126         }
127
128         template <class C>
129         static C* convertDOMWrapperToNode(v8::Handle<v8::Object> object)
130         {
131             ASSERT(maybeDOMWrapper(object));
132             ASSERT(domWrapperType(object) == V8ClassIndex::NODE);
133             return convertDOMWrapperToNative<C>(object);
134         }
135
136         template<typename T>
137         static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType type, PassRefPtr<T> imp)
138         {
139             return convertToV8Object(type, imp.get());
140         }
141
142         static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType, void*);
143
144         // Fast-path for Node objects.
145         static v8::Handle<v8::Value> convertNodeToV8Object(PassRefPtr<Node> node)
146         {
147             return convertNodeToV8Object(node.get());
148         }
149
150         static v8::Handle<v8::Value> convertNodeToV8Object(Node*);
151
152         static v8::Handle<v8::Value> convertDocumentToV8Object(Document*);
153
154         static v8::Handle<v8::Value> convertNewNodeToV8Object(PassRefPtr<Node> node)
155         {
156             return convertNewNodeToV8Object(node.get());
157         }
158
159         static v8::Handle<v8::Value> convertNewNodeToV8Object(Node* node)
160         {
161             return convertNewNodeToV8Object(node, 0, getDOMNodeMap());
162         }
163
164         static v8::Handle<v8::Value> convertNewNodeToV8Object(Node*, V8Proxy*, DOMWrapperMap<Node>&);
165
166         template <class C>
167         static C* convertToNativeObject(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object)
168         {
169             // Native event listener is per frame, it cannot be handled by this generic function.
170             ASSERT(type != V8ClassIndex::EVENTLISTENER);
171             ASSERT(type != V8ClassIndex::EVENTTARGET);
172
173             ASSERT(maybeDOMWrapper(object));
174
175 #ifndef NDEBUG
176             const bool typeIsValid =
177 #define MAKE_CASE(TYPE, NAME) (type != V8ClassIndex::TYPE) &&
178                 DOM_NODE_TYPES(MAKE_CASE)
179 #if ENABLE(SVG)
180                 SVG_NODE_TYPES(MAKE_CASE)
181 #endif
182 #undef MAKE_CASE
183                 true;
184             ASSERT(typeIsValid);
185 #endif
186
187             return convertDOMWrapperToNative<C>(object);
188         }
189
190         static V8ClassIndex::V8WrapperType domWrapperType(v8::Handle<v8::Object>);
191
192         static v8::Handle<v8::Value> convertEventToV8Object(PassRefPtr<Event> event)
193         {
194             return convertEventToV8Object(event.get());
195         }
196
197         static v8::Handle<v8::Value> convertEventToV8Object(Event*);
198
199         static Event* convertToNativeEvent(v8::Handle<v8::Value> jsEvent)
200         {
201             if (!isDOMEventWrapper(jsEvent))
202                 return 0;
203             return convertDOMWrapperToNative<Event>(v8::Handle<v8::Object>::Cast(jsEvent));
204         }
205
206         static v8::Handle<v8::Value> convertEventTargetToV8Object(PassRefPtr<EventTarget> eventTarget)
207         {
208             return convertEventTargetToV8Object(eventTarget.get());
209         }
210
211         static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*);
212
213         // Wrap and unwrap JS event listeners.
214         static v8::Handle<v8::Value> convertEventListenerToV8Object(ScriptExecutionContext* context, PassRefPtr<EventListener> eventListener)
215         {
216             return convertEventListenerToV8Object(context, eventListener.get());
217         }
218
219         static v8::Handle<v8::Value> convertEventListenerToV8Object(ScriptExecutionContext*, EventListener*);
220
221         static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
222
223         static PassRefPtr<EventListener> getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
224
225         static PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
226
227 #if ENABLE(NOTIFICATIONS)
228         static PassRefPtr<EventListener> getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
229 #endif
230
231         static PassRefPtr<EventListener> getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
232
233         static PassRefPtr<EventListener> getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
234
235         static PassRefPtr<EventListener> getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
236
237         static PassRefPtr<EventListener> getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
238
239
240         // XPath-related utilities
241         static RefPtr<XPathNSResolver> getXPathNSResolver(v8::Handle<v8::Value> value, V8Proxy* proxy = 0)
242         {
243             RefPtr<XPathNSResolver> resolver;
244             if (V8XPathNSResolver::HasInstance(value))
245                 resolver = convertToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, v8::Handle<v8::Object>::Cast(value));
246             else if (value->IsObject())
247                 resolver = V8CustomXPathNSResolver::create(proxy, value->ToObject());
248             return resolver;
249         }
250
251         // DOMImplementation is a singleton and it is handled in a special
252         // way. A wrapper is generated per document and stored in an
253         // internal field of the document.
254         static v8::Handle<v8::Value> convertDOMImplementationToV8Object(DOMImplementation*);
255
256         // Wrap JS node filter in C++.
257         static PassRefPtr<NodeFilter> wrapNativeNodeFilter(v8::Handle<v8::Value>);
258
259         static v8::Persistent<v8::FunctionTemplate> getTemplate(V8ClassIndex::V8WrapperType);
260         static v8::Local<v8::Function> getConstructorForContext(V8ClassIndex::V8WrapperType, v8::Handle<v8::Context>);
261         static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value> objectPrototype);
262         static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, DOMWindow*);
263         static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, WorkerContext*);
264
265         // Checks whether a DOM object has a JS wrapper.
266         static bool domObjectHasJSWrapper(void*);
267         // Get JS wrapper of an existing DOM object, assuming that the wrapper
268         // exists.
269         static v8::Persistent<v8::Object> jsWrapperForDOMObject(void*);
270         static v8::Persistent<v8::Object> jsWrapperForActiveDOMObject(void*);
271         // Set JS wrapper of a DOM object, the caller in charge of increase ref.
272         static void setJSWrapperForDOMObject(void*, v8::Persistent<v8::Object>);
273         static void setJSWrapperForActiveDOMObject(void*, v8::Persistent<v8::Object>);
274         static void setJSWrapperForDOMNode(Node*, v8::Persistent<v8::Object>);
275
276         // Check whether a V8 value is a wrapper of type |classType|.
277         static bool isWrapperOfType(v8::Handle<v8::Value>, V8ClassIndex::V8WrapperType);
278
279         static void* convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value>);
280
281         // Check whether a V8 value is a DOM Event wrapper.
282         static bool isDOMEventWrapper(v8::Handle<v8::Value>);
283
284         static v8::Handle<v8::Value> convertStyleSheetToV8Object(StyleSheet*);
285         static v8::Handle<v8::Value> convertCSSValueToV8Object(CSSValue*);
286         static v8::Handle<v8::Value> convertCSSRuleToV8Object(CSSRule*);
287         // Returns the JS wrapper of a window object, initializes the environment
288         // of the window frame if needed.
289         static v8::Handle<v8::Value> convertWindowToV8Object(DOMWindow*);
290
291 #if ENABLE(SVG)
292         static v8::Handle<v8::Value> convertSVGElementInstanceToV8Object(SVGElementInstance*);
293         static v8::Handle<v8::Value> convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType, void*);
294 #endif
295
296 #if ENABLE(3D_CANVAS)
297         static void setIndexedPropertiesToExternalArray(v8::Handle<v8::Object>,
298                                                         int,
299                                                         void*,
300                                                         int);
301 #endif
302
303     private:
304         // Set hidden references in a DOMWindow object of a frame.
305         static void setHiddenWindowReference(Frame*, const int internalIndex, v8::Handle<v8::Object>);
306
307         static V8ClassIndex::V8WrapperType htmlElementType(HTMLElement*);
308 #if ENABLE(SVG)
309         static V8ClassIndex::V8WrapperType svgElementType(SVGElement*);
310 #endif
311
312         // The first V8WrapperType specifies the function descriptor
313         // used to create JS object. The second V8WrapperType specifies
314         // the actual type of the void* for type casting.
315         // For example, a HTML element has HTMLELEMENT for the first V8WrapperType, but always
316         // use NODE as the second V8WrapperType. JS wrapper stores the second
317         // V8WrapperType and the void* as internal fields.
318         static v8::Local<v8::Object> instantiateV8Object(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl)
319         {
320             return instantiateV8Object(NULL, descType, cptrType, impl);
321         }
322
323         static v8::Local<v8::Object> instantiateV8Object(V8Proxy*, V8ClassIndex::V8WrapperType, V8ClassIndex::V8WrapperType, void*);
324     };
325
326 }
327
328 #endif // V8DOMWrapper_h