+ const JSCallbackObject* thisObject = jsCast<const JSCallbackObject*>(object);
+ JSContextRef ctx = toRef(exec);
+ JSObjectRef thisRef = toRef(thisObject);
+ ::JSType jsHint = hint == PreferString ? kJSTypeString : kJSTypeNumber;
+
+ for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
+ if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
+ JSValueRef exception = 0;
+ JSValueRef result = convertToType(ctx, thisRef, jsHint, &exception);
+ if (exception) {
+ throwError(exec, toJS(exec, exception));
+ return jsUndefined();
+ }
+ if (result)
+ return toJS(exec, result);
+ }
+ }
+
+ return Parent::defaultValue(object, exec, hint);
+}
+
+template <class Parent>
+bool JSCallbackObject<Parent>::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(object);
+ PropertySlot slot;
+ if (thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot)) {
+ // Ideally we should return an access descriptor, but returning a value descriptor is better than nothing.
+ JSValue value = slot.getValue(exec, propertyName);
+ if (!exec->hadException())
+ descriptor.setValue(value);
+ // We don't know whether the property is configurable, but assume it is.
+ descriptor.setConfigurable(true);
+ // We don't know whether the property is enumerable (we could call getOwnPropertyNames() to find out), but assume it isn't.
+ descriptor.setEnumerable(false);
+ return true;
+ }
+
+ return Parent::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);