• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008, 2009 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(JSValue value)39 JSQuarantinedObjectWrapper* JSQuarantinedObjectWrapper::asWrapper(JSValue 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 JSValue JSQuarantinedObjectWrapper::cachedValueGetter(ExecState*, const Identifier&, const PropertySlot& slot)
53 {
54     JSValue 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->lexicalGlobalObject())
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->lexicalGlobalObject()->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     JSValue exception = unwrappedExecState()->exception();
91     unwrappedExecState()->clearException();
92     exec->setException(wrapOutgoingValue(unwrappedExecState(), exception));
93 }
94 
markChildren(MarkStack & markStack)95 void JSQuarantinedObjectWrapper::markChildren(MarkStack& markStack)
96 {
97     JSObject::markChildren(markStack);
98 
99     markStack.append(m_unwrappedObject);
100     markStack.append(m_unwrappedGlobalObject);
101 }
102 
getOwnPropertySlot(ExecState * exec,const Identifier & identifier,PropertySlot & slot)103 bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot)
104 {
105     if (!allowsGetProperty()) {
106         slot.setUndefined();
107         return true;
108     }
109 
110     PropertySlot unwrappedSlot(m_unwrappedObject);
111     bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot);
112     if (result) {
113         JSValue unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), identifier);
114         slot.setCustom(wrapOutgoingValue(unwrappedExecState(), unwrappedValue), cachedValueGetter);
115     }
116 
117     transferExceptionToExecState(exec);
118 
119     return result;
120 }
121 
getOwnPropertySlot(ExecState * exec,unsigned identifier,PropertySlot & slot)122 bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot)
123 {
124     if (!allowsGetProperty()) {
125         slot.setUndefined();
126         return true;
127     }
128 
129     PropertySlot unwrappedSlot(m_unwrappedObject);
130     bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot);
131     if (result) {
132         JSValue unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), identifier);
133         slot.setCustom(wrapOutgoingValue(unwrappedExecState(), unwrappedValue), cachedValueGetter);
134     }
135 
136     transferExceptionToExecState(exec);
137 
138     return result;
139 }
140 
put(ExecState * exec,const Identifier & identifier,JSValue value,PutPropertySlot & slot)141 void JSQuarantinedObjectWrapper::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot)
142 {
143     if (!allowsSetProperty())
144         return;
145 
146     m_unwrappedObject->put(unwrappedExecState(), identifier, prepareIncomingValue(exec, value), slot);
147 
148     transferExceptionToExecState(exec);
149 }
150 
put(ExecState * exec,unsigned identifier,JSValue value)151 void JSQuarantinedObjectWrapper::put(ExecState* exec, unsigned identifier, JSValue value)
152 {
153     if (!allowsSetProperty())
154         return;
155 
156     m_unwrappedObject->put(unwrappedExecState(), identifier, prepareIncomingValue(exec, value));
157 
158     transferExceptionToExecState(exec);
159 }
160 
deleteProperty(ExecState * exec,const Identifier & identifier)161 bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, const Identifier& identifier)
162 {
163     if (!allowsDeleteProperty())
164         return false;
165 
166     bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier);
167 
168     transferExceptionToExecState(exec);
169 
170     return result;
171 }
172 
deleteProperty(ExecState * exec,unsigned identifier)173 bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, unsigned identifier)
174 {
175     if (!allowsDeleteProperty())
176         return false;
177 
178     bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier);
179 
180     transferExceptionToExecState(exec);
181 
182     return result;
183 }
184 
construct(ExecState * exec,JSObject * constructor,const ArgList & args)185 JSObject* JSQuarantinedObjectWrapper::construct(ExecState* exec, JSObject* constructor, const ArgList& args)
186 {
187     JSQuarantinedObjectWrapper* wrapper = static_cast<JSQuarantinedObjectWrapper*>(constructor);
188 
189     MarkedArgumentBuffer preparedArgs;
190     for (size_t i = 0; i < args.size(); ++i)
191         preparedArgs.append(wrapper->prepareIncomingValue(exec, args.at(i)));
192 
193     // FIXME: Would be nice to find a way to reuse the result of m_unwrappedObject->getConstructData
194     // from when we called it in JSQuarantinedObjectWrapper::getConstructData.
195     ConstructData unwrappedConstructData;
196     ConstructType unwrappedConstructType = wrapper->m_unwrappedObject->getConstructData(unwrappedConstructData);
197     ASSERT(unwrappedConstructType != ConstructTypeNone);
198 
199     JSValue unwrappedResult = JSC::construct(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedConstructType, unwrappedConstructData, preparedArgs);
200 
201     JSValue resultValue = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult);
202     ASSERT(resultValue.isObject());
203     JSObject* result = asObject(resultValue);
204 
205     wrapper->transferExceptionToExecState(exec);
206 
207     return result;
208 }
209 
getConstructData(ConstructData & constructData)210 ConstructType JSQuarantinedObjectWrapper::getConstructData(ConstructData& constructData)
211 {
212     if (!allowsConstruct())
213         return ConstructTypeNone;
214     ConstructData unwrappedConstructData;
215     if (m_unwrappedObject->getConstructData(unwrappedConstructData) == ConstructTypeNone)
216         return ConstructTypeNone;
217     constructData.native.function = construct;
218     return ConstructTypeHost;
219 }
220 
hasInstance(ExecState * exec,JSValue value,JSValue proto)221 bool JSQuarantinedObjectWrapper::hasInstance(ExecState* exec, JSValue value, JSValue proto)
222 {
223     if (!allowsHasInstance())
224         return false;
225 
226     bool result = m_unwrappedObject->hasInstance(unwrappedExecState(), prepareIncomingValue(exec, value), prepareIncomingValue(exec, proto));
227 
228     transferExceptionToExecState(exec);
229 
230     return result;
231 }
232 
call(ExecState * exec,JSObject * function,JSValue thisValue,const ArgList & args)233 JSValue JSQuarantinedObjectWrapper::call(ExecState* exec, JSObject* function, JSValue thisValue, const ArgList& args)
234 {
235     JSQuarantinedObjectWrapper* wrapper = static_cast<JSQuarantinedObjectWrapper*>(function);
236 
237     JSValue preparedThisValue = wrapper->prepareIncomingValue(exec, thisValue);
238 
239     MarkedArgumentBuffer preparedArgs;
240     for (size_t i = 0; i < args.size(); ++i)
241         preparedArgs.append(wrapper->prepareIncomingValue(exec, args.at(i)));
242 
243     // FIXME: Would be nice to find a way to reuse the result of m_unwrappedObject->getCallData
244     // from when we called it in JSQuarantinedObjectWrapper::getCallData.
245     CallData unwrappedCallData;
246     CallType unwrappedCallType = wrapper->m_unwrappedObject->getCallData(unwrappedCallData);
247     ASSERT(unwrappedCallType != CallTypeNone);
248 
249     JSValue unwrappedResult = JSC::call(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedCallType, unwrappedCallData, preparedThisValue, preparedArgs);
250 
251     JSValue result = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult);
252 
253     wrapper->transferExceptionToExecState(exec);
254 
255     return result;
256 }
257 
getCallData(CallData & callData)258 CallType JSQuarantinedObjectWrapper::getCallData(CallData& callData)
259 {
260     if (!allowsCallAsFunction())
261         return CallTypeNone;
262     CallData unwrappedCallData;
263     if (m_unwrappedObject->getCallData(unwrappedCallData) == CallTypeNone)
264         return CallTypeNone;
265     callData.native.function = call;
266     return CallTypeHost;
267 }
268 
getPropertyNames(ExecState *,PropertyNameArray & array)269 void JSQuarantinedObjectWrapper::getPropertyNames(ExecState*, PropertyNameArray& array)
270 {
271     if (!allowsGetPropertyNames())
272         return;
273 
274     m_unwrappedObject->getPropertyNames(unwrappedExecState(), array);
275 }
276 
277 } // namespace WebCore
278