• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2003, 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 COMPUTER, 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 COMPUTER, 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 "runtime_object.h"
28 
29 #include "JSDOMBinding.h"
30 #include "runtime_method.h"
31 #include "runtime_root.h"
32 #include <runtime/Error.h>
33 #include <runtime/ObjectPrototype.h>
34 
35 using namespace WebCore;
36 
37 namespace JSC {
38 
39 using namespace Bindings;
40 
41 const ClassInfo RuntimeObjectImp::s_info = { "RuntimeObject", 0, 0, 0 };
42 
RuntimeObjectImp(ExecState * exec,PassRefPtr<Instance> i)43 RuntimeObjectImp::RuntimeObjectImp(ExecState* exec, PassRefPtr<Instance> i)
44     // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
45     // We need to pass in the right global object for "i".
46     : JSObject(deprecatedGetDOMStructure<RuntimeObjectImp>(exec))
47     , instance(i)
48 {
49     instance->rootObject()->addRuntimeObject(this);
50 }
51 
RuntimeObjectImp(ExecState *,PassRefPtr<Structure> structure,PassRefPtr<Instance> i)52 RuntimeObjectImp::RuntimeObjectImp(ExecState*, PassRefPtr<Structure> structure, PassRefPtr<Instance> i)
53     : JSObject(structure)
54     , instance(i)
55 {
56     instance->rootObject()->addRuntimeObject(this);
57 }
58 
~RuntimeObjectImp()59 RuntimeObjectImp::~RuntimeObjectImp()
60 {
61     if (instance)
62         instance->rootObject()->removeRuntimeObject(this);
63 }
64 
invalidate()65 void RuntimeObjectImp::invalidate()
66 {
67     ASSERT(instance);
68     instance = 0;
69 }
70 
fallbackObjectGetter(ExecState * exec,const Identifier & propertyName,const PropertySlot & slot)71 JSValue RuntimeObjectImp::fallbackObjectGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
72 {
73     RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase()));
74     RefPtr<Instance> instance = thisObj->instance;
75 
76     if (!instance)
77         return throwInvalidAccessError(exec);
78 
79     instance->begin();
80 
81     Class *aClass = instance->getClass();
82     JSValue result = aClass->fallbackObject(exec, instance.get(), propertyName);
83 
84     instance->end();
85 
86     return result;
87 }
88 
fieldGetter(ExecState * exec,const Identifier & propertyName,const PropertySlot & slot)89 JSValue RuntimeObjectImp::fieldGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
90 {
91     RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase()));
92     RefPtr<Instance> instance = thisObj->instance;
93 
94     if (!instance)
95         return throwInvalidAccessError(exec);
96 
97     instance->begin();
98 
99     Class *aClass = instance->getClass();
100     Field* aField = aClass->fieldNamed(propertyName, instance.get());
101     JSValue result = aField->valueFromInstance(exec, instance.get());
102 
103     instance->end();
104 
105     return result;
106 }
107 
methodGetter(ExecState * exec,const Identifier & propertyName,const PropertySlot & slot)108 JSValue RuntimeObjectImp::methodGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
109 {
110     RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase()));
111     RefPtr<Instance> instance = thisObj->instance;
112 
113     if (!instance)
114         return throwInvalidAccessError(exec);
115 
116     instance->begin();
117 
118     Class *aClass = instance->getClass();
119     MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
120     JSValue result = new (exec) RuntimeMethod(exec, propertyName, methodList);
121 
122     instance->end();
123 
124     return result;
125 }
126 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)127 bool RuntimeObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
128 {
129     if (!instance) {
130         throwInvalidAccessError(exec);
131         return false;
132     }
133 
134     instance->begin();
135 
136     Class *aClass = instance->getClass();
137 
138     if (aClass) {
139         // See if the instance has a field with the specified name.
140         Field *aField = aClass->fieldNamed(propertyName, instance.get());
141         if (aField) {
142             slot.setCustom(this, fieldGetter);
143             instance->end();
144             return true;
145         } else {
146             // Now check if a method with specified name exists, if so return a function object for
147             // that method.
148             MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
149             if (methodList.size() > 0) {
150                 slot.setCustom(this, methodGetter);
151 
152                 instance->end();
153                 return true;
154             }
155         }
156 
157         // Try a fallback object.
158         if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) {
159             slot.setCustom(this, fallbackObjectGetter);
160             instance->end();
161             return true;
162         }
163     }
164 
165     instance->end();
166 
167     return instance->getOwnPropertySlot(this, exec, propertyName, slot);
168 }
169 
put(ExecState * exec,const Identifier & propertyName,JSValue value,PutPropertySlot & slot)170 void RuntimeObjectImp::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
171 {
172     if (!instance) {
173         throwInvalidAccessError(exec);
174         return;
175     }
176 
177     RefPtr<Instance> protector(instance);
178     instance->begin();
179 
180     // Set the value of the property.
181     Field *aField = instance->getClass()->fieldNamed(propertyName, instance.get());
182     if (aField)
183         aField->setValueToInstance(exec, instance.get(), value);
184     else if (!instance->setValueOfUndefinedField(exec, propertyName, value))
185         instance->put(this, exec, propertyName, value, slot);
186 
187     instance->end();
188 }
189 
deleteProperty(ExecState *,const Identifier &)190 bool RuntimeObjectImp::deleteProperty(ExecState*, const Identifier&)
191 {
192     // Can never remove a property of a RuntimeObject.
193     return false;
194 }
195 
defaultValue(ExecState * exec,PreferredPrimitiveType hint) const196 JSValue RuntimeObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
197 {
198     if (!instance)
199         return throwInvalidAccessError(exec);
200 
201     RefPtr<Instance> protector(instance);
202     instance->begin();
203     JSValue result = instance->defaultValue(exec, hint);
204     instance->end();
205     return result;
206 }
207 
callRuntimeObject(ExecState * exec,JSObject * function,JSValue,const ArgList & args)208 static JSValue JSC_HOST_CALL callRuntimeObject(ExecState* exec, JSObject* function, JSValue, const ArgList& args)
209 {
210     RefPtr<Instance> instance(static_cast<RuntimeObjectImp*>(function)->getInternalInstance());
211     instance->begin();
212     JSValue result = instance->invokeDefaultMethod(exec, args);
213     instance->end();
214     return result;
215 }
216 
getCallData(CallData & callData)217 CallType RuntimeObjectImp::getCallData(CallData& callData)
218 {
219     if (!instance || !instance->supportsInvokeDefaultMethod())
220         return CallTypeNone;
221     callData.native.function = callRuntimeObject;
222     return CallTypeHost;
223 }
224 
callRuntimeConstructor(ExecState * exec,JSObject * constructor,const ArgList & args)225 static JSObject* callRuntimeConstructor(ExecState* exec, JSObject* constructor, const ArgList& args)
226 {
227     RefPtr<Instance> instance(static_cast<RuntimeObjectImp*>(constructor)->getInternalInstance());
228     instance->begin();
229     JSValue result = instance->invokeConstruct(exec, args);
230     instance->end();
231 
232     ASSERT(result);
233     return result.isObject() ? static_cast<JSObject*>(result.asCell()) : constructor;
234 }
235 
getConstructData(ConstructData & constructData)236 ConstructType RuntimeObjectImp::getConstructData(ConstructData& constructData)
237 {
238     if (!instance || !instance->supportsConstruct())
239         return ConstructTypeNone;
240     constructData.native.function = callRuntimeConstructor;
241     return ConstructTypeHost;
242 }
243 
getPropertyNames(ExecState * exec,PropertyNameArray & propertyNames)244 void RuntimeObjectImp::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
245 {
246     if (!instance) {
247         throwInvalidAccessError(exec);
248         return;
249     }
250 
251     instance->begin();
252     instance->getPropertyNames(exec, propertyNames);
253     instance->end();
254 }
255 
throwInvalidAccessError(ExecState * exec)256 JSObject* RuntimeObjectImp::throwInvalidAccessError(ExecState* exec)
257 {
258     return throwError(exec, ReferenceError, "Trying to access object from destroyed plug-in.");
259 }
260 
261 }
262