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 "qscriptclass.h"
41#include "qscriptstring.h"
42
43/*!
44 \since 4.4
45 \class QScriptClass
46 \inmodule QtScript
47 \brief The QScriptClass class provides an interface for defining custom behavior of (a class of) Qt Script objects.
48
49 \ingroup script
50
51 The QScriptClass class defines an interface for handling various
52 aspects of interaction with the Qt Script objects associated with
53 the class. Such objects are created by calling
54 QScriptEngine::newObject(), passing a pointer to the QScriptClass as
55 argument.
56
57 By subclassing QScriptClass, you can define precisely how access to
58 properties of the objects that use your class is handled. This
59 enables a fully dynamic handling of properties, e.g. it's more
60 powerful than QScriptEngine::newQObject(). For example, you can use
61 QScriptClass to implement array-type objects (i.e. objects that
62 handle the \c{length} property, and properties whose names are valid
63 array indexes, in a special way), or to implement a "live"
64 (runtime-defined) proxy to an underlying object.
65
66 If you just need to handle access to a set of properties that are
67 known at the time an object is created (i.e. "semi-statically"), you
68 might consider using QScriptValue::setProperty() to define
69 getter/setter functions for the relevant properties, rather than
70 subclassing QScriptClass.
71
72 Reimplement queryProperty() to specify which properties are handled
73 in a custom way by your script class (i.e. should be
74 \b{delegated} to the QScriptClass), and which properties should
75 be handled just like normal Qt Script object properties.
76
77 Reimplement property() and setProperty() to perform the actual
78 access (read or write) to the properties that your class
79 handles. Additionally, you can reimplement propertyFlags() to
80 specify custom flags for your properties.
81
82 Reimplement newIterator() to provide an iterator for objects of your
83 custom class. This is only necessary if objects of your class can
84 have custom properties that you want to be reported when an object
85 is used together with the QScriptValueIterator class, or when an
86 object is used in a for-in enumeration statement in a script.
87
88 When implementing custom classes of objects, you typically use
89 QScriptValue::setData() to store instance-specific data as part of
90 object initialization; the data won't be accessible from scripts
91 directly, but you can access it in e.g. your reimplementations of
92 property() and setProperty() (by calling QScriptValue::data()) to
93 perform custom processing.
94
95 Reimplement prototype() to provide a custom prototype object for
96 your script class.
97
98 Reimplement supportsExtension() and extension() if your custom
99 script class supports one or more of the extensions specified by the
100 Extension enum.
101
102 \sa QScriptClassPropertyIterator, QScriptEngine::newObject(), {Defining Custom Script Classes with QScriptClass}
103*/
104
105/*!
106 \enum QScriptClass::Extension
107
108 This enum specifies the possible extensions to a QScriptClass.
109
110 \value Callable Instances of this class can be called as functions.
111
112 \value HasInstance Instances of this class implement [[HasInstance]].
113
114 \sa extension()
115*/
116
117/*!
118 \enum QScriptClass::QueryFlag
119
120 This enum describes flags that are used to query a QScriptClass
121 regarding how access to a property should be handled.
122
123 \value HandlesReadAccess The QScriptClass handles read access to this property.
124 \value HandlesWriteAccess The QScriptClass handles write access to this property.
125
126 \sa queryProperty()
127*/
128
129QT_BEGIN_NAMESPACE
130
131class QScriptClassPrivate
132{
133 Q_DECLARE_PUBLIC(QScriptClass)
134public:
135 QScriptClassPrivate() {}
136 virtual ~QScriptClassPrivate() {}
137
138 QScriptEngine *engine;
139
140 QScriptClass *q_ptr;
141};
142
143/*!
144 Constructs a QScriptClass object to be used in the given \a engine.
145
146 The engine does not take ownership of the QScriptClass object.
147*/
148QScriptClass::QScriptClass(QScriptEngine *engine)
149 : d_ptr(new QScriptClassPrivate)
150{
151 d_ptr->q_ptr = this;
152 d_ptr->engine = engine;
153}
154
155/*!
156 \internal
157*/
158QScriptClass::QScriptClass(QScriptEngine *engine, QScriptClassPrivate &dd)
159 : d_ptr(&dd)
160{
161 d_ptr->q_ptr = this;
162 d_ptr->engine = engine;
163}
164
165/*!
166 Destroys the QScriptClass object.
167
168 If a QScriptClass object is deleted before the associated engine(),
169 any Qt Script objects using the QScriptClass will be "demoted" to
170 normal Qt Script objects.
171*/
172QScriptClass::~QScriptClass()
173{
174}
175
176/*!
177 Returns the engine that this QScriptClass is associated with.
178*/
179QScriptEngine *QScriptClass::engine() const
180{
181 Q_D(const QScriptClass);
182 return d->engine;
183}
184
185/*!
186 Returns the object to be used as the prototype of new instances
187 of this class (created with QScriptEngine::newObject()).
188
189 The default implementation returns an invalid QScriptValue, meaning
190 that the standard Object prototype will be used. Reimplement this
191 function to provide your own custom prototype.
192
193 Typically you initialize your prototype object in the constructor of
194 your class, then return it in this function.
195
196 See the "Making Use of Prototype-Based Inheritance" section in the
197 Qt Script documentation for more information on how prototypes are
198 used.
199*/
200QScriptValue QScriptClass::prototype() const
201{
202 return QScriptValue();
203}
204
205/*!
206 Returns the name of the script class.
207
208 Qt Script uses this name to generate a default string representation
209 of objects in case you do not provide a toString function.
210
211 The default implementation returns a null string.
212*/
213QString QScriptClass::name() const
214{
215 return QString();
216}
217
218/*!
219 Queries this script class for how access to the property with the
220 given \a name of the given \a object should be handled. The given \a
221 flags specify the aspects of interest. This function should return a
222 subset of \a flags to indicate which aspects of property access
223 should be further handled by the script class.
224
225 For example, if the \a flags contain HandlesReadAccess, and you
226 would like your class to handle the reading of the property (through
227 the property() function), the returned flags should include
228 HandlesReadAccess. If the returned flags do not contain
229 HandlesReadAccess, the property will be handled as a normal script
230 object property.
231
232 You can optionally use the \a id argument to store a value that will
233 subsequently be passed on to functions such as property() and
234 setProperty().
235
236 The default implementation of this function returns 0.
237
238 Note: This function is only called if the given property isn't
239 already a normal property of the object. For example, say you
240 advertise that you want to handle read access to property \c{foo},
241 but not write access; if \c{foo} is then assigned a value, it will
242 become a normal script object property, and subsequently you will no
243 longer be queried regarding read access to \c{foo}.
244
245 \sa property()
246*/
247QScriptClass::QueryFlags QScriptClass::queryProperty(
248 const QScriptValue &object, const QScriptString &name,
249 QueryFlags flags, uint *id)
250{
251 Q_UNUSED(object);
252 Q_UNUSED(name);
253 Q_UNUSED(flags);
254 Q_UNUSED(id);
255 return {};
256}
257
258/*!
259 Returns the value of the property with the given \a name of the given
260 \a object.
261
262 The \a id argument is only useful if you assigned a value to it in
263 queryProperty().
264
265 The default implementation does nothing and returns an invalid QScriptValue.
266
267 \sa setProperty(), propertyFlags()
268*/
269QScriptValue QScriptClass::property(const QScriptValue &object,
270 const QScriptString &name, uint id)
271{
272 Q_UNUSED(object);
273 Q_UNUSED(name);
274 Q_UNUSED(id);
275 return QScriptValue();
276}
277
278/*!
279 Returns the flags of the property with the given \a name of the given
280 \a object.
281
282 The \a id argument is only useful if you assigned a value to it in
283 queryProperty().
284
285 The default implementation returns 0.
286
287 \sa property()
288*/
289QScriptValue::PropertyFlags QScriptClass::propertyFlags(
290 const QScriptValue &object, const QScriptString &name, uint id)
291{
292 Q_UNUSED(object);
293 Q_UNUSED(name);
294 Q_UNUSED(id);
295 return {};
296}
297
298/*!
299 Sets the property with the given \a name of the given \a object to
300 the given \a value.
301
302 The \a id argument is only useful if you assigned a value to it in
303 queryProperty().
304
305 The default implementation does nothing.
306
307 An invalid \a value represents a request to remove the property.
308
309 \sa property()
310*/
311void QScriptClass::setProperty(QScriptValue &object, const QScriptString &name,
312 uint id, const QScriptValue &value)
313{
314 Q_UNUSED(object);
315 Q_UNUSED(name);
316 Q_UNUSED(id);
317 Q_UNUSED(value);
318}
319
320/*!
321 Returns an iterator for traversing custom properties of the given \a
322 object.
323
324 The default implementation returns 0, meaning that there are no
325 custom properties to traverse.
326
327 Reimplement this function if objects of your script class can have
328 one or more custom properties (e.g. those reported to be handled by
329 queryProperty()) that you want to appear when an object's properties
330 are enumerated (e.g. by a for-in statement in a script).
331
332 Qt Script takes ownership of the new iterator object.
333
334 \sa QScriptValueIterator
335*/
336QScriptClassPropertyIterator *QScriptClass::newIterator(const QScriptValue &object)
337{
338 Q_UNUSED(object);
339 return 0;
340}
341
342/*!
343 Returns true if the QScriptClass supports the given \a extension;
344 otherwise, false is returned. By default, no extensions
345 are supported.
346
347 Reimplement this function to indicate which extensions your custom
348 class supports.
349
350 \sa extension()
351*/
352bool QScriptClass::supportsExtension(Extension extension) const
353{
354 Q_UNUSED(extension);
355 return false;
356}
357
358/*!
359 This virtual function can be reimplemented in a QScriptClass
360 subclass to provide support for extensions. The optional \a argument
361 can be provided as input to the \a extension; the result must be
362 returned in the form of a QVariant. You can call supportsExtension()
363 to check if an extension is supported by the QScriptClass. By
364 default, no extensions are supported, and this function returns an
365 invalid QVariant.
366
367 If you implement the Callable extension, Qt Script will call this
368 function when an instance of your class is called as a function
369 (e.g. from a script or using QScriptValue::call()). The \a argument
370 will contain a pointer to the QScriptContext that represents the
371 function call, and you should return a QVariant that holds the
372 result of the function call. In the following example the sum of the
373 arguments to the script function are added up and returned:
374
375 \snippet code/src_script_qscriptclass.cpp 0
376
377 If you implement the HasInstance extension, Qt Script will call this
378 function as part of evaluating the \c{instanceof} operator, as
379 described in ECMA-262 Section 11.8.6. The \a argument is a
380 QScriptValueList containing two items: The first item is the object
381 that HasInstance is being applied to (an instance of your class),
382 and the second item can be any value. extension() should return true
383 if the value delegates behavior to the object, false otherwise.
384
385 \sa supportsExtension()
386*/
387QVariant QScriptClass::extension(Extension extension, const QVariant &argument)
388{
389 Q_UNUSED(extension);
390 Q_UNUSED(argument);
391 return QVariant();
392}
393
394QT_END_NAMESPACE
395

source code of qtscript/src/script/api/qscriptclass.cpp