1/*
2 * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#ifndef APICallbackFunction_h
27#define APICallbackFunction_h
28
29#include "APICast.h"
30#include "Error.h"
31#include "JSCallbackConstructor.h"
32#include "JSLock.h"
33#include <wtf/Vector.h>
34
35namespace JSC {
36
37struct APICallbackFunction {
38
39template <typename T> static EncodedJSValue JSC_HOST_CALL call(JSGlobalObject*, CallFrame*);
40template <typename T> static EncodedJSValue JSC_HOST_CALL construct(JSGlobalObject*, CallFrame*);
41
42};
43
44template <typename T>
45EncodedJSValue JSC_HOST_CALL APICallbackFunction::call(JSGlobalObject* globalObject, CallFrame* callFrame)
46{
47 VM& vm = getVM(globalObject);
48 auto scope = DECLARE_THROW_SCOPE(vm);
49 JSContextRef execRef = toRef(globalObject);
50 JSObjectRef functionRef = toRef(callFrame->jsCallee());
51 JSObjectRef thisObjRef = toRef(jsCast<JSObject*>(callFrame->thisValue().toThis(globalObject, NotStrictMode)));
52
53 int argumentCount = static_cast<int>(callFrame->argumentCount());
54 Vector<JSValueRef, 16> arguments;
55 arguments.reserveInitialCapacity(argumentCount);
56 for (int i = 0; i < argumentCount; i++)
57 arguments.uncheckedAppend(toRef(globalObject, callFrame->uncheckedArgument(i)));
58
59 JSValueRef exception = 0;
60 JSValueRef result;
61 {
62 JSLock::DropAllLocks dropAllLocks(globalObject);
63 result = jsCast<T*>(toJS(functionRef))->functionCallback()(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception);
64 }
65 if (exception)
66 throwException(globalObject, scope, toJS(globalObject, exception));
67
68 // result must be a valid JSValue.
69 if (!result)
70 return JSValue::encode(jsUndefined());
71
72 return JSValue::encode(toJS(globalObject, result));
73}
74
75template <typename T>
76EncodedJSValue JSC_HOST_CALL APICallbackFunction::construct(JSGlobalObject* globalObject, CallFrame* callFrame)
77{
78 VM& vm = getVM(globalObject);
79 auto scope = DECLARE_THROW_SCOPE(vm);
80 JSObject* constructor = callFrame->jsCallee();
81 JSContextRef ctx = toRef(globalObject);
82 JSObjectRef constructorRef = toRef(constructor);
83
84 JSObjectCallAsConstructorCallback callback = jsCast<T*>(constructor)->constructCallback();
85 if (callback) {
86 size_t argumentCount = callFrame->argumentCount();
87 Vector<JSValueRef, 16> arguments;
88 arguments.reserveInitialCapacity(argumentCount);
89 for (size_t i = 0; i < argumentCount; ++i)
90 arguments.uncheckedAppend(toRef(globalObject, callFrame->uncheckedArgument(i)));
91
92 JSValueRef exception = 0;
93 JSObjectRef result;
94 {
95 JSLock::DropAllLocks dropAllLocks(globalObject);
96 result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception);
97 }
98 if (exception) {
99 throwException(globalObject, scope, toJS(globalObject, exception));
100 return JSValue::encode(toJS(globalObject, exception));
101 }
102 // result must be a valid JSValue.
103 if (!result)
104 return throwVMTypeError(globalObject, scope);
105 return JSValue::encode(toJS(result));
106 }
107
108 return JSValue::encode(toJS(JSObjectMake(ctx, jsCast<JSCallbackConstructor*>(constructor)->classRef(), 0)));
109}
110
111} // namespace JSC
112
113#endif // APICallbackFunction_h
114