Rubber-stamped by Brady Eidson.
[webbrowser.git] / WebCore / bridge / runtime_object.cpp
blob9583fb23f02a85a5dbf5e68f8dc134290bf72e43
1 /*
2 * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
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.
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.
26 #include "config.h"
27 #include "runtime_object.h"
29 #include "JSDOMBinding.h"
30 #include "runtime_method.h"
31 #include <runtime/Error.h>
32 #include <runtime/ObjectPrototype.h>
34 using namespace WebCore;
36 namespace JSC {
38 using namespace Bindings;
40 const ClassInfo RuntimeObjectImp::s_info = { "RuntimeObject", 0, 0, 0 };
42 RuntimeObjectImp::RuntimeObjectImp(ExecState* exec, PassRefPtr<Instance> instance)
43 // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
44 // We need to pass in the right global object for "i".
45 : JSObject(deprecatedGetDOMStructure<RuntimeObjectImp>(exec))
46 , m_instance(instance)
50 RuntimeObjectImp::RuntimeObjectImp(ExecState*, NonNullPassRefPtr<Structure> structure, PassRefPtr<Instance> instance)
51 : JSObject(structure)
52 , m_instance(instance)
56 RuntimeObjectImp::~RuntimeObjectImp()
58 if (m_instance)
59 m_instance->willDestroyRuntimeObject();
62 void RuntimeObjectImp::invalidate()
64 ASSERT(m_instance);
65 if (m_instance)
66 m_instance->willInvalidateRuntimeObject();
67 m_instance = 0;
70 JSValue RuntimeObjectImp::fallbackObjectGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
72 RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase()));
73 RefPtr<Instance> instance = thisObj->m_instance;
75 if (!instance)
76 return throwInvalidAccessError(exec);
78 instance->begin();
80 Class *aClass = instance->getClass();
81 JSValue result = aClass->fallbackObject(exec, instance.get(), propertyName);
83 instance->end();
85 return result;
88 JSValue RuntimeObjectImp::fieldGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
90 RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase()));
91 RefPtr<Instance> instance = thisObj->m_instance;
93 if (!instance)
94 return throwInvalidAccessError(exec);
96 instance->begin();
98 Class *aClass = instance->getClass();
99 Field* aField = aClass->fieldNamed(propertyName, instance.get());
100 JSValue result = aField->valueFromInstance(exec, instance.get());
102 instance->end();
104 return result;
107 JSValue RuntimeObjectImp::methodGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
109 RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase()));
110 RefPtr<Instance> instance = thisObj->m_instance;
112 if (!instance)
113 return throwInvalidAccessError(exec);
115 instance->begin();
117 Class *aClass = instance->getClass();
118 MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
119 JSValue result = new (exec) RuntimeMethod(exec, propertyName, methodList);
121 instance->end();
123 return result;
126 bool RuntimeObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
128 if (!m_instance) {
129 throwInvalidAccessError(exec);
130 return false;
133 RefPtr<Instance> instance = m_instance;
135 instance->begin();
137 Class *aClass = instance->getClass();
139 if (aClass) {
140 // See if the instance has a field with the specified name.
141 Field *aField = aClass->fieldNamed(propertyName, instance.get());
142 if (aField) {
143 slot.setCustom(this, fieldGetter);
144 instance->end();
145 return true;
146 } else {
147 // Now check if a method with specified name exists, if so return a function object for
148 // that method.
149 MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
150 if (methodList.size() > 0) {
151 slot.setCustom(this, methodGetter);
153 instance->end();
154 return true;
158 // Try a fallback object.
159 if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) {
160 slot.setCustom(this, fallbackObjectGetter);
161 instance->end();
162 return true;
166 instance->end();
168 return instance->getOwnPropertySlot(this, exec, propertyName, slot);
171 bool RuntimeObjectImp::getOwnPropertyDescriptor(ExecState *exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
173 if (!m_instance) {
174 throwInvalidAccessError(exec);
175 return false;
178 RefPtr<Instance> instance = m_instance;
179 instance->begin();
181 Class *aClass = instance->getClass();
183 if (aClass) {
184 // See if the instance has a field with the specified name.
185 Field *aField = aClass->fieldNamed(propertyName, instance.get());
186 if (aField) {
187 PropertySlot slot;
188 slot.setCustom(this, fieldGetter);
189 instance->end();
190 descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete);
191 return true;
192 } else {
193 // Now check if a method with specified name exists, if so return a function object for
194 // that method.
195 MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
196 if (methodList.size() > 0) {
197 PropertySlot slot;
198 slot.setCustom(this, methodGetter);
199 instance->end();
200 descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly);
201 return true;
205 // Try a fallback object.
206 if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) {
207 PropertySlot slot;
208 slot.setCustom(this, fallbackObjectGetter);
209 instance->end();
210 descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum);
211 return true;
215 instance->end();
217 return instance->getOwnPropertyDescriptor(this, exec, propertyName, descriptor);
220 void RuntimeObjectImp::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
222 if (!m_instance) {
223 throwInvalidAccessError(exec);
224 return;
227 RefPtr<Instance> instance = m_instance;
228 instance->begin();
230 // Set the value of the property.
231 Field *aField = instance->getClass()->fieldNamed(propertyName, instance.get());
232 if (aField)
233 aField->setValueToInstance(exec, instance.get(), value);
234 else if (!instance->setValueOfUndefinedField(exec, propertyName, value))
235 instance->put(this, exec, propertyName, value, slot);
237 instance->end();
240 bool RuntimeObjectImp::deleteProperty(ExecState*, const Identifier&)
242 // Can never remove a property of a RuntimeObject.
243 return false;
246 JSValue RuntimeObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
248 if (!m_instance)
249 return throwInvalidAccessError(exec);
251 RefPtr<Instance> instance = m_instance;
253 instance->begin();
254 JSValue result = instance->defaultValue(exec, hint);
255 instance->end();
256 return result;
259 static JSValue JSC_HOST_CALL callRuntimeObject(ExecState* exec, JSObject* function, JSValue, const ArgList& args)
261 RefPtr<Instance> instance(static_cast<RuntimeObjectImp*>(function)->getInternalInstance());
262 instance->begin();
263 JSValue result = instance->invokeDefaultMethod(exec, args);
264 instance->end();
265 return result;
268 CallType RuntimeObjectImp::getCallData(CallData& callData)
270 if (!m_instance)
271 return CallTypeNone;
273 RefPtr<Instance> instance = m_instance;
274 if (!instance->supportsInvokeDefaultMethod())
275 return CallTypeNone;
277 callData.native.function = callRuntimeObject;
278 return CallTypeHost;
281 static JSObject* callRuntimeConstructor(ExecState* exec, JSObject* constructor, const ArgList& args)
283 RefPtr<Instance> instance(static_cast<RuntimeObjectImp*>(constructor)->getInternalInstance());
284 instance->begin();
285 JSValue result = instance->invokeConstruct(exec, args);
286 instance->end();
288 ASSERT(result);
289 return result.isObject() ? static_cast<JSObject*>(result.asCell()) : constructor;
292 ConstructType RuntimeObjectImp::getConstructData(ConstructData& constructData)
294 if (!m_instance)
295 return ConstructTypeNone;
297 RefPtr<Instance> instance = m_instance;
298 if (!instance->supportsConstruct())
299 return ConstructTypeNone;
301 constructData.native.function = callRuntimeConstructor;
302 return ConstructTypeHost;
305 void RuntimeObjectImp::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
307 if (!m_instance) {
308 throwInvalidAccessError(exec);
309 return;
312 RefPtr<Instance> instance = m_instance;
314 instance->begin();
315 instance->getPropertyNames(exec, propertyNames);
316 instance->end();
319 void RuntimeObjectImp::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
321 getOwnPropertyNames(exec, propertyNames);
324 JSObject* RuntimeObjectImp::throwInvalidAccessError(ExecState* exec)
326 return throwError(exec, ReferenceError, "Trying to access object from destroyed plug-in.");