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