Fixes the assertion and crash that would happen when inspecting a element from a...
[WebKit-https.git] / WebCore / bindings / js / JSQuarantinedObjectWrapper.cpp
1 /*
2  * Copyright (C) 2008 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSQuarantinedObjectWrapper.h"
28
29 #include <kjs/JSGlobalObject.h>
30
31 using namespace KJS;
32
33 namespace WebCore {
34
35 const ClassInfo JSQuarantinedObjectWrapper::s_info = { "JSQuarantinedObjectWrapper", 0, 0, 0 };
36
37 JSQuarantinedObjectWrapper* JSQuarantinedObjectWrapper::asWrapper(JSValue* value)
38 {
39     if (!value->isObject())
40         return 0;
41
42     JSObject* object = static_cast<JSObject*>(value);
43
44     if (!object->inherits(&JSQuarantinedObjectWrapper::s_info))
45         return 0;
46
47     return static_cast<JSQuarantinedObjectWrapper*>(object);
48 }
49
50 JSValue* JSQuarantinedObjectWrapper::cachedValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
51 {
52     JSValue* v = slot.slotBase();
53     ASSERT(v);
54     return v;
55 }
56
57 JSQuarantinedObjectWrapper::JSQuarantinedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, JSValue* wrappedPrototype)
58     : JSObject(wrappedPrototype)
59     , m_unwrappedGlobalObject(unwrappedExec->dynamicGlobalObject())
60     , m_unwrappedObject(unwrappedObject)
61 {
62     ASSERT_ARG(unwrappedExec, unwrappedExec);
63     ASSERT_ARG(unwrappedObject, unwrappedObject);
64     ASSERT_ARG(wrappedPrototype, wrappedPrototype);
65     ASSERT_ARG(wrappedPrototype, !wrappedPrototype->isObject() || asWrapper(wrappedPrototype));
66 }
67
68 JSQuarantinedObjectWrapper::~JSQuarantinedObjectWrapper()
69 {
70 }
71
72 bool JSQuarantinedObjectWrapper::allowsUnwrappedAccessFrom(const ExecState* exec) const
73 {
74     return m_unwrappedGlobalObject->pageGroupIdentifier() == exec->dynamicGlobalObject()->pageGroupIdentifier();
75 }
76
77 ExecState* JSQuarantinedObjectWrapper::unwrappedExecState() const
78 {
79     return m_unwrappedGlobalObject->globalExec();
80 }
81
82 void JSQuarantinedObjectWrapper::transferExceptionToExecState(ExecState* exec) const
83 {
84     ASSERT(exec != unwrappedExecState());
85
86     if (!unwrappedExecState()->hadException())
87         return;
88
89     exec->setException(wrapOutgoingValue(unwrappedExecState(), unwrappedExecState()->exception()));
90     unwrappedExecState()->clearException();
91 }
92
93 void JSQuarantinedObjectWrapper::mark()
94 {
95     JSObject::mark();
96
97     if (!m_unwrappedObject->marked())
98         m_unwrappedObject->mark();
99     if (!m_unwrappedGlobalObject->marked())
100         m_unwrappedGlobalObject->mark();
101 }
102
103 bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot)
104 {
105     if (!allowsGetProperty()) {
106         slot.setUndefined(this);
107         return true;
108     }
109
110     PropertySlot unwrappedSlot;
111     bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot);
112     if (result) {
113         JSValue* unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), m_unwrappedObject, identifier);
114         slot.setCustom(static_cast<JSObject*>(wrapOutgoingValue(unwrappedExecState(), unwrappedValue)), cachedValueGetter);
115     }
116
117     transferExceptionToExecState(exec);
118
119     return result;
120 }
121
122 bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot)
123 {
124     if (!allowsGetProperty()) {
125         slot.setUndefined(this);
126         return true;
127     }
128
129     PropertySlot unwrappedSlot;
130     bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot);
131     if (result) {
132         JSValue* unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), m_unwrappedObject, identifier);
133         slot.setCustom(static_cast<JSObject*>(wrapOutgoingValue(unwrappedExecState(), unwrappedValue)), cachedValueGetter);
134     }
135
136     transferExceptionToExecState(exec);
137
138     return result;
139 }
140
141 void JSQuarantinedObjectWrapper::put(ExecState* exec, const Identifier& identifier, JSValue* value)
142 {
143     if (!allowsSetProperty())
144         return;
145
146     JSValue* preparedValue = prepareIncomingValue(exec, value);
147     if (!preparedValue)
148         return;
149
150     m_unwrappedObject->put(unwrappedExecState(), identifier, preparedValue);
151
152     transferExceptionToExecState(exec);
153 }
154
155 void JSQuarantinedObjectWrapper::put(ExecState* exec, unsigned identifier, JSValue* value)
156 {
157     if (!allowsSetProperty())
158         return;
159
160     JSValue* preparedValue = prepareIncomingValue(exec, value);
161     if (!preparedValue)
162         return;
163
164     m_unwrappedObject->put(unwrappedExecState(), identifier, preparedValue);
165
166     transferExceptionToExecState(exec);
167 }
168
169 bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, const Identifier& identifier)
170 {
171     if (!allowsDeleteProperty())
172         return false;
173
174     bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier);
175
176     transferExceptionToExecState(exec);
177
178     return result;
179 }
180
181 bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, unsigned identifier)
182 {
183     if (!allowsDeleteProperty())
184         return false;
185
186     bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier);
187
188     transferExceptionToExecState(exec);
189
190     return result;
191 }
192
193 bool JSQuarantinedObjectWrapper::implementsConstruct() const
194 {
195     return m_unwrappedObject->implementsConstruct();
196 }
197
198 JSObject* JSQuarantinedObjectWrapper::construct(ExecState* exec, const List& args)
199 {
200     if (!allowsConstruct())
201         return 0;
202
203     List argsCopy;
204     for (size_t i = 0; i < args.size(); ++i) {
205         JSValue* preparedValue = prepareIncomingValue(exec, args[i]);
206         if (!preparedValue)
207             return 0;
208         argsCopy.append(preparedValue);
209     }
210
211     JSValue* resultValue = wrapOutgoingValue(unwrappedExecState(), m_unwrappedObject->construct(unwrappedExecState(), argsCopy));
212     ASSERT(resultValue->isObject());
213     JSObject* result = resultValue->toObject(exec);
214
215     transferExceptionToExecState(exec);
216
217     return result;
218 }
219
220 bool JSQuarantinedObjectWrapper::implementsHasInstance() const
221 {
222     return m_unwrappedObject->implementsHasInstance();
223 }
224
225 bool JSQuarantinedObjectWrapper::hasInstance(ExecState* exec, JSValue* value)
226 {
227     if (!allowsHasInstance())
228         return false;
229
230     JSValue* preparedValue = prepareIncomingValue(exec, value);
231     if (!preparedValue)
232         return false;
233
234     bool result = m_unwrappedObject->hasInstance(unwrappedExecState(), preparedValue);
235
236     transferExceptionToExecState(exec);
237
238     return result;
239 }
240
241 bool JSQuarantinedObjectWrapper::implementsCall() const
242 {
243     return m_unwrappedObject->implementsCall();
244 }
245
246 JSValue* JSQuarantinedObjectWrapper::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
247 {
248     if (!allowsCallAsFunction())
249         return jsUndefined();
250
251     JSObject* preparedThisObj = static_cast<JSObject*>(prepareIncomingValue(exec, thisObj));
252     if (!preparedThisObj)
253         return jsUndefined();
254
255     List preparedArgs;
256     for (size_t i = 0; i < args.size(); ++i) {
257         JSValue* preparedValue = prepareIncomingValue(exec, args[i]);
258         if (!preparedValue)
259             return jsUndefined();
260         preparedArgs.append(preparedValue);
261     }
262
263     JSValue* result = wrapOutgoingValue(unwrappedExecState(), m_unwrappedObject->callAsFunction(unwrappedExecState(), preparedThisObj, preparedArgs));
264
265     transferExceptionToExecState(exec);
266
267     return result;
268 }
269
270 void JSQuarantinedObjectWrapper::getPropertyNames(ExecState* exec, PropertyNameArray& array)
271 {
272     if (!allowsGetPropertyNames())
273         return;
274
275     m_unwrappedObject->getPropertyNames(unwrappedExecState(), array);
276 }
277
278 } // namespace WebCore