1/*
2 * Copyright (C) 2009 Google 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 are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "ScriptFunctionCall.h"
33
34#include "JSDOMBinding.h"
35#include "JSMainThreadExecState.h"
36#include "ScriptValue.h"
37
38#include <runtime/JSLock.h>
39#include <runtime/UString.h>
40
41using namespace JSC;
42
43namespace WebCore {
44
45void ScriptCallArgumentHandler::appendArgument(const ScriptObject& argument)
46{
47    if (argument.scriptState() != m_exec) {
48        ASSERT_NOT_REACHED();
49        return;
50    }
51    m_arguments.append(argument.jsObject());
52}
53
54void ScriptCallArgumentHandler::appendArgument(const ScriptValue& argument)
55{
56    m_arguments.append(argument.jsValue());
57}
58
59void ScriptCallArgumentHandler::appendArgument(const String& argument)
60{
61    JSLock lock(SilenceAssertionsOnly);
62    m_arguments.append(jsString(m_exec, argument));
63}
64
65void ScriptCallArgumentHandler::appendArgument(const JSC::UString& argument)
66{
67    JSLock lock(SilenceAssertionsOnly);
68    m_arguments.append(jsString(m_exec, argument));
69}
70
71void ScriptCallArgumentHandler::appendArgument(const char* argument)
72{
73    JSLock lock(SilenceAssertionsOnly);
74    m_arguments.append(jsString(m_exec, UString(argument)));
75}
76
77void ScriptCallArgumentHandler::appendArgument(JSC::JSValue argument)
78{
79    m_arguments.append(argument);
80}
81
82void ScriptCallArgumentHandler::appendArgument(long argument)
83{
84    JSLock lock(SilenceAssertionsOnly);
85    m_arguments.append(jsNumber(argument));
86}
87
88void ScriptCallArgumentHandler::appendArgument(long long argument)
89{
90    JSLock lock(SilenceAssertionsOnly);
91    m_arguments.append(jsNumber(argument));
92}
93
94void ScriptCallArgumentHandler::appendArgument(unsigned int argument)
95{
96    JSLock lock(SilenceAssertionsOnly);
97    m_arguments.append(jsNumber(argument));
98}
99
100void ScriptCallArgumentHandler::appendArgument(unsigned long argument)
101{
102    JSLock lock(SilenceAssertionsOnly);
103    m_arguments.append(jsNumber(argument));
104}
105
106void ScriptCallArgumentHandler::appendArgument(int argument)
107{
108    JSLock lock(SilenceAssertionsOnly);
109    m_arguments.append(jsNumber(argument));
110}
111
112void ScriptCallArgumentHandler::appendArgument(bool argument)
113{
114    m_arguments.append(jsBoolean(argument));
115}
116
117ScriptFunctionCall::ScriptFunctionCall(const ScriptObject& thisObject, const String& name)
118    : ScriptCallArgumentHandler(thisObject.scriptState())
119    , m_thisObject(thisObject)
120    , m_name(name)
121{
122}
123
124ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions)
125{
126    JSObject* thisObject = m_thisObject.jsObject();
127
128    JSLock lock(SilenceAssertionsOnly);
129
130    JSValue function = thisObject->get(m_exec, Identifier(m_exec, stringToUString(m_name)));
131    if (m_exec->hadException()) {
132        if (reportExceptions)
133            reportException(m_exec, m_exec->exception());
134
135        hadException = true;
136        return ScriptValue();
137    }
138
139    CallData callData;
140    CallType callType = getCallData(function, callData);
141    if (callType == CallTypeNone)
142        return ScriptValue();
143
144    JSValue result = JSMainThreadExecState::call(m_exec, function, callType, callData, thisObject, m_arguments);
145    if (m_exec->hadException()) {
146        if (reportExceptions)
147            reportException(m_exec, m_exec->exception());
148
149        hadException = true;
150        return ScriptValue();
151    }
152
153    return ScriptValue(m_exec->globalData(), result);
154}
155
156ScriptValue ScriptFunctionCall::call()
157{
158    bool hadException = false;
159    return call(hadException);
160}
161
162ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExceptions)
163{
164    JSObject* thisObject = m_thisObject.jsObject();
165
166    JSLock lock(SilenceAssertionsOnly);
167
168    JSObject* constructor = asObject(thisObject->get(m_exec, Identifier(m_exec, stringToUString(m_name))));
169    if (m_exec->hadException()) {
170        if (reportExceptions)
171            reportException(m_exec, m_exec->exception());
172
173        hadException = true;
174        return ScriptObject();
175    }
176
177    ConstructData constructData;
178    ConstructType constructType = constructor->getConstructData(constructData);
179    if (constructType == ConstructTypeNone)
180        return ScriptObject();
181
182    JSValue result = JSC::construct(m_exec, constructor, constructType, constructData, m_arguments);
183    if (m_exec->hadException()) {
184        if (reportExceptions)
185            reportException(m_exec, m_exec->exception());
186
187        hadException = true;
188        return ScriptObject();
189    }
190
191    return ScriptObject(m_exec, asObject(result));
192}
193
194ScriptCallback::ScriptCallback(ScriptState* state, ScriptValue function)
195    : ScriptCallArgumentHandler(state)
196    , m_function(function)
197{
198}
199
200ScriptValue ScriptCallback::call()
201{
202    bool hadException;
203    return call(hadException);
204}
205
206ScriptValue ScriptCallback::call(bool& hadException)
207{
208    JSLock lock(SilenceAssertionsOnly);
209
210    CallData callData;
211    CallType callType = getCallData(m_function.jsValue(), callData);
212    if (callType == CallTypeNone)
213        return ScriptValue();
214
215    JSValue result = JSC::call(m_exec, m_function.jsValue(), callType, callData, m_function.jsValue(), m_arguments);
216    hadException = m_exec->hadException();
217
218    if (hadException) {
219        reportException(m_exec, m_exec->exception());
220        return ScriptValue();
221    }
222
223    return ScriptValue(m_exec->globalData(), result);
224}
225
226} // namespace WebCore
227