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 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 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.
29 #include "ExceptionHelpers.h"
30 #include "JSCallbackFunction.h"
31 #include "JSClassRef.h"
32 #include "JSFunction.h"
33 #include "JSGlobalObject.h"
35 #include "JSObjectRef.h"
37 #include "JSStringRef.h"
38 #include "OpaqueJSString.h"
39 #include "PropertyNameArray.h"
40 #include <wtf/Vector.h>
44 template <class Parent
>
45 inline JSCallbackObject
<Parent
>* JSCallbackObject
<Parent
>::asCallbackObject(JSValue value
)
47 ASSERT(asObject(value
)->inherits(info()));
48 return jsCast
<JSCallbackObject
*>(asObject(value
));
51 template <class Parent
>
52 inline JSCallbackObject
<Parent
>* JSCallbackObject
<Parent
>::asCallbackObject(EncodedJSValue value
)
54 ASSERT(asObject(JSValue::decode(value
))->inherits(info()));
55 return jsCast
<JSCallbackObject
*>(asObject(JSValue::decode(value
)));
58 template <class Parent
>
59 JSCallbackObject
<Parent
>::JSCallbackObject(ExecState
* exec
, Structure
* structure
, JSClassRef jsClass
, void* data
)
60 : Parent(exec
->vm(), structure
)
61 , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(data
, jsClass
)))
65 // Global object constructor.
66 // FIXME: Move this into a separate JSGlobalCallbackObject class derived from this one.
67 template <class Parent
>
68 JSCallbackObject
<Parent
>::JSCallbackObject(VM
& vm
, JSClassRef jsClass
, Structure
* structure
)
69 : Parent(vm
, structure
)
70 , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(0, jsClass
)))
74 template <class Parent
>
75 void JSCallbackObject
<Parent
>::finishCreation(ExecState
* exec
)
77 Base::finishCreation(exec
->vm());
78 ASSERT(Parent::inherits(info()));
82 // This is just for Global object, so we can assume that Base::finishCreation is JSGlobalObject::finishCreation.
83 template <class Parent
>
84 void JSCallbackObject
<Parent
>::finishCreation(VM
& vm
)
86 ASSERT(Parent::inherits(info()));
87 ASSERT(Parent::isGlobalObject());
88 Base::finishCreation(vm
);
89 init(jsCast
<JSGlobalObject
*>(this)->globalExec());
92 template <class Parent
>
93 void JSCallbackObject
<Parent
>::init(ExecState
* exec
)
97 Vector
<JSObjectInitializeCallback
, 16> initRoutines
;
98 JSClassRef jsClass
= classRef();
100 if (JSObjectInitializeCallback initialize
= jsClass
->initialize
)
101 initRoutines
.append(initialize
);
102 } while ((jsClass
= jsClass
->parentClass
));
104 // initialize from base to derived
105 for (int i
= static_cast<int>(initRoutines
.size()) - 1; i
>= 0; i
--) {
106 JSLock::DropAllLocks
dropAllLocks(exec
);
107 JSObjectInitializeCallback initialize
= initRoutines
[i
];
108 initialize(toRef(exec
), toRef(this));
111 for (JSClassRef jsClassPtr
= classRef(); jsClassPtr
; jsClassPtr
= jsClassPtr
->parentClass
) {
112 if (jsClassPtr
->finalize
) {
113 WeakSet::allocate(this, m_callbackObjectData
.get(), classRef());
119 template <class Parent
>
120 String JSCallbackObject
<Parent
>::className(const JSObject
* object
)
122 const JSCallbackObject
* thisObject
= jsCast
<const JSCallbackObject
*>(object
);
123 String thisClassName
= thisObject
->classRef()->className();
124 if (!thisClassName
.isEmpty())
125 return thisClassName
;
127 return Parent::className(object
);
130 template <class Parent
>
131 bool JSCallbackObject
<Parent
>::getOwnPropertySlot(JSObject
* object
, ExecState
* exec
, PropertyName propertyName
, PropertySlot
& slot
)
133 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(object
);
134 JSContextRef ctx
= toRef(exec
);
135 JSObjectRef thisRef
= toRef(thisObject
);
136 RefPtr
<OpaqueJSString
> propertyNameRef
;
138 if (StringImpl
* name
= propertyName
.uid()) {
139 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
140 // optional optimization to bypass getProperty in cases when we only need to know if the property exists
141 if (JSObjectHasPropertyCallback hasProperty
= jsClass
->hasProperty
) {
142 if (!propertyNameRef
)
143 propertyNameRef
= OpaqueJSString::create(name
);
144 JSLock::DropAllLocks
dropAllLocks(exec
);
145 if (hasProperty(ctx
, thisRef
, propertyNameRef
.get())) {
146 slot
.setCustom(thisObject
, ReadOnly
| DontEnum
, callbackGetter
);
149 } else if (JSObjectGetPropertyCallback getProperty
= jsClass
->getProperty
) {
150 if (!propertyNameRef
)
151 propertyNameRef
= OpaqueJSString::create(name
);
152 JSValueRef exception
= 0;
155 JSLock::DropAllLocks
dropAllLocks(exec
);
156 value
= getProperty(ctx
, thisRef
, propertyNameRef
.get(), &exception
);
159 exec
->vm().throwException(exec
, toJS(exec
, exception
));
160 slot
.setValue(thisObject
, ReadOnly
| DontEnum
, jsUndefined());
164 slot
.setValue(thisObject
, ReadOnly
| DontEnum
, toJS(exec
, value
));
169 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
170 if (staticValues
->contains(name
)) {
171 JSValue value
= thisObject
->getStaticValue(exec
, propertyName
);
173 slot
.setValue(thisObject
, ReadOnly
| DontEnum
, value
);
179 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
180 if (staticFunctions
->contains(name
)) {
181 slot
.setCustom(thisObject
, ReadOnly
| DontEnum
, staticFunctionGetter
);
188 return Parent::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
191 template <class Parent
>
192 bool JSCallbackObject
<Parent
>::getOwnPropertySlotByIndex(JSObject
* object
, ExecState
* exec
, unsigned propertyName
, PropertySlot
& slot
)
194 return object
->methodTable()->getOwnPropertySlot(object
, exec
, Identifier::from(exec
, propertyName
), slot
);
197 template <class Parent
>
198 JSValue JSCallbackObject
<Parent
>::defaultValue(const JSObject
* object
, ExecState
* exec
, PreferredPrimitiveType hint
)
200 const JSCallbackObject
* thisObject
= jsCast
<const JSCallbackObject
*>(object
);
201 JSContextRef ctx
= toRef(exec
);
202 JSObjectRef thisRef
= toRef(thisObject
);
203 ::JSType jsHint
= hint
== PreferString
? kJSTypeString
: kJSTypeNumber
;
205 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
206 if (JSObjectConvertToTypeCallback convertToType
= jsClass
->convertToType
) {
207 JSValueRef exception
= 0;
208 JSValueRef result
= convertToType(ctx
, thisRef
, jsHint
, &exception
);
210 exec
->vm().throwException(exec
, toJS(exec
, exception
));
211 return jsUndefined();
214 return toJS(exec
, result
);
218 return Parent::defaultValue(object
, exec
, hint
);
221 template <class Parent
>
222 void JSCallbackObject
<Parent
>::put(JSCell
* cell
, ExecState
* exec
, PropertyName propertyName
, JSValue value
, PutPropertySlot
& slot
)
224 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
225 JSContextRef ctx
= toRef(exec
);
226 JSObjectRef thisRef
= toRef(thisObject
);
227 RefPtr
<OpaqueJSString
> propertyNameRef
;
228 JSValueRef valueRef
= toRef(exec
, value
);
230 if (StringImpl
* name
= propertyName
.uid()) {
231 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
232 if (JSObjectSetPropertyCallback setProperty
= jsClass
->setProperty
) {
233 if (!propertyNameRef
)
234 propertyNameRef
= OpaqueJSString::create(name
);
235 JSValueRef exception
= 0;
238 JSLock::DropAllLocks
dropAllLocks(exec
);
239 result
= setProperty(ctx
, thisRef
, propertyNameRef
.get(), valueRef
, &exception
);
242 exec
->vm().throwException(exec
, toJS(exec
, exception
));
243 if (result
|| exception
)
247 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
248 if (StaticValueEntry
* entry
= staticValues
->get(name
)) {
249 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
251 if (JSObjectSetPropertyCallback setProperty
= entry
->setProperty
) {
252 JSValueRef exception
= 0;
255 JSLock::DropAllLocks
dropAllLocks(exec
);
256 result
= setProperty(ctx
, thisRef
, entry
->propertyNameRef
.get(), valueRef
, &exception
);
259 exec
->vm().throwException(exec
, toJS(exec
, exception
));
260 if (result
|| exception
)
266 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
267 if (StaticFunctionEntry
* entry
= staticFunctions
->get(name
)) {
268 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
270 thisObject
->JSCallbackObject
<Parent
>::putDirect(exec
->vm(), propertyName
, value
); // put as override property
277 return Parent::put(thisObject
, exec
, propertyName
, value
, slot
);
280 template <class Parent
>
281 void JSCallbackObject
<Parent
>::putByIndex(JSCell
* cell
, ExecState
* exec
, unsigned propertyIndex
, JSValue value
, bool shouldThrow
)
283 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
284 JSContextRef ctx
= toRef(exec
);
285 JSObjectRef thisRef
= toRef(thisObject
);
286 RefPtr
<OpaqueJSString
> propertyNameRef
;
287 JSValueRef valueRef
= toRef(exec
, value
);
288 Identifier propertyName
= Identifier::from(exec
, propertyIndex
);
290 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
291 if (JSObjectSetPropertyCallback setProperty
= jsClass
->setProperty
) {
292 if (!propertyNameRef
)
293 propertyNameRef
= OpaqueJSString::create(propertyName
.impl());
294 JSValueRef exception
= 0;
297 JSLock::DropAllLocks
dropAllLocks(exec
);
298 result
= setProperty(ctx
, thisRef
, propertyNameRef
.get(), valueRef
, &exception
);
301 exec
->vm().throwException(exec
, toJS(exec
, exception
));
302 if (result
|| exception
)
306 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
307 if (StaticValueEntry
* entry
= staticValues
->get(propertyName
.impl())) {
308 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
310 if (JSObjectSetPropertyCallback setProperty
= entry
->setProperty
) {
311 JSValueRef exception
= 0;
314 JSLock::DropAllLocks
dropAllLocks(exec
);
315 result
= setProperty(ctx
, thisRef
, entry
->propertyNameRef
.get(), valueRef
, &exception
);
318 exec
->vm().throwException(exec
, toJS(exec
, exception
));
319 if (result
|| exception
)
325 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
326 if (StaticFunctionEntry
* entry
= staticFunctions
->get(propertyName
.impl())) {
327 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
334 return Parent::putByIndex(thisObject
, exec
, propertyIndex
, value
, shouldThrow
);
337 template <class Parent
>
338 bool JSCallbackObject
<Parent
>::deleteProperty(JSCell
* cell
, ExecState
* exec
, PropertyName propertyName
)
340 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
341 JSContextRef ctx
= toRef(exec
);
342 JSObjectRef thisRef
= toRef(thisObject
);
343 RefPtr
<OpaqueJSString
> propertyNameRef
;
345 if (StringImpl
* name
= propertyName
.uid()) {
346 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
347 if (JSObjectDeletePropertyCallback deleteProperty
= jsClass
->deleteProperty
) {
348 if (!propertyNameRef
)
349 propertyNameRef
= OpaqueJSString::create(name
);
350 JSValueRef exception
= 0;
353 JSLock::DropAllLocks
dropAllLocks(exec
);
354 result
= deleteProperty(ctx
, thisRef
, propertyNameRef
.get(), &exception
);
357 exec
->vm().throwException(exec
, toJS(exec
, exception
));
358 if (result
|| exception
)
362 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
363 if (StaticValueEntry
* entry
= staticValues
->get(name
)) {
364 if (entry
->attributes
& kJSPropertyAttributeDontDelete
)
370 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
371 if (StaticFunctionEntry
* entry
= staticFunctions
->get(name
)) {
372 if (entry
->attributes
& kJSPropertyAttributeDontDelete
)
380 return Parent::deleteProperty(thisObject
, exec
, propertyName
);
383 template <class Parent
>
384 bool JSCallbackObject
<Parent
>::deletePropertyByIndex(JSCell
* cell
, ExecState
* exec
, unsigned propertyName
)
386 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
387 return thisObject
->methodTable()->deleteProperty(thisObject
, exec
, Identifier::from(exec
, propertyName
));
390 template <class Parent
>
391 ConstructType JSCallbackObject
<Parent
>::getConstructData(JSCell
* cell
, ConstructData
& constructData
)
393 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
394 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
395 if (jsClass
->callAsConstructor
) {
396 constructData
.native
.function
= construct
;
397 return ConstructTypeHost
;
400 return ConstructTypeNone
;
403 template <class Parent
>
404 EncodedJSValue JSCallbackObject
<Parent
>::construct(ExecState
* exec
)
406 JSObject
* constructor
= exec
->callee();
407 JSContextRef execRef
= toRef(exec
);
408 JSObjectRef constructorRef
= toRef(constructor
);
410 for (JSClassRef jsClass
= jsCast
<JSCallbackObject
<Parent
>*>(constructor
)->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
411 if (JSObjectCallAsConstructorCallback callAsConstructor
= jsClass
->callAsConstructor
) {
412 size_t argumentCount
= exec
->argumentCount();
413 Vector
<JSValueRef
, 16> arguments
;
414 arguments
.reserveInitialCapacity(argumentCount
);
415 for (size_t i
= 0; i
< argumentCount
; ++i
)
416 arguments
.uncheckedAppend(toRef(exec
, exec
->uncheckedArgument(i
)));
417 JSValueRef exception
= 0;
420 JSLock::DropAllLocks
dropAllLocks(exec
);
421 result
= toJS(callAsConstructor(execRef
, constructorRef
, argumentCount
, arguments
.data(), &exception
));
424 exec
->vm().throwException(exec
, toJS(exec
, exception
));
425 return JSValue::encode(result
);
429 RELEASE_ASSERT_NOT_REACHED(); // getConstructData should prevent us from reaching here
430 return JSValue::encode(JSValue());
433 template <class Parent
>
434 bool JSCallbackObject
<Parent
>::customHasInstance(JSObject
* object
, ExecState
* exec
, JSValue value
)
436 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(object
);
437 JSContextRef execRef
= toRef(exec
);
438 JSObjectRef thisRef
= toRef(thisObject
);
440 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
441 if (JSObjectHasInstanceCallback hasInstance
= jsClass
->hasInstance
) {
442 JSValueRef valueRef
= toRef(exec
, value
);
443 JSValueRef exception
= 0;
446 JSLock::DropAllLocks
dropAllLocks(exec
);
447 result
= hasInstance(execRef
, thisRef
, valueRef
, &exception
);
450 exec
->vm().throwException(exec
, toJS(exec
, exception
));
457 template <class Parent
>
458 CallType JSCallbackObject
<Parent
>::getCallData(JSCell
* cell
, CallData
& callData
)
460 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
461 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
462 if (jsClass
->callAsFunction
) {
463 callData
.native
.function
= call
;
470 template <class Parent
>
471 EncodedJSValue JSCallbackObject
<Parent
>::call(ExecState
* exec
)
473 JSContextRef execRef
= toRef(exec
);
474 JSObjectRef functionRef
= toRef(exec
->callee());
475 JSObjectRef thisObjRef
= toRef(jsCast
<JSObject
*>(exec
->thisValue().toThis(exec
, NotStrictMode
)));
477 for (JSClassRef jsClass
= jsCast
<JSCallbackObject
<Parent
>*>(toJS(functionRef
))->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
478 if (JSObjectCallAsFunctionCallback callAsFunction
= jsClass
->callAsFunction
) {
479 size_t argumentCount
= exec
->argumentCount();
480 Vector
<JSValueRef
, 16> arguments
;
481 arguments
.reserveInitialCapacity(argumentCount
);
482 for (size_t i
= 0; i
< argumentCount
; ++i
)
483 arguments
.uncheckedAppend(toRef(exec
, exec
->uncheckedArgument(i
)));
484 JSValueRef exception
= 0;
487 JSLock::DropAllLocks
dropAllLocks(exec
);
488 result
= toJS(exec
, callAsFunction(execRef
, functionRef
, thisObjRef
, argumentCount
, arguments
.data(), &exception
));
491 exec
->vm().throwException(exec
, toJS(exec
, exception
));
492 return JSValue::encode(result
);
496 RELEASE_ASSERT_NOT_REACHED(); // getCallData should prevent us from reaching here
497 return JSValue::encode(JSValue());
500 template <class Parent
>
501 void JSCallbackObject
<Parent
>::getOwnNonIndexPropertyNames(JSObject
* object
, ExecState
* exec
, PropertyNameArray
& propertyNames
, EnumerationMode mode
)
503 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(object
);
504 JSContextRef execRef
= toRef(exec
);
505 JSObjectRef thisRef
= toRef(thisObject
);
507 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
508 if (JSObjectGetPropertyNamesCallback getPropertyNames
= jsClass
->getPropertyNames
) {
509 JSLock::DropAllLocks
dropAllLocks(exec
);
510 getPropertyNames(execRef
, thisRef
, toRef(&propertyNames
));
513 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
514 typedef OpaqueJSClassStaticValuesTable::const_iterator iterator
;
515 iterator end
= staticValues
->end();
516 for (iterator it
= staticValues
->begin(); it
!= end
; ++it
) {
517 StringImpl
* name
= it
->key
.get();
518 StaticValueEntry
* entry
= it
->value
.get();
519 if (entry
->getProperty
&& (!(entry
->attributes
& kJSPropertyAttributeDontEnum
) || (mode
== IncludeDontEnumProperties
)))
520 propertyNames
.add(Identifier(exec
, name
));
524 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
525 typedef OpaqueJSClassStaticFunctionsTable::const_iterator iterator
;
526 iterator end
= staticFunctions
->end();
527 for (iterator it
= staticFunctions
->begin(); it
!= end
; ++it
) {
528 StringImpl
* name
= it
->key
.get();
529 StaticFunctionEntry
* entry
= it
->value
.get();
530 if (!(entry
->attributes
& kJSPropertyAttributeDontEnum
) || (mode
== IncludeDontEnumProperties
))
531 propertyNames
.add(Identifier(exec
, name
));
536 Parent::getOwnNonIndexPropertyNames(thisObject
, exec
, propertyNames
, mode
);
539 template <class Parent
>
540 void JSCallbackObject
<Parent
>::setPrivate(void* data
)
542 m_callbackObjectData
->privateData
= data
;
545 template <class Parent
>
546 void* JSCallbackObject
<Parent
>::getPrivate()
548 return m_callbackObjectData
->privateData
;
551 template <class Parent
>
552 bool JSCallbackObject
<Parent
>::inherits(JSClassRef c
) const
554 for (JSClassRef jsClass
= classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
561 template <class Parent
>
562 JSValue JSCallbackObject
<Parent
>::getStaticValue(ExecState
* exec
, PropertyName propertyName
)
564 JSObjectRef thisRef
= toRef(this);
566 if (StringImpl
* name
= propertyName
.uid()) {
567 for (JSClassRef jsClass
= classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
568 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
569 if (StaticValueEntry
* entry
= staticValues
->get(name
)) {
570 if (JSObjectGetPropertyCallback getProperty
= entry
->getProperty
) {
571 JSValueRef exception
= 0;
574 JSLock::DropAllLocks
dropAllLocks(exec
);
575 value
= getProperty(toRef(exec
), thisRef
, entry
->propertyNameRef
.get(), &exception
);
578 exec
->vm().throwException(exec
, toJS(exec
, exception
));
579 return jsUndefined();
582 return toJS(exec
, value
);
592 template <class Parent
>
593 EncodedJSValue JSCallbackObject
<Parent
>::staticFunctionGetter(ExecState
* exec
, JSObject
* slotParent
, EncodedJSValue
, PropertyName propertyName
)
595 JSCallbackObject
* thisObj
= asCallbackObject(slotParent
);
597 // Check for cached or override property.
598 PropertySlot
slot2(thisObj
);
599 if (Parent::getOwnPropertySlot(thisObj
, exec
, propertyName
, slot2
))
600 return JSValue::encode(slot2
.getValue(exec
, propertyName
));
602 if (StringImpl
* name
= propertyName
.uid()) {
603 for (JSClassRef jsClass
= thisObj
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
604 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
605 if (StaticFunctionEntry
* entry
= staticFunctions
->get(name
)) {
606 if (JSObjectCallAsFunctionCallback callAsFunction
= entry
->callAsFunction
) {
608 JSObject
* o
= JSCallbackFunction::create(vm
, thisObj
->globalObject(), callAsFunction
, name
);
609 thisObj
->putDirect(vm
, propertyName
, o
, entry
->attributes
);
610 return JSValue::encode(o
);
617 return JSValue::encode(exec
->vm().throwException(exec
, createReferenceError(exec
, ASCIILiteral("Static function property defined with NULL callAsFunction callback."))));
620 template <class Parent
>
621 EncodedJSValue JSCallbackObject
<Parent
>::callbackGetter(ExecState
* exec
, JSObject
* slotParent
, EncodedJSValue
, PropertyName propertyName
)
623 JSCallbackObject
* thisObj
= asCallbackObject(slotParent
);
625 JSObjectRef thisRef
= toRef(thisObj
);
626 RefPtr
<OpaqueJSString
> propertyNameRef
;
628 if (StringImpl
* name
= propertyName
.uid()) {
629 for (JSClassRef jsClass
= thisObj
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
630 if (JSObjectGetPropertyCallback getProperty
= jsClass
->getProperty
) {
631 if (!propertyNameRef
)
632 propertyNameRef
= OpaqueJSString::create(name
);
633 JSValueRef exception
= 0;
636 JSLock::DropAllLocks
dropAllLocks(exec
);
637 value
= getProperty(toRef(exec
), thisRef
, propertyNameRef
.get(), &exception
);
640 exec
->vm().throwException(exec
, toJS(exec
, exception
));
641 return JSValue::encode(jsUndefined());
644 return JSValue::encode(toJS(exec
, value
));
649 return JSValue::encode(exec
->vm().throwException(exec
, createReferenceError(exec
, ASCIILiteral("hasProperty callback returned true for a property that doesn't exist."))));