2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "ExceptionHelpers.h"
31 #include "JSCallbackFunction.h"
32 #include "JSClassRef.h"
33 #include "JSFunction.h"
34 #include "JSGlobalObject.h"
36 #include "JSObjectRef.h"
38 #include "JSStringRef.h"
39 #include "OpaqueJSString.h"
40 #include "PropertyNameArray.h"
41 #include <wtf/Vector.h>
45 template <class Parent
>
46 inline JSCallbackObject
<Parent
>* JSCallbackObject
<Parent
>::asCallbackObject(JSValue value
)
48 ASSERT(asObject(value
)->inherits(&s_info
));
49 return jsCast
<JSCallbackObject
*>(asObject(value
));
52 template <class Parent
>
53 JSCallbackObject
<Parent
>::JSCallbackObject(ExecState
* exec
, Structure
* structure
, JSClassRef jsClass
, void* data
)
54 : Parent(exec
->vm(), structure
)
55 , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(data
, jsClass
)))
59 // Global object constructor.
60 // FIXME: Move this into a separate JSGlobalCallbackObject class derived from this one.
61 template <class Parent
>
62 JSCallbackObject
<Parent
>::JSCallbackObject(VM
& vm
, JSClassRef jsClass
, Structure
* structure
)
63 : Parent(vm
, structure
)
64 , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(0, jsClass
)))
68 template <class Parent
>
69 void JSCallbackObject
<Parent
>::finishCreation(ExecState
* exec
)
71 Base::finishCreation(exec
->vm());
72 ASSERT(Parent::inherits(&s_info
));
76 // This is just for Global object, so we can assume that Base::finishCreation is JSGlobalObject::finishCreation.
77 template <class Parent
>
78 void JSCallbackObject
<Parent
>::finishCreation(VM
& vm
)
80 ASSERT(Parent::inherits(&s_info
));
81 ASSERT(Parent::isGlobalObject());
82 Base::finishCreation(vm
);
83 init(jsCast
<JSGlobalObject
*>(this)->globalExec());
86 template <class Parent
>
87 void JSCallbackObject
<Parent
>::init(ExecState
* exec
)
91 Vector
<JSObjectInitializeCallback
, 16> initRoutines
;
92 JSClassRef jsClass
= classRef();
94 if (JSObjectInitializeCallback initialize
= jsClass
->initialize
)
95 initRoutines
.append(initialize
);
96 } while ((jsClass
= jsClass
->parentClass
));
98 // initialize from base to derived
99 for (int i
= static_cast<int>(initRoutines
.size()) - 1; i
>= 0; i
--) {
100 APICallbackShim
callbackShim(exec
);
101 JSObjectInitializeCallback initialize
= initRoutines
[i
];
102 initialize(toRef(exec
), toRef(this));
105 for (JSClassRef jsClassPtr
= classRef(); jsClassPtr
; jsClassPtr
= jsClassPtr
->parentClass
) {
106 if (jsClassPtr
->finalize
) {
107 WeakSet::allocate(this, m_callbackObjectData
.get(), classRef());
113 template <class Parent
>
114 String JSCallbackObject
<Parent
>::className(const JSObject
* object
)
116 const JSCallbackObject
* thisObject
= jsCast
<const JSCallbackObject
*>(object
);
117 String thisClassName
= thisObject
->classRef()->className();
118 if (!thisClassName
.isEmpty())
119 return thisClassName
;
121 return Parent::className(object
);
124 template <class Parent
>
125 bool JSCallbackObject
<Parent
>::getOwnPropertySlot(JSCell
* cell
, ExecState
* exec
, PropertyName propertyName
, PropertySlot
& slot
)
127 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
128 JSContextRef ctx
= toRef(exec
);
129 JSObjectRef thisRef
= toRef(thisObject
);
130 RefPtr
<OpaqueJSString
> propertyNameRef
;
132 if (StringImpl
* name
= propertyName
.publicName()) {
133 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
134 // optional optimization to bypass getProperty in cases when we only need to know if the property exists
135 if (JSObjectHasPropertyCallback hasProperty
= jsClass
->hasProperty
) {
136 if (!propertyNameRef
)
137 propertyNameRef
= OpaqueJSString::create(name
);
138 APICallbackShim
callbackShim(exec
);
139 if (hasProperty(ctx
, thisRef
, propertyNameRef
.get())) {
140 slot
.setCustom(thisObject
, callbackGetter
);
143 } else if (JSObjectGetPropertyCallback getProperty
= jsClass
->getProperty
) {
144 if (!propertyNameRef
)
145 propertyNameRef
= OpaqueJSString::create(name
);
146 JSValueRef exception
= 0;
149 APICallbackShim
callbackShim(exec
);
150 value
= getProperty(ctx
, thisRef
, propertyNameRef
.get(), &exception
);
153 throwError(exec
, toJS(exec
, exception
));
154 slot
.setValue(jsUndefined());
158 slot
.setValue(toJS(exec
, value
));
163 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
164 if (staticValues
->contains(name
)) {
165 JSValue value
= thisObject
->getStaticValue(exec
, propertyName
);
167 slot
.setValue(value
);
173 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
174 if (staticFunctions
->contains(name
)) {
175 slot
.setCustom(thisObject
, staticFunctionGetter
);
182 return Parent::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
185 template <class Parent
>
186 bool JSCallbackObject
<Parent
>::getOwnPropertySlotByIndex(JSCell
* cell
, ExecState
* exec
, unsigned propertyName
, PropertySlot
& slot
)
188 return cell
->methodTable()->getOwnPropertySlot(cell
, exec
, Identifier::from(exec
, propertyName
), slot
);
191 template <class Parent
>
192 JSValue JSCallbackObject
<Parent
>::defaultValue(const JSObject
* object
, ExecState
* exec
, PreferredPrimitiveType hint
)
194 const JSCallbackObject
* thisObject
= jsCast
<const JSCallbackObject
*>(object
);
195 JSContextRef ctx
= toRef(exec
);
196 JSObjectRef thisRef
= toRef(thisObject
);
197 ::JSType jsHint
= hint
== PreferString
? kJSTypeString
: kJSTypeNumber
;
199 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
200 if (JSObjectConvertToTypeCallback convertToType
= jsClass
->convertToType
) {
201 JSValueRef exception
= 0;
202 JSValueRef result
= convertToType(ctx
, thisRef
, jsHint
, &exception
);
204 throwError(exec
, toJS(exec
, exception
));
205 return jsUndefined();
208 return toJS(exec
, result
);
212 return Parent::defaultValue(object
, exec
, hint
);
215 template <class Parent
>
216 bool JSCallbackObject
<Parent
>::getOwnPropertyDescriptor(JSObject
* object
, ExecState
* exec
, PropertyName propertyName
, PropertyDescriptor
& descriptor
)
218 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(object
);
219 PropertySlot
slot(thisObject
);
220 if (thisObject
->methodTable()->getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
)) {
221 // Ideally we should return an access descriptor, but returning a value descriptor is better than nothing.
222 JSValue value
= slot
.getValue(exec
, propertyName
);
223 if (!exec
->hadException())
224 descriptor
.setValue(value
);
225 // We don't know whether the property is configurable, but assume it is.
226 descriptor
.setConfigurable(true);
227 // We don't know whether the property is enumerable (we could call getOwnPropertyNames() to find out), but assume it isn't.
228 descriptor
.setEnumerable(false);
232 return Parent::getOwnPropertyDescriptor(thisObject
, exec
, propertyName
, descriptor
);
235 template <class Parent
>
236 void JSCallbackObject
<Parent
>::put(JSCell
* cell
, ExecState
* exec
, PropertyName propertyName
, JSValue value
, PutPropertySlot
& slot
)
238 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
239 JSContextRef ctx
= toRef(exec
);
240 JSObjectRef thisRef
= toRef(thisObject
);
241 RefPtr
<OpaqueJSString
> propertyNameRef
;
242 JSValueRef valueRef
= toRef(exec
, value
);
244 if (StringImpl
* name
= propertyName
.publicName()) {
245 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
246 if (JSObjectSetPropertyCallback setProperty
= jsClass
->setProperty
) {
247 if (!propertyNameRef
)
248 propertyNameRef
= OpaqueJSString::create(name
);
249 JSValueRef exception
= 0;
252 APICallbackShim
callbackShim(exec
);
253 result
= setProperty(ctx
, thisRef
, propertyNameRef
.get(), valueRef
, &exception
);
256 throwError(exec
, toJS(exec
, exception
));
257 if (result
|| exception
)
261 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
262 if (StaticValueEntry
* entry
= staticValues
->get(name
)) {
263 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
265 if (JSObjectSetPropertyCallback setProperty
= entry
->setProperty
) {
266 if (!propertyNameRef
)
267 propertyNameRef
= OpaqueJSString::create(name
);
268 JSValueRef exception
= 0;
271 APICallbackShim
callbackShim(exec
);
272 result
= setProperty(ctx
, thisRef
, propertyNameRef
.get(), valueRef
, &exception
);
275 throwError(exec
, toJS(exec
, exception
));
276 if (result
|| exception
)
282 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
283 if (StaticFunctionEntry
* entry
= staticFunctions
->get(name
)) {
284 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
286 thisObject
->JSCallbackObject
<Parent
>::putDirect(exec
->vm(), propertyName
, value
); // put as override property
293 return Parent::put(thisObject
, exec
, propertyName
, value
, slot
);
296 template <class Parent
>
297 void JSCallbackObject
<Parent
>::putByIndex(JSCell
* cell
, ExecState
* exec
, unsigned propertyIndex
, JSValue value
, bool shouldThrow
)
299 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
300 JSContextRef ctx
= toRef(exec
);
301 JSObjectRef thisRef
= toRef(thisObject
);
302 RefPtr
<OpaqueJSString
> propertyNameRef
;
303 JSValueRef valueRef
= toRef(exec
, value
);
304 Identifier propertyName
= Identifier(exec
, String::number(propertyIndex
));
306 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
307 if (JSObjectSetPropertyCallback setProperty
= jsClass
->setProperty
) {
308 if (!propertyNameRef
)
309 propertyNameRef
= OpaqueJSString::create(propertyName
.impl());
310 JSValueRef exception
= 0;
313 APICallbackShim
callbackShim(exec
);
314 result
= setProperty(ctx
, thisRef
, propertyNameRef
.get(), valueRef
, &exception
);
317 throwError(exec
, toJS(exec
, exception
));
318 if (result
|| exception
)
322 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
323 if (StaticValueEntry
* entry
= staticValues
->get(propertyName
.impl())) {
324 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
326 if (JSObjectSetPropertyCallback setProperty
= entry
->setProperty
) {
327 if (!propertyNameRef
)
328 propertyNameRef
= OpaqueJSString::create(propertyName
.impl());
329 JSValueRef exception
= 0;
332 APICallbackShim
callbackShim(exec
);
333 result
= setProperty(ctx
, thisRef
, propertyNameRef
.get(), valueRef
, &exception
);
336 throwError(exec
, toJS(exec
, exception
));
337 if (result
|| exception
)
343 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
344 if (StaticFunctionEntry
* entry
= staticFunctions
->get(propertyName
.impl())) {
345 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
352 return Parent::putByIndex(thisObject
, exec
, propertyIndex
, value
, shouldThrow
);
355 template <class Parent
>
356 bool JSCallbackObject
<Parent
>::deleteProperty(JSCell
* cell
, ExecState
* exec
, PropertyName propertyName
)
358 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
359 JSContextRef ctx
= toRef(exec
);
360 JSObjectRef thisRef
= toRef(thisObject
);
361 RefPtr
<OpaqueJSString
> propertyNameRef
;
363 if (StringImpl
* name
= propertyName
.publicName()) {
364 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
365 if (JSObjectDeletePropertyCallback deleteProperty
= jsClass
->deleteProperty
) {
366 if (!propertyNameRef
)
367 propertyNameRef
= OpaqueJSString::create(name
);
368 JSValueRef exception
= 0;
371 APICallbackShim
callbackShim(exec
);
372 result
= deleteProperty(ctx
, thisRef
, propertyNameRef
.get(), &exception
);
375 throwError(exec
, toJS(exec
, exception
));
376 if (result
|| exception
)
380 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
381 if (StaticValueEntry
* entry
= staticValues
->get(name
)) {
382 if (entry
->attributes
& kJSPropertyAttributeDontDelete
)
388 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
389 if (StaticFunctionEntry
* entry
= staticFunctions
->get(name
)) {
390 if (entry
->attributes
& kJSPropertyAttributeDontDelete
)
398 return Parent::deleteProperty(thisObject
, exec
, propertyName
);
401 template <class Parent
>
402 bool JSCallbackObject
<Parent
>::deletePropertyByIndex(JSCell
* cell
, ExecState
* exec
, unsigned propertyName
)
404 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
405 return thisObject
->methodTable()->deleteProperty(thisObject
, exec
, Identifier::from(exec
, propertyName
));
408 template <class Parent
>
409 ConstructType JSCallbackObject
<Parent
>::getConstructData(JSCell
* cell
, ConstructData
& constructData
)
411 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
412 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
413 if (jsClass
->callAsConstructor
) {
414 constructData
.native
.function
= construct
;
415 return ConstructTypeHost
;
418 return ConstructTypeNone
;
421 template <class Parent
>
422 EncodedJSValue JSCallbackObject
<Parent
>::construct(ExecState
* exec
)
424 JSObject
* constructor
= exec
->callee();
425 JSContextRef execRef
= toRef(exec
);
426 JSObjectRef constructorRef
= toRef(constructor
);
428 for (JSClassRef jsClass
= jsCast
<JSCallbackObject
<Parent
>*>(constructor
)->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
429 if (JSObjectCallAsConstructorCallback callAsConstructor
= jsClass
->callAsConstructor
) {
430 size_t argumentCount
= exec
->argumentCount();
431 Vector
<JSValueRef
, 16> arguments
;
432 arguments
.reserveInitialCapacity(argumentCount
);
433 for (size_t i
= 0; i
< argumentCount
; ++i
)
434 arguments
.uncheckedAppend(toRef(exec
, exec
->argument(i
)));
435 JSValueRef exception
= 0;
438 APICallbackShim
callbackShim(exec
);
439 result
= toJS(callAsConstructor(execRef
, constructorRef
, argumentCount
, arguments
.data(), &exception
));
442 throwError(exec
, toJS(exec
, exception
));
443 return JSValue::encode(result
);
447 RELEASE_ASSERT_NOT_REACHED(); // getConstructData should prevent us from reaching here
448 return JSValue::encode(JSValue());
451 template <class Parent
>
452 bool JSCallbackObject
<Parent
>::customHasInstance(JSObject
* object
, ExecState
* exec
, JSValue value
)
454 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(object
);
455 JSContextRef execRef
= toRef(exec
);
456 JSObjectRef thisRef
= toRef(thisObject
);
458 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
459 if (JSObjectHasInstanceCallback hasInstance
= jsClass
->hasInstance
) {
460 JSValueRef valueRef
= toRef(exec
, value
);
461 JSValueRef exception
= 0;
464 APICallbackShim
callbackShim(exec
);
465 result
= hasInstance(execRef
, thisRef
, valueRef
, &exception
);
468 throwError(exec
, toJS(exec
, exception
));
475 template <class Parent
>
476 CallType JSCallbackObject
<Parent
>::getCallData(JSCell
* cell
, CallData
& callData
)
478 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
479 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
480 if (jsClass
->callAsFunction
) {
481 callData
.native
.function
= call
;
488 template <class Parent
>
489 EncodedJSValue JSCallbackObject
<Parent
>::call(ExecState
* exec
)
491 JSContextRef execRef
= toRef(exec
);
492 JSObjectRef functionRef
= toRef(exec
->callee());
493 JSObjectRef thisObjRef
= toRef(exec
->hostThisValue().toThisObject(exec
));
495 for (JSClassRef jsClass
= jsCast
<JSCallbackObject
<Parent
>*>(toJS(functionRef
))->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
496 if (JSObjectCallAsFunctionCallback callAsFunction
= jsClass
->callAsFunction
) {
497 size_t argumentCount
= exec
->argumentCount();
498 Vector
<JSValueRef
, 16> arguments
;
499 arguments
.reserveInitialCapacity(argumentCount
);
500 for (size_t i
= 0; i
< argumentCount
; ++i
)
501 arguments
.uncheckedAppend(toRef(exec
, exec
->argument(i
)));
502 JSValueRef exception
= 0;
505 APICallbackShim
callbackShim(exec
);
506 result
= toJS(exec
, callAsFunction(execRef
, functionRef
, thisObjRef
, argumentCount
, arguments
.data(), &exception
));
509 throwError(exec
, toJS(exec
, exception
));
510 return JSValue::encode(result
);
514 RELEASE_ASSERT_NOT_REACHED(); // getCallData should prevent us from reaching here
515 return JSValue::encode(JSValue());
518 template <class Parent
>
519 void JSCallbackObject
<Parent
>::getOwnNonIndexPropertyNames(JSObject
* object
, ExecState
* exec
, PropertyNameArray
& propertyNames
, EnumerationMode mode
)
521 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(object
);
522 JSContextRef execRef
= toRef(exec
);
523 JSObjectRef thisRef
= toRef(thisObject
);
525 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
526 if (JSObjectGetPropertyNamesCallback getPropertyNames
= jsClass
->getPropertyNames
) {
527 APICallbackShim
callbackShim(exec
);
528 getPropertyNames(execRef
, thisRef
, toRef(&propertyNames
));
531 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
532 typedef OpaqueJSClassStaticValuesTable::const_iterator iterator
;
533 iterator end
= staticValues
->end();
534 for (iterator it
= staticValues
->begin(); it
!= end
; ++it
) {
535 StringImpl
* name
= it
->key
.get();
536 StaticValueEntry
* entry
= it
->value
.get();
537 if (entry
->getProperty
&& (!(entry
->attributes
& kJSPropertyAttributeDontEnum
) || (mode
== IncludeDontEnumProperties
)))
538 propertyNames
.add(Identifier(exec
, name
));
542 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
543 typedef OpaqueJSClassStaticFunctionsTable::const_iterator iterator
;
544 iterator end
= staticFunctions
->end();
545 for (iterator it
= staticFunctions
->begin(); it
!= end
; ++it
) {
546 StringImpl
* name
= it
->key
.get();
547 StaticFunctionEntry
* entry
= it
->value
.get();
548 if (!(entry
->attributes
& kJSPropertyAttributeDontEnum
) || (mode
== IncludeDontEnumProperties
))
549 propertyNames
.add(Identifier(exec
, name
));
554 Parent::getOwnNonIndexPropertyNames(thisObject
, exec
, propertyNames
, mode
);
557 template <class Parent
>
558 void JSCallbackObject
<Parent
>::setPrivate(void* data
)
560 m_callbackObjectData
->privateData
= data
;
563 template <class Parent
>
564 void* JSCallbackObject
<Parent
>::getPrivate()
566 return m_callbackObjectData
->privateData
;
569 template <class Parent
>
570 bool JSCallbackObject
<Parent
>::inherits(JSClassRef c
) const
572 for (JSClassRef jsClass
= classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
579 template <class Parent
>
580 JSValue JSCallbackObject
<Parent
>::getStaticValue(ExecState
* exec
, PropertyName propertyName
)
582 JSObjectRef thisRef
= toRef(this);
583 RefPtr
<OpaqueJSString
> propertyNameRef
;
585 if (StringImpl
* name
= propertyName
.publicName()) {
586 for (JSClassRef jsClass
= classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
587 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
588 if (StaticValueEntry
* entry
= staticValues
->get(name
)) {
589 if (JSObjectGetPropertyCallback getProperty
= entry
->getProperty
) {
590 if (!propertyNameRef
)
591 propertyNameRef
= OpaqueJSString::create(name
);
592 JSValueRef exception
= 0;
595 APICallbackShim
callbackShim(exec
);
596 value
= getProperty(toRef(exec
), thisRef
, propertyNameRef
.get(), &exception
);
599 throwError(exec
, toJS(exec
, exception
));
600 return jsUndefined();
603 return toJS(exec
, value
);
613 template <class Parent
>
614 JSValue JSCallbackObject
<Parent
>::staticFunctionGetter(ExecState
* exec
, JSValue slotParent
, PropertyName propertyName
)
616 JSCallbackObject
* thisObj
= asCallbackObject(slotParent
);
618 // Check for cached or override property.
619 PropertySlot
slot2(thisObj
);
620 if (Parent::getOwnPropertySlot(thisObj
, exec
, propertyName
, slot2
))
621 return slot2
.getValue(exec
, propertyName
);
623 if (StringImpl
* name
= propertyName
.publicName()) {
624 for (JSClassRef jsClass
= thisObj
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
625 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
626 if (StaticFunctionEntry
* entry
= staticFunctions
->get(name
)) {
627 if (JSObjectCallAsFunctionCallback callAsFunction
= entry
->callAsFunction
) {
629 JSObject
* o
= JSCallbackFunction::create(exec
, thisObj
->globalObject(), callAsFunction
, name
);
630 thisObj
->putDirect(exec
->vm(), propertyName
, o
, entry
->attributes
);
638 return throwError(exec
, createReferenceError(exec
, ASCIILiteral("Static function property defined with NULL callAsFunction callback.")));
641 template <class Parent
>
642 JSValue JSCallbackObject
<Parent
>::callbackGetter(ExecState
* exec
, JSValue slotParent
, PropertyName propertyName
)
644 JSCallbackObject
* thisObj
= asCallbackObject(slotParent
);
646 JSObjectRef thisRef
= toRef(thisObj
);
647 RefPtr
<OpaqueJSString
> propertyNameRef
;
649 if (StringImpl
* name
= propertyName
.publicName()) {
650 for (JSClassRef jsClass
= thisObj
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
651 if (JSObjectGetPropertyCallback getProperty
= jsClass
->getProperty
) {
652 if (!propertyNameRef
)
653 propertyNameRef
= OpaqueJSString::create(name
);
654 JSValueRef exception
= 0;
657 APICallbackShim
callbackShim(exec
);
658 value
= getProperty(toRef(exec
), thisRef
, propertyNameRef
.get(), &exception
);
661 throwError(exec
, toJS(exec
, exception
));
662 return jsUndefined();
665 return toJS(exec
, value
);
670 return throwError(exec
, createReferenceError(exec
, ASCIILiteral("hasProperty callback returned true for a property that doesn't exist.")));