1
/****************************************************************************
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
** Contact: Nokia Corporation (qt-info@nokia.com)
6
** This file is part of the QtScript module of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
10
** Licensees holding valid Qt Commercial licenses may use this file in
11
** accordance with the Qt Commercial License Agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Nokia.
15
** GNU Lesser General Public License Usage
16
** Alternatively, this file may be used under the terms of the GNU Lesser
17
** General Public License version 2.1 as published by the Free Software
18
** Foundation and appearing in the file LICENSE.LGPL included in the
19
** packaging of this file. Please review the following information to
20
** ensure the GNU Lesser General Public License version 2.1 requirements
21
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23
** In addition, as a special exception, Nokia gives you certain
24
** additional rights. These rights are described in the Nokia Qt LGPL
25
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
28
** GNU General Public License Usage
29
** Alternatively, this file may be used under the terms of the GNU
30
** General Public License version 3.0 as published by the Free Software
31
** Foundation and appearing in the file LICENSE.GPL included in the
32
** packaging of this file. Please review the following information to
33
** ensure the GNU General Public License version 3.0 requirements will be
34
** met: http://www.gnu.org/copyleft/gpl.html.
36
** If you are unsure which license is appropriate for your use, please
37
** contact the sales department at http://www.qtsoftware.com/contact.
40
****************************************************************************/
42
#include <QtCore/QtDebug>
46
#include "qscriptcontext_p.h"
47
#include "qscriptengine_p.h"
48
#include "qscriptvalueimpl_p.h"
49
#include "qscriptmember_p.h"
50
#include "qscriptobject_p.h"
51
#include "qscriptprettypretty_p.h"
52
#include "qscriptast_p.h"
53
#include "qscriptnodepool_p.h"
54
#include "qscriptcompiler_p.h"
55
#include "qscriptextenumeration_p.h"
57
#include <math.h> // floor & friends...
61
#define Q_SCRIPT_NO_PRINT_GENERATED_CODE
63
#define Q_SCRIPT_NO_JOINED_FUNCTION
65
#define CHECK_TEMPSTACK(needed) do { \
66
if (stackPtr + needed >= eng->tempStackEnd) { \
67
throwError(QLatin1String("out of memory")); \
72
#ifndef Q_SCRIPT_NO_PRINT_GENERATED_CODE
73
static QTextStream qout(stderr, QIODevice::WriteOnly);
76
static inline void qscript_uint_to_string_helper(uint i, QString &s)
79
case 0: case 1: case 2: case 3: case 4:
80
case 5: case 6: case 7: case 8: case 9:
81
s += QLatin1Char('0' + i);
85
qscript_uint_to_string_helper(i / 10, s);
86
s += QLatin1Char('0' + (i % 10));
90
static inline void qscript_uint_to_string(qsreal i, QString &s)
92
if ((i < 0) || (i > 0xFFFFFFFF))
93
return; // nothing to do
95
qsreal x = ::fmod(i, 10);
97
if (x != 0.0 && x != 1.0
98
&& x != 2.0 && x != 3.0
99
&& x != 4.0 && x != 5.0
100
&& x != 6.0 && x != 7.0
101
&& x != 8.0 && x != 9.0)
102
return; // nothing to do
104
qscript_uint_to_string_helper(uint(i), s);
107
static inline quint32 toArrayIndex(const QScriptValueImpl &v)
110
quint32 ui = v.toUInt32();
111
if (qsreal(ui) == v.m_number_value)
113
} else if (v.isString()) {
114
QByteArray bytes = v.m_string_value->s.toUtf8();
116
quint32 pos = strtoul(bytes.constData(), &eptr, 10);
117
if ((eptr == bytes.constData() + bytes.size())
118
&& (QByteArray::number(pos) == bytes)) {
125
#define CREATE_MEMBER(__obj__, __name__, __member__, __flags__) do { \
126
(__obj__).createMember(__name__, __member__, __flags__); \
127
eng->adjustBytesAllocated(sizeof(QScript::Member) + sizeof(QScriptValueImpl)); \
130
#define BEGIN_PREFIX_OPERATOR \
131
QScriptValue::ResolveFlags mode; \
132
mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value) \
133
| QScriptValue::ResolvePrototype; \
135
QScriptValueImpl object = eng->toObject(stackPtr[-1]); \
136
if (!object.isObject()) { \
138
throwTypeError(QLatin1String("not an object")); \
141
QScriptNameIdImpl *memberName = 0; \
142
if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique) \
143
memberName = stackPtr[0].m_string_value; \
145
memberName = eng->nameId(stackPtr[0].toString(), /*persistent=*/false); \
146
QScript::Member member; \
147
QScriptValueImpl base; \
148
QScriptValueImpl value; \
149
QScriptValueImpl getter; \
150
QScriptValueImpl setter; \
151
const bool isMemberAssignment = (object.m_object_value != m_scopeChain.m_object_value); \
152
if (object.resolve(memberName, &member, &base, mode, QScript::ReadWrite)) { \
153
base.get(member, &value); \
154
if (hasUncaughtException()) { \
157
} else if (member.isGetterOrSetter()) { \
158
if (member.isGetter()) { \
160
if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { \
162
throwError(QLatin1String("No setter defined")); \
165
base.get(member, &setter); \
168
QScript::Member tmp = member; \
169
if (!base.m_object_value->findGetter(&member)) { \
171
throwError(QLatin1String("No getter defined")); \
174
base.get(member, &getter); \
177
value = getter.call(object); \
178
if (hasUncaughtException()) { \
183
} else if (!isMemberAssignment) { \
185
throwNotDefined(memberName); \
189
CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \
193
#define END_PREFIX_OPERATOR \
194
if (member.isSetter()) { \
195
setter.call(object, QScriptValueImplList() << value); \
196
if (hasUncaughtException()) { \
201
if (member.isWritable()) { \
202
if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { \
204
CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \
206
base.put(member, value); \
207
if (hasUncaughtException()) { \
213
*--stackPtr = value; \
216
#define BEGIN_INPLACE_OPERATOR \
217
if (! stackPtr[-1].isReference()) { \
219
throwSyntaxError(QLatin1String("invalid assignment lvalue")); \
222
QScriptValue::ResolveFlags mode; \
223
mode = QScriptValue::ResolveFlags(stackPtr[-1].m_int_value) \
224
| QScriptValue::ResolvePrototype; \
225
QScriptValueImpl object = eng->toObject(stackPtr[-3]); \
226
if (! object.isValid()) { \
228
throwTypeError(QLatin1String("not an object")); \
231
QScriptNameIdImpl *memberName = 0; \
232
if (stackPtr[-2].isString() && stackPtr[-2].m_string_value->unique) \
233
memberName = stackPtr[-2].m_string_value; \
235
memberName = eng->nameId(stackPtr[-2].toString(), /*persistent=*/false); \
236
QScriptValueImpl lhs; \
237
QScriptValueImpl base; \
238
QScript::Member member; \
239
QScriptValueImpl getter; \
240
QScriptValueImpl setter; \
241
const bool isMemberAssignment = (object.m_object_value != m_scopeChain.m_object_value); \
242
if (object.resolve(memberName, &member, &base, mode, QScript::ReadWrite)) { \
243
base.get(member, &lhs); \
244
if (hasUncaughtException()) { \
247
} else if (member.isGetterOrSetter()) { \
248
if (member.isGetter()) { \
250
if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { \
252
throwError(QLatin1String("No setter defined")); \
255
base.get(member, &setter); \
258
QScript::Member tmp = member; \
259
if (!base.m_object_value->findGetter(&member)) { \
261
throwError(QLatin1String("No getter defined")); \
264
base.get(member, &getter); \
267
lhs = getter.call(object); \
268
if (hasUncaughtException()) { \
273
} else if (!isMemberAssignment) { \
275
throwNotDefined(memberName); \
279
CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \
282
QScriptValueImpl rhs = stackPtr[0];
284
#define END_INPLACE_OPERATOR \
285
if (member.isSetter()) { \
286
setter.call(object, QScriptValueImplList() << *stackPtr); \
287
if (hasUncaughtException()) { \
292
if (member.isWritable()) { \
293
if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { \
295
CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \
297
base.put(member, *stackPtr); \
298
if (hasUncaughtException()) { \
308
void ScriptFunction::execute(QScriptContextPrivate *context)
310
if (! m_compiledCode) {
311
QScriptEnginePrivate *eng = context->engine();
312
Compiler compiler(eng);
314
CompilationUnit unit = compiler.compile(m_definition->body, formals);
315
if (! unit.isValid()) {
316
context->throwError(unit.errorMessage());
320
m_compiledCode = m_astPool->createCompiledCode(m_definition->body, unit);
323
context->execute(m_compiledCode);
326
QString ScriptFunction::toString(QScriptContextPrivate *) const
329
QTextStream out(&str, QIODevice::WriteOnly);
330
PrettyPretty pp(out);
331
pp(m_definition, /*indent=*/ 0);
335
QString ScriptFunction::fileName() const
337
return m_astPool->fileName();
340
QString ScriptFunction::functionName() const
342
if (!m_definition->name)
344
return m_definition->name->s;
347
int ScriptFunction::startLineNumber() const
349
return m_definition->startLine;
352
int ScriptFunction::endLineNumber() const
354
return m_definition->endLine;
357
} // namespace QScript
362
Resolves and gets the value specified by \a stackPtr.
363
stackPtr[0] contains the member specifier, stackPtr[-1] contains the object.
364
If the member can be resolved, sets \a value to the value of that member,
365
otherwise returns false.
367
bool QScriptContextPrivate::resolveField(QScriptEnginePrivate *eng,
368
QScriptValueImpl *stackPtr,
369
QScriptValueImpl *value)
371
const QScriptValueImpl &m = stackPtr[0];
372
QScriptValueImpl &object = stackPtr[-1];
374
if (! object.isObject())
375
object = eng->toObject(object);
377
if (! object.isValid())
380
if (QScript::Ecma::Array::Instance *arrayInstance = eng->arrayConstructor->get(object)) {
381
quint32 pos = toArrayIndex(m);
382
if (pos != 0xFFFFFFFF) {
383
*value = arrayInstance->value.at(pos);
385
if (! value->isValid())
386
*value = eng->undefinedValue();
392
QScriptNameIdImpl *nameId = m.isString() ? m.m_string_value : 0;
394
if (! nameId || ! nameId->unique)
395
nameId = eng->nameId(QScriptEnginePrivate::convertToNativeString(m), /*persistent=*/false); // ### slow!
397
QScript::Member member;
398
QScriptValueImpl base;
400
if (! object.resolve(nameId, &member, &base, QScriptValue::ResolveFull, QScript::Read)) // ### ...
403
if (QScriptEnginePrivate::strictlyEquals(base, eng->m_globalObject))
405
else if (object.classInfo() == eng->m_class_with)
406
stackPtr[-1] = object.prototype();
408
base.get(member, value);
410
if (member.isGetterOrSetter()) {
411
// call the getter function
412
QScriptValueImpl getter;
413
if (member.isGetter()) {
416
if (!base.m_object_value->findGetter(&member)) {
417
*value = eng->undefinedValue();
420
base.get(member, &getter);
422
*value = getter.call(object);
428
void QScriptContextPrivate::execute(QScript::Code *code)
430
int oldCurrentLine = currentLine;
431
int oldCurrentColumn = currentColumn;
432
QScript::Code *oldCode = m_code;
435
#ifndef Q_SCRIPT_NO_PRINT_GENERATED_CODE
436
qout << QLatin1String("function:") << endl;
437
for (QScriptInstruction *current = code->firstInstruction; current != code->lastInstruction; ++current) {
438
qout << int(current - code->firstInstruction) << QLatin1String(":\t");
439
current->print(qout);
445
QScriptEnginePrivate *eng = engine();
447
bool wasEvaluating = eng->m_evaluating;
448
if (!wasEvaluating) {
449
eng->setupProcessEvents();
450
eng->resetAbortFlag();
452
eng->m_evaluating = true;
454
// set up the temp stack
456
stackPtr = tempStack = eng->tempStackBegin;
458
QScriptValueImpl undefined(eng->undefinedValue());
461
m_state = QScriptContext::NormalState;
462
m_result = undefined;
463
firstInstruction = code->firstInstruction;
464
lastInstruction = code->lastInstruction;
465
iPtr = code->firstInstruction;
467
if (!m_scopeChain.isValid())
468
m_scopeChain = m_activation;
470
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
471
eng->notifyFunctionEntry(this);
474
#ifndef Q_SCRIPT_DIRECT_CODE
476
# define I(opc) case QScriptInstruction::OP_##opc
477
# define Next() goto Lfetch
478
# define Done() goto Ldone
479
# define HandleException() goto Lhandle_exception
480
# define Abort() goto Labort
487
# define I(opc) qscript_execute_##opc
488
# define Next() goto *iPtr->code
489
# define Done() goto Ldone
490
# define HandleException() goto Lhandle_exception
491
# define Abort() goto Labort
493
static void * const jump_table[] = {
495
# define Q_SCRIPT_DEFINE_OPERATOR(op) &&I(op),
496
# include "instruction.table"
497
# undef Q_SCRIPT_DEFINE_OPERATOR
501
if (!code->optimized) {
502
for (QScriptInstruction *current = code->firstInstruction; current != code->lastInstruction; ++current) {
503
current->code = jump_table[current->op];
506
code->optimized = true;
512
#ifndef Q_SCRIPT_DIRECT_CODE
526
*(++stackPtr) = undefined;
533
*(++stackPtr) = QScriptValueImpl(true);
540
*(++stackPtr) = QScriptValueImpl(false);
547
Q_ASSERT(m_thisObject.isObject());
548
*++stackPtr = m_thisObject;
555
*++stackPtr = m_activation;
562
*(++stackPtr) = eng->nullValue();
569
*++stackPtr = iPtr->operand[0];
577
*++stackPtr = iPtr->operand[0];
584
eng->newNameId(++stackPtr, iPtr->operand[0].m_string_value);
592
*stackPtr = stackPtr[-1];
598
QScriptValueImpl tmp = stackPtr[0];
599
*stackPtr = stackPtr[-1];
607
int n = iPtr->operand[0].m_int_value;
610
throwError(QLatin1String("invalid argument"));
615
*++stackPtr = argument(n);
623
QScriptNameIdImpl *memberName = iPtr->operand[0].m_string_value;
625
QScriptValueImpl base;
626
QScript::Member member;
628
QScriptObject *instance = m_scopeChain.m_object_value;
629
if (instance->findMember(memberName, &member)) {
630
instance->get(member, ++stackPtr);
633
if (m_scopeChain.resolve_helper(memberName, &member, &base, QScriptValue::ResolveFull, QScript::Read)) {
634
base.get(member, ++stackPtr);
635
if (hasUncaughtException()) {
640
throwNotDefined(memberName);
644
if (member.isGetterOrSetter()) {
645
// locate the getter function
646
QScriptValueImpl getter;
647
if (member.isGetter()) {
650
if (!base.m_object_value->findGetter(&member)) {
652
throwError(QLatin1String("No getter defined"));
655
base.get(member, &getter);
657
// decide the this-object. This is the object that actually
658
// has the getter (in its prototype chain).
659
QScriptValueImpl object = m_scopeChain;
660
while (!object.resolve(memberName, &member, &base, QScriptValue::ResolvePrototype, QScript::Read))
661
object = object.scope();
662
if (object.classInfo() == eng->m_class_with)
663
object = object.prototype();
665
*stackPtr = getter.call(object);
666
if (hasUncaughtException()) {
676
Q_ASSERT(iPtr->operand[0].isString());
679
*++stackPtr = m_scopeChain;
680
*++stackPtr = iPtr->operand[0];
681
eng->newReference(++stackPtr, QScriptValue::ResolveScope);
687
Q_ASSERT(stackPtr[-1].isReference());
689
const QScriptValueImpl &object = stackPtr[-3];
690
QScriptNameIdImpl *memberName = stackPtr[-2].m_string_value;
691
const QScriptValueImpl &value = stackPtr[0];
693
QScript::Member member;
694
QScriptValueImpl base;
696
if (! object.resolve(memberName, &member, &base, QScriptValue::ResolveLocal, QScript::Write)) {
698
CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
701
base.put(member, value);
703
if (hasUncaughtException())
710
int argc = iPtr->operand[0].m_int_value;
711
QScriptValueImpl *argp = stackPtr - argc;
713
QScriptValueImpl base;
714
QScriptValueImpl callee;
716
bool isReference = argp[0].isReference();
718
if (! isReference) { // we have a value
719
base = eng->m_globalObject;
721
} else if (resolveField(eng, &argp[-1], &callee)) {
722
if (hasUncaughtException()) {
728
QScriptValueImpl member = argp[-1];
730
Q_ASSERT(isReference);
733
if (member.isString())
734
throwNotDefined(member.toString());
736
throwNotDefined(QLatin1String("function"));
740
Q_ASSERT(base.isValid());
741
Q_ASSERT(callee.isValid());
743
QScriptFunction *function = QScriptEnginePrivate::convertToNativeFunction(callee);
745
QScriptValueImpl member = argp[-1];
747
if (member.isString()) {
748
message = QString::fromLatin1("%0 is not a function")
749
.arg(member.toString());
751
message = QLatin1String("not a function");
753
throwTypeError(message);
757
if (++eng->m_callDepth == eng->m_maxCallDepth) {
758
throwError(QLatin1String("call stack overflow"));
762
QScriptContextPrivate *nested_data = eng->pushContext();
763
nested_data->m_thisObject = base;
764
nested_data->m_callee = callee;
766
// create the activation
767
eng->newActivation(&nested_data->m_activation);
768
QScriptObject *activation_data = nested_data->m_activation.m_object_value;
770
int formalCount = function->formals.count();
771
int mx = qMax(formalCount, argc);
772
activation_data->m_members.resize(mx);
773
activation_data->m_values.resize(mx);
774
for (int i = 0; i < mx; ++i) {
775
QScriptNameIdImpl *nameId = 0;
777
nameId = function->formals.at(i);
779
activation_data->m_members[i].object(nameId, i,
780
QScriptValue::Undeletable
781
| QScriptValue::SkipInEnumeration);
782
activation_data->m_values[i] = (i < argc) ? argp[i + 1] : undefined;
785
nested_data->argc = argc;
786
if (callee.m_object_value->m_scope.isValid())
787
activation_data->m_scope = callee.m_object_value->m_scope;
789
activation_data->m_scope = eng->m_globalObject;
790
nested_data->tempStack = stackPtr;
791
nested_data->args = &argp[1];
793
function->execute(nested_data);
801
if (nested_data->m_state == QScriptContext::ExceptionState) {
803
if (eng->shouldAbort())
810
*++stackPtr = nested_data->m_result;
814
if (eng->shouldAbort())
817
if (eng->m_processEventsInterval > 0)
818
eng->processEvents();
827
eng->arrayConstructor->newArray(++stackPtr, QScript::Array(eng));
835
QString pattern = eng->toString(iPtr->operand[0].m_string_value);
837
QString literal = pattern;
840
if (iPtr->operand[1].isValid()) {
841
flags = iPtr->operand[1].m_int_value;
844
literal += QLatin1String("/");
845
literal += QString::number(flags);
852
// lazy compilation of regexp literals
853
QHash<QString, QRegExp>::const_iterator it;
854
it = eng->m_regExpLiterals.constFind(literal);
855
if (it == eng->m_regExpLiterals.constEnd()) {
856
rx = QScript::Ecma::RegExp::toRegExp(pattern, flags);
857
eng->m_regExpLiterals.insert(literal, rx);
861
eng->regexpConstructor->newRegExp(++stackPtr, rx, flags);
863
eng->regexpConstructor->newRegExp(++stackPtr, pattern, flags);
871
eng->objectConstructor->newObject(++stackPtr);
877
int argc = iPtr->operand[0].m_int_value;
878
QScriptValueImpl *argp = stackPtr - argc;
880
// QScriptValueImpl base;
881
QScriptValueImpl callee;
883
bool isReference = argp[0].isReference();
885
if (! isReference) { // we have a value
886
// base = eng->globalObject;
888
} else if (resolveField(eng, &argp[-1], &callee)) {
890
if (hasUncaughtException()) {
895
QScriptValueImpl member = argp[-1];
897
Q_ASSERT(isReference);
900
if (member.isString())
901
throwNotDefined(member.toString());
903
throwNotDefined(QLatin1String("constructor"));
907
// Q_ASSERT(base.isValid());
908
Q_ASSERT(callee.isValid());
910
QScriptFunction *function = QScriptEnginePrivate::convertToNativeFunction(callee);
912
QScriptValueImpl member = argp[-1];
914
if (member.isString()) {
915
message = QString::fromLatin1("%0 is not a constructor")
916
.arg(member.toString());
918
message = QLatin1String("not a constructor");
920
throwTypeError(message);
924
if (++eng->m_callDepth == eng->m_maxCallDepth) {
925
throwError(QLatin1String("call stack overflow"));
929
QScriptContextPrivate *nested_data = eng->pushContext();
930
nested_data->m_callee = callee;
931
nested_data->m_calledAsConstructor = true;
933
// create the activation
934
eng->newActivation(&nested_data->m_activation);
935
QScriptObject *activation_data = nested_data->m_activation.m_object_value;
937
int formalCount = function->formals.count();
938
int mx = qMax(formalCount, argc);
939
activation_data->m_members.resize(mx);
940
activation_data->m_values.resize(mx);
941
for (int i = 0; i < mx; ++i) {
942
QScriptNameIdImpl *nameId = 0;
944
nameId = function->formals.at(i);
946
activation_data->m_members[i].object(nameId, i,
947
QScriptValue::Undeletable
948
| QScriptValue::SkipInEnumeration);
949
activation_data->m_values[i] = (i < argc) ? argp[i + 1] : undefined;
952
eng->objectConstructor->newObject(&nested_data->m_thisObject);
953
nested_data->argc = argc;
954
if (callee.m_object_value->m_scope.isValid())
955
activation_data->m_scope = callee.m_object_value->m_scope;
957
activation_data->m_scope = eng->m_globalObject;
958
nested_data->tempStack = stackPtr;
959
nested_data->args = &argp[1];
960
nested_data->m_result = undefined;
962
QScriptObject *instance = nested_data->m_thisObject.m_object_value;
965
QScriptValueImpl dummy;
966
QScript::Member proto;
967
if (callee.resolve(eng->idTable()->id_prototype, &proto, &dummy, QScriptValue::ResolveLocal, QScript::Read))
968
callee.get(proto, &instance->m_prototype);
969
if (!instance->m_prototype.isObject())
970
instance->m_prototype = eng->objectConstructor->publicPrototype;
972
function->execute(nested_data);
980
if (! nested_data->m_result.isValid())
981
nested_data->m_result = undefined;
982
else if (! nested_data->m_result.isObject())
983
nested_data->m_result = nested_data->m_thisObject;
985
if (nested_data->m_state == QScriptContext::ExceptionState) {
987
if (eng->shouldAbort())
995
*++stackPtr = nested_data->m_result;
999
if (eng->shouldAbort())
1002
if (eng->m_processEventsInterval > 0)
1003
eng->processEvents();
1010
QScriptValueImpl object = eng->toObject(stackPtr[-1]);
1011
if (! object.isValid()) {
1013
throwTypeError(QLatin1String("not an object"));
1017
QScriptValueImpl m = stackPtr[0];
1019
QScript::Ecma::Array::Instance *arrayInstance = 0;
1020
if (object.classInfo() == eng->arrayConstructor->classInfo())
1021
arrayInstance = static_cast<QScript::Ecma::Array::Instance *> (object.m_object_value->m_data);
1023
if (arrayInstance) {
1024
quint32 pos = toArrayIndex(m);
1025
if (pos != 0xFFFFFFFF) {
1026
QScriptValueImpl val = arrayInstance->value.at(pos);
1027
if (val.isValid()) {
1035
QScriptNameIdImpl *nameId = m.isString() ? m.m_string_value : 0;
1037
if (! nameId || ! nameId->unique) {
1041
qscript_uint_to_string(m.m_number_value, str);
1044
str = QScriptEnginePrivate::convertToNativeString(m);
1046
nameId = eng->nameId(str, /*persistent=*/false);
1049
QScript::Member member;
1050
QScriptValueImpl base;
1052
if (object.resolve(nameId, &member, &base, QScriptValue::ResolvePrototype, QScript::Read)) {
1053
base.get(member, --stackPtr);
1054
if (hasUncaughtException()) {
1057
} else if (member.isGetterOrSetter()) {
1058
// call the getter function
1059
QScriptValueImpl getter;
1060
if (member.isGetter()) {
1063
if (!base.m_object_value->findGetter(&member)) {
1065
throwError(QLatin1String("No getter defined"));
1068
base.get(member, &getter);
1070
*stackPtr = getter.call(object);
1071
if (hasUncaughtException()) {
1077
*(--stackPtr) = undefined;
1085
QScript::Member member;
1086
QScriptValueImpl base;
1087
QScriptNameIdImpl *arguments = eng->idTable()->id_arguments;
1088
if (!m_activation.resolve(arguments, &member, &base, QScriptValue::ResolveLocal, QScript::Read)) {
1089
CREATE_MEMBER(m_activation, arguments, &member, QScriptValue::Undeletable);
1090
if (!m_arguments.isValid()) {
1091
if (eng->strictlyEquals(m_activation, eng->globalObject()))
1092
m_arguments = undefined;
1094
eng->newArguments(&m_arguments, m_activation, argc, m_callee);
1096
m_activation.put(member, m_arguments);
1103
QScriptValueImpl &act = m_activation;
1105
QScriptNameIdImpl *memberName = iPtr->operand[0].m_string_value;
1106
bool readOnly = iPtr->operand[1].m_int_value != 0;
1107
QScript::Member member;
1108
QScriptValueImpl object;
1110
if (! act.resolve(memberName, &member, &object, QScriptValue::ResolveLocal, QScript::ReadWrite)) {
1111
uint flags = QScriptValue::Undeletable;
1113
flags |= QScript::Member::UninitializedConst | QScriptValue::ReadOnly;
1114
CREATE_MEMBER(act, memberName, &member, flags);
1115
act.put(member, undefined);
1122
if (! stackPtr[-1].isReference()) {
1124
throwSyntaxError(QLatin1String("invalid assignment lvalue"));
1128
QScriptValue::ResolveFlags mode;
1129
mode = QScriptValue::ResolveFlags(stackPtr[-1].m_int_value)
1130
| QScriptValue::ResolvePrototype;
1132
QScriptValueImpl object = eng->toObject(stackPtr[-3]);
1133
if (! object.isValid()) {
1135
throwTypeError(QLatin1String("invalid assignment lvalue"));
1139
QScriptValueImpl m = stackPtr[-2];
1140
QScriptValueImpl value = stackPtr[0];
1142
quint32 pos = 0xFFFFFFFF;
1144
QScript::Ecma::Array::Instance *arrayInstance = eng->arrayConstructor->get(object);
1146
pos = toArrayIndex(m);
1150
if (pos != 0xFFFFFFFF)
1151
arrayInstance->value.assign(pos, value);
1154
QScriptNameIdImpl *memberName;
1156
if (m.isString() && m.m_string_value->unique)
1157
memberName = m.m_string_value;
1159
memberName = eng->nameId(QScriptEnginePrivate::convertToNativeString(m), /*persistent=*/false);
1161
QScriptValueImpl base;
1162
QScript::Member member;
1164
const bool isMemberAssignment = (object.m_object_value != m_scopeChain.m_object_value);
1165
if (! object.resolve(memberName, &member, &base, mode, QScript::Write)) {
1166
if (isMemberAssignment)
1169
base = eng->m_globalObject;
1171
CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1174
if (value.isString() && ! value.m_string_value->unique)
1175
eng->newNameId(&value, value.m_string_value->s);
1177
if (member.isGetterOrSetter()) {
1178
// find and call setter(value)
1179
QScriptValueImpl setter;
1180
if (!member.isSetter()) {
1181
if (!base.m_object_value->findSetter(&member)) {
1183
throwError(QLatin1String("no setter defined"));
1187
base.get(member, &setter);
1189
if (!isMemberAssignment) {
1190
// decide the this-object. This is the object that actually
1191
// has the setter (in its prototype chain).
1192
while (!object.resolve(memberName, &member, &base, QScriptValue::ResolvePrototype, QScript::Write))
1193
object = object.scope();
1194
if (object.classInfo() == eng->m_class_with)
1195
object = object.prototype();
1198
value = setter.call(object, QScriptValueImplList() << value);
1199
if (hasUncaughtException()) {
1204
if (object.classInfo() == eng->m_class_with)
1205
object = object.prototype();
1207
if (member.isWritable()) {
1208
if (isMemberAssignment && (base.m_object_value != object.m_object_value)) {
1210
CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1212
base.put(member, value);
1213
} else if (member.isUninitializedConst()) {
1214
base.put(member, value);
1215
if (member.isObjectProperty()) {
1216
base.m_object_value->m_members[member.id()]
1217
.unsetFlags(QScript::Member::UninitializedConst);
1220
if (hasUncaughtException()) {
1233
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1234
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]);
1235
*(--stackPtr) = QScriptValueImpl(v1 & v2);
1241
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1242
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]);
1243
*(--stackPtr) = QScriptValueImpl(v1 | v2);
1249
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1250
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]);
1251
*(--stackPtr) = QScriptValueImpl(v1 ^ v2);
1257
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]);
1258
*stackPtr = QScriptValueImpl(~v1);
1264
bool v1 = QScriptEnginePrivate::convertToNativeBoolean(stackPtr[0]);
1265
*stackPtr = QScriptValueImpl(!v1);
1271
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1272
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]) & 0x1f;
1273
*(--stackPtr) = QScriptValueImpl(v1 << v2);
1279
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]);
1280
qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]);
1282
*(--stackPtr) = QScriptValueImpl(::fmod(v1, v2));
1288
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1289
quint32 v2 = QScriptEnginePrivate::toUint32 (eng->convertToNativeDouble(stackPtr[0])) & 0x1f;
1290
*(--stackPtr) = QScriptValueImpl(v1 >> v2);
1296
quint32 v1 = QScriptEnginePrivate::toUint32 (eng->convertToNativeDouble(stackPtr[-1]));
1297
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]) & 0x1f;
1298
*(--stackPtr) = QScriptValueImpl(v1 >> v2);
1304
QScriptValueImpl object = stackPtr[-1];
1305
QScriptValueImpl ctor = stackPtr[0];
1307
if (!ctor.isObject() || !ctor.implementsHasInstance()) {
1309
throwTypeError(QLatin1String("invalid 'instanceof' operand"));
1313
bool result = ctor.hasInstance(object);
1314
if (eng->hasUncaughtException()) {
1319
*(--stackPtr) = QScriptValueImpl(result);
1325
QScriptValueImpl object = stackPtr[0];
1326
if (!object.isObject()) {
1328
throwTypeError(QLatin1String("invalid 'in' operand"));
1331
QString propertyName = QScriptEnginePrivate::convertToNativeString(stackPtr[-1]);
1332
bool result = object.property(propertyName, QScriptValue::ResolvePrototype).isValid(); // ### hasProperty()
1333
*(--stackPtr) = QScriptValueImpl(result);
1339
QScriptValueImpl lhs = eng->toPrimitive(stackPtr[-1], QScriptValueImpl::NoTypeHint);
1340
QScriptValueImpl rhs = eng->toPrimitive(stackPtr[0], QScriptValueImpl::NoTypeHint);
1342
if (lhs.isString() || rhs.isString()) {
1343
QString tmp = QScriptEnginePrivate::convertToNativeString(lhs);
1344
tmp += QScriptEnginePrivate::convertToNativeString(rhs);
1345
eng->newString(--stackPtr, tmp);
1347
qsreal tmp = QScriptEnginePrivate::convertToNativeDouble(lhs);
1348
tmp += QScriptEnginePrivate::convertToNativeDouble(rhs);
1349
*(--stackPtr) = QScriptValueImpl(tmp);
1357
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]);
1358
qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]);
1359
*(--stackPtr) = QScriptValueImpl(v1 / v2);
1365
QScriptValueImpl v1 = stackPtr[-1];
1366
QScriptValueImpl v2 = stackPtr[0];
1367
*(--stackPtr) = QScriptValueImpl(eq_cmp(v1, v2));
1373
QScriptValueImpl v1 = stackPtr[0];
1374
QScriptValueImpl v2 = stackPtr[-1];
1375
*(--stackPtr) = QScriptValueImpl(le_cmp(v1, v2));
1381
QScriptValueImpl v1 = stackPtr[0];
1382
QScriptValueImpl v2 = stackPtr[-1];
1383
*(--stackPtr) = QScriptValueImpl(lt_cmp(v1, v2));
1389
QScriptValueImpl v1 = stackPtr[-1];
1390
QScriptValueImpl v2 = stackPtr[0];
1391
*(--stackPtr) = QScriptValueImpl(le_cmp(v1, v2));
1397
QScriptValueImpl v1 = stackPtr[-1];
1398
QScriptValueImpl v2 = stackPtr[0];
1399
*(--stackPtr) = QScriptValueImpl(lt_cmp(v1, v2));
1405
QScriptValueImpl v1 = stackPtr[-1];
1406
QScriptValueImpl v2 = stackPtr[0];
1407
*(--stackPtr) = QScriptValueImpl(!eq_cmp(v1, v2));
1413
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]);
1414
qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]);
1415
*(--stackPtr) = QScriptValueImpl(v1 * v2);
1421
QScriptValueImpl v1 = stackPtr[-1];
1422
QScriptValueImpl v2 = stackPtr[0];
1423
*(--stackPtr) = strict_eq_cmp(v1, v2);
1429
QScriptValueImpl v1 = stackPtr[-1];
1430
QScriptValueImpl v2 = stackPtr[0];
1431
*(--stackPtr) = ! strict_eq_cmp(v1, v2);
1437
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]);
1438
qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]);
1439
*(--stackPtr) = QScriptValueImpl(v1 - v2);
1445
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(*stackPtr);
1446
*stackPtr = QScriptValueImpl(-v1);
1452
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(*stackPtr);
1453
*stackPtr = QScriptValueImpl(+v1);
1459
eng->maybeProcessEvents();
1460
if (hasUncaughtException())
1462
if (eng->shouldAbort())
1464
iPtr += iPtr->operand[0].m_int_value;
1469
if (! QScriptEnginePrivate::convertToNativeBoolean(*stackPtr--))
1470
iPtr += iPtr->operand[0].m_int_value;
1477
if (eng->convertToNativeBoolean(*stackPtr--))
1478
iPtr += iPtr->operand[0].m_int_value;
1487
QScript::AST::FunctionExpression *expr = static_cast<QScript::AST::FunctionExpression *> (iPtr->operand[0].m_ptr_value);
1489
#ifndef Q_SCRIPT_NO_JOINED_FUNCTION
1490
if (QScript::Code *code = eng->findCode(functionBody)) {
1491
QScriptValueImpl value = code->value;
1493
if (isValid(value)) {
1494
QScriptObject *instance = value.m_object_value;
1495
Q_ASSERT(instance != 0);
1497
if (instance->m_scope.m_object_value == m_scopeChain.m_object_value)
1499
*++stackPtr = value;
1507
QScript::ScriptFunction *function = new QScript::ScriptFunction(expr, code->astPool);
1509
// update the formals
1510
for (QScript::AST::FormalParameterList *it = expr->formals; it != 0; it = it->next) {
1511
function->formals.append(it->name);
1513
function->length = function->formals.count();
1515
eng->functionConstructor->newFunction(++stackPtr, function);
1517
QScriptObject *instance = stackPtr->m_object_value;
1518
// initialize [[scope]]
1519
instance->m_scope = m_scopeChain;
1521
// create and initialize `prototype'
1522
QScriptValueImpl proto;
1523
eng->objectConstructor->newObject(&proto);
1525
QScript::Member member;
1526
CREATE_MEMBER(proto, eng->idTable()->id_constructor, &member,
1527
QScriptValue::Undeletable
1528
| QScriptValue::SkipInEnumeration);
1529
proto.put(member, *stackPtr);
1531
stackPtr->createMember(eng->idTable()->id_prototype, &member,
1532
QScriptValue::Undeletable);
1533
stackPtr->put(member, proto);
1540
if (! stackPtr[0].isReference()) {
1542
throwSyntaxError(QLatin1String("invalid increment operand"));
1546
BEGIN_PREFIX_OPERATOR
1548
qsreal x = QScriptEnginePrivate::convertToNativeDouble(value);
1549
value = QScriptValueImpl(x + 1);
1556
if (! stackPtr[0].isReference()) {
1558
throwSyntaxError(QLatin1String("invalid decrement operand"));
1562
BEGIN_PREFIX_OPERATOR
1564
qsreal x = QScriptEnginePrivate::convertToNativeDouble(value);
1565
value = QScriptValueImpl(x - 1);
1572
if (! stackPtr[0].isReference()) {
1574
throwSyntaxError(QLatin1String("invalid increment operand"));
1578
QScriptValue::ResolveFlags mode;
1579
mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value)
1580
| QScriptValue::ResolvePrototype;
1584
QScriptValueImpl object = eng->toObject(stackPtr[-1]);
1585
if (!object.isObject()) {
1587
throwTypeError(QLatin1String("not an object"));
1591
QScriptNameIdImpl *memberName = 0;
1592
if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique)
1593
memberName = stackPtr[0].m_string_value;
1595
memberName = eng->nameId(stackPtr[0].toString(), /*persistent=*/false);
1597
QScript::Member member;
1598
QScriptValueImpl base;
1599
QScriptValueImpl value;
1600
QScriptObject *instance = object.m_object_value;
1601
const bool isMemberAssignment = (instance != m_scopeChain.m_object_value);
1602
if (instance->findMember(memberName, &member)) {
1603
if (!member.isGetterOrSetter()) {
1604
QScriptValueImpl &r = instance->reference(member);
1606
*(--stackPtr) = QScriptValueImpl(r.m_number_value);
1613
} else if (!object.resolve_helper(memberName, &member, &base, mode, QScript::ReadWrite)) {
1614
if (!isMemberAssignment) {
1616
throwNotDefined(memberName);
1620
CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1621
base.put(member, undefined);
1624
QScriptValueImpl getter;
1625
QScriptValueImpl setter;
1626
base.get(member, &value);
1627
if (hasUncaughtException()) {
1630
} else if (member.isGetterOrSetter()) {
1631
if (member.isGetter()) {
1633
if (!member.isSetter() && !base.m_object_value->findSetter(&member)) {
1635
throwError(QLatin1String("No setter defined"));
1638
base.get(member, &setter);
1641
QScript::Member tmp = member;
1642
if (!base.m_object_value->findGetter(&member)) {
1644
throwError(QLatin1String("No getter defined"));
1647
base.get(member, &getter);
1650
value = getter.call(object);
1651
if (hasUncaughtException()) {
1657
qsreal x = QScriptEnginePrivate::convertToNativeDouble(value);
1659
value = QScriptValueImpl(x + 1);
1661
if (member.isSetter()) {
1662
setter.call(object, QScriptValueImplList() << value);
1663
if (hasUncaughtException()) {
1668
if (isMemberAssignment && (base.m_object_value != object.m_object_value)) {
1670
CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1672
if (member.isWritable()) {
1673
base.put(member, value);
1674
if (hasUncaughtException()) {
1681
*(--stackPtr) = QScriptValueImpl(x);
1688
// ### most of the code is duplicated from PostIncr -- try to merge
1689
if (! stackPtr[0].isReference()) {
1691
throwSyntaxError(QLatin1String("invalid decrement operand"));
1695
QScriptValue::ResolveFlags mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value)
1696
| QScriptValue::ResolvePrototype;
1700
QScriptValueImpl object = eng->toObject(stackPtr[-1]);
1701
if (!object.isObject()) {
1703
throwTypeError(QLatin1String("not an object"));
1707
QScriptNameIdImpl *memberName = 0;
1708
if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique)
1709
memberName = stackPtr[0].m_string_value;
1711
memberName = eng->nameId(stackPtr[0].toString(), /*persistent=*/false);
1713
QScript::Member member;
1714
QScriptValueImpl base;
1715
QScriptValueImpl value;
1716
QScriptObject *instance = object.m_object_value;
1717
const bool isMemberAssignment = (instance != m_scopeChain.m_object_value);
1718
if (instance->findMember(memberName, &member)) {
1719
if (!member.isGetterOrSetter()) {
1720
QScriptValueImpl &r = instance->reference(member);
1722
*(--stackPtr) = QScriptValueImpl(r.m_number_value);
1729
} else if (! object.resolve_helper(memberName, &member, &base, mode, QScript::ReadWrite)) {
1730
if (!isMemberAssignment) {
1732
throwNotDefined(memberName);
1736
CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1737
base.put(member, undefined);
1740
QScriptValueImpl getter;
1741
QScriptValueImpl setter;
1742
base.get(member, &value);
1743
if (hasUncaughtException()) {
1746
} else if (member.isGetterOrSetter()) {
1747
if (member.isGetter()) {
1749
if (!member.isSetter() && !base.m_object_value->findSetter(&member)) {
1751
throwError(QLatin1String("No setter defined"));
1754
base.get(member, &setter);
1757
QScript::Member tmp = member;
1758
if (!base.m_object_value->findGetter(&member)) {
1760
throwError(QLatin1String("No getter defined"));
1763
base.get(member, &getter);
1766
value = getter.call(object);
1767
if (hasUncaughtException()) {
1773
qsreal x = QScriptEnginePrivate::convertToNativeDouble(value);
1775
value = QScriptValueImpl(x - 1);
1777
if (member.isSetter()) {
1778
setter.call(object, QScriptValueImplList() << value);
1779
if (hasUncaughtException()) {
1784
if (isMemberAssignment && (base.m_object_value != object.m_object_value)) {
1786
CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1788
if (member.isWritable()) {
1789
base.put(member, value);
1790
if (hasUncaughtException()) {
1797
*(--stackPtr) = QScriptValueImpl(x);
1804
BEGIN_INPLACE_OPERATOR
1806
lhs = eng->toPrimitive(lhs);
1807
rhs = eng->toPrimitive(rhs);
1808
if (lhs.isString() || rhs.isString()) {
1809
if (lhs.isString() && !lhs.m_string_value->unique) {
1810
lhs.m_string_value->s += QScriptEnginePrivate::convertToNativeString(rhs);
1814
QString tmp = QScriptEnginePrivate::convertToNativeString(lhs);
1815
tmp += QScriptEnginePrivate::convertToNativeString(rhs);
1817
eng->newString(stackPtr, tmp);
1820
qsreal tmp = QScriptEnginePrivate::convertToNativeDouble(lhs);
1821
tmp += QScriptEnginePrivate::convertToNativeDouble(rhs);
1823
*stackPtr = QScriptValueImpl(tmp);
1826
END_INPLACE_OPERATOR
1831
BEGIN_INPLACE_OPERATOR
1833
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
1834
qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
1837
*stackPtr = QScriptValueImpl(v1 - v2);
1839
END_INPLACE_OPERATOR
1844
BEGIN_INPLACE_OPERATOR
1846
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1847
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1850
*stackPtr = QScriptValueImpl(v1 & v2);
1852
END_INPLACE_OPERATOR
1857
BEGIN_INPLACE_OPERATOR
1859
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
1860
qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
1863
*stackPtr = QScriptValueImpl(v1 / v2);
1865
END_INPLACE_OPERATOR
1868
I(InplaceLeftShift):
1870
BEGIN_INPLACE_OPERATOR
1872
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1873
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1876
*stackPtr = QScriptValueImpl(v1 << v2);
1878
END_INPLACE_OPERATOR
1883
BEGIN_INPLACE_OPERATOR
1885
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
1886
qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
1889
*stackPtr = QScriptValueImpl(::fmod (v1, v2));
1891
END_INPLACE_OPERATOR
1896
BEGIN_INPLACE_OPERATOR
1898
qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
1899
qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
1902
*stackPtr = QScriptValueImpl(v1 * v2);
1904
END_INPLACE_OPERATOR
1909
BEGIN_INPLACE_OPERATOR
1911
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1912
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1915
*stackPtr = QScriptValueImpl(v1 | v2);
1917
END_INPLACE_OPERATOR
1920
I(InplaceRightShift):
1922
BEGIN_INPLACE_OPERATOR
1924
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1925
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1928
*stackPtr = QScriptValueImpl(v1 >> v2);
1930
END_INPLACE_OPERATOR
1933
I(InplaceURightShift):
1935
BEGIN_INPLACE_OPERATOR
1937
quint32 v1 = QScriptEnginePrivate::toUint32 (eng->convertToNativeDouble(lhs));
1938
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1941
*stackPtr = QScriptValueImpl(v1 >> v2);
1943
END_INPLACE_OPERATOR
1948
BEGIN_INPLACE_OPERATOR
1950
qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1951
qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1954
*stackPtr = QScriptValueImpl(v1 ^ v2);
1956
END_INPLACE_OPERATOR
1962
eng->newReference(++stackPtr, QScriptValue::ResolveLocal);
1968
QScriptValueImpl value;
1970
bool isReference = stackPtr[0].isReference();
1972
if (! isReference) { // we have a value
1973
value = stackPtr[0];
1974
} else if (resolveField(eng, &stackPtr[-1], &value)) {
1976
if (hasUncaughtException()) {
1987
switch (value.type()) {
1988
case QScript::InvalidType:
1989
typeName = QLatin1String("invalid");
1992
case QScript::UndefinedType:
1993
typeName = QLatin1String("undefined");
1996
case QScript::NullType:
1997
typeName = QLatin1String("object");
2000
case QScript::BooleanType:
2001
typeName = QLatin1String("boolean");
2004
case QScript::IntegerType:
2005
case QScript::NumberType:
2006
typeName = QLatin1String("number");
2009
case QScript::StringType:
2010
case QScript::LazyStringType:
2011
typeName = QLatin1String("string");
2014
case QScript::ReferenceType:
2015
typeName = QLatin1String("reference");
2018
case QScript::PointerType:
2019
typeName = QLatin1String("pointer");
2022
case QScript::ObjectType:
2023
if (value.isFunction())
2024
typeName = QLatin1String("function");
2026
typeName = QLatin1String("object");
2030
eng->newString(stackPtr, typeName);
2037
eng->maybeProcessEvents();
2038
if (hasUncaughtException())
2040
if (eng->shouldAbort())
2042
currentLine = iPtr->operand[0].m_int_value;
2043
currentColumn = iPtr->operand[1].m_int_value;
2044
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2045
if (eng->shouldNotify()) {
2046
eng->notifyPositionChange(this);
2047
if (hasUncaughtException())
2049
if (eng->shouldAbort())
2059
if (! stackPtr[0].isReference())
2063
QScriptValueImpl object = stackPtr[-2];
2064
if (!object.isObject())
2065
object = eng->toObject(object);
2067
QScriptNameIdImpl *nameId = 0;
2068
if (stackPtr[-1].isString() && stackPtr[-1].m_string_value->unique) {
2069
nameId = stackPtr[-1].m_string_value;
2071
nameId = eng->nameId(QScriptEnginePrivate::convertToNativeString(stackPtr[-1]),
2072
/*persistent=*/false);
2074
if (object.classInfo() == eng->m_class_with)
2075
object = object.prototype();
2076
result = object.deleteProperty(nameId, QScriptValue::ResolveScope);
2080
*stackPtr = QScriptValueImpl(result);
2086
I(NewEnumeration): {
2088
QScriptValueImpl object = eng->toObject(stackPtr[0]);
2089
eng->enumerationConstructor->newEnumeration(&e, object);
2095
I(ToFirstElement): {
2096
QScript::Ext::Enumeration::Instance *e = eng->enumerationConstructor->get(stackPtr[0]);
2104
I(HasNextElement): {
2105
QScript::Ext::Enumeration::Instance *e = eng->enumerationConstructor->get(stackPtr[0]);
2107
e->hasNext(this, stackPtr);
2113
// the Enumeration should be located below the result of I(Resolve)
2114
if (! stackPtr[0].isReference()) {
2115
throwTypeError(QLatin1String("QScript.VM.NextElement"));
2119
QScript::Ext::Enumeration::Instance *e = eng->enumerationConstructor->get(stackPtr[-3]);
2121
throwTypeError(QLatin1String("QScript.VM.NextElement"));
2124
e->next(this, ++stackPtr);
2137
m_result = *stackPtr;
2144
Q_ASSERT(stackPtr->isValid());
2145
m_result = *stackPtr--;
2146
if (!m_result.isError() && !exceptionHandlerContext())
2147
eng->m_exceptionBacktrace = backtrace();
2148
m_state = QScriptContext::ExceptionState;
2149
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2150
eng->notifyException(this);
2152
} HandleException();
2156
Q_ASSERT(stackPtr->isValid());
2157
m_result = *stackPtr--;
2168
QScriptValueImpl object = eng->toObject(*stackPtr--);
2169
if (! object.isValid()) {
2170
throwTypeError(QLatin1String("value has no properties"));
2173
QScriptValueImpl withObject;
2174
eng->newObject(&withObject, object, eng->m_class_with);
2175
withObject.m_object_value->m_scope = m_scopeChain;
2176
m_scopeChain = withObject;
2182
QScriptValueImpl withObject = m_scopeChain;
2183
m_scopeChain = withObject.m_object_value->m_scope;
2189
// result contains the thrown object
2190
QScriptValueImpl object;
2191
eng->newObject(&object, undefined); // ### prototype
2192
QScript::Member member;
2193
CREATE_MEMBER(object, iPtr->operand[0].m_string_value, &member, /*flags=*/0);
2194
object.put(member, m_result);
2195
// make catch-object head of scopechain
2196
object.m_object_value->m_scope = m_scopeChain;
2197
m_scopeChain = object;
2205
// remove catch-object from scopechain
2206
QScriptValueImpl object = m_scopeChain;
2207
m_scopeChain = object.m_object_value->m_scope;
2215
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2216
eng->notifyDebugger(this);
2221
#ifndef Q_SCRIPT_DIRECT_CODE
2229
errorLineNumber = currentLine;
2232
Q_ASSERT(m_result.isValid());
2234
if (m_state == QScriptContext::ExceptionState) {
2236
// exception thrown in catch -- clean up scopechain
2237
QScriptValueImpl object = m_scopeChain;
2238
m_scopeChain = object.m_object_value->m_scope;
2242
// see if we have an exception handler in this context
2243
const QScriptInstruction *exPtr = findExceptionHandler(iPtr);
2245
if (m_scopeChain.classInfo() == eng->m_class_with) {
2246
// clean up effects of with-statements if necessary
2248
for (++iPtr; iPtr != exPtr; ++iPtr) {
2249
if (iPtr->op == QScriptInstruction::OP_EnterWith) {
2251
} else if (iPtr->op == QScriptInstruction::OP_LeaveWith) {
2253
if (withLevel < 0) {
2254
QScriptValueImpl withObject = m_scopeChain;
2255
m_scopeChain = withObject.m_object_value->m_scope;
2262
// go to the handler
2264
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2265
eng->notifyExceptionCatch(this);
2269
if (!parentContext()) {
2270
// pop all the top-level with-objects
2271
while ((m_scopeChain.classInfo() == eng->m_class_with)
2272
&& !m_scopeChain.internalValue().isValid()) {
2273
QScriptValueImpl withObject = m_scopeChain;
2274
m_scopeChain = withObject.m_object_value->m_scope;
2281
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2282
eng->notifyFunctionExit(this);
2287
currentLine = oldCurrentLine;
2288
currentColumn = oldCurrentColumn;
2291
eng->m_evaluating = wasEvaluating;
2294
QScriptValueImpl QScriptContextPrivate::throwError(QScriptContext::Error error, const QString &text)
2296
QScriptEnginePrivate *eng_p = engine();
2297
QScript::Ecma::Error *ctor = eng_p->errorConstructor;
2298
m_result.invalidate();
2300
case QScriptContext::ReferenceError:
2301
ctor->newReferenceError(&m_result, text);
2303
case QScriptContext::SyntaxError:
2304
ctor->newSyntaxError(&m_result, text);
2306
case QScriptContext::TypeError:
2307
ctor->newTypeError(&m_result, text);
2309
case QScriptContext::RangeError:
2310
ctor->newRangeError(&m_result, text);
2312
case QScriptContext::URIError:
2313
ctor->newURIError(&m_result, text);
2315
case QScriptContext::UnknownError:
2317
ctor->newError(&m_result, text);
2319
setDebugInformation(&m_result);
2320
m_state = QScriptContext::ExceptionState;
2321
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2322
eng_p->notifyException(this);
2327
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2328
qint64 QScriptContextPrivate::scriptId() const
2332
return m_code->astPool->id();
2336
QString QScriptContextPrivate::fileName() const
2340
return m_code->astPool->fileName();
2343
QString QScriptContextPrivate::functionName() const
2345
if (!m_callee.isValid())
2347
QScriptFunction *fun = m_callee.toFunction();
2349
return fun->functionName();
2353
void QScriptContextPrivate::setDebugInformation(QScriptValueImpl *error) const
2355
QScriptEnginePrivate *eng_p = engine();
2356
error->setProperty(QLatin1String("lineNumber"), QScriptValueImpl(currentLine));
2357
if (!fileName().isEmpty())
2358
error->setProperty(QLatin1String("fileName"), QScriptValueImpl(eng_p, fileName()));
2360
const QScriptContextPrivate *ctx = this;
2361
QScriptValueImpl stackArray = eng_p->newArray();
2364
QScriptValueImpl obj = eng_p->newObject();
2365
obj.setProperty(QLatin1String("frame"), ctx->activationObject());
2366
obj.setProperty(QLatin1String("lineNumber"), QScriptValueImpl(ctx->currentLine));
2367
if (!ctx->fileName().isEmpty())
2368
obj.setProperty(QLatin1String("fileName"), QScriptValueImpl(eng_p, ctx->fileName()));
2369
if (!ctx->functionName().isEmpty())
2370
obj.setProperty(QLatin1String("functionName"), QScriptValueImpl(eng_p, ctx->functionName()));
2371
stackArray.setProperty(i, obj);
2372
ctx = ctx->parentContext();
2375
error->setProperty(QLatin1String("stack"), stackArray);
2378
QStringList QScriptContextPrivate::backtrace() const
2381
const QScriptContextPrivate *ctx = this;
2384
QString functionName = ctx->functionName();
2385
if (!functionName.isEmpty())
2388
if (ctx->parentContext()) {
2389
if (ctx->callee().isFunction()
2390
&& ctx->callee().toFunction()->type() != QScriptFunction::Script) {
2391
s += QLatin1String("<native>");
2393
s += QLatin1String("<anonymous>");
2396
s += QLatin1String("<global>");
2399
s += QLatin1String("(");
2400
for (int i = 0; i < ctx->argc; ++i) {
2402
s += QLatin1String(",");
2403
QScriptValueImpl arg = ctx->args[i];
2405
s += QLatin1String("[object Object]"); // don't do a function call
2407
s += arg.toString();
2409
s += QLatin1String(")@");
2410
s += ctx->fileName();
2411
s += QString::fromLatin1(":%0").arg(ctx->currentLine);
2413
ctx = ctx->parentContext();
2418
QScriptValueImpl QScriptContextPrivate::throwError(const QString &text)
2420
return throwError(QScriptContext::UnknownError, text);
2423
QScriptValueImpl QScriptContextPrivate::throwNotImplemented(const QString &name)
2425
return throwTypeError(QString::fromUtf8("%1 is not implemented").arg(name));
2428
QScriptValueImpl QScriptContextPrivate::throwNotDefined(const QString &name)
2430
return throwError(QScriptContext::ReferenceError,
2431
QString::fromUtf8("%1 is not defined").arg(name));
2434
QScriptValueImpl QScriptContextPrivate::throwNotDefined(QScriptNameIdImpl *nameId)
2436
return throwNotDefined(QScriptEnginePrivate::toString(nameId));
2439
bool QScriptContextPrivate::eq_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs)
2441
if (lhs.isNull() && rhs.isUndefined())
2444
else if (lhs.isUndefined() && rhs.isNull())
2447
else if (isNumerical(lhs) && rhs.isString())
2448
return QScriptEnginePrivate::convertToNativeDouble(lhs) == QScriptEnginePrivate::convertToNativeDouble(rhs);
2450
else if (lhs.isString() && isNumerical(rhs))
2451
return QScriptEnginePrivate::convertToNativeDouble(lhs) == QScriptEnginePrivate::convertToNativeDouble(rhs);
2453
else if (lhs.isBoolean())
2454
return eq_cmp(QScriptValueImpl(QScriptEnginePrivate::convertToNativeDouble(lhs)), rhs);
2456
else if (rhs.isBoolean())
2457
return eq_cmp(lhs, QScriptValueImpl(QScriptEnginePrivate::convertToNativeDouble(rhs)));
2459
else if (lhs.isObject() && ! rhs.isNull()) {
2460
lhs = lhs.engine()->toPrimitive(lhs);
2462
if (lhs.isValid() && ! lhs.isObject())
2463
return eq_cmp(lhs, rhs);
2466
else if (rhs.isObject() && ! lhs.isNull()) {
2467
rhs = rhs.engine()->toPrimitive(rhs);
2469
if (rhs.isValid() && ! rhs.isObject())
2470
return eq_cmp(lhs, rhs);
2476
#if defined(Q_CC_GNU) && __GNUC__ <= 3
2477
bool QScriptContextPrivate::lt_cmp(QScriptValueImpl lhs, QScriptValueImpl rhs)
2479
if (lhs.type() == rhs.type()) {
2480
switch (lhs.type()) {
2481
case QScript::InvalidType:
2482
case QScript::UndefinedType:
2483
case QScript::NullType:
2486
case QScript::NumberType:
2487
return lhs.m_number_value < rhs.m_number_value;
2489
case QScript::IntegerType:
2490
return lhs.m_int_value < rhs.m_int_value;
2492
case QScript::BooleanType:
2493
return lhs.m_bool_value < rhs.m_bool_value;
2500
bool QScriptContextPrivate::lt_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs)
2503
if ((lhs.type() == rhs.type()) && (lhs.type() == QScript::StringType))
2504
return lhs.m_string_value->s < rhs.m_string_value->s;
2507
lhs = lhs.engine()->toPrimitive(lhs, QScriptValueImpl::NumberTypeHint);
2510
rhs = rhs.engine()->toPrimitive(rhs, QScriptValueImpl::NumberTypeHint);
2512
if (lhs.isString() && rhs.isString())
2513
return QScriptEnginePrivate::convertToNativeString(lhs) < QScriptEnginePrivate::convertToNativeString(rhs);
2515
qsreal n1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
2516
qsreal n2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
2517
#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET
2518
if (qIsNaN(n1) || qIsNaN(n2))
2524
bool QScriptContextPrivate::le_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs)
2526
if ((lhs.type() == rhs.type()) && (lhs.type() == QScript::StringType))
2527
return lhs.m_string_value->s <= rhs.m_string_value->s;
2530
lhs = lhs.engine()->toPrimitive(lhs, QScriptValueImpl::NumberTypeHint);
2533
rhs = rhs.engine()->toPrimitive(rhs, QScriptValueImpl::NumberTypeHint);
2535
if (lhs.isString() && rhs.isString())
2536
return QScriptEnginePrivate::convertToNativeString(lhs) <= QScriptEnginePrivate::convertToNativeString(rhs);
2538
qsreal n1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
2539
qsreal n2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
2543
const QScriptInstruction *QScriptContextPrivate::findExceptionHandler(
2544
const QScriptInstruction *ip) const
2547
int offset = ip - m_code->firstInstruction;
2548
for (int i = 0; i < m_code->exceptionHandlers.count(); ++i) {
2549
QScript::ExceptionHandlerDescriptor e = m_code->exceptionHandlers.at(i);
2550
if (offset >= e.startInstruction() && offset <= e.endInstruction()) {
2551
return m_code->firstInstruction + e.handlerInstruction();
2557
const QScriptInstruction *QScriptContextPrivate::findExceptionHandlerRecursive(
2558
const QScriptInstruction *ip, QScriptContextPrivate **handlerContext) const
2560
const QScriptContextPrivate *ctx = this;
2561
const QScriptInstruction *iip = ip;
2564
const QScriptInstruction *ep = ctx->findExceptionHandler(iip);
2566
Q_ASSERT(handlerContext);
2567
*handlerContext = const_cast<QScriptContextPrivate*>(ctx);
2571
ctx = ctx->parentContext();
2579
Requires that iPtr in current context is in sync
2581
QScriptContextPrivate *QScriptContextPrivate::exceptionHandlerContext() const
2583
QScriptContextPrivate *handlerContext;
2584
if (findExceptionHandlerRecursive(iPtr, &handlerContext))
2585
return handlerContext;
2589
QScriptContext *QScriptContextPrivate::get(QScriptContextPrivate *d)
2598
#endif // QT_NO_SCRIPT