Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / bridge / runtime_object.cpp
1 /*
2  * Copyright (C) 2003, 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 "runtime_object.h"
28
29 #include "JSDOMBinding.h"
30 #include "runtime_method.h"
31 #include <runtime/Error.h>
32
33 using namespace WebCore;
34
35 namespace JSC {
36 namespace Bindings {
37
38 WEBCORE_EXPORT const ClassInfo RuntimeObject::s_info = { "RuntimeObject", &Base::s_info, 0, CREATE_METHOD_TABLE(RuntimeObject) };
39
40 RuntimeObject::RuntimeObject(VM& vm, Structure* structure, RefPtr<Instance>&& instance)
41     : JSDestructibleObject(vm, structure)
42     , m_instance(WTFMove(instance))
43 {
44 }
45
46 void RuntimeObject::finishCreation(VM& vm)
47 {
48     Base::finishCreation(vm);
49     ASSERT(inherits(info()));
50 }
51
52 void RuntimeObject::destroy(JSCell* cell)
53 {
54     static_cast<RuntimeObject*>(cell)->RuntimeObject::~RuntimeObject();
55 }
56
57 void RuntimeObject::invalidate()
58 {
59     ASSERT(m_instance);
60     if (m_instance)
61         m_instance->willInvalidateRuntimeObject();
62     m_instance = nullptr;
63 }
64
65 EncodedJSValue RuntimeObject::fallbackObjectGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName propertyName)
66 {
67     RuntimeObject* thisObj = jsCast<RuntimeObject*>(slotBase);
68     RefPtr<Instance> instance = thisObj->m_instance;
69
70     if (!instance)
71         return JSValue::encode(throwInvalidAccessError(exec));
72     
73     instance->begin();
74
75     Class *aClass = instance->getClass();
76     JSValue result = aClass->fallbackObject(exec, instance.get(), propertyName);
77
78     instance->end();
79             
80     return JSValue::encode(result);
81 }
82
83 EncodedJSValue RuntimeObject::fieldGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName propertyName)
84 {    
85     RuntimeObject* thisObj = jsCast<RuntimeObject*>(slotBase);
86     RefPtr<Instance> instance = thisObj->m_instance;
87
88     if (!instance)
89         return JSValue::encode(throwInvalidAccessError(exec));
90     
91     instance->begin();
92
93     Class *aClass = instance->getClass();
94     Field* aField = aClass->fieldNamed(propertyName, instance.get());
95     JSValue result = aField->valueFromInstance(exec, instance.get());
96     
97     instance->end();
98             
99     return JSValue::encode(result);
100 }
101
102 EncodedJSValue RuntimeObject::methodGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName propertyName)
103 {
104     RuntimeObject* thisObj = jsCast<RuntimeObject*>(slotBase);
105     RefPtr<Instance> instance = thisObj->m_instance;
106
107     if (!instance)
108         return JSValue::encode(throwInvalidAccessError(exec));
109     
110     instance->begin();
111
112     JSValue method = instance->getMethod(exec, propertyName);
113
114     instance->end();
115             
116     return JSValue::encode(method);
117 }
118
119 bool RuntimeObject::getOwnPropertySlot(JSObject* object, ExecState *exec, PropertyName propertyName, PropertySlot& slot)
120 {
121     RuntimeObject* thisObject = jsCast<RuntimeObject*>(object);
122     if (!thisObject->m_instance) {
123         throwInvalidAccessError(exec);
124         return false;
125     }
126     
127     RefPtr<Instance> instance = thisObject->m_instance;
128
129     instance->begin();
130     
131     Class *aClass = instance->getClass();
132     
133     if (aClass) {
134         // See if the instance has a field with the specified name.
135         Field *aField = aClass->fieldNamed(propertyName, instance.get());
136         if (aField) {
137             slot.setCustom(thisObject, DontDelete, thisObject->fieldGetter);
138             instance->end();
139             return true;
140         } else {
141             // Now check if a method with specified name exists, if so return a function object for
142             // that method.
143             if (aClass->methodNamed(propertyName, instance.get())) {
144                 slot.setCustom(thisObject, DontDelete | ReadOnly, thisObject->methodGetter);
145                 
146                 instance->end();
147                 return true;
148             }
149         }
150
151         // Try a fallback object.
152         if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) {
153             slot.setCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->fallbackObjectGetter);
154             instance->end();
155             return true;
156         }
157     }
158         
159     instance->end();
160     
161     return instance->getOwnPropertySlot(thisObject, exec, propertyName, slot);
162 }
163
164 void RuntimeObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
165 {
166     RuntimeObject* thisObject = jsCast<RuntimeObject*>(cell);
167     if (!thisObject->m_instance) {
168         throwInvalidAccessError(exec);
169         return;
170     }
171     
172     RefPtr<Instance> instance = thisObject->m_instance;
173     instance->begin();
174
175     // Set the value of the property.
176     Field *aField = instance->getClass()->fieldNamed(propertyName, instance.get());
177     if (aField)
178         aField->setValueToInstance(exec, instance.get(), value);
179     else if (!instance->setValueOfUndefinedField(exec, propertyName, value))
180         instance->put(thisObject, exec, propertyName, value, slot);
181
182     instance->end();
183 }
184
185 bool RuntimeObject::deleteProperty(JSCell*, ExecState*, PropertyName)
186 {
187     // Can never remove a property of a RuntimeObject.
188     return false;
189 }
190
191 JSValue RuntimeObject::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint)
192 {
193     const RuntimeObject* thisObject = jsCast<const RuntimeObject*>(object);
194     if (!thisObject->m_instance)
195         return throwInvalidAccessError(exec);
196     
197     RefPtr<Instance> instance = thisObject->m_instance;
198
199     instance->begin();
200     JSValue result = instance->defaultValue(exec, hint);
201     instance->end();
202     return result;
203 }
204
205 static EncodedJSValue JSC_HOST_CALL callRuntimeObject(ExecState* exec)
206 {
207     ASSERT(exec->callee()->inherits(RuntimeObject::info()));
208     RefPtr<Instance> instance(static_cast<RuntimeObject*>(exec->callee())->getInternalInstance());
209     instance->begin();
210     JSValue result = instance->invokeDefaultMethod(exec);
211     instance->end();
212     return JSValue::encode(result);
213 }
214
215 CallType RuntimeObject::getCallData(JSCell* cell, CallData& callData)
216 {
217     RuntimeObject* thisObject = jsCast<RuntimeObject*>(cell);
218     if (!thisObject->m_instance)
219         return CallTypeNone;
220     
221     RefPtr<Instance> instance = thisObject->m_instance;
222     if (!instance->supportsInvokeDefaultMethod())
223         return CallTypeNone;
224     
225     callData.native.function = callRuntimeObject;
226     return CallTypeHost;
227 }
228
229 static EncodedJSValue JSC_HOST_CALL callRuntimeConstructor(ExecState* exec)
230 {
231     JSObject* constructor = exec->callee();
232     ASSERT(constructor->inherits(RuntimeObject::info()));
233     RefPtr<Instance> instance(static_cast<RuntimeObject*>(exec->callee())->getInternalInstance());
234     instance->begin();
235     ArgList args(exec);
236     JSValue result = instance->invokeConstruct(exec, args);
237     instance->end();
238     
239     ASSERT(result);
240     return JSValue::encode(result.isObject() ? jsCast<JSObject*>(result.asCell()) : constructor);
241 }
242
243 ConstructType RuntimeObject::getConstructData(JSCell* cell, ConstructData& constructData)
244 {
245     RuntimeObject* thisObject = jsCast<RuntimeObject*>(cell);
246     if (!thisObject->m_instance)
247         return ConstructTypeNone;
248     
249     RefPtr<Instance> instance = thisObject->m_instance;
250     if (!instance->supportsConstruct())
251         return ConstructTypeNone;
252     
253     constructData.native.function = callRuntimeConstructor;
254     return ConstructTypeHost;
255 }
256
257 void RuntimeObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode)
258 {
259     RuntimeObject* thisObject = jsCast<RuntimeObject*>(object);
260     if (!thisObject->m_instance) {
261         throwInvalidAccessError(exec);
262         return;
263     }
264
265     RefPtr<Instance> instance = thisObject->m_instance;
266     
267     instance->begin();
268     instance->getPropertyNames(exec, propertyNames);
269     instance->end();
270 }
271
272 JSObject* RuntimeObject::throwInvalidAccessError(ExecState* exec)
273 {
274     return exec->vm().throwException(exec, createReferenceError(exec, "Trying to access object from destroyed plug-in."));
275 }
276
277 }
278 }