~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/script/qscriptcontext_p.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/****************************************************************************
2
 
**
3
 
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
 
** Contact: Nokia Corporation (qt-info@nokia.com)
5
 
**
6
 
** This file is part of the QtScript module of the Qt Toolkit.
7
 
**
8
 
** $QT_BEGIN_LICENSE:LGPL$
9
 
** Commercial Usage
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.
14
 
**
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.
22
 
**
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
26
 
** package.
27
 
**
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.
35
 
**
36
 
** If you are unsure which license is appropriate for your use, please
37
 
** contact the sales department at http://www.qtsoftware.com/contact.
38
 
** $QT_END_LICENSE$
39
 
**
40
 
****************************************************************************/
41
 
 
42
 
#include <QtCore/QtDebug>
43
 
 
44
 
#ifndef QT_NO_SCRIPT
45
 
 
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"
56
 
 
57
 
#include <math.h> // floor & friends...
58
 
 
59
 
QT_BEGIN_NAMESPACE
60
 
 
61
 
#define Q_SCRIPT_NO_PRINT_GENERATED_CODE
62
 
 
63
 
#define Q_SCRIPT_NO_JOINED_FUNCTION
64
 
 
65
 
#define CHECK_TEMPSTACK(needed) do { \
66
 
    if (stackPtr + needed >= eng->tempStackEnd) { \
67
 
        throwError(QLatin1String("out of memory")); \
68
 
        HandleException(); \
69
 
    } \
70
 
} while (0)
71
 
 
72
 
#ifndef Q_SCRIPT_NO_PRINT_GENERATED_CODE
73
 
static QTextStream qout(stderr, QIODevice::WriteOnly);
74
 
#endif
75
 
 
76
 
static inline void qscript_uint_to_string_helper(uint i, QString &s)
77
 
{
78
 
    switch (i) {
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);
82
 
        break;
83
 
 
84
 
    default:
85
 
        qscript_uint_to_string_helper(i / 10, s);
86
 
        s += QLatin1Char('0' + (i % 10));
87
 
    }
88
 
}
89
 
 
90
 
static inline void qscript_uint_to_string(qsreal i, QString &s)
91
 
{
92
 
    if ((i < 0) || (i > 0xFFFFFFFF))
93
 
        return; // nothing to do
94
 
 
95
 
    qsreal x = ::fmod(i, 10);
96
 
 
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
103
 
 
104
 
    qscript_uint_to_string_helper(uint(i), s);
105
 
}
106
 
 
107
 
static inline quint32 toArrayIndex(const QScriptValueImpl &v)
108
 
{
109
 
    if (v.isNumber()) {
110
 
        quint32 ui = v.toUInt32();
111
 
        if (qsreal(ui) == v.m_number_value)
112
 
            return ui;
113
 
    } else if (v.isString()) {
114
 
        QByteArray bytes = v.m_string_value->s.toUtf8();
115
 
        char *eptr;
116
 
        quint32 pos = strtoul(bytes.constData(), &eptr, 10);
117
 
        if ((eptr == bytes.constData() + bytes.size())
118
 
            && (QByteArray::number(pos) == bytes)) {
119
 
            return pos;
120
 
        }
121
 
    }
122
 
    return 0xFFFFFFFF;
123
 
}
124
 
 
125
 
#define CREATE_MEMBER(__obj__, __name__, __member__, __flags__) do { \
126
 
    (__obj__).createMember(__name__, __member__, __flags__); \
127
 
    eng->adjustBytesAllocated(sizeof(QScript::Member) + sizeof(QScriptValueImpl)); \
128
 
} while (0)
129
 
 
130
 
#define BEGIN_PREFIX_OPERATOR \
131
 
    QScriptValue::ResolveFlags mode; \
132
 
    mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value) \
133
 
    | QScriptValue::ResolvePrototype; \
134
 
    --stackPtr; \
135
 
    QScriptValueImpl object = eng->toObject(stackPtr[-1]); \
136
 
    if (!object.isObject()) { \
137
 
        stackPtr -= 2;  \
138
 
        throwTypeError(QLatin1String("not an object")); \
139
 
        HandleException(); \
140
 
    } \
141
 
    QScriptNameIdImpl *memberName = 0; \
142
 
    if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique) \
143
 
        memberName = stackPtr[0].m_string_value; \
144
 
    else \
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()) { \
155
 
            stackPtr -= 2; \
156
 
            HandleException(); \
157
 
        } else if (member.isGetterOrSetter()) { \
158
 
            if (member.isGetter()) { \
159
 
                getter = value; \
160
 
                if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { \
161
 
                    stackPtr -= 2; \
162
 
                    throwError(QLatin1String("No setter defined")); \
163
 
                    HandleException(); \
164
 
                } \
165
 
                base.get(member, &setter); \
166
 
            } else { \
167
 
                setter = value; \
168
 
                QScript::Member tmp = member; \
169
 
                if (!base.m_object_value->findGetter(&member)) { \
170
 
                    stackPtr -= 2; \
171
 
                    throwError(QLatin1String("No getter defined")); \
172
 
                    HandleException(); \
173
 
                } \
174
 
                base.get(member, &getter); \
175
 
                member = tmp; \
176
 
            } \
177
 
            value = getter.call(object); \
178
 
            if (hasUncaughtException()) { \
179
 
                stackPtr -= 2; \
180
 
                Done(); \
181
 
            } \
182
 
        } \
183
 
    } else if (!isMemberAssignment) { \
184
 
        stackPtr -= 2; \
185
 
        throwNotDefined(memberName); \
186
 
        HandleException(); \
187
 
    } else { \
188
 
        base = object; \
189
 
        CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \
190
 
        value = undefined; \
191
 
    }
192
 
 
193
 
#define END_PREFIX_OPERATOR \
194
 
    if (member.isSetter()) { \
195
 
        setter.call(object, QScriptValueImplList() << value); \
196
 
        if (hasUncaughtException()) { \
197
 
            stackPtr -= 2; \
198
 
            Done(); \
199
 
        } \
200
 
    } else { \
201
 
        if (member.isWritable()) { \
202
 
            if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { \
203
 
                base = object; \
204
 
                CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \
205
 
            } \
206
 
            base.put(member, value); \
207
 
            if (hasUncaughtException()) { \
208
 
                stackPtr -= 2; \
209
 
                HandleException(); \
210
 
            } \
211
 
        } \
212
 
    } \
213
 
    *--stackPtr = value; \
214
 
    ++iPtr;
215
 
 
216
 
#define BEGIN_INPLACE_OPERATOR \
217
 
    if (! stackPtr[-1].isReference()) { \
218
 
        stackPtr -= 2; \
219
 
        throwSyntaxError(QLatin1String("invalid assignment lvalue")); \
220
 
        HandleException(); \
221
 
    } \
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()) { \
227
 
        stackPtr -= 4; \
228
 
        throwTypeError(QLatin1String("not an object")); \
229
 
        HandleException(); \
230
 
    } \
231
 
    QScriptNameIdImpl *memberName = 0; \
232
 
    if (stackPtr[-2].isString() && stackPtr[-2].m_string_value->unique) \
233
 
        memberName = stackPtr[-2].m_string_value; \
234
 
    else \
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()) { \
245
 
            stackPtr -= 4; \
246
 
            HandleException(); \
247
 
        } else if (member.isGetterOrSetter()) { \
248
 
            if (member.isGetter()) { \
249
 
                getter = lhs; \
250
 
                if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { \
251
 
                    stackPtr -= 4; \
252
 
                    throwError(QLatin1String("No setter defined")); \
253
 
                    HandleException(); \
254
 
                } \
255
 
                base.get(member, &setter); \
256
 
            } else { \
257
 
                setter = lhs; \
258
 
                QScript::Member tmp = member; \
259
 
                if (!base.m_object_value->findGetter(&member)) { \
260
 
                    stackPtr -= 4; \
261
 
                    throwError(QLatin1String("No getter defined")); \
262
 
                    HandleException(); \
263
 
                } \
264
 
                base.get(member, &getter); \
265
 
                member = tmp; \
266
 
            } \
267
 
            lhs = getter.call(object); \
268
 
            if (hasUncaughtException()) { \
269
 
                stackPtr -= 4; \
270
 
                Done(); \
271
 
            } \
272
 
        } \
273
 
    } else if (!isMemberAssignment) { \
274
 
        stackPtr -= 4; \
275
 
        throwNotDefined(memberName); \
276
 
        HandleException(); \
277
 
    } else { \
278
 
        base = object; \
279
 
        CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \
280
 
        lhs = undefined; \
281
 
    } \
282
 
    QScriptValueImpl rhs = stackPtr[0];
283
 
 
284
 
#define END_INPLACE_OPERATOR \
285
 
    if (member.isSetter()) { \
286
 
        setter.call(object, QScriptValueImplList() << *stackPtr); \
287
 
        if (hasUncaughtException()) { \
288
 
            stackPtr -= 1; \
289
 
            Done(); \
290
 
        } \
291
 
    } else { \
292
 
        if (member.isWritable()) { \
293
 
            if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { \
294
 
                base = object; \
295
 
                CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \
296
 
            } \
297
 
            base.put(member, *stackPtr); \
298
 
            if (hasUncaughtException()) { \
299
 
                stackPtr -= 1; \
300
 
                HandleException(); \
301
 
            } \
302
 
        } \
303
 
    } \
304
 
    ++iPtr;
305
 
 
306
 
namespace QScript {
307
 
 
308
 
void ScriptFunction::execute(QScriptContextPrivate *context)
309
 
{
310
 
    if (! m_compiledCode) {
311
 
        QScriptEnginePrivate *eng = context->engine();
312
 
        Compiler compiler(eng);
313
 
 
314
 
        CompilationUnit unit = compiler.compile(m_definition->body, formals);
315
 
        if (! unit.isValid()) {
316
 
            context->throwError(unit.errorMessage());
317
 
            return;
318
 
        }
319
 
 
320
 
        m_compiledCode = m_astPool->createCompiledCode(m_definition->body, unit);
321
 
    }
322
 
 
323
 
    context->execute(m_compiledCode);
324
 
}
325
 
 
326
 
QString ScriptFunction::toString(QScriptContextPrivate *) const
327
 
{
328
 
    QString str;
329
 
    QTextStream out(&str, QIODevice::WriteOnly);
330
 
    PrettyPretty pp(out);
331
 
    pp(m_definition, /*indent=*/ 0);
332
 
    return str;
333
 
}
334
 
 
335
 
QString ScriptFunction::fileName() const
336
 
{
337
 
    return m_astPool->fileName();
338
 
}
339
 
 
340
 
QString ScriptFunction::functionName() const
341
 
{
342
 
    if (!m_definition->name)
343
 
        return QString();
344
 
    return m_definition->name->s;
345
 
}
346
 
 
347
 
int ScriptFunction::startLineNumber() const
348
 
{
349
 
    return m_definition->startLine;
350
 
}
351
 
 
352
 
int ScriptFunction::endLineNumber() const
353
 
{
354
 
    return m_definition->endLine;
355
 
}
356
 
 
357
 
} // namespace QScript
358
 
 
359
 
/*!
360
 
  \internal
361
 
 
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.
366
 
*/
367
 
bool QScriptContextPrivate::resolveField(QScriptEnginePrivate *eng,
368
 
                                         QScriptValueImpl *stackPtr,
369
 
                                         QScriptValueImpl *value)
370
 
{
371
 
    const QScriptValueImpl &m = stackPtr[0];
372
 
    QScriptValueImpl &object = stackPtr[-1];
373
 
 
374
 
    if (! object.isObject())
375
 
        object = eng->toObject(object);
376
 
 
377
 
    if (! object.isValid())
378
 
        return false;
379
 
 
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);
384
 
 
385
 
            if (! value->isValid())
386
 
                *value = eng->undefinedValue();
387
 
 
388
 
            return true;
389
 
        }
390
 
    }
391
 
 
392
 
    QScriptNameIdImpl *nameId = m.isString() ? m.m_string_value : 0;
393
 
 
394
 
    if (! nameId || ! nameId->unique)
395
 
        nameId = eng->nameId(QScriptEnginePrivate::convertToNativeString(m), /*persistent=*/false); // ### slow!
396
 
 
397
 
    QScript::Member member;
398
 
    QScriptValueImpl base;
399
 
 
400
 
    if (! object.resolve(nameId, &member, &base, QScriptValue::ResolveFull, QScript::Read)) // ### ...
401
 
        return false;
402
 
 
403
 
    if (QScriptEnginePrivate::strictlyEquals(base, eng->m_globalObject))
404
 
        stackPtr[-1] = base;
405
 
    else if (object.classInfo() == eng->m_class_with)
406
 
        stackPtr[-1] = object.prototype();
407
 
 
408
 
    base.get(member, value);
409
 
 
410
 
    if (member.isGetterOrSetter()) {
411
 
        // call the getter function
412
 
        QScriptValueImpl getter;
413
 
        if (member.isGetter()) {
414
 
            getter = *value;
415
 
        } else {
416
 
            if (!base.m_object_value->findGetter(&member)) {
417
 
                *value = eng->undefinedValue();
418
 
                return true;
419
 
            }
420
 
            base.get(member, &getter);
421
 
        }
422
 
        *value = getter.call(object);
423
 
    }
424
 
 
425
 
    return true;
426
 
}
427
 
 
428
 
void QScriptContextPrivate::execute(QScript::Code *code)
429
 
{
430
 
    int oldCurrentLine = currentLine;
431
 
    int oldCurrentColumn = currentColumn;
432
 
    QScript::Code *oldCode = m_code;
433
 
    m_code = code;
434
 
 
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);
440
 
        qout << endl;
441
 
    }
442
 
    qout << endl;
443
 
#endif
444
 
 
445
 
    QScriptEnginePrivate *eng = engine();
446
 
 
447
 
    bool wasEvaluating = eng->m_evaluating;
448
 
    if (!wasEvaluating) {
449
 
        eng->setupProcessEvents();
450
 
        eng->resetAbortFlag();
451
 
    }
452
 
    eng->m_evaluating = true;
453
 
 
454
 
    // set up the temp stack
455
 
    if (! tempStack)
456
 
        stackPtr = tempStack = eng->tempStackBegin;
457
 
 
458
 
    QScriptValueImpl undefined(eng->undefinedValue());
459
 
 
460
 
    catching = false;
461
 
    m_state = QScriptContext::NormalState;
462
 
    m_result = undefined;
463
 
    firstInstruction = code->firstInstruction;
464
 
    lastInstruction = code->lastInstruction;
465
 
    iPtr = code->firstInstruction;
466
 
 
467
 
    if (!m_scopeChain.isValid())
468
 
        m_scopeChain = m_activation;
469
 
 
470
 
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
471
 
    eng->notifyFunctionEntry(this);
472
 
#endif
473
 
 
474
 
#ifndef Q_SCRIPT_DIRECT_CODE
475
 
 
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
481
 
 
482
 
Lfetch:
483
 
 
484
 
 
485
 
#else
486
 
 
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
492
 
 
493
 
    static void * const jump_table[] = {
494
 
 
495
 
#  define Q_SCRIPT_DEFINE_OPERATOR(op) &&I(op),
496
 
#  include "instruction.table"
497
 
#  undef Q_SCRIPT_DEFINE_OPERATOR
498
 
    }; // jump_table
499
 
 
500
 
 
501
 
    if (!code->optimized) {
502
 
        for (QScriptInstruction *current = code->firstInstruction; current != code->lastInstruction; ++current) {
503
 
            current->code = jump_table[current->op];
504
 
        }
505
 
 
506
 
        code->optimized = true;
507
 
    }
508
 
 
509
 
#endif
510
 
Ltop:
511
 
 
512
 
#ifndef Q_SCRIPT_DIRECT_CODE
513
 
    switch (iPtr->op) {
514
 
#else
515
 
    goto *iPtr->code;
516
 
#endif
517
 
 
518
 
    I(Nop):
519
 
    {
520
 
        ++iPtr;
521
 
    }   Next();
522
 
 
523
 
    I(LoadUndefined):
524
 
    {
525
 
        CHECK_TEMPSTACK(1);
526
 
        *(++stackPtr) = undefined;
527
 
        ++iPtr;
528
 
    }   Next();
529
 
 
530
 
    I(LoadTrue):
531
 
    {
532
 
        CHECK_TEMPSTACK(1);
533
 
        *(++stackPtr) = QScriptValueImpl(true);
534
 
        ++iPtr;
535
 
    }   Next();
536
 
 
537
 
    I(LoadFalse):
538
 
    {
539
 
        CHECK_TEMPSTACK(1);
540
 
        *(++stackPtr) = QScriptValueImpl(false);
541
 
        ++iPtr;
542
 
    }   Next();
543
 
 
544
 
    I(LoadThis):
545
 
    {
546
 
        CHECK_TEMPSTACK(1);
547
 
        Q_ASSERT(m_thisObject.isObject());
548
 
        *++stackPtr = m_thisObject;
549
 
        ++iPtr;
550
 
    }   Next();
551
 
 
552
 
    I(LoadActivation):
553
 
    {
554
 
        CHECK_TEMPSTACK(1);
555
 
        *++stackPtr = m_activation;
556
 
        ++iPtr;
557
 
    }   Next();
558
 
 
559
 
    I(LoadNull):
560
 
    {
561
 
        CHECK_TEMPSTACK(1);
562
 
        *(++stackPtr) = eng->nullValue();
563
 
        ++iPtr;
564
 
    }   Next();
565
 
 
566
 
    I(LoadNumber):
567
 
    {
568
 
        CHECK_TEMPSTACK(1);
569
 
        *++stackPtr = iPtr->operand[0];
570
 
        ++iPtr;
571
 
    }   Next();
572
 
 
573
 
 
574
 
    I(LoadString):
575
 
    {
576
 
        CHECK_TEMPSTACK(1);
577
 
        *++stackPtr = iPtr->operand[0];
578
 
        ++iPtr;
579
 
    }   Next();
580
 
 
581
 
    I(NewString):
582
 
    {
583
 
        CHECK_TEMPSTACK(1);
584
 
        eng->newNameId(++stackPtr, iPtr->operand[0].m_string_value);
585
 
        ++iPtr;
586
 
    }   Next();
587
 
 
588
 
    I(Duplicate):
589
 
    {
590
 
        CHECK_TEMPSTACK(1);
591
 
        ++stackPtr;
592
 
        *stackPtr = stackPtr[-1];
593
 
        ++iPtr;
594
 
    }   Next();
595
 
 
596
 
    I(Swap):
597
 
    {
598
 
        QScriptValueImpl tmp = stackPtr[0];
599
 
        *stackPtr = stackPtr[-1];
600
 
        stackPtr[-1] = tmp;
601
 
        ++iPtr;
602
 
    }   Next();
603
 
 
604
 
    
605
 
    I(Receive):
606
 
    {
607
 
        int n = iPtr->operand[0].m_int_value;
608
 
 
609
 
        if (n >= argc) {
610
 
            throwError(QLatin1String("invalid argument"));
611
 
            HandleException();
612
 
        }
613
 
 
614
 
        CHECK_TEMPSTACK(1);
615
 
        *++stackPtr = argument(n);
616
 
        ++iPtr;
617
 
    }   Next();
618
 
 
619
 
    I(Fetch):
620
 
    {
621
 
        CHECK_TEMPSTACK(1);
622
 
 
623
 
        QScriptNameIdImpl *memberName = iPtr->operand[0].m_string_value;
624
 
 
625
 
        QScriptValueImpl base;
626
 
        QScript::Member member;
627
 
 
628
 
        QScriptObject *instance = m_scopeChain.m_object_value;
629
 
        if (instance->findMember(memberName, &member)) {
630
 
            instance->get(member, ++stackPtr);
631
 
            base = m_scopeChain;
632
 
        } else {
633
 
            if (m_scopeChain.resolve_helper(memberName, &member, &base, QScriptValue::ResolveFull, QScript::Read)) {
634
 
                base.get(member, ++stackPtr);
635
 
                if (hasUncaughtException()) {
636
 
                    stackPtr -= 1;
637
 
                    HandleException();
638
 
                }
639
 
            } else {
640
 
                throwNotDefined(memberName);
641
 
                HandleException();
642
 
            }
643
 
        }
644
 
        if (member.isGetterOrSetter()) {
645
 
            // locate the getter function
646
 
            QScriptValueImpl getter;
647
 
            if (member.isGetter()) {
648
 
                getter = *stackPtr;
649
 
            } else {
650
 
                if (!base.m_object_value->findGetter(&member)) {
651
 
                    stackPtr -= 1;
652
 
                    throwError(QLatin1String("No getter defined"));
653
 
                    HandleException();
654
 
                }
655
 
                base.get(member, &getter);
656
 
            }
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();
664
 
 
665
 
            *stackPtr = getter.call(object);
666
 
            if (hasUncaughtException()) {
667
 
                stackPtr -= 1;
668
 
                Done();
669
 
            }
670
 
        }
671
 
        ++iPtr;
672
 
    }   Next();
673
 
 
674
 
    I(Resolve):
675
 
    {
676
 
        Q_ASSERT(iPtr->operand[0].isString());
677
 
 
678
 
        CHECK_TEMPSTACK(2);
679
 
        *++stackPtr = m_scopeChain;
680
 
        *++stackPtr = iPtr->operand[0];
681
 
        eng->newReference(++stackPtr, QScriptValue::ResolveScope);
682
 
        ++iPtr;
683
 
    }   Next();
684
 
 
685
 
    I(PutField):
686
 
    {
687
 
        Q_ASSERT(stackPtr[-1].isReference());
688
 
 
689
 
        const QScriptValueImpl &object = stackPtr[-3];
690
 
        QScriptNameIdImpl *memberName = stackPtr[-2].m_string_value;
691
 
        const QScriptValueImpl &value = stackPtr[0];
692
 
 
693
 
        QScript::Member member;
694
 
        QScriptValueImpl base;
695
 
 
696
 
        if (! object.resolve(memberName, &member, &base, QScriptValue::ResolveLocal, QScript::Write)) {
697
 
            base = object;
698
 
            CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
699
 
        }
700
 
 
701
 
        base.put(member, value);
702
 
        stackPtr -= 4;
703
 
        if (hasUncaughtException())
704
 
            HandleException();
705
 
        ++iPtr;
706
 
    }   Next();
707
 
 
708
 
    I(Call):
709
 
    {
710
 
        int argc = iPtr->operand[0].m_int_value;
711
 
        QScriptValueImpl *argp = stackPtr - argc;
712
 
 
713
 
        QScriptValueImpl base;
714
 
        QScriptValueImpl callee;
715
 
 
716
 
        bool isReference = argp[0].isReference();
717
 
 
718
 
        if (! isReference) { // we have a value
719
 
            base = eng->m_globalObject;
720
 
            callee = argp[0];
721
 
        } else if (resolveField(eng, &argp[-1], &callee)) {
722
 
            if (hasUncaughtException()) {
723
 
                stackPtr = argp - 3;
724
 
                HandleException();
725
 
            }
726
 
            base = argp[-2];
727
 
        } else {
728
 
            QScriptValueImpl member = argp[-1];
729
 
            stackPtr = argp - 1;
730
 
            Q_ASSERT(isReference);
731
 
            stackPtr -= 2;
732
 
 
733
 
            if (member.isString())
734
 
                throwNotDefined(member.toString());
735
 
            else
736
 
                throwNotDefined(QLatin1String("function"));
737
 
            HandleException();
738
 
        }
739
 
 
740
 
        Q_ASSERT(base.isValid());
741
 
        Q_ASSERT(callee.isValid());
742
 
 
743
 
        QScriptFunction *function = QScriptEnginePrivate::convertToNativeFunction(callee);
744
 
        if (! function) {
745
 
            QScriptValueImpl member = argp[-1];
746
 
            QString message;
747
 
            if (member.isString()) {
748
 
                message = QString::fromLatin1("%0 is not a function")
749
 
                          .arg(member.toString());
750
 
            } else {
751
 
                message = QLatin1String("not a function");
752
 
            }
753
 
            throwTypeError(message);
754
 
            HandleException();
755
 
        }
756
 
 
757
 
        if (++eng->m_callDepth == eng->m_maxCallDepth) {
758
 
            throwError(QLatin1String("call stack overflow"));
759
 
            HandleException();
760
 
        }
761
 
 
762
 
        QScriptContextPrivate *nested_data = eng->pushContext();
763
 
        nested_data->m_thisObject = base;
764
 
        nested_data->m_callee = callee;
765
 
 
766
 
        // create the activation
767
 
        eng->newActivation(&nested_data->m_activation);
768
 
        QScriptObject *activation_data = nested_data->m_activation.m_object_value;
769
 
 
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;
776
 
            if (i < formalCount)
777
 
                nameId = function->formals.at(i);
778
 
 
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;
783
 
        }
784
 
 
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;
788
 
        else
789
 
            activation_data->m_scope = eng->m_globalObject;
790
 
        nested_data->tempStack = stackPtr;
791
 
        nested_data->args = &argp[1];
792
 
 
793
 
        function->execute(nested_data);
794
 
 
795
 
        --eng->m_callDepth;
796
 
 
797
 
        stackPtr = argp - 1;
798
 
        if (isReference)
799
 
            stackPtr -= 2;
800
 
 
801
 
        if (nested_data->m_state == QScriptContext::ExceptionState) {
802
 
            eng->popContext();
803
 
            if (eng->shouldAbort())
804
 
                Abort();
805
 
            else
806
 
                Done();
807
 
        }
808
 
 
809
 
        CHECK_TEMPSTACK(1);
810
 
        *++stackPtr = nested_data->m_result;
811
 
 
812
 
        eng->popContext();
813
 
 
814
 
        if (eng->shouldAbort())
815
 
            Abort();
816
 
 
817
 
        if (eng->m_processEventsInterval > 0)
818
 
            eng->processEvents();
819
 
 
820
 
        ++iPtr;
821
 
    }   Next();
822
 
 
823
 
 
824
 
    I(NewArray):
825
 
    {
826
 
        CHECK_TEMPSTACK(1);
827
 
        eng->arrayConstructor->newArray(++stackPtr, QScript::Array(eng));
828
 
        ++iPtr;
829
 
    }   Next();
830
 
 
831
 
    I(NewRegExp):
832
 
    {
833
 
        CHECK_TEMPSTACK(1);
834
 
 
835
 
        QString pattern = eng->toString(iPtr->operand[0].m_string_value);
836
 
#ifndef QT_NO_REGEXP
837
 
        QString literal = pattern;
838
 
#endif
839
 
        int flags = 0;
840
 
        if (iPtr->operand[1].isValid()) {
841
 
            flags = iPtr->operand[1].m_int_value;
842
 
#ifndef QT_NO_REGEXP
843
 
            if (flags != 0) {
844
 
                literal += QLatin1String("/");
845
 
                literal += QString::number(flags);
846
 
            }
847
 
#endif
848
 
        }
849
 
 
850
 
#ifndef QT_NO_REGEXP
851
 
        QRegExp rx;
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);
858
 
        } else {
859
 
            rx = *it;
860
 
        }
861
 
        eng->regexpConstructor->newRegExp(++stackPtr, rx, flags);
862
 
#else
863
 
        eng->regexpConstructor->newRegExp(++stackPtr, pattern, flags);
864
 
#endif
865
 
        ++iPtr;
866
 
    }   Next();
867
 
 
868
 
    I(NewObject):
869
 
    {
870
 
        CHECK_TEMPSTACK(1);
871
 
        eng->objectConstructor->newObject(++stackPtr);
872
 
        ++iPtr;
873
 
    }   Next();
874
 
 
875
 
    I(New):
876
 
    {
877
 
        int argc = iPtr->operand[0].m_int_value;
878
 
        QScriptValueImpl *argp = stackPtr - argc;
879
 
 
880
 
        // QScriptValueImpl base;
881
 
        QScriptValueImpl callee;
882
 
 
883
 
        bool isReference = argp[0].isReference();
884
 
 
885
 
        if (! isReference) { // we have a value
886
 
            // base = eng->globalObject;
887
 
            callee = argp[0];
888
 
        } else if (resolveField(eng, &argp[-1], &callee)) {
889
 
            // base = argp[-2];
890
 
            if (hasUncaughtException()) {
891
 
                stackPtr = argp - 3;
892
 
                HandleException();
893
 
            }
894
 
        } else {
895
 
            QScriptValueImpl member = argp[-1];
896
 
            stackPtr = argp - 1;
897
 
            Q_ASSERT(isReference);
898
 
            stackPtr -= 2;
899
 
 
900
 
            if (member.isString())
901
 
                throwNotDefined(member.toString());
902
 
            else
903
 
                throwNotDefined(QLatin1String("constructor"));
904
 
            HandleException();
905
 
        }
906
 
 
907
 
        // Q_ASSERT(base.isValid());
908
 
        Q_ASSERT(callee.isValid());
909
 
 
910
 
        QScriptFunction *function = QScriptEnginePrivate::convertToNativeFunction(callee);
911
 
        if (! function) {
912
 
            QScriptValueImpl member = argp[-1];
913
 
            QString message;
914
 
            if (member.isString()) {
915
 
                message = QString::fromLatin1("%0 is not a constructor")
916
 
                          .arg(member.toString());
917
 
            } else {
918
 
                message = QLatin1String("not a constructor");
919
 
            }
920
 
            throwTypeError(message);
921
 
            HandleException();
922
 
        }
923
 
 
924
 
        if (++eng->m_callDepth == eng->m_maxCallDepth) {
925
 
            throwError(QLatin1String("call stack overflow"));
926
 
            HandleException();
927
 
        }
928
 
 
929
 
        QScriptContextPrivate *nested_data = eng->pushContext();
930
 
        nested_data->m_callee = callee;
931
 
        nested_data->m_calledAsConstructor = true;
932
 
 
933
 
        // create the activation
934
 
        eng->newActivation(&nested_data->m_activation);
935
 
        QScriptObject *activation_data = nested_data->m_activation.m_object_value;
936
 
 
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;
943
 
            if (i < formalCount)
944
 
                nameId = function->formals.at(i);
945
 
 
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;
950
 
        }
951
 
 
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;
956
 
        else
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;
961
 
 
962
 
        QScriptObject *instance = nested_data->m_thisObject.m_object_value;
963
 
 
964
 
        // set [[prototype]]
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;
971
 
 
972
 
        function->execute(nested_data);
973
 
 
974
 
        --eng->m_callDepth;
975
 
 
976
 
        stackPtr = argp - 1;
977
 
        if (isReference)
978
 
            stackPtr -= 2;
979
 
 
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;
984
 
 
985
 
        if (nested_data->m_state == QScriptContext::ExceptionState) {
986
 
            eng->popContext();
987
 
            if (eng->shouldAbort())
988
 
                Abort();
989
 
            else
990
 
                Done();
991
 
        }
992
 
 
993
 
        CHECK_TEMPSTACK(1);
994
 
 
995
 
        *++stackPtr = nested_data->m_result;
996
 
 
997
 
        eng->popContext();
998
 
 
999
 
        if (eng->shouldAbort())
1000
 
            Abort();
1001
 
 
1002
 
        if (eng->m_processEventsInterval > 0)
1003
 
            eng->processEvents();
1004
 
 
1005
 
        ++iPtr;
1006
 
    }   Next();
1007
 
 
1008
 
    I(FetchField):
1009
 
    {
1010
 
        QScriptValueImpl object = eng->toObject(stackPtr[-1]);
1011
 
        if (! object.isValid()) {
1012
 
            stackPtr -= 2;
1013
 
            throwTypeError(QLatin1String("not an object"));
1014
 
            HandleException();
1015
 
        }
1016
 
 
1017
 
        QScriptValueImpl m = stackPtr[0];
1018
 
 
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);
1022
 
 
1023
 
        if (arrayInstance) {
1024
 
            quint32 pos = toArrayIndex(m);
1025
 
            if (pos != 0xFFFFFFFF) {
1026
 
                QScriptValueImpl val = arrayInstance->value.at(pos);
1027
 
                if (val.isValid()) {
1028
 
                    *--stackPtr = val;
1029
 
                    ++iPtr;
1030
 
                    Next();
1031
 
                }
1032
 
            }
1033
 
        }
1034
 
 
1035
 
        QScriptNameIdImpl *nameId = m.isString() ? m.m_string_value : 0;
1036
 
 
1037
 
        if (! nameId || ! nameId->unique) {
1038
 
            QString str;
1039
 
 
1040
 
            if (m.isNumber())
1041
 
                qscript_uint_to_string(m.m_number_value, str);
1042
 
 
1043
 
            if (str.isEmpty())
1044
 
                str = QScriptEnginePrivate::convertToNativeString(m);
1045
 
 
1046
 
            nameId = eng->nameId(str, /*persistent=*/false);
1047
 
        }
1048
 
 
1049
 
        QScript::Member member;
1050
 
        QScriptValueImpl base;
1051
 
 
1052
 
        if (object.resolve(nameId, &member, &base, QScriptValue::ResolvePrototype, QScript::Read)) {
1053
 
            base.get(member, --stackPtr);
1054
 
            if (hasUncaughtException()) {
1055
 
                stackPtr -= 1;
1056
 
                HandleException();
1057
 
            } else if (member.isGetterOrSetter()) {
1058
 
                // call the getter function
1059
 
                QScriptValueImpl getter;
1060
 
                if (member.isGetter()) {
1061
 
                    getter = *stackPtr;
1062
 
                } else {
1063
 
                    if (!base.m_object_value->findGetter(&member)) {
1064
 
                        stackPtr -= 1;
1065
 
                        throwError(QLatin1String("No getter defined"));
1066
 
                        HandleException();
1067
 
                    }
1068
 
                    base.get(member, &getter);
1069
 
                }
1070
 
                *stackPtr = getter.call(object);
1071
 
                if (hasUncaughtException()) {
1072
 
                    stackPtr -= 1;
1073
 
                    Done();
1074
 
                }
1075
 
            }
1076
 
        } else {
1077
 
            *(--stackPtr) = undefined;
1078
 
        }
1079
 
 
1080
 
        ++iPtr;
1081
 
    }   Next();
1082
 
 
1083
 
    I(LazyArguments):
1084
 
    {
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;
1093
 
                else
1094
 
                    eng->newArguments(&m_arguments, m_activation, argc, m_callee);
1095
 
            }
1096
 
            m_activation.put(member, m_arguments);
1097
 
        }
1098
 
        ++iPtr;
1099
 
    }   Next();
1100
 
 
1101
 
    I(DeclareLocal):
1102
 
    {
1103
 
        QScriptValueImpl &act = m_activation;
1104
 
 
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;
1109
 
 
1110
 
        if (! act.resolve(memberName, &member, &object, QScriptValue::ResolveLocal, QScript::ReadWrite)) {
1111
 
            uint flags = QScriptValue::Undeletable;
1112
 
            if (readOnly)
1113
 
                flags |= QScript::Member::UninitializedConst | QScriptValue::ReadOnly;
1114
 
            CREATE_MEMBER(act, memberName, &member, flags);
1115
 
            act.put(member, undefined);
1116
 
        }
1117
 
        ++iPtr;
1118
 
    }   Next();
1119
 
 
1120
 
    I(Assign):
1121
 
    {
1122
 
        if (! stackPtr[-1].isReference()) {
1123
 
            stackPtr -= 2;
1124
 
            throwSyntaxError(QLatin1String("invalid assignment lvalue"));
1125
 
            HandleException();
1126
 
        }
1127
 
 
1128
 
        QScriptValue::ResolveFlags mode;
1129
 
        mode = QScriptValue::ResolveFlags(stackPtr[-1].m_int_value)
1130
 
               | QScriptValue::ResolvePrototype;
1131
 
 
1132
 
        QScriptValueImpl object = eng->toObject(stackPtr[-3]);
1133
 
        if (! object.isValid()) {
1134
 
            stackPtr -= 4;
1135
 
            throwTypeError(QLatin1String("invalid assignment lvalue"));
1136
 
            HandleException();
1137
 
        }
1138
 
 
1139
 
        QScriptValueImpl m = stackPtr[-2];
1140
 
        QScriptValueImpl value = stackPtr[0];
1141
 
 
1142
 
        quint32 pos = 0xFFFFFFFF;
1143
 
 
1144
 
        QScript::Ecma::Array::Instance *arrayInstance = eng->arrayConstructor->get(object);
1145
 
        if (arrayInstance)
1146
 
            pos = toArrayIndex(m);
1147
 
 
1148
 
        stackPtr -= 3;
1149
 
 
1150
 
        if (pos != 0xFFFFFFFF)
1151
 
            arrayInstance->value.assign(pos, value);
1152
 
 
1153
 
        else {
1154
 
            QScriptNameIdImpl *memberName;
1155
 
 
1156
 
            if (m.isString() && m.m_string_value->unique)
1157
 
                memberName = m.m_string_value;
1158
 
            else
1159
 
                memberName = eng->nameId(QScriptEnginePrivate::convertToNativeString(m), /*persistent=*/false);
1160
 
 
1161
 
            QScriptValueImpl base;
1162
 
            QScript::Member member;
1163
 
 
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)
1167
 
                    base = object;
1168
 
                else
1169
 
                    base = eng->m_globalObject;
1170
 
 
1171
 
                CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1172
 
            }
1173
 
 
1174
 
            if (value.isString() && ! value.m_string_value->unique)
1175
 
                eng->newNameId(&value, value.m_string_value->s);
1176
 
 
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)) {
1182
 
                        stackPtr -= 1;
1183
 
                        throwError(QLatin1String("no setter defined"));
1184
 
                        HandleException();
1185
 
                    }
1186
 
                }
1187
 
                base.get(member, &setter);
1188
 
 
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();
1196
 
                }
1197
 
 
1198
 
                value = setter.call(object, QScriptValueImplList() << value);
1199
 
                if (hasUncaughtException()) {
1200
 
                    stackPtr -= 1;
1201
 
                    Done();
1202
 
                }
1203
 
            } else {
1204
 
                if (object.classInfo() == eng->m_class_with)
1205
 
                    object = object.prototype();
1206
 
 
1207
 
                if (member.isWritable()) {
1208
 
                    if (isMemberAssignment && (base.m_object_value != object.m_object_value)) {
1209
 
                        base = object;
1210
 
                        CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1211
 
                    }
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);
1218
 
                    }
1219
 
                }
1220
 
                if (hasUncaughtException()) {
1221
 
                    stackPtr -= 1;
1222
 
                    HandleException();
1223
 
                }
1224
 
            }
1225
 
        }
1226
 
 
1227
 
        *stackPtr = value;
1228
 
        ++iPtr;
1229
 
    }   Next();
1230
 
 
1231
 
    I(BitAnd):
1232
 
    {
1233
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1234
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]);
1235
 
        *(--stackPtr) = QScriptValueImpl(v1 & v2);
1236
 
        ++iPtr;
1237
 
    }   Next();
1238
 
 
1239
 
    I(BitOr):
1240
 
    {
1241
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1242
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]);
1243
 
        *(--stackPtr) = QScriptValueImpl(v1 | v2);
1244
 
        ++iPtr;
1245
 
    }   Next();
1246
 
 
1247
 
    I(BitXor):
1248
 
    {
1249
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1250
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]);
1251
 
        *(--stackPtr) = QScriptValueImpl(v1 ^ v2);
1252
 
        ++iPtr;
1253
 
    }   Next();
1254
 
 
1255
 
    I(BitNot):
1256
 
    {
1257
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]);
1258
 
        *stackPtr = QScriptValueImpl(~v1);
1259
 
        ++iPtr;
1260
 
    }   Next();
1261
 
 
1262
 
    I(Not):
1263
 
    {
1264
 
        bool v1 = QScriptEnginePrivate::convertToNativeBoolean(stackPtr[0]);
1265
 
        *stackPtr = QScriptValueImpl(!v1);
1266
 
        ++iPtr;
1267
 
    }   Next();
1268
 
 
1269
 
    I(LeftShift):
1270
 
    {
1271
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1272
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]) & 0x1f;
1273
 
        *(--stackPtr) = QScriptValueImpl(v1 << v2);
1274
 
        ++iPtr;
1275
 
    } Next();
1276
 
 
1277
 
    I(Mod):
1278
 
    {
1279
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]);
1280
 
        qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]);
1281
 
 
1282
 
        *(--stackPtr) = QScriptValueImpl(::fmod(v1, v2));
1283
 
        ++iPtr;
1284
 
    }   Next();
1285
 
 
1286
 
    I(RightShift):
1287
 
    {
1288
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]);
1289
 
        quint32 v2 = QScriptEnginePrivate::toUint32 (eng->convertToNativeDouble(stackPtr[0])) & 0x1f;
1290
 
        *(--stackPtr) = QScriptValueImpl(v1 >> v2);
1291
 
        ++iPtr;
1292
 
    }   Next();
1293
 
 
1294
 
    I(URightShift):
1295
 
    {
1296
 
        quint32 v1 = QScriptEnginePrivate::toUint32 (eng->convertToNativeDouble(stackPtr[-1]));
1297
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]) & 0x1f;
1298
 
        *(--stackPtr) = QScriptValueImpl(v1 >> v2);
1299
 
        ++iPtr;
1300
 
    }   Next();
1301
 
 
1302
 
    I(InstanceOf):
1303
 
    {
1304
 
        QScriptValueImpl object = stackPtr[-1];
1305
 
        QScriptValueImpl ctor = stackPtr[0];
1306
 
 
1307
 
        if (!ctor.isObject() || !ctor.implementsHasInstance()) {
1308
 
            stackPtr -= 2;
1309
 
            throwTypeError(QLatin1String("invalid 'instanceof' operand"));
1310
 
            HandleException();
1311
 
        }
1312
 
 
1313
 
        bool result = ctor.hasInstance(object);
1314
 
        if (eng->hasUncaughtException()) {
1315
 
            stackPtr -= 2;
1316
 
            HandleException();
1317
 
        }
1318
 
 
1319
 
        *(--stackPtr) = QScriptValueImpl(result);
1320
 
        ++iPtr;
1321
 
    }   Next();
1322
 
 
1323
 
    I(In):
1324
 
    {
1325
 
        QScriptValueImpl object = stackPtr[0];
1326
 
        if (!object.isObject()) {
1327
 
            stackPtr -= 2;
1328
 
            throwTypeError(QLatin1String("invalid 'in' operand"));
1329
 
            HandleException();
1330
 
        }
1331
 
        QString propertyName = QScriptEnginePrivate::convertToNativeString(stackPtr[-1]);
1332
 
        bool result = object.property(propertyName, QScriptValue::ResolvePrototype).isValid(); // ### hasProperty()
1333
 
        *(--stackPtr) = QScriptValueImpl(result);
1334
 
        ++iPtr;
1335
 
    }   Next();
1336
 
 
1337
 
    I(Add):
1338
 
    {
1339
 
        QScriptValueImpl lhs = eng->toPrimitive(stackPtr[-1], QScriptValueImpl::NoTypeHint);
1340
 
        QScriptValueImpl rhs = eng->toPrimitive(stackPtr[0], QScriptValueImpl::NoTypeHint);
1341
 
 
1342
 
        if (lhs.isString() || rhs.isString()) {
1343
 
            QString tmp = QScriptEnginePrivate::convertToNativeString(lhs);
1344
 
            tmp += QScriptEnginePrivate::convertToNativeString(rhs);
1345
 
            eng->newString(--stackPtr, tmp);
1346
 
        } else {
1347
 
            qsreal tmp = QScriptEnginePrivate::convertToNativeDouble(lhs);
1348
 
            tmp += QScriptEnginePrivate::convertToNativeDouble(rhs);
1349
 
            *(--stackPtr) = QScriptValueImpl(tmp);
1350
 
        }
1351
 
 
1352
 
        ++iPtr;
1353
 
    }   Next();
1354
 
 
1355
 
    I(Div):
1356
 
    {
1357
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]);
1358
 
        qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]);
1359
 
        *(--stackPtr) = QScriptValueImpl(v1 / v2);
1360
 
        ++iPtr;
1361
 
    }   Next();
1362
 
 
1363
 
    I(Equal):
1364
 
    {
1365
 
        QScriptValueImpl v1 = stackPtr[-1];
1366
 
        QScriptValueImpl v2 = stackPtr[0];
1367
 
        *(--stackPtr) = QScriptValueImpl(eq_cmp(v1, v2));
1368
 
        ++iPtr;
1369
 
    }   Next();
1370
 
 
1371
 
    I(GreatOrEqual):
1372
 
    {
1373
 
        QScriptValueImpl v1 = stackPtr[0];
1374
 
        QScriptValueImpl v2 = stackPtr[-1];
1375
 
        *(--stackPtr) = QScriptValueImpl(le_cmp(v1, v2));
1376
 
        ++iPtr;
1377
 
    }   Next();
1378
 
 
1379
 
    I(GreatThan):
1380
 
    {
1381
 
        QScriptValueImpl v1 = stackPtr[0];
1382
 
        QScriptValueImpl v2 = stackPtr[-1];
1383
 
        *(--stackPtr) = QScriptValueImpl(lt_cmp(v1, v2));
1384
 
        ++iPtr;
1385
 
    }   Next();
1386
 
 
1387
 
    I(LessOrEqual):
1388
 
    {
1389
 
        QScriptValueImpl v1 = stackPtr[-1];
1390
 
        QScriptValueImpl v2 = stackPtr[0];
1391
 
        *(--stackPtr) = QScriptValueImpl(le_cmp(v1, v2));
1392
 
        ++iPtr;
1393
 
    }   Next();
1394
 
 
1395
 
    I(LessThan):
1396
 
    {
1397
 
        QScriptValueImpl v1 = stackPtr[-1];
1398
 
        QScriptValueImpl v2 = stackPtr[0];
1399
 
        *(--stackPtr) = QScriptValueImpl(lt_cmp(v1, v2));
1400
 
        ++iPtr;
1401
 
    }   Next();
1402
 
 
1403
 
    I(NotEqual):
1404
 
    {
1405
 
        QScriptValueImpl v1 = stackPtr[-1];
1406
 
        QScriptValueImpl v2 = stackPtr[0];
1407
 
        *(--stackPtr) = QScriptValueImpl(!eq_cmp(v1, v2));
1408
 
        ++iPtr;
1409
 
    }   Next();
1410
 
 
1411
 
    I(Mul):
1412
 
    {
1413
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]);
1414
 
        qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]);
1415
 
        *(--stackPtr) = QScriptValueImpl(v1 * v2);
1416
 
        ++iPtr;
1417
 
    }   Next();
1418
 
 
1419
 
    I(StrictEqual):
1420
 
    {
1421
 
        QScriptValueImpl v1 = stackPtr[-1];
1422
 
        QScriptValueImpl v2 = stackPtr[0];
1423
 
        *(--stackPtr) = strict_eq_cmp(v1, v2);
1424
 
        ++iPtr;
1425
 
    }   Next();
1426
 
 
1427
 
    I(StrictNotEqual):
1428
 
    {
1429
 
        QScriptValueImpl v1 = stackPtr[-1];
1430
 
        QScriptValueImpl v2 = stackPtr[0];
1431
 
        *(--stackPtr) = ! strict_eq_cmp(v1, v2);
1432
 
        ++iPtr;
1433
 
    }   Next();
1434
 
 
1435
 
    I(Sub):
1436
 
    {
1437
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]);
1438
 
        qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]);
1439
 
        *(--stackPtr) = QScriptValueImpl(v1 - v2);
1440
 
        ++iPtr;
1441
 
    }   Next();
1442
 
 
1443
 
    I(UnaryMinus):
1444
 
    {
1445
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(*stackPtr);
1446
 
        *stackPtr = QScriptValueImpl(-v1);
1447
 
        ++iPtr;
1448
 
    }   Next();
1449
 
 
1450
 
    I(UnaryPlus):
1451
 
    {
1452
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(*stackPtr);
1453
 
        *stackPtr = QScriptValueImpl(+v1);
1454
 
        ++iPtr;
1455
 
    }   Next();
1456
 
 
1457
 
    I(Branch):
1458
 
    {
1459
 
        eng->maybeProcessEvents();
1460
 
        if (hasUncaughtException())
1461
 
            HandleException();
1462
 
        if (eng->shouldAbort())
1463
 
            Abort();
1464
 
        iPtr += iPtr->operand[0].m_int_value;
1465
 
    }   Next();
1466
 
 
1467
 
    I(BranchFalse):
1468
 
    {
1469
 
        if (! QScriptEnginePrivate::convertToNativeBoolean(*stackPtr--))
1470
 
            iPtr += iPtr->operand[0].m_int_value;
1471
 
        else
1472
 
            ++iPtr;
1473
 
    }   Next();
1474
 
 
1475
 
    I(BranchTrue):
1476
 
    {
1477
 
        if (eng->convertToNativeBoolean(*stackPtr--))
1478
 
            iPtr += iPtr->operand[0].m_int_value;
1479
 
        else
1480
 
            ++iPtr;
1481
 
    }   Next();
1482
 
 
1483
 
    I(NewClosure):
1484
 
    {
1485
 
        CHECK_TEMPSTACK(1);
1486
 
 
1487
 
        QScript::AST::FunctionExpression *expr = static_cast<QScript::AST::FunctionExpression *> (iPtr->operand[0].m_ptr_value);
1488
 
 
1489
 
#ifndef Q_SCRIPT_NO_JOINED_FUNCTION
1490
 
        if (QScript::Code *code = eng->findCode(functionBody)) {
1491
 
            QScriptValueImpl value = code->value;
1492
 
 
1493
 
            if (isValid(value)) {
1494
 
                QScriptObject *instance = value.m_object_value;
1495
 
                Q_ASSERT(instance != 0);
1496
 
 
1497
 
                if (instance->m_scope.m_object_value == m_scopeChain.m_object_value)
1498
 
                {
1499
 
                    *++stackPtr = value;
1500
 
                    ++iPtr;
1501
 
                    Next();
1502
 
                }
1503
 
            }
1504
 
        }
1505
 
#endif
1506
 
 
1507
 
        QScript::ScriptFunction *function = new QScript::ScriptFunction(expr, code->astPool);
1508
 
 
1509
 
        // update the formals
1510
 
        for (QScript::AST::FormalParameterList *it = expr->formals; it != 0; it = it->next) {
1511
 
            function->formals.append(it->name);
1512
 
        }
1513
 
        function->length = function->formals.count();
1514
 
 
1515
 
        eng->functionConstructor->newFunction(++stackPtr, function);
1516
 
 
1517
 
        QScriptObject *instance = stackPtr->m_object_value;
1518
 
        // initialize [[scope]]
1519
 
        instance->m_scope = m_scopeChain;
1520
 
 
1521
 
        // create and initialize `prototype'
1522
 
        QScriptValueImpl proto;
1523
 
        eng->objectConstructor->newObject(&proto);
1524
 
 
1525
 
        QScript::Member member;
1526
 
        CREATE_MEMBER(proto, eng->idTable()->id_constructor, &member,
1527
 
                      QScriptValue::Undeletable
1528
 
                      | QScriptValue::SkipInEnumeration);
1529
 
        proto.put(member, *stackPtr);
1530
 
 
1531
 
        stackPtr->createMember(eng->idTable()->id_prototype, &member,
1532
 
                                       QScriptValue::Undeletable);
1533
 
        stackPtr->put(member, proto);
1534
 
 
1535
 
        ++iPtr;
1536
 
    }   Next();
1537
 
 
1538
 
    I(Incr):
1539
 
    {
1540
 
        if (! stackPtr[0].isReference()) {
1541
 
            stackPtr -= 1;
1542
 
            throwSyntaxError(QLatin1String("invalid increment operand"));
1543
 
            HandleException();
1544
 
        }
1545
 
 
1546
 
        BEGIN_PREFIX_OPERATOR
1547
 
 
1548
 
        qsreal x = QScriptEnginePrivate::convertToNativeDouble(value);
1549
 
        value = QScriptValueImpl(x + 1);
1550
 
 
1551
 
        END_PREFIX_OPERATOR
1552
 
    }   Next();
1553
 
 
1554
 
    I(Decr):
1555
 
    {
1556
 
        if (! stackPtr[0].isReference()) {
1557
 
            stackPtr -= 1;
1558
 
            throwSyntaxError(QLatin1String("invalid decrement operand"));
1559
 
            HandleException();
1560
 
        }
1561
 
 
1562
 
        BEGIN_PREFIX_OPERATOR
1563
 
 
1564
 
        qsreal x = QScriptEnginePrivate::convertToNativeDouble(value);
1565
 
        value = QScriptValueImpl(x - 1);
1566
 
 
1567
 
        END_PREFIX_OPERATOR
1568
 
    }   Next();
1569
 
 
1570
 
    I(PostIncr):
1571
 
    {
1572
 
        if (! stackPtr[0].isReference()) {
1573
 
            stackPtr -= 1;
1574
 
            throwSyntaxError(QLatin1String("invalid increment operand"));
1575
 
            HandleException();
1576
 
        }
1577
 
 
1578
 
        QScriptValue::ResolveFlags mode;
1579
 
        mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value)
1580
 
               | QScriptValue::ResolvePrototype;
1581
 
 
1582
 
        --stackPtr;
1583
 
 
1584
 
        QScriptValueImpl object = eng->toObject(stackPtr[-1]);
1585
 
        if (!object.isObject()) {
1586
 
            stackPtr -= 2;
1587
 
            throwTypeError(QLatin1String("not an object"));
1588
 
            HandleException();
1589
 
        }
1590
 
 
1591
 
        QScriptNameIdImpl *memberName = 0;
1592
 
        if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique)
1593
 
            memberName = stackPtr[0].m_string_value;
1594
 
        else
1595
 
            memberName = eng->nameId(stackPtr[0].toString(), /*persistent=*/false);
1596
 
 
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);
1605
 
                if (r.isNumber()) {
1606
 
                    *(--stackPtr) = QScriptValueImpl(r.m_number_value);
1607
 
                    r.incr();
1608
 
                    ++iPtr;
1609
 
                    Next();
1610
 
                }
1611
 
            }
1612
 
            base = object;
1613
 
        } else if (!object.resolve_helper(memberName, &member, &base, mode, QScript::ReadWrite)) {
1614
 
            if (!isMemberAssignment) {
1615
 
                stackPtr -= 2;
1616
 
                throwNotDefined(memberName);
1617
 
                HandleException();
1618
 
            }
1619
 
            base = object;
1620
 
            CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1621
 
            base.put(member, undefined);
1622
 
        }
1623
 
 
1624
 
        QScriptValueImpl getter;
1625
 
        QScriptValueImpl setter;
1626
 
        base.get(member, &value);
1627
 
        if (hasUncaughtException()) {
1628
 
            stackPtr -= 2;
1629
 
            HandleException();
1630
 
        } else if (member.isGetterOrSetter()) {
1631
 
            if (member.isGetter()) {
1632
 
                getter = value;
1633
 
                if (!member.isSetter() && !base.m_object_value->findSetter(&member)) {
1634
 
                    stackPtr -= 2;
1635
 
                    throwError(QLatin1String("No setter defined"));
1636
 
                    HandleException();
1637
 
                }
1638
 
                base.get(member, &setter);
1639
 
            } else {
1640
 
                setter = value;
1641
 
                QScript::Member tmp = member;
1642
 
                if (!base.m_object_value->findGetter(&member)) {
1643
 
                    stackPtr -= 2;
1644
 
                    throwError(QLatin1String("No getter defined"));
1645
 
                    HandleException();
1646
 
                }
1647
 
                base.get(member, &getter);
1648
 
                member = tmp;
1649
 
            }
1650
 
            value = getter.call(object);
1651
 
            if (hasUncaughtException()) {
1652
 
                stackPtr -= 2;
1653
 
                Done();
1654
 
            }
1655
 
        }
1656
 
 
1657
 
        qsreal x = QScriptEnginePrivate::convertToNativeDouble(value);
1658
 
 
1659
 
        value = QScriptValueImpl(x + 1);
1660
 
 
1661
 
        if (member.isSetter()) {
1662
 
            setter.call(object, QScriptValueImplList() << value);
1663
 
            if (hasUncaughtException()) {
1664
 
                stackPtr -= 2;
1665
 
                Done();
1666
 
            }
1667
 
        } else {
1668
 
            if (isMemberAssignment && (base.m_object_value != object.m_object_value)) {
1669
 
                base = object;
1670
 
                CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1671
 
            }
1672
 
            if (member.isWritable()) {
1673
 
                base.put(member, value);
1674
 
                if (hasUncaughtException()) {
1675
 
                    stackPtr -= 2;
1676
 
                    HandleException();
1677
 
                }
1678
 
            }
1679
 
        }
1680
 
 
1681
 
        *(--stackPtr) = QScriptValueImpl(x);
1682
 
 
1683
 
        ++iPtr;
1684
 
    }   Next();
1685
 
 
1686
 
    I(PostDecr):
1687
 
    {
1688
 
        // ### most of the code is duplicated from PostIncr -- try to merge
1689
 
        if (! stackPtr[0].isReference()) {
1690
 
            stackPtr -= 1;
1691
 
            throwSyntaxError(QLatin1String("invalid decrement operand"));
1692
 
            HandleException();
1693
 
        }
1694
 
 
1695
 
        QScriptValue::ResolveFlags mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value)
1696
 
                                          | QScriptValue::ResolvePrototype;
1697
 
 
1698
 
        --stackPtr;
1699
 
 
1700
 
        QScriptValueImpl object = eng->toObject(stackPtr[-1]);
1701
 
        if (!object.isObject()) {
1702
 
            stackPtr -= 2;
1703
 
            throwTypeError(QLatin1String("not an object"));
1704
 
            HandleException();
1705
 
        }
1706
 
 
1707
 
        QScriptNameIdImpl *memberName = 0;
1708
 
        if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique)
1709
 
            memberName = stackPtr[0].m_string_value;
1710
 
        else
1711
 
            memberName = eng->nameId(stackPtr[0].toString(), /*persistent=*/false);
1712
 
 
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);
1721
 
                if (r.isNumber()) {
1722
 
                    *(--stackPtr) = QScriptValueImpl(r.m_number_value);
1723
 
                    r.decr();
1724
 
                    ++iPtr;
1725
 
                    Next();
1726
 
                }
1727
 
            }
1728
 
            base = object;
1729
 
        } else if (! object.resolve_helper(memberName, &member, &base, mode, QScript::ReadWrite)) {
1730
 
            if (!isMemberAssignment) {
1731
 
                stackPtr -= 2;
1732
 
                throwNotDefined(memberName);
1733
 
                HandleException();
1734
 
            }
1735
 
            base = object;
1736
 
            CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1737
 
            base.put(member, undefined);
1738
 
        }
1739
 
 
1740
 
        QScriptValueImpl getter;
1741
 
        QScriptValueImpl setter;
1742
 
        base.get(member, &value);
1743
 
        if (hasUncaughtException()) {
1744
 
            stackPtr -= 2;
1745
 
            HandleException();
1746
 
        } else if (member.isGetterOrSetter()) {
1747
 
            if (member.isGetter()) {
1748
 
                getter = value;
1749
 
                if (!member.isSetter() && !base.m_object_value->findSetter(&member)) {
1750
 
                    stackPtr -= 2;
1751
 
                    throwError(QLatin1String("No setter defined"));
1752
 
                    HandleException();
1753
 
                }
1754
 
                base.get(member, &setter);
1755
 
            } else {
1756
 
                setter = value;
1757
 
                QScript::Member tmp = member;
1758
 
                if (!base.m_object_value->findGetter(&member)) {
1759
 
                    stackPtr -= 2;
1760
 
                    throwError(QLatin1String("No getter defined"));
1761
 
                    HandleException();
1762
 
                }
1763
 
                base.get(member, &getter);
1764
 
                member = tmp;
1765
 
            }
1766
 
            value = getter.call(object);
1767
 
            if (hasUncaughtException()) {
1768
 
                stackPtr -= 2;
1769
 
                Done();
1770
 
            }
1771
 
        }
1772
 
 
1773
 
        qsreal x = QScriptEnginePrivate::convertToNativeDouble(value);
1774
 
 
1775
 
        value = QScriptValueImpl(x - 1);
1776
 
 
1777
 
        if (member.isSetter()) {
1778
 
            setter.call(object, QScriptValueImplList() << value);
1779
 
            if (hasUncaughtException()) {
1780
 
                stackPtr -= 2;
1781
 
                Done();
1782
 
            }
1783
 
        } else {
1784
 
            if (isMemberAssignment && (base.m_object_value != object.m_object_value)) {
1785
 
                base = object;
1786
 
                CREATE_MEMBER(base, memberName, &member, /*flags=*/0);
1787
 
            }
1788
 
            if (member.isWritable()) {
1789
 
                base.put(member, value);
1790
 
                if (hasUncaughtException()) {
1791
 
                    stackPtr -= 2;
1792
 
                    HandleException();
1793
 
                }
1794
 
            }
1795
 
        }
1796
 
 
1797
 
        *(--stackPtr) = QScriptValueImpl(x);
1798
 
 
1799
 
        ++iPtr;
1800
 
    }   Next();
1801
 
 
1802
 
    I(InplaceAdd):
1803
 
    {
1804
 
        BEGIN_INPLACE_OPERATOR
1805
 
 
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);
1811
 
                stackPtr -= 3;
1812
 
                *stackPtr = lhs;
1813
 
            } else {
1814
 
                QString tmp = QScriptEnginePrivate::convertToNativeString(lhs);
1815
 
                tmp += QScriptEnginePrivate::convertToNativeString(rhs);
1816
 
                stackPtr -= 3;
1817
 
                eng->newString(stackPtr, tmp);
1818
 
            }
1819
 
        } else {
1820
 
            qsreal tmp = QScriptEnginePrivate::convertToNativeDouble(lhs);
1821
 
            tmp += QScriptEnginePrivate::convertToNativeDouble(rhs);
1822
 
            stackPtr -= 3;
1823
 
            *stackPtr = QScriptValueImpl(tmp);
1824
 
        }
1825
 
 
1826
 
        END_INPLACE_OPERATOR
1827
 
    }   Next();
1828
 
 
1829
 
    I(InplaceSub):
1830
 
    {
1831
 
        BEGIN_INPLACE_OPERATOR
1832
 
 
1833
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
1834
 
        qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
1835
 
 
1836
 
        stackPtr -= 3;
1837
 
        *stackPtr = QScriptValueImpl(v1 - v2);
1838
 
 
1839
 
        END_INPLACE_OPERATOR
1840
 
    }   Next();
1841
 
 
1842
 
    I(InplaceAnd):
1843
 
    {
1844
 
        BEGIN_INPLACE_OPERATOR
1845
 
 
1846
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1847
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1848
 
 
1849
 
        stackPtr -= 3;
1850
 
        *stackPtr = QScriptValueImpl(v1 & v2);
1851
 
 
1852
 
        END_INPLACE_OPERATOR
1853
 
    }   Next();
1854
 
 
1855
 
    I(InplaceDiv):
1856
 
    {
1857
 
        BEGIN_INPLACE_OPERATOR
1858
 
 
1859
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
1860
 
        qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
1861
 
 
1862
 
        stackPtr -= 3;
1863
 
        *stackPtr = QScriptValueImpl(v1 / v2);
1864
 
 
1865
 
        END_INPLACE_OPERATOR
1866
 
    }   Next();
1867
 
 
1868
 
    I(InplaceLeftShift):
1869
 
    {
1870
 
        BEGIN_INPLACE_OPERATOR
1871
 
 
1872
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1873
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1874
 
 
1875
 
        stackPtr -= 3;
1876
 
        *stackPtr = QScriptValueImpl(v1 << v2);
1877
 
 
1878
 
        END_INPLACE_OPERATOR
1879
 
    }   Next();
1880
 
 
1881
 
    I(InplaceMod):
1882
 
    {
1883
 
        BEGIN_INPLACE_OPERATOR
1884
 
 
1885
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
1886
 
        qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
1887
 
 
1888
 
        stackPtr -= 3;
1889
 
        *stackPtr = QScriptValueImpl(::fmod (v1, v2));
1890
 
 
1891
 
        END_INPLACE_OPERATOR
1892
 
    }   Next();
1893
 
 
1894
 
    I(InplaceMul):
1895
 
    {
1896
 
        BEGIN_INPLACE_OPERATOR
1897
 
 
1898
 
        qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
1899
 
        qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
1900
 
 
1901
 
        stackPtr -= 3;
1902
 
        *stackPtr = QScriptValueImpl(v1 * v2);
1903
 
 
1904
 
        END_INPLACE_OPERATOR
1905
 
    }   Next();
1906
 
 
1907
 
    I(InplaceOr):
1908
 
    {
1909
 
        BEGIN_INPLACE_OPERATOR
1910
 
 
1911
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1912
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1913
 
 
1914
 
        stackPtr -= 3;
1915
 
        *stackPtr = QScriptValueImpl(v1 | v2);
1916
 
 
1917
 
        END_INPLACE_OPERATOR
1918
 
    }   Next();
1919
 
 
1920
 
    I(InplaceRightShift):
1921
 
    {
1922
 
        BEGIN_INPLACE_OPERATOR
1923
 
 
1924
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1925
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1926
 
 
1927
 
        stackPtr -= 3;
1928
 
        *stackPtr = QScriptValueImpl(v1 >> v2);
1929
 
 
1930
 
        END_INPLACE_OPERATOR
1931
 
    }   Next();
1932
 
 
1933
 
    I(InplaceURightShift):
1934
 
    {
1935
 
        BEGIN_INPLACE_OPERATOR
1936
 
 
1937
 
        quint32 v1 = QScriptEnginePrivate::toUint32 (eng->convertToNativeDouble(lhs));
1938
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1939
 
 
1940
 
        stackPtr -= 3;
1941
 
        *stackPtr = QScriptValueImpl(v1 >> v2);
1942
 
 
1943
 
        END_INPLACE_OPERATOR
1944
 
    }   Next();
1945
 
 
1946
 
    I(InplaceXor):
1947
 
    {
1948
 
        BEGIN_INPLACE_OPERATOR
1949
 
 
1950
 
        qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs);
1951
 
        qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs);
1952
 
 
1953
 
        stackPtr -= 3;
1954
 
        *stackPtr = QScriptValueImpl(v1 ^ v2);
1955
 
 
1956
 
        END_INPLACE_OPERATOR
1957
 
    }   Next();
1958
 
 
1959
 
    I(MakeReference):
1960
 
    {
1961
 
        CHECK_TEMPSTACK(1);
1962
 
        eng->newReference(++stackPtr, QScriptValue::ResolveLocal);
1963
 
        ++iPtr;
1964
 
    }   Next();
1965
 
 
1966
 
    I(TypeOf):
1967
 
    {
1968
 
        QScriptValueImpl value;
1969
 
 
1970
 
        bool isReference = stackPtr[0].isReference();
1971
 
 
1972
 
        if (! isReference) { // we have a value
1973
 
            value = stackPtr[0];
1974
 
        } else if (resolveField(eng, &stackPtr[-1], &value)) {
1975
 
            stackPtr -= 2;
1976
 
            if (hasUncaughtException()) {
1977
 
                stackPtr -= 1;
1978
 
                HandleException();
1979
 
            }
1980
 
        } else {
1981
 
            value = undefined;
1982
 
            stackPtr -= 2;
1983
 
        }
1984
 
 
1985
 
        QString typeName;
1986
 
 
1987
 
        switch (value.type()) {
1988
 
        case QScript::InvalidType:
1989
 
            typeName = QLatin1String("invalid");
1990
 
            break;
1991
 
 
1992
 
        case QScript::UndefinedType:
1993
 
            typeName = QLatin1String("undefined");
1994
 
            break;
1995
 
 
1996
 
        case QScript::NullType:
1997
 
            typeName = QLatin1String("object");
1998
 
            break;
1999
 
 
2000
 
        case QScript::BooleanType:
2001
 
            typeName = QLatin1String("boolean");
2002
 
            break;
2003
 
 
2004
 
        case QScript::IntegerType:
2005
 
        case QScript::NumberType:
2006
 
            typeName = QLatin1String("number");
2007
 
            break;
2008
 
 
2009
 
        case QScript::StringType:
2010
 
        case QScript::LazyStringType:
2011
 
            typeName = QLatin1String("string");
2012
 
            break;
2013
 
 
2014
 
        case QScript::ReferenceType:
2015
 
            typeName = QLatin1String("reference");
2016
 
            break;
2017
 
 
2018
 
        case QScript::PointerType:
2019
 
            typeName = QLatin1String("pointer");
2020
 
            break;
2021
 
 
2022
 
        case QScript::ObjectType:
2023
 
            if (value.isFunction())
2024
 
                typeName = QLatin1String("function");
2025
 
            else
2026
 
                typeName = QLatin1String("object");
2027
 
            break;
2028
 
        }
2029
 
 
2030
 
        eng->newString(stackPtr, typeName);
2031
 
        ++iPtr;
2032
 
    }   Next();
2033
 
 
2034
 
    I(Line):
2035
 
    {
2036
 
        eng->maybeGC();
2037
 
        eng->maybeProcessEvents();
2038
 
        if (hasUncaughtException())
2039
 
            HandleException();
2040
 
        if (eng->shouldAbort())
2041
 
            Abort();
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())
2048
 
                HandleException();
2049
 
            if (eng->shouldAbort())
2050
 
                Abort();
2051
 
        }
2052
 
#endif
2053
 
        ++iPtr;
2054
 
    }   Next();
2055
 
 
2056
 
    I(Delete):
2057
 
    {
2058
 
        bool result;
2059
 
        if (! stackPtr[0].isReference())
2060
 
            result = true;
2061
 
 
2062
 
        else {
2063
 
            QScriptValueImpl object = stackPtr[-2];
2064
 
            if (!object.isObject())
2065
 
                object = eng->toObject(object);
2066
 
 
2067
 
            QScriptNameIdImpl *nameId = 0;
2068
 
            if (stackPtr[-1].isString() && stackPtr[-1].m_string_value->unique) {
2069
 
                nameId = stackPtr[-1].m_string_value;
2070
 
            } else {
2071
 
                nameId = eng->nameId(QScriptEnginePrivate::convertToNativeString(stackPtr[-1]),
2072
 
                                     /*persistent=*/false);
2073
 
            }
2074
 
            if (object.classInfo() == eng->m_class_with)
2075
 
                object = object.prototype();
2076
 
            result = object.deleteProperty(nameId, QScriptValue::ResolveScope);
2077
 
            stackPtr -= 2;
2078
 
        }
2079
 
 
2080
 
        *stackPtr = QScriptValueImpl(result);
2081
 
 
2082
 
        ++iPtr;
2083
 
    }   Next();
2084
 
 
2085
 
 
2086
 
    I(NewEnumeration): {
2087
 
        QScriptValueImpl e;
2088
 
        QScriptValueImpl object = eng->toObject(stackPtr[0]);
2089
 
        eng->enumerationConstructor->newEnumeration(&e, object);
2090
 
        *stackPtr = e;
2091
 
        ++iPtr;
2092
 
    }   Next();
2093
 
 
2094
 
 
2095
 
    I(ToFirstElement): {
2096
 
        QScript::Ext::Enumeration::Instance *e = eng->enumerationConstructor->get(stackPtr[0]);
2097
 
        Q_ASSERT(e != 0);
2098
 
        e->toFront();
2099
 
        --stackPtr;
2100
 
        ++iPtr;
2101
 
    }   Next();
2102
 
 
2103
 
 
2104
 
    I(HasNextElement): {
2105
 
        QScript::Ext::Enumeration::Instance *e = eng->enumerationConstructor->get(stackPtr[0]);
2106
 
        Q_ASSERT(e != 0);
2107
 
        e->hasNext(this, stackPtr);
2108
 
        ++iPtr;
2109
 
    }   Next();
2110
 
 
2111
 
 
2112
 
    I(NextElement): {
2113
 
        // the Enumeration should be located below the result of I(Resolve)
2114
 
        if (! stackPtr[0].isReference()) {
2115
 
            throwTypeError(QLatin1String("QScript.VM.NextElement"));
2116
 
            HandleException();
2117
 
        }
2118
 
 
2119
 
        QScript::Ext::Enumeration::Instance *e = eng->enumerationConstructor->get(stackPtr[-3]);
2120
 
        if (! e) {
2121
 
            throwTypeError(QLatin1String("QScript.VM.NextElement"));
2122
 
            HandleException();
2123
 
        }
2124
 
        e->next(this, ++stackPtr);
2125
 
        ++iPtr;
2126
 
    }   Next();
2127
 
 
2128
 
 
2129
 
    I(Pop):
2130
 
    {
2131
 
        --stackPtr;
2132
 
        ++iPtr;
2133
 
    }   Next();
2134
 
 
2135
 
    I(Sync):
2136
 
    {
2137
 
        m_result = *stackPtr;
2138
 
        --stackPtr;
2139
 
        ++iPtr;
2140
 
    }   Next();
2141
 
 
2142
 
    I(Throw):
2143
 
    {
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);
2151
 
#endif
2152
 
    }   HandleException();
2153
 
 
2154
 
    I(Ret):
2155
 
    {
2156
 
        Q_ASSERT(stackPtr->isValid());
2157
 
        m_result = *stackPtr--;
2158
 
        ++iPtr;
2159
 
    }   Done();
2160
 
 
2161
 
    I(Halt):
2162
 
    {
2163
 
        ++iPtr;
2164
 
    }   Done();
2165
 
 
2166
 
    I(EnterWith):
2167
 
    {
2168
 
        QScriptValueImpl object = eng->toObject(*stackPtr--);
2169
 
        if (! object.isValid()) {
2170
 
            throwTypeError(QLatin1String("value has no properties"));
2171
 
            HandleException();
2172
 
        }
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;
2177
 
        ++iPtr;
2178
 
    }   Next();
2179
 
 
2180
 
    I(LeaveWith):
2181
 
    {
2182
 
        QScriptValueImpl withObject = m_scopeChain;
2183
 
        m_scopeChain = withObject.m_object_value->m_scope;
2184
 
        ++iPtr;
2185
 
    }   Next();
2186
 
 
2187
 
    I(BeginCatch):
2188
 
    {
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;
2198
 
 
2199
 
        catching = true;
2200
 
        ++iPtr;
2201
 
    }   Next();
2202
 
 
2203
 
    I(EndCatch):
2204
 
    {
2205
 
        // remove catch-object from scopechain
2206
 
        QScriptValueImpl object = m_scopeChain;
2207
 
        m_scopeChain = object.m_object_value->m_scope;
2208
 
 
2209
 
        catching = false;
2210
 
        ++iPtr;
2211
 
    }   Next();
2212
 
 
2213
 
    I(Debugger):
2214
 
    {
2215
 
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2216
 
        eng->notifyDebugger(this);
2217
 
#endif
2218
 
        ++iPtr;
2219
 
    }   Next();
2220
 
 
2221
 
#ifndef Q_SCRIPT_DIRECT_CODE
2222
 
    I(Dummy):
2223
 
    { ; }
2224
 
 
2225
 
    } // end switch
2226
 
#endif
2227
 
 
2228
 
Lhandle_exception:
2229
 
    errorLineNumber = currentLine;
2230
 
 
2231
 
Ldone:
2232
 
    Q_ASSERT(m_result.isValid());
2233
 
 
2234
 
    if (m_state == QScriptContext::ExceptionState) {
2235
 
        if (catching) {
2236
 
            // exception thrown in catch -- clean up scopechain
2237
 
            QScriptValueImpl object = m_scopeChain;
2238
 
            m_scopeChain = object.m_object_value->m_scope;
2239
 
            catching = false;
2240
 
        }
2241
 
 
2242
 
        // see if we have an exception handler in this context
2243
 
        const QScriptInstruction *exPtr = findExceptionHandler(iPtr);
2244
 
        if (exPtr) {
2245
 
            if (m_scopeChain.classInfo() == eng->m_class_with) {
2246
 
                // clean up effects of with-statements if necessary
2247
 
                int withLevel = 0;
2248
 
                for (++iPtr; iPtr != exPtr; ++iPtr) {
2249
 
                    if (iPtr->op == QScriptInstruction::OP_EnterWith) {
2250
 
                        ++withLevel;
2251
 
                    } else if (iPtr->op == QScriptInstruction::OP_LeaveWith) {
2252
 
                        --withLevel;
2253
 
                        if (withLevel < 0) {
2254
 
                            QScriptValueImpl withObject = m_scopeChain;
2255
 
                            m_scopeChain = withObject.m_object_value->m_scope;
2256
 
                        }
2257
 
                    }
2258
 
                }
2259
 
            } else {
2260
 
                iPtr = exPtr;
2261
 
            }
2262
 
            // go to the handler
2263
 
            recover();
2264
 
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2265
 
            eng->notifyExceptionCatch(this);
2266
 
#endif
2267
 
            goto Ltop;
2268
 
        } else {
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;
2275
 
                }
2276
 
            }
2277
 
        }
2278
 
    }
2279
 
 
2280
 
Labort:
2281
 
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2282
 
    eng->notifyFunctionExit(this);
2283
 
#endif
2284
 
 
2285
 
    eng->maybeGC();
2286
 
 
2287
 
    currentLine = oldCurrentLine;
2288
 
    currentColumn = oldCurrentColumn;
2289
 
    m_code = oldCode;
2290
 
 
2291
 
    eng->m_evaluating = wasEvaluating;
2292
 
}
2293
 
 
2294
 
QScriptValueImpl QScriptContextPrivate::throwError(QScriptContext::Error error, const QString &text)
2295
 
{
2296
 
    QScriptEnginePrivate *eng_p = engine();
2297
 
    QScript::Ecma::Error *ctor = eng_p->errorConstructor;
2298
 
    m_result.invalidate();
2299
 
    switch (error) {
2300
 
    case QScriptContext::ReferenceError:
2301
 
        ctor->newReferenceError(&m_result, text);
2302
 
        break;
2303
 
    case QScriptContext::SyntaxError:
2304
 
        ctor->newSyntaxError(&m_result, text);
2305
 
        break;
2306
 
    case QScriptContext::TypeError:
2307
 
        ctor->newTypeError(&m_result, text);
2308
 
        break;
2309
 
    case QScriptContext::RangeError:
2310
 
        ctor->newRangeError(&m_result, text);
2311
 
        break;
2312
 
    case QScriptContext::URIError:
2313
 
        ctor->newURIError(&m_result, text);
2314
 
        break;
2315
 
    case QScriptContext::UnknownError:
2316
 
    default:
2317
 
        ctor->newError(&m_result, text);
2318
 
    }
2319
 
    setDebugInformation(&m_result);
2320
 
    m_state = QScriptContext::ExceptionState;
2321
 
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2322
 
        eng_p->notifyException(this);
2323
 
#endif
2324
 
    return m_result;
2325
 
}
2326
 
 
2327
 
#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
2328
 
qint64 QScriptContextPrivate::scriptId() const
2329
 
{
2330
 
    if (!m_code)
2331
 
        return -1;
2332
 
    return m_code->astPool->id();
2333
 
}
2334
 
#endif
2335
 
 
2336
 
QString QScriptContextPrivate::fileName() const
2337
 
{
2338
 
    if (!m_code)
2339
 
        return QString();
2340
 
    return m_code->astPool->fileName();
2341
 
}
2342
 
 
2343
 
QString QScriptContextPrivate::functionName() const
2344
 
{
2345
 
    if (!m_callee.isValid())
2346
 
        return QString();
2347
 
    QScriptFunction *fun = m_callee.toFunction();
2348
 
    if (fun)
2349
 
        return fun->functionName();
2350
 
    return QString();
2351
 
}
2352
 
 
2353
 
void QScriptContextPrivate::setDebugInformation(QScriptValueImpl *error) const
2354
 
{
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()));
2359
 
 
2360
 
    const QScriptContextPrivate *ctx = this;
2361
 
    QScriptValueImpl stackArray = eng_p->newArray();
2362
 
    int i = 0;
2363
 
    while (ctx) {
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();
2373
 
        ++i;
2374
 
    }
2375
 
    error->setProperty(QLatin1String("stack"), stackArray);
2376
 
}
2377
 
 
2378
 
QStringList QScriptContextPrivate::backtrace() const
2379
 
{
2380
 
    QStringList result;
2381
 
    const QScriptContextPrivate *ctx = this;
2382
 
    while (ctx) {
2383
 
        QString s;
2384
 
        QString functionName = ctx->functionName();
2385
 
        if (!functionName.isEmpty())
2386
 
            s += functionName;
2387
 
        else {
2388
 
            if (ctx->parentContext()) {
2389
 
                if (ctx->callee().isFunction()
2390
 
                    && ctx->callee().toFunction()->type() != QScriptFunction::Script) {
2391
 
                    s += QLatin1String("<native>");
2392
 
                } else {
2393
 
                    s += QLatin1String("<anonymous>");
2394
 
                }
2395
 
            } else {
2396
 
                s += QLatin1String("<global>");
2397
 
            }
2398
 
        }
2399
 
        s += QLatin1String("(");
2400
 
        for (int i = 0; i < ctx->argc; ++i) {
2401
 
            if (i > 0)
2402
 
                s += QLatin1String(",");
2403
 
            QScriptValueImpl arg = ctx->args[i];
2404
 
            if (arg.isObject())
2405
 
                s += QLatin1String("[object Object]"); // don't do a function call
2406
 
            else
2407
 
                s += arg.toString();
2408
 
        }
2409
 
        s += QLatin1String(")@");
2410
 
        s += ctx->fileName();
2411
 
        s += QString::fromLatin1(":%0").arg(ctx->currentLine);
2412
 
        result.append(s);
2413
 
        ctx = ctx->parentContext();
2414
 
    }
2415
 
    return result;
2416
 
}
2417
 
 
2418
 
QScriptValueImpl QScriptContextPrivate::throwError(const QString &text)
2419
 
{
2420
 
    return throwError(QScriptContext::UnknownError, text);
2421
 
}
2422
 
 
2423
 
QScriptValueImpl QScriptContextPrivate::throwNotImplemented(const QString &name)
2424
 
{
2425
 
    return throwTypeError(QString::fromUtf8("%1 is not implemented").arg(name));
2426
 
}
2427
 
 
2428
 
QScriptValueImpl QScriptContextPrivate::throwNotDefined(const QString &name)
2429
 
{
2430
 
    return throwError(QScriptContext::ReferenceError,
2431
 
                      QString::fromUtf8("%1 is not defined").arg(name));
2432
 
}
2433
 
 
2434
 
QScriptValueImpl QScriptContextPrivate::throwNotDefined(QScriptNameIdImpl *nameId)
2435
 
{
2436
 
    return throwNotDefined(QScriptEnginePrivate::toString(nameId));
2437
 
}
2438
 
 
2439
 
bool QScriptContextPrivate::eq_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs)
2440
 
{
2441
 
    if (lhs.isNull() && rhs.isUndefined())
2442
 
        return true;
2443
 
 
2444
 
    else if (lhs.isUndefined() && rhs.isNull())
2445
 
        return true;
2446
 
 
2447
 
    else if (isNumerical(lhs) && rhs.isString())
2448
 
        return QScriptEnginePrivate::convertToNativeDouble(lhs) == QScriptEnginePrivate::convertToNativeDouble(rhs);
2449
 
 
2450
 
    else if (lhs.isString() && isNumerical(rhs))
2451
 
        return QScriptEnginePrivate::convertToNativeDouble(lhs) == QScriptEnginePrivate::convertToNativeDouble(rhs);
2452
 
 
2453
 
    else if (lhs.isBoolean())
2454
 
        return eq_cmp(QScriptValueImpl(QScriptEnginePrivate::convertToNativeDouble(lhs)), rhs);
2455
 
 
2456
 
    else if (rhs.isBoolean())
2457
 
        return eq_cmp(lhs, QScriptValueImpl(QScriptEnginePrivate::convertToNativeDouble(rhs)));
2458
 
 
2459
 
    else if (lhs.isObject() && ! rhs.isNull()) {
2460
 
        lhs = lhs.engine()->toPrimitive(lhs);
2461
 
 
2462
 
        if (lhs.isValid() && ! lhs.isObject())
2463
 
            return eq_cmp(lhs, rhs);
2464
 
    }
2465
 
 
2466
 
    else if (rhs.isObject() && ! lhs.isNull()) {
2467
 
        rhs = rhs.engine()->toPrimitive(rhs);
2468
 
 
2469
 
        if (rhs.isValid() && ! rhs.isObject())
2470
 
            return eq_cmp(lhs, rhs);
2471
 
    }
2472
 
 
2473
 
    return false;
2474
 
}
2475
 
 
2476
 
#if defined(Q_CC_GNU) && __GNUC__ <= 3
2477
 
bool QScriptContextPrivate::lt_cmp(QScriptValueImpl lhs, QScriptValueImpl rhs)
2478
 
{
2479
 
    if (lhs.type() == rhs.type()) {
2480
 
        switch (lhs.type()) {
2481
 
        case QScript::InvalidType:
2482
 
        case QScript::UndefinedType:
2483
 
        case QScript::NullType:
2484
 
            return false;
2485
 
 
2486
 
        case QScript::NumberType:
2487
 
            return lhs.m_number_value < rhs.m_number_value;
2488
 
 
2489
 
        case QScript::IntegerType:
2490
 
            return lhs.m_int_value < rhs.m_int_value;
2491
 
 
2492
 
        case QScript::BooleanType:
2493
 
            return lhs.m_bool_value < rhs.m_bool_value;
2494
 
 
2495
 
        default:
2496
 
            break;
2497
 
        } // switch
2498
 
    }
2499
 
#else
2500
 
bool QScriptContextPrivate::lt_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs)
2501
 
{
2502
 
#endif
2503
 
    if ((lhs.type() == rhs.type()) && (lhs.type() == QScript::StringType))
2504
 
        return lhs.m_string_value->s < rhs.m_string_value->s;
2505
 
 
2506
 
    if (lhs.isObject())
2507
 
        lhs = lhs.engine()->toPrimitive(lhs, QScriptValueImpl::NumberTypeHint);
2508
 
 
2509
 
    if (rhs.isObject())
2510
 
        rhs = rhs.engine()->toPrimitive(rhs, QScriptValueImpl::NumberTypeHint);
2511
 
 
2512
 
    if (lhs.isString() && rhs.isString())
2513
 
        return QScriptEnginePrivate::convertToNativeString(lhs) < QScriptEnginePrivate::convertToNativeString(rhs);
2514
 
 
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))
2519
 
        return false;
2520
 
#endif
2521
 
    return n1 < n2;
2522
 
}
2523
 
 
2524
 
bool QScriptContextPrivate::le_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs)
2525
 
{
2526
 
    if ((lhs.type() == rhs.type()) && (lhs.type() == QScript::StringType))
2527
 
        return lhs.m_string_value->s <= rhs.m_string_value->s;
2528
 
 
2529
 
    if (lhs.isObject())
2530
 
        lhs = lhs.engine()->toPrimitive(lhs, QScriptValueImpl::NumberTypeHint);
2531
 
 
2532
 
    if (rhs.isObject())
2533
 
        rhs = rhs.engine()->toPrimitive(rhs, QScriptValueImpl::NumberTypeHint);
2534
 
 
2535
 
    if (lhs.isString() && rhs.isString())
2536
 
        return QScriptEnginePrivate::convertToNativeString(lhs) <= QScriptEnginePrivate::convertToNativeString(rhs);
2537
 
 
2538
 
    qsreal n1 = QScriptEnginePrivate::convertToNativeDouble(lhs);
2539
 
    qsreal n2 = QScriptEnginePrivate::convertToNativeDouble(rhs);
2540
 
    return n1 <= n2;
2541
 
}
2542
 
 
2543
 
const QScriptInstruction *QScriptContextPrivate::findExceptionHandler(
2544
 
    const QScriptInstruction *ip) const
2545
 
{
2546
 
    Q_ASSERT(m_code);
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();
2552
 
        }
2553
 
    }
2554
 
    return 0;
2555
 
}
2556
 
 
2557
 
const QScriptInstruction *QScriptContextPrivate::findExceptionHandlerRecursive(
2558
 
    const QScriptInstruction *ip, QScriptContextPrivate **handlerContext) const
2559
 
{
2560
 
    const QScriptContextPrivate *ctx = this;
2561
 
    const QScriptInstruction *iip = ip;
2562
 
    while (ctx) {
2563
 
        if (ctx->m_code) {
2564
 
            const QScriptInstruction *ep = ctx->findExceptionHandler(iip);
2565
 
            if (ep) {
2566
 
                Q_ASSERT(handlerContext);
2567
 
                *handlerContext = const_cast<QScriptContextPrivate*>(ctx);
2568
 
                return ep;
2569
 
            }
2570
 
        }
2571
 
        ctx = ctx->parentContext();
2572
 
        if (ctx)
2573
 
            iip = ctx->iPtr;
2574
 
    }
2575
 
    return 0;
2576
 
}
2577
 
 
2578
 
/*!
2579
 
  Requires that iPtr in current context is in sync
2580
 
*/
2581
 
QScriptContextPrivate *QScriptContextPrivate::exceptionHandlerContext() const
2582
 
{
2583
 
    QScriptContextPrivate *handlerContext;
2584
 
    if (findExceptionHandlerRecursive(iPtr, &handlerContext))
2585
 
        return handlerContext;
2586
 
    return 0;
2587
 
}
2588
 
 
2589
 
QScriptContext *QScriptContextPrivate::get(QScriptContextPrivate *d)
2590
 
{
2591
 
    if (d)
2592
 
        return d->q_func();
2593
 
    return 0;
2594
 
}
2595
 
 
2596
 
QT_END_NAMESPACE
2597
 
 
2598
 
#endif // QT_NO_SCRIPT