1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtScript module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "config.h"
41#include "qscriptfunction_p.h"
42
43#include "private/qscriptengine_p.h"
44#include "qscriptcontext.h"
45#include "private/qscriptcontext_p.h"
46#include "private/qscriptvalue_p.h"
47#include "qscriptactivationobject_p.h"
48#include "qscriptobject_p.h"
49
50#include "JSGlobalObject.h"
51#include "DebuggerCallFrame.h"
52#include "Debugger.h"
53
54namespace JSC
55{
56ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScript::FunctionWrapper));
57ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScript::FunctionWithArgWrapper));
58}
59
60QT_BEGIN_NAMESPACE
61
62namespace QScript
63{
64
65const JSC::ClassInfo FunctionWrapper::info = { .className: "QtNativeFunctionWrapper", .parentClass: &PrototypeFunction::info, .staticPropHashTable: 0, .classPropHashTableGetterFunction: 0 };
66const JSC::ClassInfo FunctionWithArgWrapper::info = { .className: "QtNativeFunctionWithArgWrapper", .parentClass: &PrototypeFunction::info, .staticPropHashTable: 0, .classPropHashTableGetterFunction: 0 };
67
68FunctionWrapper::FunctionWrapper(JSC::ExecState *exec, int length, const JSC::Identifier &name,
69 QScriptEngine::FunctionSignature function)
70 : JSC::PrototypeFunction(exec, length, name, proxyCall),
71 data(new Data())
72{
73 data->function = function;
74}
75
76FunctionWrapper::~FunctionWrapper()
77{
78 delete data;
79}
80
81JSC::ConstructType FunctionWrapper::getConstructData(JSC::ConstructData& consData)
82{
83 consData.native.function = proxyConstruct;
84 consData.native.function.doNotCallDebuggerFunctionExit();
85 return JSC::ConstructTypeHost;
86}
87
88JSC::JSValue FunctionWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObject *callee,
89 JSC::JSValue thisObject, const JSC::ArgList &args)
90{
91 FunctionWrapper *self = static_cast<FunctionWrapper*>(callee);
92 QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec);
93
94 JSC::ExecState *oldFrame = eng_p->currentFrame;
95 eng_p->pushContext(exec, thisObject, args, callee);
96 QScriptContext *ctx = eng_p->contextForFrame(frame: eng_p->currentFrame);
97
98 QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(d: eng_p));
99 if (!result.isValid())
100 result = QScriptValue(QScriptValue::UndefinedValue);
101
102 eng_p->popContext();
103 eng_p->currentFrame = oldFrame;
104
105 return eng_p->scriptValueToJSCValue(value: result);
106}
107
108JSC::JSObject* FunctionWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObject *callee,
109 const JSC::ArgList &args)
110{
111 FunctionWrapper *self = static_cast<FunctionWrapper*>(callee);
112 QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec);
113
114 JSC::ExecState *oldFrame = eng_p->currentFrame;
115 eng_p->pushContext(exec, JSC::JSValue(), args, callee, calledAsConstructor: true);
116 QScriptContext *ctx = eng_p->contextForFrame(frame: eng_p->currentFrame);
117
118 QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(d: eng_p));
119
120 if (JSC::Debugger* debugger = eng_p->originalGlobalObject()->debugger())
121 debugger->functionExit(returnValue: QScriptValuePrivate::get(q: result)->jscValue, sourceID: -1);
122
123 if (!result.isObject())
124 result = ctx->thisObject();
125
126 eng_p->popContext();
127 eng_p->currentFrame = oldFrame;
128
129 return JSC::asObject(value: eng_p->scriptValueToJSCValue(value: result));
130}
131
132FunctionWithArgWrapper::FunctionWithArgWrapper(JSC::ExecState *exec, int length, const JSC::Identifier &name,
133 QScriptEngine::FunctionWithArgSignature function, void *arg)
134 : JSC::PrototypeFunction(exec, length, name, proxyCall),
135 data(new Data())
136{
137 data->function = function;
138 data->arg = arg;
139}
140
141FunctionWithArgWrapper::~FunctionWithArgWrapper()
142{
143 delete data;
144}
145
146JSC::ConstructType FunctionWithArgWrapper::getConstructData(JSC::ConstructData& consData)
147{
148 consData.native.function = proxyConstruct;
149 return JSC::ConstructTypeHost;
150}
151
152JSC::JSValue FunctionWithArgWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObject *callee,
153 JSC::JSValue thisObject, const JSC::ArgList &args)
154{
155 FunctionWithArgWrapper *self = static_cast<FunctionWithArgWrapper*>(callee);
156 QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec);
157
158 JSC::ExecState *oldFrame = eng_p->currentFrame;
159 eng_p->pushContext(exec, thisObject, args, callee);
160 QScriptContext *ctx = eng_p->contextForFrame(frame: eng_p->currentFrame);
161
162 QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(d: eng_p), self->data->arg);
163
164 eng_p->popContext();
165 eng_p->currentFrame = oldFrame;
166
167 return eng_p->scriptValueToJSCValue(value: result);
168}
169
170JSC::JSObject* FunctionWithArgWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObject *callee,
171 const JSC::ArgList &args)
172{
173 FunctionWithArgWrapper *self = static_cast<FunctionWithArgWrapper*>(callee);
174 QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec);
175
176 JSC::ExecState *oldFrame = eng_p->currentFrame;
177 eng_p->pushContext(exec, JSC::JSValue(), args, callee, calledAsConstructor: true);
178 QScriptContext *ctx = eng_p->contextForFrame(frame: eng_p->currentFrame);
179
180 QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(d: eng_p) , self->data->arg);
181 if (!result.isObject())
182 result = ctx->thisObject();
183
184 eng_p->popContext();
185 eng_p->currentFrame = oldFrame;
186
187 return JSC::asObject(value: eng_p->scriptValueToJSCValue(value: result));
188}
189
190} // namespace QScript
191
192QT_END_NAMESPACE
193

source code of qtscript/src/script/bridge/qscriptfunction.cpp