diff options
author | Lars Knoll <lars.knoll@digia.com> | 2014-03-18 09:12:42 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-19 08:14:50 +0100 |
commit | cfd3eda076e81d56f985c830663ae93317b6ef8b (patch) | |
tree | b46fd616bfbe5170fd65198a561f19d7a5f37c0e | |
parent | 4606bd668375770b8f9d84b1739c8a17cfc928d7 (diff) |
Fixes to for...in statement
Properly convert the argument to an object if
it's not null or undefined as mandated by the
standard.
Add a similar test case for the with statement.
Change-Id: Idd8e245e8dae4803eb0e2010e3d43bb912670444
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.h | 2 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 4 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm_p.h | 2 | ||||
-rw-r--r-- | src/qml/jit/qv4regalloc.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qml/qjsengine/tst_qjsengine.cpp | 33 |
9 files changed, 40 insertions, 11 deletions
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 4ae65938da..b8f56e990e 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -1231,7 +1231,7 @@ void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionNam addInstruction(call); } -void InstructionSelection::callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result) +void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result) { Instruction::CallBuiltinForeachIteratorObject call; call.arg = getParam(arg); diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index 4c01434156..0aa1972fb4 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -93,7 +93,7 @@ protected: virtual void callBuiltinReThrow(); virtual void callBuiltinUnwindException(IR::Temp *); virtual void callBuiltinPushCatchScope(const QString &exceptionName); - virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result); + virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result); virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result); virtual void callBuiltinPushWithScope(IR::Temp *arg); virtual void callBuiltinPopScope(); diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index 0e429423ab..0dbf58ad5c 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -313,7 +313,7 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result) } return; case IR::Name::builtin_foreach_iterator_object: { - IR::Temp *arg = call->args->expr->asTemp(); + IR::Expr *arg = call->args->expr; assert(arg != 0); callBuiltinForeachIteratorObject(arg, result); } return; diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index f4aab412df..c0de4ec8bf 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -125,7 +125,7 @@ public: // to implement by subclasses: virtual void callBuiltinReThrow() = 0; virtual void callBuiltinUnwindException(IR::Temp *) = 0; virtual void callBuiltinPushCatchScope(const QString &exceptionName) = 0; - virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result) = 0; + virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result) = 0; virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) = 0; virtual void callBuiltinPushWithScope(IR::Temp *arg) = 0; virtual void callBuiltinPopScope() = 0; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 5e51b84cd5..d30d69e68f 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -474,12 +474,12 @@ void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionNam generateFunctionCall(Assembler::ContextRegister, Runtime::pushCatchScope, Assembler::ContextRegister, s); } -void InstructionSelection::callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result) +void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result) { Q_ASSERT(arg); Q_ASSERT(result); - generateFunctionCall(result, Runtime::foreachIterator, Assembler::ContextRegister, Assembler::Reference(arg)); + generateFunctionCall(result, Runtime::foreachIterator, Assembler::ContextRegister, Assembler::PointerToValue(arg)); } void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 62891e4273..0e8db93e85 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -89,7 +89,7 @@ protected: virtual void callBuiltinReThrow(); virtual void callBuiltinUnwindException(IR::Temp *); virtual void callBuiltinPushCatchScope(const QString &exceptionName); - virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result); + virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result); virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result); virtual void callBuiltinPushWithScope(IR::Temp *arg); virtual void callBuiltinPopScope(); diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 72ec66d1c2..506fd8df6d 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -207,7 +207,7 @@ protected: // IRDecoder virtual void callBuiltinReThrow() {} virtual void callBuiltinUnwindException(IR::Temp *) {} virtual void callBuiltinPushCatchScope(const QString &) {}; - virtual void callBuiltinForeachIteratorObject(IR::Temp *, IR::Temp *) {} + virtual void callBuiltinForeachIteratorObject(IR::Expr *, IR::Temp *) {} virtual void callBuiltinForeachNextProperty(IR::Temp *, IR::Temp *) {} virtual void callBuiltinForeachNextPropertyname(IR::Temp *, IR::Temp *) {} virtual void callBuiltinPushWithScope(IR::Temp *) {} diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 431c2d6979..bbebc2184e 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -632,7 +632,7 @@ ReturnedValue Runtime::foreachIterator(ExecutionContext *ctx, const ValueRef in) Scope scope(ctx); Scoped<Object> o(scope, (Object *)0); if (!in->isNullOrUndefined()) - o = in; + o = in->toObject(ctx); Scoped<Object> it(scope, ctx->engine->newForEachIteratorObject(ctx, o)); return it.asReturnedValue(); } diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 263dd0f963..ed6b5a9d42 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -115,7 +115,8 @@ private slots: void jsForInStatement_prototypeProperties(); void jsForInStatement_mutateWhileIterating(); void jsForInStatement_arrays(); - void jsForInStatement_nullAndUndefined(); + void jsForInStatement_constant(); + void with_constant(); void stringObjects(); void jsStringPrototypeReplaceBugs(); void getterSetterThisObject_global(); @@ -1983,7 +1984,7 @@ void tst_QJSEngine::jsForInStatement_arrays() } } -void tst_QJSEngine::jsForInStatement_nullAndUndefined() +void tst_QJSEngine::jsForInStatement_constant() { QJSEngine eng; { @@ -1996,6 +1997,34 @@ void tst_QJSEngine::jsForInStatement_nullAndUndefined() QVERIFY(ret.isBool()); QVERIFY(ret.toBool()); } + { + QJSValue ret = eng.evaluate("r = false; for (var p in 1) r = true; r"); + QVERIFY(ret.isBool()); + QVERIFY(!ret.toBool()); + } + { + QJSValue ret = eng.evaluate("r = false; for (var p in 'abc') r = true; r"); + QVERIFY(ret.isBool()); + QVERIFY(ret.toBool()); + } +} + +void tst_QJSEngine::with_constant() +{ + QJSEngine eng; + { + QJSValue ret = eng.evaluate("r = false; with(null) { r= true; } r"); + QVERIFY(ret.isError()); + } + { + QJSValue ret = eng.evaluate("r = false; with(undefined) { r= true; } r"); + QVERIFY(ret.isError()); + } + { + QJSValue ret = eng.evaluate("r = false; with(1) { r= true; } r"); + QVERIFY(ret.isBool()); + QVERIFY(ret.toBool()); + } } void tst_QJSEngine::stringObjects() |