Qt 4.8
qscriptclassobject.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtScript module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL-ONLY$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser
11 ** General Public License version 2.1 as published by the Free Software
12 ** Foundation and appearing in the file LICENSE.LGPL included in the
13 ** packaging of this file. Please review the following information to
14 ** ensure the GNU Lesser General Public License version 2.1 requirements
15 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** If you have questions regarding the use of this file, please contact
18 ** us via http://www.qt-project.org/.
19 **
20 ** $QT_END_LICENSE$
21 **
22 ****************************************************************************/
23 
24 #include "config.h"
25 #include "qscriptclassobject_p.h"
26 
27 #include "../api/qscriptengine.h"
28 #include "../api/qscriptengine_p.h"
29 #include "../api/qscriptcontext.h"
30 #include "../api/qscriptcontext_p.h"
31 #include "../api/qscriptclass.h"
32 #include "../api/qscriptclasspropertyiterator.h"
33 
34 #include "Error.h"
35 #include "PropertyNameArray.h"
36 
40 
42 
43 namespace QScript
44 {
45 
47  : m_scriptClass(scriptClass)
48 {
49 }
50 
52 {
53 }
54 
56 {
57  return ClassObject;
58 }
59 
61  JSC::ExecState *exec,
62  const JSC::Identifier &propertyName,
63  JSC::PropertySlot &slot)
64 {
66  QScript::SaveFrameHelper saveFrame(engine, exec);
67  // for compatibility with the old back-end, normal JS properties
68  // are queried first.
69  if (QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot))
70  return true;
71 
72  QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
73  QScriptString scriptName;
74  QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
75  QScriptStringPrivate::init(scriptName, &scriptName_d);
76  uint id = 0;
77  QScriptClass::QueryFlags flags = m_scriptClass->queryProperty(
78  scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id);
79  if (flags & QScriptClass::HandlesReadAccess) {
80  QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id);
81  if (!value.isValid()) {
82  // The class claims to have the property, but returned an invalid
83  // value. Silently convert to undefined to avoid the invalid value
84  // "escaping" into JS.
86  }
87  slot.setValue(engine->scriptValueToJSCValue(value));
88  return true;
89  }
90  return false;
91 }
92 
94  JSC::ExecState *exec,
95  const JSC::Identifier &propertyName,
96  JSC::PropertyDescriptor &descriptor)
97 {
99  QScript::SaveFrameHelper saveFrame(engine, exec);
100  // for compatibility with the old back-end, normal JS properties
101  // are queried first.
102  if (QScriptObjectDelegate::getOwnPropertyDescriptor(object, exec, propertyName, descriptor))
103  return true;
104 
105  QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
106  QScriptString scriptName;
107  QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
108  QScriptStringPrivate::init(scriptName, &scriptName_d);
109  uint id = 0;
110  QScriptClass::QueryFlags qflags = m_scriptClass->queryProperty(
111  scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id);
112  if (qflags & QScriptClass::HandlesReadAccess) {
113  QScriptValue::PropertyFlags pflags = m_scriptClass->propertyFlags(scriptObject, scriptName, id);
114  unsigned attribs = 0;
115  if (pflags & QScriptValue::ReadOnly)
116  attribs |= JSC::ReadOnly;
117  if (pflags & QScriptValue::SkipInEnumeration)
118  attribs |= JSC::DontEnum;
119  if (pflags & QScriptValue::Undeletable)
120  attribs |= JSC::DontDelete;
121  if (pflags & QScriptValue::PropertyGetter)
122  attribs |= JSC::Getter;
123  if (pflags & QScriptValue::PropertySetter)
124  attribs |= JSC::Setter;
125  attribs |= pflags & QScriptValue::UserRange;
126  // Rather than calling the getter, we could return an access descriptor here.
127  QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id);
128  if (!value.isValid()) {
129  // The class claims to have the property, but returned an invalid
130  // value. Silently convert to undefined to avoid the invalid value
131  // "escaping" into JS.
133  }
134  descriptor.setDescriptor(engine->scriptValueToJSCValue(value), attribs);
135  return true;
136  }
137  return false;
138 }
139 
140 void ClassObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec,
141  const JSC::Identifier &propertyName,
142  JSC::JSValue value, JSC::PutPropertySlot &slot)
143 {
145  QScript::SaveFrameHelper saveFrame(engine, exec);
146  QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
147  QScriptString scriptName;
148  QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
149  QScriptStringPrivate::init(scriptName, &scriptName_d);
150  uint id = 0;
151  QScriptClass::QueryFlags flags = m_scriptClass->queryProperty(
152  scriptObject, scriptName, QScriptClass::HandlesWriteAccess, &id);
153  if (flags & QScriptClass::HandlesWriteAccess) {
154  m_scriptClass->setProperty(scriptObject, scriptName, id, engine->scriptValueFromJSCValue(value));
155  return;
156  }
157  QScriptObjectDelegate::put(object, exec, propertyName, value, slot);
158 }
159 
160 bool ClassObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec,
161  const JSC::Identifier &propertyName)
162 {
163  // ### avoid duplication of put()
165  QScript::SaveFrameHelper saveFrame(engine, exec);
166  QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
167  QScriptString scriptName;
168  QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
169  QScriptStringPrivate::init(scriptName, &scriptName_d);
170  uint id = 0;
171  QScriptClass::QueryFlags flags = m_scriptClass->queryProperty(
172  scriptObject, scriptName, QScriptClass::HandlesWriteAccess, &id);
173  if (flags & QScriptClass::HandlesWriteAccess) {
174  if (m_scriptClass->propertyFlags(scriptObject, scriptName, id) & QScriptValue::Undeletable)
175  return false;
176  m_scriptClass->setProperty(scriptObject, scriptName, id, QScriptValue());
177  return true;
178  }
179  return QScriptObjectDelegate::deleteProperty(object, exec, propertyName);
180 }
181 
182 void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec,
183  JSC::PropertyNameArray &propertyNames,
184  JSC::EnumerationMode mode)
185 {
186  // For compatibility with the old back-end, normal JS properties
187  // are added first.
188  QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode);
189 
191  QScript::SaveFrameHelper saveFrame(engine, exec);
192  QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
194  if (it != 0) {
195  while (it->hasNext()) {
196  it->next();
197  QString name = it->name().toString();
198  propertyNames.add(JSC::Identifier(exec, name));
199  }
200  delete it;
201  }
202 }
203 
204 JSC::CallType ClassObjectDelegate::getCallData(QScriptObject*, JSC::CallData &callData)
205 {
207  return JSC::CallTypeNone;
208  callData.native.function = call;
209  return JSC::CallTypeHost;
210 }
211 
212 JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC::JSObject *callee,
213  JSC::JSValue thisValue, const JSC::ArgList &args)
214 {
215  if (!callee->inherits(&QScriptObject::info))
216  return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object");
217  QScriptObject *obj = static_cast<QScriptObject*>(callee);
218  QScriptObjectDelegate *delegate = obj->delegate();
219  if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject))
220  return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object");
221 
222  QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass();
224 
225  JSC::ExecState *oldFrame = eng_p->currentFrame;
226  eng_p->pushContext(exec, thisValue, args, callee);
228  QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj);
229  QVariant result = scriptClass->extension(QScriptClass::Callable, QVariant::fromValue(ctx));
230  eng_p->popContext();
231  eng_p->currentFrame = oldFrame;
232  return QScriptEnginePrivate::jscValueFromVariant(exec, result);
233 }
234 
235 JSC::ConstructType ClassObjectDelegate::getConstructData(QScriptObject*, JSC::ConstructData &constructData)
236 {
238  return JSC::ConstructTypeNone;
239  constructData.native.function = construct;
240  return JSC::ConstructTypeHost;
241 }
242 
243 JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObject *callee,
244  const JSC::ArgList &args)
245 {
246  Q_ASSERT(callee->inherits(&QScriptObject::info));
247  QScriptObject *obj = static_cast<QScriptObject*>(callee);
248  QScriptObjectDelegate *delegate = obj->delegate();
249  QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass();
250 
252  JSC::ExecState *oldFrame = eng_p->currentFrame;
253  eng_p->pushContext(exec, JSC::JSValue(), args, callee, true);
255 
256  QScriptValue defaultObject = ctx->thisObject();
258  if (!result.isObject())
259  result = defaultObject;
260  eng_p->popContext();
261  eng_p->currentFrame = oldFrame;
262  return JSC::asObject(eng_p->scriptValueToJSCValue(result));
263 }
264 
265 bool ClassObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exec,
266  JSC::JSValue value, JSC::JSValue proto)
267 {
268  if (!scriptClass()->supportsExtension(QScriptClass::HasInstance))
269  return QScriptObjectDelegate::hasInstance(object, exec, value, proto);
270  QScriptValueList args;
272  QScript::SaveFrameHelper saveFrame(eng_p, exec);
273  args << eng_p->scriptValueFromJSCValue(object) << eng_p->scriptValueFromJSCValue(value);
275  return result.toBool();
276 }
277 
278 } // namespace QScript
279 
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
The QScriptContext class represents a Qt Script function invocation.
static JSC::JSObject * construct(JSC::ExecState *, JSC::JSObject *, const JSC::ArgList &)
ClassObjectDelegate(QScriptClass *scriptClass)
static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState *, JSC::JSObject *, JSC::JSValue, const JSC::ArgList &)
virtual bool deleteProperty(QScriptObject *, JSC::ExecState *, const JSC::Identifier &propertyName)
QScriptEnginePrivate * scriptEngineFromExec(const JSC::ExecState *exec)
virtual void getOwnPropertyNames(QScriptObject *, JSC::ExecState *, JSC::PropertyNameArray &, JSC::EnumerationMode mode=JSC::ExcludeDontEnumProperties)
virtual Type type() const =0
virtual bool hasInstance(QScriptObject *, JSC::ExecState *, JSC::JSValue value, JSC::JSValue proto)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static JSC::JSValue jscValueFromVariant(JSC::ExecState *, const QVariant &value)
The QScriptClass class provides an interface for defining custom behavior of (a class of) Qt Script o...
Definition: qscriptclass.h:43
#define it(className, varName)
JSC::CallFrame * pushContext(JSC::CallFrame *exec, JSC::JSValue thisObject, const JSC::ArgList &args, JSC::JSObject *callee, bool calledAsConstructor=false, bool clearScopeChain=false)
JSC native function doesn&#39;t have different stackframe or context.
QScriptObjectDelegate * delegate() const
virtual bool getOwnPropertyDescriptor(QScriptObject *, JSC::ExecState *, const JSC::Identifier &propertyName, JSC::PropertyDescriptor &)
bool toBool() const
Returns the variant as a bool if the variant has type() Bool.
Definition: qvariant.cpp:2691
static void init(QScriptString &q, QScriptStringPrivate *d)
static const JSC::ClassInfo info
The QString class provides a Unicode character string.
Definition: qstring.h:83
virtual void put(QScriptObject *, JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue, JSC::PutPropertySlot &)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
JSC::ExecState * currentFrame
virtual JSC::ConstructType getConstructData(QScriptObject *, JSC::ConstructData &)
The QScriptString class acts as a handle to "interned" strings in a QScriptEngine.
Definition: qscriptstring.h:38
virtual bool supportsExtension(Extension extension) const
Returns true if the QScriptClass supports the given extension; otherwise, false is returned...
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
virtual QVariant extension(Extension extension, const QVariant &argument=QVariant())
This virtual function can be reimplemented in a QScriptClass subclass to provide support for extensio...
QScriptClass * scriptClass() const
JSC::JSValue scriptValueToJSCValue(const QScriptValue &value)
static QScriptContext * contextForFrame(JSC::ExecState *frame)
The QScriptClassPropertyIterator class provides an iterator interface for custom Qt Script objects...
const char * name
virtual void next()=0
Advances the iterator by one position.
unsigned int uint
Definition: qglobal.h:996
virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
Queries this script class for how access to the property with the given name of the given object shou...
virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id)
Returns the value of the property with the given name of the given object.
virtual JSC::CallType getCallData(QScriptObject *, JSC::CallData &)
static QVariant fromValue(const T &value)
Returns a QVariant containing a copy of value.
Definition: qvariant.h:336
#define Q_DECLARE_METATYPE(TYPE)
This macro makes the type Type known to QMetaType as long as it provides a public default constructor...
Definition: qmetatype.h:265
virtual bool hasNext() const =0
Returns true if there is at least one item ahead of the iterator (i.
virtual void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value)
Sets the property with the given name of the given object to the given value.
virtual QScriptString name() const =0
Returns the name of the last property that was jumped over using next() or previous().
PropertyFlags
Definition: qmetaobject_p.h:61
virtual bool getOwnPropertySlot(QScriptObject *, JSC::ExecState *, const JSC::Identifier &propertyName, JSC::PropertySlot &)
#define ctx
Definition: qgl.cpp:6094
virtual bool getOwnPropertySlot(QScriptObject *, JSC::ExecState *, const JSC::Identifier &propertyName, JSC::PropertySlot &)
T qvariant_cast(const QVariant &)
Definition: qvariant.h:571
virtual void put(QScriptObject *, JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue, JSC::PutPropertySlot &)
QScriptValue scriptValueFromJSCValue(JSC::JSValue value)
virtual bool hasInstance(QScriptObject *, JSC::ExecState *, JSC::JSValue value, JSC::JSValue proto)
QScriptValue thisObject() const
Returns the `this&#39; object associated with this QScriptContext.
virtual bool deleteProperty(QScriptObject *, JSC::ExecState *, const JSC::Identifier &propertyName)
QString toString() const
Returns the string that this QScriptString represents, or a null string if this QScriptString is not ...
The QScriptValue class acts as a container for the Qt Script data types.
Definition: qscriptvalue.h:57
virtual QScriptValue::PropertyFlags propertyFlags(const QScriptValue &object, const QScriptString &name, uint id)
Returns the flags of the property with the given name of the given object.
bool isValid() const
Returns true if this QScriptValue is valid; otherwise returns false.
virtual void getOwnPropertyNames(QScriptObject *, JSC::ExecState *, JSC::PropertyNameArray &, JSC::EnumerationMode mode=JSC::ExcludeDontEnumProperties)
virtual bool getOwnPropertyDescriptor(QScriptObject *, JSC::ExecState *, const JSC::Identifier &propertyName, JSC::PropertyDescriptor &)
bool isObject() const
Returns true if this QScriptValue is of the Object type; otherwise returns false. ...
virtual QScriptClassPropertyIterator * newIterator(const QScriptValue &object)
Returns an iterator for traversing custom properties of the given object.