source: trunk/src/script/bridge/qscriptdeclarativeclass.cpp@ 1030

Last change on this file since 1030 was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

  • Property svn:eol-style set to native
File size: 18.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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 QtDeclarative 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 "qscriptdeclarativeclass_p.h"
25#include "qscriptdeclarativeobject_p.h"
26#include "qscriptobject_p.h"
27#include "qscriptstaticscopeobject_p.h"
28#include <QtScript/qscriptstring.h>
29#include <QtScript/qscriptengine.h>
30#include <QtScript/qscriptengineagent.h>
31#include <private/qscriptengine_p.h>
32#include <private/qscriptvalue_p.h>
33#include <private/qscriptqobject_p.h>
34#include <private/qscriptactivationobject_p.h>
35#include <QtCore/qstringlist.h>
36
37QT_BEGIN_NAMESPACE
38
39/*!
40\class QScriptDeclarativeClass::Value
41\internal
42\brief The QScriptDeclarativeClass::Value class acts as a container for JavaScript data types.
43
44QScriptDeclarativeClass::Value class is similar to QScriptValue, but it is slightly faster.
45Unlike QScriptValue, however, Value instances cannot be stored as they may not survive garbage
46collection. If you need to store a Value, convert it to a QScriptValue and store that.
47*/
48
49QScriptDeclarativeClass::Value::Value()
50{
51 new (this) JSC::JSValue(JSC::jsUndefined());
52}
53
54QScriptDeclarativeClass::Value::Value(const Value &other)
55{
56 new (this) JSC::JSValue((JSC::JSValue &)other);
57}
58
59static QScriptDeclarativeClass::Value jscToValue(const JSC::JSValue &val)
60{
61 return QScriptDeclarativeClass::Value((QScriptDeclarativeClass::Value &)val);
62}
63
64QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, int value)
65{
66 new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
67}
68
69QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, uint value)
70{
71 new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
72}
73
74QScriptDeclarativeClass::Value::Value(QScriptContext *, bool value)
75{
76 if (value)
77 new (this) JSC::JSValue(JSC::JSValue::JSTrue);
78 else
79 new (this) JSC::JSValue(JSC::JSValue::JSFalse);
80}
81
82QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, double value)
83{
84 new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
85}
86
87QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, float value)
88{
89 new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
90}
91
92QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QString &value)
93{
94 new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::frameForContext(ctxt), value));
95}
96
97QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QScriptValue &value)
98{
99 new (this) JSC::JSValue(QScriptEnginePrivate::get(ctxt->engine())->scriptValueToJSCValue(value));
100}
101
102QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, int value)
103{
104 new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
105}
106
107QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, uint value)
108{
109 new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
110}
111
112QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, bool value)
113{
114 if (value)
115 new (this) JSC::JSValue(JSC::JSValue::JSTrue);
116 else
117 new (this) JSC::JSValue(JSC::JSValue::JSFalse);
118}
119
120QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, double value)
121{
122 new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
123}
124
125QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, float value)
126{
127 new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
128}
129
130QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QString &value)
131{
132 new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::get(eng)->currentFrame, value));
133}
134
135QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QScriptValue &value)
136{
137 new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->scriptValueToJSCValue(value));
138}
139
140QScriptDeclarativeClass::Value::~Value()
141{
142 ((JSC::JSValue *)(this))->~JSValue();
143}
144
145QScriptValue QScriptDeclarativeClass::Value::toScriptValue(QScriptEngine *engine) const
146{
147 return QScriptEnginePrivate::get(engine)->scriptValueFromJSCValue((JSC::JSValue &)*this);
148}
149
150QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier()
151 : identifier(0), engine(0)
152{
153 new (&d) JSC::Identifier();
154}
155
156QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier()
157{
158 if (engine) {
159 QScript::APIShim shim(engine);
160 ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
161 } else {
162 ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
163 }
164}
165
166QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(const PersistentIdentifier &other)
167{
168 identifier = other.identifier;
169 engine = other.engine;
170 new (&d) JSC::Identifier((JSC::Identifier &)(other.d));
171}
172
173QScriptDeclarativeClass::PersistentIdentifier &
174QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentifier &other)
175{
176 identifier = other.identifier;
177 engine = other.engine;
178 ((JSC::Identifier &)d) = (JSC::Identifier &)(other.d);
179 return *this;
180}
181
182QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine)
183: d_ptr(new QScriptDeclarativeClassPrivate)
184{
185 Q_ASSERT(sizeof(void*) == sizeof(JSC::Identifier));
186 d_ptr->q_ptr = this;
187 d_ptr->engine = engine;
188}
189
190QScriptValue QScriptDeclarativeClass::newObject(QScriptEngine *engine,
191 QScriptDeclarativeClass *scriptClass,
192 Object *object)
193{
194 Q_ASSERT(engine);
195 Q_ASSERT(scriptClass);
196
197 QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine));
198 QScript::APIShim shim(p);
199
200 JSC::ExecState* exec = p->currentFrame;
201 QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
202 result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
203 return p->scriptValueFromJSCValue(result);
204}
205
206QScriptDeclarativeClass::Value
207QScriptDeclarativeClass::newObjectValue(QScriptEngine *engine,
208 QScriptDeclarativeClass *scriptClass,
209 Object *object)
210{
211 Q_ASSERT(engine);
212 Q_ASSERT(scriptClass);
213
214 QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine));
215 QScript::APIShim shim(p);
216
217 JSC::ExecState* exec = p->currentFrame;
218 QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
219 result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
220 return jscToValue(JSC::JSValue(result));
221}
222
223QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v)
224{
225 QScriptValuePrivate *d = QScriptValuePrivate::get(v);
226 if (!d || !d->isJSC())
227 return 0;
228 return QScriptEnginePrivate::declarativeClass(d->jscValue);
229}
230
231QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v)
232{
233 QScriptValuePrivate *d = QScriptValuePrivate::get(v);
234 if (!d || !d->isJSC())
235 return 0;
236 return QScriptEnginePrivate::declarativeObject(d->jscValue);
237}
238
239QScriptValue QScriptDeclarativeClass::function(const QScriptValue &v, const Identifier &name)
240{
241 QScriptValuePrivate *d = QScriptValuePrivate::get(v);
242
243 if (!d->isObject())
244 return QScriptValue();
245
246 QScript::APIShim shim(d->engine);
247 JSC::ExecState *exec = d->engine->currentFrame;
248 JSC::JSObject *object = d->jscValue.getObject();
249 JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
250 JSC::JSValue result;
251
252 JSC::Identifier id(exec, (JSC::UString::Rep *)name);
253
254 if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
255 result = slot.getValue(exec, id);
256 if (QScript::isFunction(result))
257 return d->engine->scriptValueFromJSCValue(result);
258 }
259
260 return QScriptValue();
261}
262
263QScriptValue QScriptDeclarativeClass::property(const QScriptValue &v, const Identifier &name)
264{
265 QScriptValuePrivate *d = QScriptValuePrivate::get(v);
266
267 if (!d->isObject())
268 return QScriptValue();
269
270 QScript::APIShim shim(d->engine);
271 JSC::ExecState *exec = d->engine->currentFrame;
272 JSC::JSObject *object = d->jscValue.getObject();
273 JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
274 JSC::JSValue result;
275
276 JSC::Identifier id(exec, (JSC::UString::Rep *)name);
277
278 if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
279 result = slot.getValue(exec, id);
280 return d->engine->scriptValueFromJSCValue(result);
281 }
282
283 return QScriptValue();
284}
285
286QScriptDeclarativeClass::Value
287QScriptDeclarativeClass::functionValue(const QScriptValue &v, const Identifier &name)
288{
289 QScriptValuePrivate *d = QScriptValuePrivate::get(v);
290
291 if (!d->isObject())
292 return Value();
293
294 QScript::APIShim shim(d->engine);
295 JSC::ExecState *exec = d->engine->currentFrame;
296 JSC::JSObject *object = d->jscValue.getObject();
297 JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
298 JSC::JSValue result;
299
300 JSC::Identifier id(exec, (JSC::UString::Rep *)name);
301
302 if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
303 result = slot.getValue(exec, id);
304 if (QScript::isFunction(result))
305 return jscToValue(result);
306 }
307
308 return Value();
309}
310
311QScriptDeclarativeClass::Value
312QScriptDeclarativeClass::propertyValue(const QScriptValue &v, const Identifier &name)
313{
314 QScriptValuePrivate *d = QScriptValuePrivate::get(v);
315
316 if (!d->isObject())
317 return Value();
318
319 QScript::APIShim shim(d->engine);
320 JSC::ExecState *exec = d->engine->currentFrame;
321 JSC::JSObject *object = d->jscValue.getObject();
322 JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
323 JSC::JSValue result;
324
325 JSC::Identifier id(exec, (JSC::UString::Rep *)name);
326
327 if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
328 result = slot.getValue(exec, id);
329 return jscToValue(result);
330 }
331
332 return Value();
333}
334
335/*
336Returns the scope chain entry at \a index. If index is less than 0, returns
337entries starting at the end. For example, scopeChainValue(context, -1) will return
338the value last in the scope chain.
339*/
340QScriptValue QScriptDeclarativeClass::scopeChainValue(QScriptContext *context, int index)
341{
342 context->activationObject(); //ensure the creation of the normal scope for native context
343 const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(context);
344 QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
345 QScript::APIShim shim(engine);
346
347 JSC::ScopeChainNode *node = frame->scopeChain();
348 JSC::ScopeChainIterator it(node);
349
350 if (index < 0) {
351 int count = 0;
352 for (it = node->begin(); it != node->end(); ++it)
353 ++count;
354
355 index = qAbs(index);
356 if (index > count)
357 return QScriptValue();
358 else
359 index = count - index;
360 }
361
362 for (it = node->begin(); it != node->end(); ++it) {
363
364 if (index == 0) {
365
366 JSC::JSObject *object = *it;
367 if (!object) return QScriptValue();
368
369 if (object->inherits(&QScript::QScriptActivationObject::info)
370 && (static_cast<QScript::QScriptActivationObject*>(object)->delegate() != 0)) {
371 // Return the object that property access is being delegated to
372 object = static_cast<QScript::QScriptActivationObject*>(object)->delegate();
373 }
374 return engine->scriptValueFromJSCValue(object);
375
376 } else {
377 --index;
378 }
379
380 }
381
382 return QScriptValue();
383}
384
385/*!
386 Enters a new execution context and returns the associated
387 QScriptContext object.
388
389 Once you are done with the context, you should call popContext() to
390 restore the old context.
391
392 By default, the `this' object of the new context is the Global Object.
393 The context's \l{QScriptContext::callee()}{callee}() will be invalid.
394
395 Unlike pushContext(), the default scope chain is reset to include
396 only the global object and the QScriptContext's activation object.
397
398 \sa QScriptEngine::popContext()
399*/
400QScriptContext * QScriptDeclarativeClass::pushCleanContext(QScriptEngine *engine)
401{
402 if (!engine)
403 return 0;
404
405 QScriptEnginePrivate *d = QScriptEnginePrivate::get(engine);
406 QScript::APIShim shim(d);
407
408 JSC::CallFrame* newFrame = d->pushContext(d->currentFrame,
409 d->currentFrame->globalData().dynamicGlobalObject,
410 JSC::ArgList(), /*callee = */0, false, true);
411
412 if (engine->agent())
413 engine->agent()->contextPush();
414
415 return d->contextForFrame(newFrame);
416}
417
418QScriptDeclarativeClass::~QScriptDeclarativeClass()
419{
420}
421
422QScriptEngine *QScriptDeclarativeClass::engine() const
423{
424 return d_ptr->engine;
425}
426
427bool QScriptDeclarativeClass::supportsCall() const
428{
429 return d_ptr->supportsCall;
430}
431
432void QScriptDeclarativeClass::setSupportsCall(bool c)
433{
434 d_ptr->supportsCall = c;
435}
436
437QScriptDeclarativeClass::PersistentIdentifier
438QScriptDeclarativeClass::createPersistentIdentifier(const QString &str)
439{
440 QScriptEnginePrivate *p =
441 static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine));
442 QScript::APIShim shim(p);
443 JSC::ExecState* exec = p->currentFrame;
444
445 PersistentIdentifier rv(p);
446 new (&rv.d) JSC::Identifier(exec, (UChar *)str.constData(), str.size());
447 rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();
448 return rv;
449}
450
451QScriptDeclarativeClass::PersistentIdentifier
452QScriptDeclarativeClass::createPersistentIdentifier(const Identifier &id)
453{
454 QScriptEnginePrivate *p =
455 static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine));
456 QScript::APIShim shim(p);
457 JSC::ExecState* exec = p->currentFrame;
458
459 PersistentIdentifier rv(p);
460 new (&rv.d) JSC::Identifier(exec, (JSC::UString::Rep *)id);
461 rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();
462 return rv;
463}
464
465QString QScriptDeclarativeClass::toString(const Identifier &identifier)
466{
467 JSC::UString::Rep *r = (JSC::UString::Rep *)identifier;
468 return QString((QChar *)r->data(), r->size());
469}
470
471quint32 QScriptDeclarativeClass::toArrayIndex(const Identifier &identifier, bool *ok)
472{
473 JSC::UString::Rep *r = (JSC::UString::Rep *)identifier;
474 JSC::UString s(r);
475 return s.toArrayIndex(ok);
476}
477
478QScriptClass::QueryFlags
479QScriptDeclarativeClass::queryProperty(Object *object, const Identifier &name,
480 QScriptClass::QueryFlags flags)
481{
482 Q_UNUSED(object);
483 Q_UNUSED(name);
484 Q_UNUSED(flags);
485 return 0;
486}
487
488QScriptDeclarativeClass::Value
489QScriptDeclarativeClass::property(Object *object, const Identifier &name)
490{
491 Q_UNUSED(object);
492 Q_UNUSED(name);
493 return Value();
494}
495
496void QScriptDeclarativeClass::setProperty(Object *object, const Identifier &name,
497 const QScriptValue &value)
498{
499 Q_UNUSED(object);
500 Q_UNUSED(name);
501 Q_UNUSED(value);
502}
503
504QScriptValue::PropertyFlags
505QScriptDeclarativeClass::propertyFlags(Object *object, const Identifier &name)
506{
507 Q_UNUSED(object);
508 Q_UNUSED(name);
509 return 0;
510}
511
512QScriptDeclarativeClass::Value QScriptDeclarativeClass::call(Object *object,
513 QScriptContext *ctxt)
514{
515 Q_UNUSED(object);
516 Q_UNUSED(ctxt);
517 return Value();
518}
519
520bool QScriptDeclarativeClass::compare(Object *o, Object *o2)
521{
522 return o == o2;
523}
524
525QStringList QScriptDeclarativeClass::propertyNames(Object *object)
526{
527 Q_UNUSED(object);
528 return QStringList();
529}
530
531bool QScriptDeclarativeClass::isQObject() const
532{
533 return false;
534}
535
536QObject *QScriptDeclarativeClass::toQObject(Object *, bool *ok)
537{
538 if (ok) *ok = false;
539 return 0;
540}
541
542QVariant QScriptDeclarativeClass::toVariant(Object *, bool *ok)
543{
544 if (ok) *ok = false;
545 return QVariant();
546}
547
548QScriptContext *QScriptDeclarativeClass::context() const
549{
550 return d_ptr->context;
551}
552
553/*!
554 Creates a scope object with a fixed set of undeletable properties.
555*/
556QScriptValue QScriptDeclarativeClass::newStaticScopeObject(
557 QScriptEngine *engine, int propertyCount, const QString *names,
558 const QScriptValue *values, const QScriptValue::PropertyFlags *flags)
559{
560 QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine);
561 QScript::APIShim shim(eng_p);
562 JSC::ExecState *exec = eng_p->currentFrame;
563 QScriptStaticScopeObject::PropertyInfo *props = new QScriptStaticScopeObject::PropertyInfo[propertyCount];
564 for (int i = 0; i < propertyCount; ++i) {
565 unsigned attribs = QScriptEnginePrivate::propertyFlagsToJSCAttributes(flags[i]);
566 Q_ASSERT_X(attribs & JSC::DontDelete, Q_FUNC_INFO, "All properties must be undeletable");
567 JSC::Identifier id = JSC::Identifier(exec, names[i]);
568 JSC::JSValue jsval = eng_p->scriptValueToJSCValue(values[i]);
569 props[i] = QScriptStaticScopeObject::PropertyInfo(id, jsval, attribs);
570 }
571 QScriptValue result = eng_p->scriptValueFromJSCValue(new (exec)QScriptStaticScopeObject(eng_p->staticScopeObjectStructure,
572 propertyCount, props));
573 delete[] props;
574 return result;
575}
576
577/*!
578 Creates a static scope object that's initially empty, but to which new
579 properties can be added.
580*/
581QScriptValue QScriptDeclarativeClass::newStaticScopeObject(QScriptEngine *engine)
582{
583 QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine);
584 QScript::APIShim shim(eng_p);
585 return eng_p->scriptValueFromJSCValue(new (eng_p->currentFrame)QScriptStaticScopeObject(eng_p->staticScopeObjectStructure));
586}
587
588QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.