source: trunk/src/script/bridge/qscriptclassobject.cpp@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 10.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtScript module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL-ONLY$
10** GNU Lesser General Public License Usage
11** This file may be used under the terms of the GNU Lesser
12** General Public License version 2.1 as published by the Free Software
13** Foundation and appearing in the file LICENSE.LGPL included in the
14** packaging of this file. Please review the following information to
15** ensure the GNU Lesser General Public License version 2.1 requirements
16** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17**
18** If you have questions regarding the use of this file, please contact
19** Nokia at [email protected].
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
37Q_DECLARE_METATYPE(QScriptContext*)
38Q_DECLARE_METATYPE(QScriptValue)
39Q_DECLARE_METATYPE(QScriptValueList)
40
41QT_BEGIN_NAMESPACE
42
43namespace QScript
44{
45
46ClassObjectDelegate::ClassObjectDelegate(QScriptClass *scriptClass)
47 : m_scriptClass(scriptClass)
48{
49}
50
51ClassObjectDelegate::~ClassObjectDelegate()
52{
53}
54
55QScriptObjectDelegate::Type ClassObjectDelegate::type() const
56{
57 return ClassObject;
58}
59
60bool ClassObjectDelegate::getOwnPropertySlot(QScriptObject* object,
61 JSC::ExecState *exec,
62 const JSC::Identifier &propertyName,
63 JSC::PropertySlot &slot)
64{
65 QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
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 slot.setValue(engine->scriptValueToJSCValue(value));
82 return true;
83 }
84 return false;
85}
86
87void ClassObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec,
88 const JSC::Identifier &propertyName,
89 JSC::JSValue value, JSC::PutPropertySlot &slot)
90{
91 QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
92 QScript::SaveFrameHelper saveFrame(engine, exec);
93 QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
94 QScriptString scriptName;
95 QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
96 QScriptStringPrivate::init(scriptName, &scriptName_d);
97 uint id = 0;
98 QScriptClass::QueryFlags flags = m_scriptClass->queryProperty(
99 scriptObject, scriptName, QScriptClass::HandlesWriteAccess, &id);
100 if (flags & QScriptClass::HandlesWriteAccess) {
101 m_scriptClass->setProperty(scriptObject, scriptName, id, engine->scriptValueFromJSCValue(value));
102 return;
103 }
104 QScriptObjectDelegate::put(object, exec, propertyName, value, slot);
105}
106
107bool ClassObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec,
108 const JSC::Identifier &propertyName,
109 bool checkDontDelete)
110{
111 // ### avoid duplication of put()
112 QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
113 QScript::SaveFrameHelper saveFrame(engine, exec);
114 QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
115 QScriptString scriptName;
116 QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
117 QScriptStringPrivate::init(scriptName, &scriptName_d);
118 uint id = 0;
119 QScriptClass::QueryFlags flags = m_scriptClass->queryProperty(
120 scriptObject, scriptName, QScriptClass::HandlesWriteAccess, &id);
121 if (flags & QScriptClass::HandlesWriteAccess) {
122 if (m_scriptClass->propertyFlags(scriptObject, scriptName, id) & QScriptValue::Undeletable)
123 return false;
124 m_scriptClass->setProperty(scriptObject, scriptName, id, QScriptValue());
125 return true;
126 }
127 return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete);
128}
129
130bool ClassObjectDelegate::getPropertyAttributes(const QScriptObject* object, JSC::ExecState *exec,
131 const JSC::Identifier &propertyName,
132 unsigned &attribs) const
133{
134 QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
135 QScript::SaveFrameHelper saveFrame(engine, exec);
136 QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
137 QScriptString scriptName;
138 QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated);
139 QScriptStringPrivate::init(scriptName, &scriptName_d);
140 uint id = 0;
141 QScriptClass::QueryFlags flags = m_scriptClass->queryProperty(
142 scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id);
143 if (flags & QScriptClass::HandlesReadAccess) {
144 QScriptValue::PropertyFlags flags = m_scriptClass->propertyFlags(scriptObject, scriptName, id);
145 attribs = 0;
146 if (flags & QScriptValue::ReadOnly)
147 attribs |= JSC::ReadOnly;
148 if (flags & QScriptValue::SkipInEnumeration)
149 attribs |= JSC::DontEnum;
150 if (flags & QScriptValue::Undeletable)
151 attribs |= JSC::DontDelete;
152 if (flags & QScriptValue::PropertyGetter)
153 attribs |= JSC::Getter;
154 if (flags & QScriptValue::PropertySetter)
155 attribs |= JSC::Setter;
156 attribs |= flags & QScriptValue::UserRange;
157 return true;
158 }
159 return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs);
160}
161
162void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec,
163 JSC::PropertyNameArray &propertyNames,
164 bool includeNonEnumerable)
165{
166 QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
167 QScript::SaveFrameHelper saveFrame(engine, exec);
168 QScriptValue scriptObject = engine->scriptValueFromJSCValue(object);
169 QScriptClassPropertyIterator *it = m_scriptClass->newIterator(scriptObject);
170 if (it != 0) {
171 while (it->hasNext()) {
172 it->next();
173 QString name = it->name().toString();
174 propertyNames.add(JSC::Identifier(exec, name));
175 }
176 delete it;
177 }
178 QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable);
179}
180
181JSC::CallType ClassObjectDelegate::getCallData(QScriptObject*, JSC::CallData &callData)
182{
183 if (!m_scriptClass->supportsExtension(QScriptClass::Callable))
184 return JSC::CallTypeNone;
185 callData.native.function = call;
186 return JSC::CallTypeHost;
187}
188
189JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC::JSObject *callee,
190 JSC::JSValue thisValue, const JSC::ArgList &args)
191{
192 if (!callee->inherits(&QScriptObject::info))
193 return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object");
194 QScriptObject *obj = static_cast<QScriptObject*>(callee);
195 QScriptObjectDelegate *delegate = obj->delegate();
196 if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject))
197 return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object");
198
199 QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass();
200 QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
201
202 JSC::ExecState *oldFrame = eng_p->currentFrame;
203 eng_p->pushContext(exec, thisValue, args, callee);
204 QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame);
205 QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj);
206 QVariant result = scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx));
207 eng_p->popContext();
208 eng_p->currentFrame = oldFrame;
209 return eng_p->jscValueFromVariant(result);
210}
211
212JSC::ConstructType ClassObjectDelegate::getConstructData(QScriptObject*, JSC::ConstructData &constructData)
213{
214 if (!m_scriptClass->supportsExtension(QScriptClass::Callable))
215 return JSC::ConstructTypeNone;
216 constructData.native.function = construct;
217 return JSC::ConstructTypeHost;
218}
219
220JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObject *callee,
221 const JSC::ArgList &args)
222{
223 Q_ASSERT(callee->inherits(&QScriptObject::info));
224 QScriptObject *obj = static_cast<QScriptObject*>(callee);
225 QScriptObjectDelegate *delegate = obj->delegate();
226 QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass();
227
228 QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
229 JSC::ExecState *oldFrame = eng_p->currentFrame;
230 eng_p->pushContext(exec, JSC::JSValue(), args, callee, true);
231 QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame);
232
233 QScriptValue defaultObject = ctx->thisObject();
234 QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx)));
235 if (!result.isObject())
236 result = defaultObject;
237 eng_p->popContext();
238 eng_p->currentFrame = oldFrame;
239 return JSC::asObject(eng_p->scriptValueToJSCValue(result));
240}
241
242bool ClassObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exec,
243 JSC::JSValue value, JSC::JSValue proto)
244{
245 if (!scriptClass()->supportsExtension(QScriptClass::HasInstance))
246 return QScriptObjectDelegate::hasInstance(object, exec, value, proto);
247 QScriptValueList args;
248 QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
249 QScript::SaveFrameHelper saveFrame(eng_p, exec);
250 args << eng_p->scriptValueFromJSCValue(object) << eng_p->scriptValueFromJSCValue(value);
251 QVariant result = scriptClass()->extension(QScriptClass::HasInstance, qVariantFromValue(args));
252 return result.toBool();
253}
254
255} // namespace QScript
256
257QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.