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
->globalData(), 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(JSGlobalData
& globalData
, JSClassRef jsClass
, Structure
* structure
)
63 : Parent(globalData
, structure
)
64 , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(0, jsClass
)))
68 template <class Parent
>
69 void JSCallbackObject
<Parent
>::finishCreation(ExecState
* exec
)
71 Base::finishCreation(exec
->globalData());
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(JSGlobalData
& globalData
)
80 ASSERT(Parent::inherits(&s_info
));
81 ASSERT(Parent::isGlobalObject());
82 Base::finishCreation(globalData
);
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 UString JSCallbackObject
<Parent
>::className(const JSObject
* object
)
116 const JSCallbackObject
* thisObject
= jsCast
<const JSCallbackObject
*>(object
);
117 UString 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
, const Identifier
& propertyName
, PropertySlot
& slot
)
127 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
128 JSContextRef ctx
= toRef(exec
);
129 JSObjectRef thisRef
= toRef(thisObject
);
130 RefPtr
<OpaqueJSString
> propertyNameRef
;
132 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
133 // optional optimization to bypass getProperty in cases when we only need to know if the property exists
134 if (JSObjectHasPropertyCallback hasProperty
= jsClass
->hasProperty
) {
135 if (!propertyNameRef
)
136 propertyNameRef
= OpaqueJSString::create(propertyName
.ustring());
137 APICallbackShim
callbackShim(exec
);
138 if (hasProperty(ctx
, thisRef
, propertyNameRef
.get())) {
139 slot
.setCustom(thisObject
, callbackGetter
);
142 } else if (JSObjectGetPropertyCallback getProperty
= jsClass
->getProperty
) {
143 if (!propertyNameRef
)
144 propertyNameRef
= OpaqueJSString::create(propertyName
.ustring());
145 JSValueRef exception
= 0;
148 APICallbackShim
callbackShim(exec
);
149 value
= getProperty(ctx
, thisRef
, propertyNameRef
.get(), &exception
);
152 throwError(exec
, toJS(exec
, exception
));
153 slot
.setValue(jsUndefined());
157 slot
.setValue(toJS(exec
, value
));
162 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
163 if (staticValues
->contains(propertyName
.impl())) {
164 JSValue value
= thisObject
->getStaticValue(exec
, propertyName
);
166 slot
.setValue(value
);
172 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
173 if (staticFunctions
->contains(propertyName
.impl())) {
174 slot
.setCustom(thisObject
, staticFunctionGetter
);
180 return Parent::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
183 template <class Parent
>
184 JSValue JSCallbackObject
<Parent
>::defaultValue(const JSObject
* object
, ExecState
* exec
, PreferredPrimitiveType hint
)
186 const JSCallbackObject
* thisObject
= jsCast
<const JSCallbackObject
*>(object
);
187 JSContextRef ctx
= toRef(exec
);
188 JSObjectRef thisRef
= toRef(thisObject
);
189 ::JSType jsHint
= hint
== PreferString
? kJSTypeString
: kJSTypeNumber
;
191 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
192 if (JSObjectConvertToTypeCallback convertToType
= jsClass
->convertToType
) {
193 JSValueRef exception
= 0;
194 JSValueRef result
= convertToType(ctx
, thisRef
, jsHint
, &exception
);
196 throwError(exec
, toJS(exec
, exception
));
197 return jsUndefined();
200 return toJS(exec
, result
);
204 return Parent::defaultValue(object
, exec
, hint
);
207 template <class Parent
>
208 bool JSCallbackObject
<Parent
>::getOwnPropertyDescriptor(JSObject
* object
, ExecState
* exec
, const Identifier
& propertyName
, PropertyDescriptor
& descriptor
)
210 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(object
);
212 if (thisObject
->methodTable()->getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
)) {
213 // Ideally we should return an access descriptor, but returning a value descriptor is better than nothing.
214 JSValue value
= slot
.getValue(exec
, propertyName
);
215 if (!exec
->hadException())
216 descriptor
.setValue(value
);
217 // We don't know whether the property is configurable, but assume it is.
218 descriptor
.setConfigurable(true);
219 // We don't know whether the property is enumerable (we could call getOwnPropertyNames() to find out), but assume it isn't.
220 descriptor
.setEnumerable(false);
224 return Parent::getOwnPropertyDescriptor(thisObject
, exec
, propertyName
, descriptor
);
227 template <class Parent
>
228 void JSCallbackObject
<Parent
>::put(JSCell
* cell
, ExecState
* exec
, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
)
230 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
231 JSContextRef ctx
= toRef(exec
);
232 JSObjectRef thisRef
= toRef(thisObject
);
233 RefPtr
<OpaqueJSString
> propertyNameRef
;
234 JSValueRef valueRef
= toRef(exec
, value
);
236 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
237 if (JSObjectSetPropertyCallback setProperty
= jsClass
->setProperty
) {
238 if (!propertyNameRef
)
239 propertyNameRef
= OpaqueJSString::create(propertyName
.ustring());
240 JSValueRef exception
= 0;
243 APICallbackShim
callbackShim(exec
);
244 result
= setProperty(ctx
, thisRef
, propertyNameRef
.get(), valueRef
, &exception
);
247 throwError(exec
, toJS(exec
, exception
));
248 if (result
|| exception
)
252 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
253 if (StaticValueEntry
* entry
= staticValues
->get(propertyName
.impl())) {
254 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
256 if (JSObjectSetPropertyCallback setProperty
= entry
->setProperty
) {
257 if (!propertyNameRef
)
258 propertyNameRef
= OpaqueJSString::create(propertyName
.ustring());
259 JSValueRef exception
= 0;
262 APICallbackShim
callbackShim(exec
);
263 result
= setProperty(ctx
, thisRef
, propertyNameRef
.get(), valueRef
, &exception
);
266 throwError(exec
, toJS(exec
, exception
));
267 if (result
|| exception
)
273 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
274 if (StaticFunctionEntry
* entry
= staticFunctions
->get(propertyName
.impl())) {
275 if (entry
->attributes
& kJSPropertyAttributeReadOnly
)
277 thisObject
->JSCallbackObject
<Parent
>::putDirect(exec
->globalData(), propertyName
, value
); // put as override property
283 return Parent::put(thisObject
, exec
, propertyName
, value
, slot
);
286 template <class Parent
>
287 bool JSCallbackObject
<Parent
>::deleteProperty(JSCell
* cell
, ExecState
* exec
, const Identifier
& propertyName
)
289 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
290 JSContextRef ctx
= toRef(exec
);
291 JSObjectRef thisRef
= toRef(thisObject
);
292 RefPtr
<OpaqueJSString
> propertyNameRef
;
294 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
295 if (JSObjectDeletePropertyCallback deleteProperty
= jsClass
->deleteProperty
) {
296 if (!propertyNameRef
)
297 propertyNameRef
= OpaqueJSString::create(propertyName
.ustring());
298 JSValueRef exception
= 0;
301 APICallbackShim
callbackShim(exec
);
302 result
= deleteProperty(ctx
, thisRef
, propertyNameRef
.get(), &exception
);
305 throwError(exec
, toJS(exec
, exception
));
306 if (result
|| exception
)
310 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
311 if (StaticValueEntry
* entry
= staticValues
->get(propertyName
.impl())) {
312 if (entry
->attributes
& kJSPropertyAttributeDontDelete
)
318 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
319 if (StaticFunctionEntry
* entry
= staticFunctions
->get(propertyName
.impl())) {
320 if (entry
->attributes
& kJSPropertyAttributeDontDelete
)
327 return Parent::deleteProperty(thisObject
, exec
, propertyName
);
330 template <class Parent
>
331 bool JSCallbackObject
<Parent
>::deletePropertyByIndex(JSCell
* cell
, ExecState
* exec
, unsigned propertyName
)
333 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
334 return thisObject
->methodTable()->deleteProperty(thisObject
, exec
, Identifier::from(exec
, propertyName
));
337 template <class Parent
>
338 ConstructType JSCallbackObject
<Parent
>::getConstructData(JSCell
* cell
, ConstructData
& constructData
)
340 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
341 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
342 if (jsClass
->callAsConstructor
) {
343 constructData
.native
.function
= construct
;
344 return ConstructTypeHost
;
347 return ConstructTypeNone
;
350 template <class Parent
>
351 EncodedJSValue JSCallbackObject
<Parent
>::construct(ExecState
* exec
)
353 JSObject
* constructor
= exec
->callee();
354 JSContextRef execRef
= toRef(exec
);
355 JSObjectRef constructorRef
= toRef(constructor
);
357 for (JSClassRef jsClass
= jsCast
<JSCallbackObject
<Parent
>*>(constructor
)->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
358 if (JSObjectCallAsConstructorCallback callAsConstructor
= jsClass
->callAsConstructor
) {
359 int argumentCount
= static_cast<int>(exec
->argumentCount());
360 Vector
<JSValueRef
, 16> arguments(argumentCount
);
361 for (int i
= 0; i
< argumentCount
; i
++)
362 arguments
[i
] = toRef(exec
, exec
->argument(i
));
363 JSValueRef exception
= 0;
366 APICallbackShim
callbackShim(exec
);
367 result
= toJS(callAsConstructor(execRef
, constructorRef
, argumentCount
, arguments
.data(), &exception
));
370 throwError(exec
, toJS(exec
, exception
));
371 return JSValue::encode(result
);
375 ASSERT_NOT_REACHED(); // getConstructData should prevent us from reaching here
376 return JSValue::encode(JSValue());
379 template <class Parent
>
380 bool JSCallbackObject
<Parent
>::hasInstance(JSObject
* object
, ExecState
* exec
, JSValue value
, JSValue
)
382 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(object
);
383 JSContextRef execRef
= toRef(exec
);
384 JSObjectRef thisRef
= toRef(thisObject
);
386 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
387 if (JSObjectHasInstanceCallback hasInstance
= jsClass
->hasInstance
) {
388 JSValueRef valueRef
= toRef(exec
, value
);
389 JSValueRef exception
= 0;
392 APICallbackShim
callbackShim(exec
);
393 result
= hasInstance(execRef
, thisRef
, valueRef
, &exception
);
396 throwError(exec
, toJS(exec
, exception
));
403 template <class Parent
>
404 CallType JSCallbackObject
<Parent
>::getCallData(JSCell
* cell
, CallData
& callData
)
406 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(cell
);
407 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
408 if (jsClass
->callAsFunction
) {
409 callData
.native
.function
= call
;
416 template <class Parent
>
417 EncodedJSValue JSCallbackObject
<Parent
>::call(ExecState
* exec
)
419 JSContextRef execRef
= toRef(exec
);
420 JSObjectRef functionRef
= toRef(exec
->callee());
421 JSObjectRef thisObjRef
= toRef(exec
->hostThisValue().toThisObject(exec
));
423 for (JSClassRef jsClass
= jsCast
<JSCallbackObject
<Parent
>*>(toJS(functionRef
))->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
424 if (JSObjectCallAsFunctionCallback callAsFunction
= jsClass
->callAsFunction
) {
425 int argumentCount
= static_cast<int>(exec
->argumentCount());
426 Vector
<JSValueRef
, 16> arguments(argumentCount
);
427 for (int i
= 0; i
< argumentCount
; i
++)
428 arguments
[i
] = toRef(exec
, exec
->argument(i
));
429 JSValueRef exception
= 0;
432 APICallbackShim
callbackShim(exec
);
433 result
= toJS(exec
, callAsFunction(execRef
, functionRef
, thisObjRef
, argumentCount
, arguments
.data(), &exception
));
436 throwError(exec
, toJS(exec
, exception
));
437 return JSValue::encode(result
);
441 ASSERT_NOT_REACHED(); // getCallData should prevent us from reaching here
442 return JSValue::encode(JSValue());
445 template <class Parent
>
446 void JSCallbackObject
<Parent
>::getOwnPropertyNames(JSObject
* object
, ExecState
* exec
, PropertyNameArray
& propertyNames
, EnumerationMode mode
)
448 JSCallbackObject
* thisObject
= jsCast
<JSCallbackObject
*>(object
);
449 JSContextRef execRef
= toRef(exec
);
450 JSObjectRef thisRef
= toRef(thisObject
);
452 for (JSClassRef jsClass
= thisObject
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
453 if (JSObjectGetPropertyNamesCallback getPropertyNames
= jsClass
->getPropertyNames
) {
454 APICallbackShim
callbackShim(exec
);
455 getPropertyNames(execRef
, thisRef
, toRef(&propertyNames
));
458 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
)) {
459 typedef OpaqueJSClassStaticValuesTable::const_iterator iterator
;
460 iterator end
= staticValues
->end();
461 for (iterator it
= staticValues
->begin(); it
!= end
; ++it
) {
462 StringImpl
* name
= it
->first
.get();
463 StaticValueEntry
* entry
= it
->second
.get();
464 if (entry
->getProperty
&& (!(entry
->attributes
& kJSPropertyAttributeDontEnum
) || (mode
== IncludeDontEnumProperties
)))
465 propertyNames
.add(Identifier(exec
, name
));
469 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
470 typedef OpaqueJSClassStaticFunctionsTable::const_iterator iterator
;
471 iterator end
= staticFunctions
->end();
472 for (iterator it
= staticFunctions
->begin(); it
!= end
; ++it
) {
473 StringImpl
* name
= it
->first
.get();
474 StaticFunctionEntry
* entry
= it
->second
.get();
475 if (!(entry
->attributes
& kJSPropertyAttributeDontEnum
) || (mode
== IncludeDontEnumProperties
))
476 propertyNames
.add(Identifier(exec
, name
));
481 Parent::getOwnPropertyNames(thisObject
, exec
, propertyNames
, mode
);
484 template <class Parent
>
485 void JSCallbackObject
<Parent
>::setPrivate(void* data
)
487 m_callbackObjectData
->privateData
= data
;
490 template <class Parent
>
491 void* JSCallbackObject
<Parent
>::getPrivate()
493 return m_callbackObjectData
->privateData
;
496 template <class Parent
>
497 bool JSCallbackObject
<Parent
>::inherits(JSClassRef c
) const
499 for (JSClassRef jsClass
= classRef(); jsClass
; jsClass
= jsClass
->parentClass
)
506 template <class Parent
>
507 JSValue JSCallbackObject
<Parent
>::getStaticValue(ExecState
* exec
, const Identifier
& propertyName
)
509 JSObjectRef thisRef
= toRef(this);
510 RefPtr
<OpaqueJSString
> propertyNameRef
;
512 for (JSClassRef jsClass
= classRef(); jsClass
; jsClass
= jsClass
->parentClass
)
513 if (OpaqueJSClassStaticValuesTable
* staticValues
= jsClass
->staticValues(exec
))
514 if (StaticValueEntry
* entry
= staticValues
->get(propertyName
.impl()))
515 if (JSObjectGetPropertyCallback getProperty
= entry
->getProperty
) {
516 if (!propertyNameRef
)
517 propertyNameRef
= OpaqueJSString::create(propertyName
.ustring());
518 JSValueRef exception
= 0;
521 APICallbackShim
callbackShim(exec
);
522 value
= getProperty(toRef(exec
), thisRef
, propertyNameRef
.get(), &exception
);
525 throwError(exec
, toJS(exec
, exception
));
526 return jsUndefined();
529 return toJS(exec
, value
);
535 template <class Parent
>
536 JSValue JSCallbackObject
<Parent
>::staticFunctionGetter(ExecState
* exec
, JSValue slotParent
, const Identifier
& propertyName
)
538 JSCallbackObject
* thisObj
= asCallbackObject(slotParent
);
540 // Check for cached or override property.
541 PropertySlot
slot2(thisObj
);
542 if (Parent::getOwnPropertySlot(thisObj
, exec
, propertyName
, slot2
))
543 return slot2
.getValue(exec
, propertyName
);
545 for (JSClassRef jsClass
= thisObj
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
) {
546 if (OpaqueJSClassStaticFunctionsTable
* staticFunctions
= jsClass
->staticFunctions(exec
)) {
547 if (StaticFunctionEntry
* entry
= staticFunctions
->get(propertyName
.impl())) {
548 if (JSObjectCallAsFunctionCallback callAsFunction
= entry
->callAsFunction
) {
550 JSObject
* o
= JSCallbackFunction::create(exec
, thisObj
->globalObject(), callAsFunction
, propertyName
);
551 thisObj
->putDirect(exec
->globalData(), propertyName
, o
, entry
->attributes
);
558 return throwError(exec
, createReferenceError(exec
, "Static function property defined with NULL callAsFunction callback."));
561 template <class Parent
>
562 JSValue JSCallbackObject
<Parent
>::callbackGetter(ExecState
* exec
, JSValue slotParent
, const Identifier
& propertyName
)
564 JSCallbackObject
* thisObj
= asCallbackObject(slotParent
);
566 JSObjectRef thisRef
= toRef(thisObj
);
567 RefPtr
<OpaqueJSString
> propertyNameRef
;
569 for (JSClassRef jsClass
= thisObj
->classRef(); jsClass
; jsClass
= jsClass
->parentClass
)
570 if (JSObjectGetPropertyCallback getProperty
= jsClass
->getProperty
) {
571 if (!propertyNameRef
)
572 propertyNameRef
= OpaqueJSString::create(propertyName
.ustring());
573 JSValueRef exception
= 0;
576 APICallbackShim
callbackShim(exec
);
577 value
= getProperty(toRef(exec
), thisRef
, propertyNameRef
.get(), &exception
);
580 throwError(exec
, toJS(exec
, exception
));
581 return jsUndefined();
584 return toJS(exec
, value
);
587 return throwError(exec
, createReferenceError(exec
, "hasProperty callback returned true for a property that doesn't exist."));