]> git.saurik.com Git - apple/javascriptcore.git/blame - bindings/runtime_object.cpp
JavaScriptCore-466.1.tar.gz
[apple/javascriptcore.git] / bindings / runtime_object.cpp
CommitLineData
b37bf2e1
A
1/*
2 * Copyright (C) 2003 Apple Computer, 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 "error_object.h"
30#include "operations.h"
31#include "runtime_method.h"
32#include "runtime_root.h"
33
34using namespace KJS;
35using namespace Bindings;
36
37const ClassInfo RuntimeObjectImp::info = { "RuntimeObject", 0, 0 };
38
39RuntimeObjectImp::RuntimeObjectImp(Bindings::Instance *i)
40: instance(i)
41{
42 instance->rootObject()->addRuntimeObject(this);
43}
44
45RuntimeObjectImp::~RuntimeObjectImp()
46{
47 if (instance)
48 instance->rootObject()->removeRuntimeObject(this);
49}
50
51void RuntimeObjectImp::invalidate()
52{
53 ASSERT(instance);
54 instance = 0;
55}
56
57JSValue *RuntimeObjectImp::fallbackObjectGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
58{
59 RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
60 RefPtr<Bindings::Instance> instance = thisObj->instance;
61
62 if (!instance)
63 return throwInvalidAccessError(exec);
64
65 instance->begin();
66
67 Class *aClass = instance->getClass();
68 JSValue* result = aClass->fallbackObject(exec, instance.get(), propertyName);
69
70 instance->end();
71
72 return result;
73}
74
75JSValue *RuntimeObjectImp::fieldGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
76{
77 RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
78 RefPtr<Bindings::Instance> instance = thisObj->instance;
79
80 if (!instance)
81 return throwInvalidAccessError(exec);
82
83 instance->begin();
84
85 Class *aClass = instance->getClass();
86 Field* aField = aClass->fieldNamed(propertyName, instance.get());
87 JSValue *result = instance->getValueOfField(exec, aField);
88
89 instance->end();
90
91 return result;
92}
93
94JSValue *RuntimeObjectImp::methodGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
95{
96 RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
97 RefPtr<Bindings::Instance> instance = thisObj->instance;
98
99 if (!instance)
100 return throwInvalidAccessError(exec);
101
102 instance->begin();
103
104 Class *aClass = instance->getClass();
105 MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
106 JSValue *result = new RuntimeMethod(exec, propertyName, methodList);
107
108 instance->end();
109
110 return result;
111}
112
113bool RuntimeObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
114{
115 if (!instance) {
116 throwInvalidAccessError(exec);
117 return false;
118 }
119
120 instance->begin();
121
122 Class *aClass = instance->getClass();
123
124 if (aClass) {
125 // See if the instance has a field with the specified name.
126 Field *aField = aClass->fieldNamed(propertyName, instance.get());
127 if (aField) {
128 slot.setCustom(this, fieldGetter);
129 instance->end();
130 return true;
131 } else {
132 // Now check if a method with specified name exists, if so return a function object for
133 // that method.
134 MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
135 if (methodList.size() > 0) {
136 slot.setCustom(this, methodGetter);
137
138 instance->end();
139 return true;
140 }
141 }
142
143 // Try a fallback object.
144 if (!aClass->fallbackObject(exec, instance.get(), propertyName)->isUndefined()) {
145 slot.setCustom(this, fallbackObjectGetter);
146 instance->end();
147 return true;
148 }
149 }
150
151 instance->end();
152
153 // don't call superclass, because runtime objects can't have custom properties or a prototype
154 return false;
155}
156
157void RuntimeObjectImp::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int)
158{
159 if (!instance) {
160 throwInvalidAccessError(exec);
161 return;
162 }
163
164 RefPtr<Bindings::Instance> protector(instance);
165 instance->begin();
166
167 // Set the value of the property.
168 Field *aField = instance->getClass()->fieldNamed(propertyName, instance.get());
169 if (aField)
170 instance->setValueOfField(exec, aField, value);
171 else if (instance->supportsSetValueOfUndefinedField())
172 instance->setValueOfUndefinedField(exec, propertyName, value);
173
174 instance->end();
175}
176
177bool RuntimeObjectImp::canPut(ExecState* exec, const Identifier& propertyName) const
178{
179 if (!instance) {
180 throwInvalidAccessError(exec);
181 return false;
182 }
183
184 instance->begin();
185
186 Field *aField = instance->getClass()->fieldNamed(propertyName, instance.get());
187
188 instance->end();
189
190 return !!aField;
191}
192
193bool RuntimeObjectImp::deleteProperty(ExecState*, const Identifier&)
194{
195 // Can never remove a property of a RuntimeObject.
196 return false;
197}
198
199JSValue *RuntimeObjectImp::defaultValue(ExecState* exec, JSType hint) const
200{
201 if (!instance)
202 return throwInvalidAccessError(exec);
203
204 JSValue *result;
205
206 RefPtr<Bindings::Instance> protector(instance);
207 instance->begin();
208
209 result = instance->defaultValue(hint);
210
211 instance->end();
212
213 return result;
214}
215
216bool RuntimeObjectImp::implementsCall() const
217{
218 if (!instance)
219 return false;
220
221 return instance->implementsCall();
222}
223
224JSValue *RuntimeObjectImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
225{
226 if (!instance)
227 return throwInvalidAccessError(exec);
228
229 RefPtr<Bindings::Instance> protector(instance);
230 instance->begin();
231
232 JSValue *aValue = instance->invokeDefaultMethod(exec, args);
233
234 instance->end();
235
236 return aValue;
237}
238
239void RuntimeObjectImp::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
240{
241 if (!instance) {
242 throwInvalidAccessError(exec);
243 return;
244 }
245
246 instance->begin();
247 instance->getPropertyNames(exec, propertyNames);
248 instance->end();
249}
250
251JSObject* RuntimeObjectImp::throwInvalidAccessError(ExecState* exec)
252{
253 return throwError(exec, ReferenceError, "Trying to access object from destroyed plug-in.");
254}