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 "qscriptdeclarativeobject_p.h" |
42 | |
43 | #include "../api/qscriptengine.h" |
44 | #include "../api/qscriptengine_p.h" |
45 | #include "../api/qscriptcontext.h" |
46 | #include "../api/qscriptcontext_p.h" |
47 | #include "../api/qscriptclass.h" |
48 | #include "../api/qscriptclasspropertyiterator.h" |
49 | |
50 | #include "Error.h" |
51 | #include "PropertyNameArray.h" |
52 | |
53 | #include <QtCore/qstringlist.h> |
54 | |
55 | Q_DECLARE_METATYPE(QScriptContext*) |
56 | Q_DECLARE_METATYPE(QScriptValue) |
57 | Q_DECLARE_METATYPE(QScriptValueList) |
58 | |
59 | QT_BEGIN_NAMESPACE |
60 | |
61 | namespace QScript |
62 | { |
63 | |
64 | DeclarativeObjectDelegate::DeclarativeObjectDelegate(QScriptDeclarativeClass *c, |
65 | QScriptDeclarativeClass::Object *o) |
66 | : m_class(c), m_object(o) |
67 | { |
68 | } |
69 | |
70 | DeclarativeObjectDelegate::~DeclarativeObjectDelegate() |
71 | { |
72 | delete m_object; |
73 | } |
74 | |
75 | QScriptObjectDelegate::Type DeclarativeObjectDelegate::type() const |
76 | { |
77 | return DeclarativeClassObject; |
78 | } |
79 | |
80 | bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object, |
81 | JSC::ExecState *exec, |
82 | const JSC::Identifier &propertyName, |
83 | JSC::PropertySlot &slot) |
84 | { |
85 | QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); |
86 | |
87 | QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(c: m_class); |
88 | p->context = reinterpret_cast<QScriptContext *>(exec); |
89 | QScriptClass::QueryFlags flags = |
90 | m_class->queryProperty(m_object, identifier, flags: QScriptClass::HandlesReadAccess); |
91 | if (flags & QScriptClass::HandlesReadAccess) { |
92 | QScriptDeclarativeClass::Value val = m_class->property(m_object, identifier); |
93 | p->context = 0; |
94 | slot.setValue((const JSC::JSValue &)val); |
95 | return true; |
96 | } |
97 | p->context = 0; |
98 | |
99 | return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot); |
100 | } |
101 | |
102 | void DeclarativeObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, |
103 | const JSC::Identifier &propertyName, |
104 | JSC::JSValue value, JSC::PutPropertySlot &slot) |
105 | { |
106 | QScriptEnginePrivate *engine = scriptEngineFromExec(exec); |
107 | QScript::SaveFrameHelper saveFrame(engine, exec); |
108 | QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); |
109 | |
110 | QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(c: m_class); |
111 | p->context = reinterpret_cast<QScriptContext *>(exec); |
112 | QScriptClass::QueryFlags flags = |
113 | m_class->queryProperty(m_object, identifier, flags: QScriptClass::HandlesWriteAccess); |
114 | if (flags & QScriptClass::HandlesWriteAccess) { |
115 | m_class->setProperty(m_object, name: identifier, engine->scriptValueFromJSCValue(value)); |
116 | p->context = 0; |
117 | return; |
118 | } |
119 | p->context = 0; |
120 | |
121 | QScriptObjectDelegate::put(object, exec, propertyName, value, slot); |
122 | } |
123 | |
124 | bool DeclarativeObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec, |
125 | const JSC::Identifier &propertyName) |
126 | { |
127 | return QScriptObjectDelegate::deleteProperty(object, exec, propertyName); |
128 | } |
129 | |
130 | void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec, |
131 | JSC::PropertyNameArray &propertyNames, |
132 | JSC::EnumerationMode mode) |
133 | { |
134 | QStringList properties = m_class->propertyNames(m_object); |
135 | for (int ii = 0; ii < properties.count(); ++ii) { |
136 | const QString &name = properties.at(i: ii); |
137 | propertyNames.add(JSC::Identifier(exec, name)); |
138 | } |
139 | |
140 | QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode); |
141 | } |
142 | |
143 | JSC::CallType DeclarativeObjectDelegate::getCallData(QScriptObject *object, JSC::CallData &callData) |
144 | { |
145 | if (!QScriptDeclarativeClassPrivate::get(c: m_class)->supportsCall) |
146 | return JSC::CallTypeNone; |
147 | callData.native.function = call; |
148 | return JSC::CallTypeHost; |
149 | } |
150 | |
151 | JSC::JSValue DeclarativeObjectDelegate::call(JSC::ExecState *exec, JSC::JSObject *callee, |
152 | JSC::JSValue thisValue, const JSC::ArgList &args) |
153 | { |
154 | if (!callee->inherits(info: &QScriptObject::info)) |
155 | return JSC::throwError(exec, JSC::TypeError, message: "callee is not a DeclarativeObject object" ); |
156 | QScriptObject *obj = static_cast<QScriptObject*>(callee); |
157 | QScriptObjectDelegate *delegate = obj->delegate(); |
158 | if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) |
159 | return JSC::throwError(exec, JSC::TypeError, message: "callee is not a DeclarativeObject object" ); |
160 | |
161 | QScriptDeclarativeClass *scriptClass = static_cast<DeclarativeObjectDelegate*>(delegate)->m_class; |
162 | QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); |
163 | |
164 | QScript::SaveFrameHelper saveFrame(eng_p, exec); |
165 | eng_p->pushContext(exec, thisObject: thisValue, args, callee); |
166 | QScriptContext *ctxt = eng_p->contextForFrame(frame: eng_p->currentFrame); |
167 | |
168 | QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(value: obj); |
169 | QScriptDeclarativeClass::Value result = |
170 | scriptClass->call(static_cast<DeclarativeObjectDelegate*>(delegate)->m_object, ctxt); |
171 | |
172 | eng_p->popContext(); |
173 | return (JSC::JSValue &)(result); |
174 | } |
175 | |
176 | JSC::ConstructType DeclarativeObjectDelegate::getConstructData(QScriptObject* object, JSC::ConstructData &constructData) |
177 | { |
178 | return QScriptObjectDelegate::getConstructData(object, constructData); |
179 | } |
180 | |
181 | bool DeclarativeObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exec, |
182 | JSC::JSValue value, JSC::JSValue proto) |
183 | { |
184 | return QScriptObjectDelegate::hasInstance(object, exec, value, proto); |
185 | } |
186 | |
187 | bool DeclarativeObjectDelegate::compareToObject(QScriptObject *o, JSC::ExecState *exec, JSC::JSObject *o2) |
188 | { |
189 | if (!o2->inherits(info: &QScriptObject::info)) |
190 | return false; |
191 | |
192 | QScriptObject *scriptObject = static_cast<QScriptObject*>(o2); |
193 | QScriptObjectDelegate *delegate = scriptObject->delegate(); |
194 | if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) |
195 | return false; |
196 | |
197 | DeclarativeObjectDelegate *other = static_cast<DeclarativeObjectDelegate*>(delegate); |
198 | if (m_class != other->m_class) |
199 | return false; |
200 | else |
201 | return m_class->compare(m_object, other->m_object); |
202 | } |
203 | |
204 | } // namespace QScript |
205 | |
206 | QT_END_NAMESPACE |
207 | |