2 * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE 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 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.
27 #import "JavaScriptCore.h"
29 #if JSC_OBJC_API_ENABLED
31 #import "APICallbackFunction.h"
34 #import "JSCJSValueInlines.h"
36 #import "JSCellInlines.h"
37 #import "JSContextInternal.h"
38 #import "JSWrapperMap.h"
39 #import "JSValueInternal.h"
40 #import "ObjCCallbackFunction.h"
41 #import "ObjcRuntimeExtras.h"
42 #import "StructureInlines.h"
43 #import <objc/runtime.h>
44 #import <wtf/RetainPtr.h>
46 class CallbackArgument {
47 WTF_MAKE_FAST_ALLOCATED;
49 virtual ~CallbackArgument();
50 virtual void set(NSInvocation *, NSInteger, JSContext *, JSValueRef, JSValueRef*) = 0;
52 std::unique_ptr<CallbackArgument> m_next;
55 CallbackArgument::~CallbackArgument()
59 class CallbackArgumentBoolean : public CallbackArgument {
60 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
62 bool value = JSValueToBoolean([context JSGlobalContextRef], argument);
63 [invocation setArgument:&value atIndex:argumentNumber];
68 class CallbackArgumentInteger : public CallbackArgument {
69 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
71 T value = (T)JSC::toInt32(JSValueToNumber([context JSGlobalContextRef], argument, exception));
72 [invocation setArgument:&value atIndex:argumentNumber];
77 class CallbackArgumentDouble : public CallbackArgument {
78 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
80 T value = (T)JSValueToNumber([context JSGlobalContextRef], argument, exception);
81 [invocation setArgument:&value atIndex:argumentNumber];
85 class CallbackArgumentJSValue : public CallbackArgument {
86 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
88 JSValue *value = [JSValue valueWithJSValueRef:argument inContext:context];
89 [invocation setArgument:&value atIndex:argumentNumber];
93 class CallbackArgumentId : public CallbackArgument {
94 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
96 id value = valueToObject(context, argument);
97 [invocation setArgument:&value atIndex:argumentNumber];
101 class CallbackArgumentOfClass : public CallbackArgument {
103 CallbackArgumentOfClass(Class cls)
109 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
111 JSGlobalContextRef contextRef = [context JSGlobalContextRef];
113 id object = tryUnwrapObjcObject(contextRef, argument);
114 if (object && [object isKindOfClass:m_class.get()]) {
115 [invocation setArgument:&object atIndex:argumentNumber];
119 if (JSValueIsNull(contextRef, argument) || JSValueIsUndefined(contextRef, argument)) {
121 [invocation setArgument:&object atIndex:argumentNumber];
125 *exception = toRef(JSC::createTypeError(toJS(contextRef), ASCIILiteral("Argument does not match Objective-C Class")));
128 RetainPtr<Class> m_class;
131 class CallbackArgumentNSNumber : public CallbackArgument {
132 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
134 id value = valueToNumber([context JSGlobalContextRef], argument, exception);
135 [invocation setArgument:&value atIndex:argumentNumber];
139 class CallbackArgumentNSString : public CallbackArgument {
140 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
142 id value = valueToString([context JSGlobalContextRef], argument, exception);
143 [invocation setArgument:&value atIndex:argumentNumber];
147 class CallbackArgumentNSDate : public CallbackArgument {
148 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
150 id value = valueToDate([context JSGlobalContextRef], argument, exception);
151 [invocation setArgument:&value atIndex:argumentNumber];
155 class CallbackArgumentNSArray : public CallbackArgument {
156 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
158 id value = valueToArray([context JSGlobalContextRef], argument, exception);
159 [invocation setArgument:&value atIndex:argumentNumber];
163 class CallbackArgumentNSDictionary : public CallbackArgument {
164 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
166 id value = valueToDictionary([context JSGlobalContextRef], argument, exception);
167 [invocation setArgument:&value atIndex:argumentNumber];
171 class CallbackArgumentStruct : public CallbackArgument {
173 CallbackArgumentStruct(NSInvocation *conversionInvocation, const char* encodedType)
174 : m_conversionInvocation(conversionInvocation)
175 , m_buffer(encodedType)
180 void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
182 JSValue *value = [JSValue valueWithJSValueRef:argument inContext:context];
183 [m_conversionInvocation invokeWithTarget:value];
184 [m_conversionInvocation getReturnValue:m_buffer];
185 [invocation setArgument:m_buffer atIndex:argumentNumber];
188 RetainPtr<NSInvocation> m_conversionInvocation;
189 StructBuffer m_buffer;
192 class ArgumentTypeDelegate {
194 typedef std::unique_ptr<CallbackArgument> ResultType;
197 static ResultType typeInteger()
199 return std::make_unique<CallbackArgumentInteger<T>>();
203 static ResultType typeDouble()
205 return std::make_unique<CallbackArgumentDouble<T>>();
208 static ResultType typeBool()
210 return std::make_unique<CallbackArgumentBoolean>();
213 static ResultType typeVoid()
215 RELEASE_ASSERT_NOT_REACHED();
219 static ResultType typeId()
221 return std::make_unique<CallbackArgumentId>();
224 static ResultType typeOfClass(const char* begin, const char* end)
226 StringRange copy(begin, end);
227 Class cls = objc_getClass(copy);
231 if (cls == [JSValue class])
232 return std::make_unique<CallbackArgumentJSValue>();
233 if (cls == [NSString class])
234 return std::make_unique<CallbackArgumentNSString>();
235 if (cls == [NSNumber class])
236 return std::make_unique<CallbackArgumentNSNumber>();
237 if (cls == [NSDate class])
238 return std::make_unique<CallbackArgumentNSDate>();
239 if (cls == [NSArray class])
240 return std::make_unique<CallbackArgumentNSArray>();
241 if (cls == [NSDictionary class])
242 return std::make_unique<CallbackArgumentNSDictionary>();
244 return std::make_unique<CallbackArgumentOfClass>(cls);
247 static ResultType typeBlock(const char*, const char*)
252 static ResultType typeStruct(const char* begin, const char* end)
254 StringRange copy(begin, end);
255 if (NSInvocation *invocation = valueToTypeInvocationFor(copy))
256 return std::make_unique<CallbackArgumentStruct>(invocation, copy);
261 class CallbackResult {
262 WTF_MAKE_FAST_ALLOCATED;
264 virtual ~CallbackResult()
268 virtual JSValueRef get(NSInvocation *, JSContext *, JSValueRef*) = 0;
271 class CallbackResultVoid : public CallbackResult {
272 JSValueRef get(NSInvocation *, JSContext *context, JSValueRef*) override
274 return JSValueMakeUndefined([context JSGlobalContextRef]);
278 class CallbackResultId : public CallbackResult {
279 JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
282 [invocation getReturnValue:&value];
283 return objectToValue(context, value);
288 class CallbackResultNumeric : public CallbackResult {
289 JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
292 [invocation getReturnValue:&value];
293 return JSValueMakeNumber([context JSGlobalContextRef], value);
297 class CallbackResultBoolean : public CallbackResult {
298 JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
301 [invocation getReturnValue:&value];
302 return JSValueMakeBoolean([context JSGlobalContextRef], value);
306 class CallbackResultStruct : public CallbackResult {
308 CallbackResultStruct(NSInvocation *conversionInvocation, const char* encodedType)
309 : m_conversionInvocation(conversionInvocation)
310 , m_buffer(encodedType)
315 JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
317 [invocation getReturnValue:m_buffer];
319 [m_conversionInvocation setArgument:m_buffer atIndex:2];
320 [m_conversionInvocation setArgument:&context atIndex:3];
321 [m_conversionInvocation invokeWithTarget:[JSValue class]];
324 [m_conversionInvocation getReturnValue:&value];
325 return valueInternalValue(value);
328 RetainPtr<NSInvocation> m_conversionInvocation;
329 StructBuffer m_buffer;
332 class ResultTypeDelegate {
334 typedef std::unique_ptr<CallbackResult> ResultType;
337 static ResultType typeInteger()
339 return std::make_unique<CallbackResultNumeric<T>>();
343 static ResultType typeDouble()
345 return std::make_unique<CallbackResultNumeric<T>>();
348 static ResultType typeBool()
350 return std::make_unique<CallbackResultBoolean>();
353 static ResultType typeVoid()
355 return std::make_unique<CallbackResultVoid>();
358 static ResultType typeId()
360 return std::make_unique<CallbackResultId>();
363 static ResultType typeOfClass(const char*, const char*)
365 return std::make_unique<CallbackResultId>();
368 static ResultType typeBlock(const char*, const char*)
370 return std::make_unique<CallbackResultId>();
373 static ResultType typeStruct(const char* begin, const char* end)
375 StringRange copy(begin, end);
376 if (NSInvocation *invocation = typeToValueInvocationFor(copy))
377 return std::make_unique<CallbackResultStruct>(invocation, copy);
384 CallbackInstanceMethod,
391 class ObjCCallbackFunctionImpl {
393 ObjCCallbackFunctionImpl(NSInvocation *invocation, CallbackType type, Class instanceClass, std::unique_ptr<CallbackArgument> arguments, std::unique_ptr<CallbackResult> result)
395 , m_instanceClass(instanceClass)
396 , m_invocation(invocation)
397 , m_arguments(WTFMove(arguments))
398 , m_result(WTFMove(result))
400 ASSERT((type != CallbackInstanceMethod && type != CallbackInitMethod) || instanceClass);
403 void destroy(Heap& heap)
405 // We need to explicitly release the target since we didn't call
406 // -retainArguments on m_invocation (and we don't want to do so).
407 if (m_type == CallbackBlock || m_type == CallbackClassMethod)
408 heap.releaseSoon(adoptNS([m_invocation.get() target]));
409 m_instanceClass = nil;
412 JSValueRef call(JSContext *context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
416 return m_type == CallbackBlock ? [m_invocation target] : nil;
419 id wrappedConstructor()
423 return [m_invocation target];
424 case CallbackInitMethod:
425 return m_instanceClass.get();
431 bool isConstructible()
433 return !!wrappedBlock() || m_type == CallbackInitMethod;
440 RetainPtr<Class> m_instanceClass;
441 RetainPtr<NSInvocation> m_invocation;
442 std::unique_ptr<CallbackArgument> m_arguments;
443 std::unique_ptr<CallbackResult> m_result;
446 static JSValueRef objCCallbackFunctionCallAsFunction(JSContextRef callerContext, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
448 // Retake the API lock - we need this for a few reasons:
449 // (1) We don't want to support the C-API's confusing drops-locks-once policy - should only drop locks if we can do so recursively.
450 // (2) We're calling some JSC internals that require us to be on the 'inside' - e.g. createTypeError.
451 // (3) We need to be locked (per context would be fine) against conflicting usage of the ObjCCallbackFunction's NSInvocation.
452 JSC::JSLockHolder locker(toJS(callerContext));
454 ObjCCallbackFunction* callback = static_cast<ObjCCallbackFunction*>(toJS(function));
455 ObjCCallbackFunctionImpl* impl = callback->impl();
456 JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(callback->globalObject()->globalExec())];
458 CallbackData callbackData;
461 [context beginCallbackWithData:&callbackData calleeValue:function thisValue:thisObject argumentCount:argumentCount arguments:arguments];
462 result = impl->call(context, thisObject, argumentCount, arguments, exception);
463 if (context.exception)
464 *exception = valueInternalValue(context.exception);
465 [context endCallbackWithData:&callbackData];
470 static JSObjectRef objCCallbackFunctionCallAsConstructor(JSContextRef callerContext, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
472 JSC::JSLockHolder locker(toJS(callerContext));
474 ObjCCallbackFunction* callback = static_cast<ObjCCallbackFunction*>(toJS(constructor));
475 ObjCCallbackFunctionImpl* impl = callback->impl();
476 JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(toJS(callerContext)->lexicalGlobalObject()->globalExec())];
478 CallbackData callbackData;
481 [context beginCallbackWithData:&callbackData calleeValue:constructor thisValue:nullptr argumentCount:argumentCount arguments:arguments];
482 result = impl->call(context, nullptr, argumentCount, arguments, exception);
483 if (context.exception)
484 *exception = valueInternalValue(context.exception);
485 [context endCallbackWithData:&callbackData];
488 JSGlobalContextRef contextRef = [context JSGlobalContextRef];
492 if (!JSValueIsObject(contextRef, result)) {
493 *exception = toRef(JSC::createTypeError(toJS(contextRef), ASCIILiteral("Objective-C blocks called as constructors must return an object.")));
496 return (JSObjectRef)result;
499 const JSC::ClassInfo ObjCCallbackFunction::s_info = { "CallbackFunction", &Base::s_info, 0, CREATE_METHOD_TABLE(ObjCCallbackFunction) };
501 ObjCCallbackFunction::ObjCCallbackFunction(JSC::VM& vm, JSC::Structure* structure, JSObjectCallAsFunctionCallback functionCallback, JSObjectCallAsConstructorCallback constructCallback, std::unique_ptr<ObjCCallbackFunctionImpl> impl)
502 : Base(vm, structure)
503 , m_functionCallback(functionCallback)
504 , m_constructCallback(constructCallback)
505 , m_impl(WTFMove(impl))
509 ObjCCallbackFunction* ObjCCallbackFunction::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, const String& name, std::unique_ptr<ObjCCallbackFunctionImpl> impl)
511 Structure* structure = globalObject->objcCallbackFunctionStructure();
512 ObjCCallbackFunction* function = new (NotNull, allocateCell<ObjCCallbackFunction>(vm.heap)) ObjCCallbackFunction(vm, structure, objCCallbackFunctionCallAsFunction, objCCallbackFunctionCallAsConstructor, WTFMove(impl));
513 function->finishCreation(vm, name);
517 void ObjCCallbackFunction::destroy(JSCell* cell)
519 ObjCCallbackFunction& function = *jsCast<ObjCCallbackFunction*>(cell);
520 function.impl()->destroy(*Heap::heap(cell));
521 function.~ObjCCallbackFunction();
525 CallType ObjCCallbackFunction::getCallData(JSCell*, CallData& callData)
527 callData.native.function = APICallbackFunction::call<ObjCCallbackFunction>;
528 return CallType::Host;
531 ConstructType ObjCCallbackFunction::getConstructData(JSCell* cell, ConstructData& constructData)
533 ObjCCallbackFunction* callback = jsCast<ObjCCallbackFunction*>(cell);
534 if (!callback->impl()->isConstructible())
535 return Base::getConstructData(cell, constructData);
536 constructData.native.function = APICallbackFunction::construct<ObjCCallbackFunction>;
537 return ConstructType::Host;
540 String ObjCCallbackFunctionImpl::name()
542 if (m_type == CallbackInitMethod)
543 return class_getName(m_instanceClass.get());
544 // FIXME: Maybe we could support having the selector as the name of the non-init
545 // functions to make it a bit more user-friendly from the JS side?
549 JSValueRef ObjCCallbackFunctionImpl::call(JSContext *context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
551 JSGlobalContextRef contextRef = [context JSGlobalContextRef];
554 size_t firstArgument;
556 case CallbackInitMethod: {
557 RELEASE_ASSERT(!thisObject);
558 target = [m_instanceClass alloc];
559 if (!target || ![target isKindOfClass:m_instanceClass.get()]) {
560 *exception = toRef(JSC::createTypeError(toJS(contextRef), ASCIILiteral("self type check failed for Objective-C instance method")));
561 return JSValueMakeUndefined(contextRef);
563 [m_invocation setTarget:target];
567 case CallbackInstanceMethod: {
568 target = tryUnwrapObjcObject(contextRef, thisObject);
569 if (!target || ![target isKindOfClass:m_instanceClass.get()]) {
570 *exception = toRef(JSC::createTypeError(toJS(contextRef), ASCIILiteral("self type check failed for Objective-C instance method")));
571 return JSValueMakeUndefined(contextRef);
573 [m_invocation setTarget:target];
577 case CallbackClassMethod:
584 size_t argumentNumber = 0;
585 for (CallbackArgument* argument = m_arguments.get(); argument; argument = argument->m_next.get()) {
586 JSValueRef value = argumentNumber < argumentCount ? arguments[argumentNumber] : JSValueMakeUndefined(contextRef);
587 argument->set(m_invocation.get(), argumentNumber + firstArgument, context, value, exception);
589 return JSValueMakeUndefined(contextRef);
593 [m_invocation invoke];
595 JSValueRef result = m_result->get(m_invocation.get(), context, exception);
597 // Balance our call to -alloc with a call to -autorelease. We have to do this after calling -init
598 // because init family methods are allowed to release the allocated object and return something
599 // else in its place.
600 if (m_type == CallbackInitMethod) {
601 id objcResult = tryUnwrapObjcObject(contextRef, result);
603 [objcResult autorelease];
611 static bool blockSignatureContainsClass()
613 static bool containsClass = ^{
614 id block = ^(NSString *string){ return string; };
615 return _Block_has_signature(block) && strstr(_Block_signature(block), "NSString");
617 return containsClass;
620 static inline bool skipNumber(const char*& position)
622 if (!isASCIIDigit(*position))
624 while (isASCIIDigit(*++position)) { }
628 static JSObjectRef objCCallbackFunctionForInvocation(JSContext *context, NSInvocation *invocation, CallbackType type, Class instanceClass, const char* signatureWithObjcClasses)
630 if (!signatureWithObjcClasses)
633 const char* position = signatureWithObjcClasses;
635 auto result = parseObjCType<ResultTypeDelegate>(position);
636 if (!result || !skipNumber(position))
640 case CallbackInitMethod:
641 case CallbackInstanceMethod:
642 case CallbackClassMethod:
643 // Methods are passed two implicit arguments - (id)self, and the selector.
644 if ('@' != *position++ || !skipNumber(position) || ':' != *position++ || !skipNumber(position))
648 // Blocks are passed one implicit argument - the block, of type "@?".
649 if (('@' != *position++) || ('?' != *position++) || !skipNumber(position))
651 // Only allow arguments of type 'id' if the block signature contains the NS type information.
652 if ((!blockSignatureContainsClass() && strchr(position, '@')))
657 std::unique_ptr<CallbackArgument> arguments;
658 auto* nextArgument = &arguments;
659 unsigned argumentCount = 0;
661 auto argument = parseObjCType<ArgumentTypeDelegate>(position);
662 if (!argument || !skipNumber(position))
665 *nextArgument = WTFMove(argument);
666 nextArgument = &(*nextArgument)->m_next;
670 JSC::ExecState* exec = toJS([context JSGlobalContextRef]);
671 JSC::JSLockHolder locker(exec);
672 auto impl = std::make_unique<JSC::ObjCCallbackFunctionImpl>(invocation, type, instanceClass, WTFMove(arguments), WTFMove(result));
673 const String& name = impl->name();
674 return toRef(JSC::ObjCCallbackFunction::create(exec->vm(), exec->lexicalGlobalObject(), name, WTFMove(impl)));
677 JSObjectRef objCCallbackFunctionForInit(JSContext *context, Class cls, Protocol *protocol, SEL sel, const char* types)
679 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:types]];
680 [invocation setSelector:sel];
681 return objCCallbackFunctionForInvocation(context, invocation, CallbackInitMethod, cls, _protocol_getMethodTypeEncoding(protocol, sel, YES, YES));
684 JSObjectRef objCCallbackFunctionForMethod(JSContext *context, Class cls, Protocol *protocol, BOOL isInstanceMethod, SEL sel, const char* types)
686 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:types]];
687 [invocation setSelector:sel];
688 // We need to retain the target Class because m_invocation doesn't retain it by default (and we don't want it to).
689 // FIXME: What releases it?
690 if (!isInstanceMethod)
691 [invocation setTarget:[cls retain]];
692 return objCCallbackFunctionForInvocation(context, invocation, isInstanceMethod ? CallbackInstanceMethod : CallbackClassMethod, isInstanceMethod ? cls : nil, _protocol_getMethodTypeEncoding(protocol, sel, YES, isInstanceMethod));
695 JSObjectRef objCCallbackFunctionForBlock(JSContext *context, id target)
697 if (!_Block_has_signature(target))
699 const char* signature = _Block_signature(target);
700 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:signature]];
702 // We don't want to use -retainArguments because that leaks memory. Arguments
703 // would be retained indefinitely between invocations of the callback.
704 // Additionally, we copy the target because we want the block to stick around
705 // until the ObjCCallbackFunctionImpl is destroyed.
706 [invocation setTarget:[target copy]];
708 return objCCallbackFunctionForInvocation(context, invocation, CallbackBlock, nil, signature);
711 id tryUnwrapConstructor(JSObjectRef object)
713 if (!toJS(object)->inherits(JSC::ObjCCallbackFunction::info()))
715 JSC::ObjCCallbackFunctionImpl* impl = static_cast<JSC::ObjCCallbackFunction*>(toJS(object))->impl();
716 if (!impl->isConstructible())
718 return impl->wrappedConstructor();