• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <runtime/JSGlobalObject.h>
30 
31 using namespace JSC;
32 
33 namespace WebCore {
34 
35 ASSERT_CLASS_FITS_IN_CELL(JSQuarantinedObjectWrapper)
36 
37 const ClassInfo JSQuarantinedObjectWrapper::s_info = { "JSQuarantinedObjectWrapper", 0, 0, 0 };
38 
asWrapper(JSValuePtr value)39 JSQuarantinedObjectWrapper* JSQuarantinedObjectWrapper::asWrapper(JSValuePtr value)
40 {
41     if (!value.isObject())
42         return 0;
43 
44     JSObject* object = asObject(value);
45 
46     if (!object->inherits(&JSQuarantinedObjectWrapper::s_info))
47         return 0;
48 
49     return static_cast<JSQuarantinedObjectWrapper*>(object);
50 }
51 
cachedValueGetter(ExecState *,const Identifier &,const PropertySlot & slot)52 JSValuePtr JSQuarantinedObjectWrapper::cachedValueGetter(ExecState*, const Identifier&, const PropertySlot& slot)
53 {
54     JSValuePtr v = slot.slotBase();
55     ASSERT(v);
56     return v;
57 }
58 
JSQuarantinedObjectWrapper(ExecState * unwrappedExec,JSObject * unwrappedObject,PassRefPtr<Structure> structure)59 JSQuarantinedObjectWrapper::JSQuarantinedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, PassRefPtr<Structure> structure)
60     : JSObject(structure)
61     , m_unwrappedGlobalObject(unwrappedExec->dynamicGlobalObject())
62     , m_unwrappedObject(unwrappedObject)
63 {
64     ASSERT_ARG(unwrappedExec, unwrappedExec);
65     ASSERT_ARG(unwrappedObject, unwrappedObject);
66     ASSERT(this->structure());
67 }
68 
~JSQuarantinedObjectWrapper()69 JSQuarantinedObjectWrapper::~JSQuarantinedObjectWrapper()
70 {
71 }
72 
allowsUnwrappedAccessFrom(ExecState * exec) const73 bool JSQuarantinedObjectWrapper::allowsUnwrappedAccessFrom(ExecState* exec) const
74 {
75     return m_unwrappedGlobalObject->profileGroup() == exec->dynamicGlobalObject()->profileGroup();
76 }
77 
unwrappedExecState() const78 ExecState* JSQuarantinedObjectWrapper::unwrappedExecState() const
79 {
80     return m_unwrappedGlobalObject->globalExec();
81 }
82 
transferExceptionToExecState(ExecState * exec) const83 void JSQuarantinedObjectWrapper::transferExceptionToExecState(ExecState* exec) const
84 {
85     ASSERT(exec != unwrappedExecState());
86 
87     if (!unwrappedExecState()->hadException())
88         return;
89 
90     exec->setException(wrapOutgoingValue(unwrappedExecState(), unwrappedExecState()->exception()));
91     unwrappedExecState()->clearException();
92 }
93 
mark()94 void JSQuarantinedObjectWrapper::mark()
95 {
96     JSObject::mark();
97 
98     if (!m_unwrappedObject->marked())
99         m_unwrappedObject->mark();
100     if (!m_unwrappedGlobalObject->marked())
101         m_unwrappedGlobalObject->mark();
102 }
103 
getOwnPropertySlot(ExecState * exec,const Identifier & identifier,PropertySlot & slot)104 bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot)
105 {
106     if (!allowsGetProperty()) {
107         slot.setUndefined();
108         return true;
109     }
110 
111     PropertySlot unwrappedSlot(m_unwrappedObject);
112     bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot);
113     if (result) {
114         JSValuePtr unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), identifier);
115         slot.setCustom(wrapOutgoingValue(unwrappedExecState(), unwrappedValue), cachedValueGetter);
116     }
117 
118     transferExceptionToExecState(exec);
119 
120     return result;
121 }
122 
getOwnPropertySlot(ExecState * exec,unsigned identifier,PropertySlot & slot)123 bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot)
124 {
125     if (!allowsGetProperty()) {
126         slot.setUndefined();
127         return true;
128     }
129 
130     PropertySlot unwrappedSlot(m_unwrappedObject);
131     bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot);
132     if (result) {
133         JSValuePtr unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), identifier);
134         slot.setCustom(wrapOutgoingValue(unwrappedExecState(), unwrappedValue), cachedValueGetter);
135     }
136 
137     transferExceptionToExecState(exec);
138 
139     return result;
140 }
141 
put(ExecState * exec,const Identifier & identifier,JSValuePtr value,PutPropertySlot & slot)142 void JSQuarantinedObjectWrapper::put(ExecState* exec, const Identifier& identifier, JSValuePtr value, PutPropertySlot& slot)
143 {
144     if (!allowsSetProperty())
145         return;
146 
147     m_unwrappedObject->put(unwrappedExecState(), identifier, prepareIncomingValue(exec, value), slot);
148 
149     transferExceptionToExecState(exec);
150 }
151 
put(ExecState * exec,unsigned identifier,JSValuePtr value)152 void JSQuarantinedObjectWrapper::put(ExecState* exec, unsigned identifier, JSValuePtr value)
153 {
154     if (!allowsSetProperty())
155         return;
156 
157     m_unwrappedObject->put(unwrappedExecState(), identifier, prepareIncomingValue(exec, value));
158 
159     transferExceptionToExecState(exec);
160 }
161 
deleteProperty(ExecState * exec,const Identifier & identifier)162 bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, const Identifier& identifier)
163 {
164     if (!allowsDeleteProperty())
165         return false;
166 
167     bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier);
168 
169     transferExceptionToExecState(exec);
170 
171     return result;
172 }
173 
deleteProperty(ExecState * exec,unsigned identifier)174 bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, unsigned identifier)
175 {
176     if (!allowsDeleteProperty())
177         return false;
178 
179     bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier);
180 
181     transferExceptionToExecState(exec);
182 
183     return result;
184 }
185 
construct(ExecState * exec,JSObject * constructor,const ArgList & args)186 JSObject* JSQuarantinedObjectWrapper::construct(ExecState* exec, JSObject* constructor, const ArgList& args)
187 {
188     JSQuarantinedObjectWrapper* wrapper = static_cast<JSQuarantinedObjectWrapper*>(constructor);
189 
190     ArgList preparedArgs;
191     for (size_t i = 0; i < args.size(); ++i)
192         preparedArgs.append(wrapper->prepareIncomingValue(exec, args.at(exec, i)));
193 
194     // FIXME: Would be nice to find a way to reuse the result of m_unwrappedObject->getConstructData
195     // from when we called it in JSQuarantinedObjectWrapper::getConstructData.
196     ConstructData unwrappedConstructData;
197     ConstructType unwrappedConstructType = wrapper->m_unwrappedObject->getConstructData(unwrappedConstructData);
198     ASSERT(unwrappedConstructType != ConstructTypeNone);
199 
200     JSValuePtr unwrappedResult = JSC::construct(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedConstructType, unwrappedConstructData, preparedArgs);
201 
202     JSValuePtr resultValue = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult);
203     ASSERT(resultValue.isObject());
204     JSObject* result = asObject(resultValue);
205 
206     wrapper->transferExceptionToExecState(exec);
207 
208     return result;
209 }
210 
getConstructData(ConstructData & constructData)211 ConstructType JSQuarantinedObjectWrapper::getConstructData(ConstructData& constructData)
212 {
213     if (!allowsConstruct())
214         return ConstructTypeNone;
215     ConstructData unwrappedConstructData;
216     if (m_unwrappedObject->getConstructData(unwrappedConstructData) == ConstructTypeNone)
217         return ConstructTypeNone;
218     constructData.native.function = construct;
219     return ConstructTypeHost;
220 }
221 
hasInstance(ExecState * exec,JSValuePtr value,JSValuePtr proto)222 bool JSQuarantinedObjectWrapper::hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr proto)
223 {
224     if (!allowsHasInstance())
225         return false;
226 
227     bool result = m_unwrappedObject->hasInstance(unwrappedExecState(), prepareIncomingValue(exec, value), prepareIncomingValue(exec, proto));
228 
229     transferExceptionToExecState(exec);
230 
231     return result;
232 }
233 
call(ExecState * exec,JSObject * function,JSValuePtr thisValue,const ArgList & args)234 JSValuePtr JSQuarantinedObjectWrapper::call(ExecState* exec, JSObject* function, JSValuePtr thisValue, const ArgList& args)
235 {
236     JSQuarantinedObjectWrapper* wrapper = static_cast<JSQuarantinedObjectWrapper*>(function);
237 
238     JSValuePtr preparedThisValue = wrapper->prepareIncomingValue(exec, thisValue);
239 
240     ArgList preparedArgs;
241     for (size_t i = 0; i < args.size(); ++i)
242         preparedArgs.append(wrapper->prepareIncomingValue(exec, args.at(exec, i)));
243 
244     // FIXME: Would be nice to find a way to reuse the result of m_unwrappedObject->getCallData
245     // from when we called it in JSQuarantinedObjectWrapper::getCallData.
246     CallData unwrappedCallData;
247     CallType unwrappedCallType = wrapper->m_unwrappedObject->getCallData(unwrappedCallData);
248     ASSERT(unwrappedCallType != CallTypeNone);
249 
250     JSValuePtr unwrappedResult = JSC::call(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedCallType, unwrappedCallData, preparedThisValue, preparedArgs);
251 
252     JSValuePtr result = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult);
253 
254     wrapper->transferExceptionToExecState(exec);
255 
256     return result;
257 }
258 
getCallData(CallData & callData)259 CallType JSQuarantinedObjectWrapper::getCallData(CallData& callData)
260 {
261     if (!allowsCallAsFunction())
262         return CallTypeNone;
263     CallData unwrappedCallData;
264     if (m_unwrappedObject->getCallData(unwrappedCallData) == CallTypeNone)
265         return CallTypeNone;
266     callData.native.function = call;
267     return CallTypeHost;
268 }
269 
getPropertyNames(ExecState *,PropertyNameArray & array)270 void JSQuarantinedObjectWrapper::getPropertyNames(ExecState*, PropertyNameArray& array)
271 {
272     if (!allowsGetPropertyNames())
273         return;
274 
275     m_unwrappedObject->getPropertyNames(unwrappedExecState(), array);
276 }
277 
278 } // namespace WebCore
279