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