aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-09-06 13:38:23 +0200
committerLars Knoll <lars.knoll@qt.io>2018-09-07 10:31:57 +0000
commitbd4064eabf79a6166805c877ee622931df6fb172 (patch)
tree9a9d96fbb224ada879836dbfb7cff9e93b44946f /src/qml
parent15bdbd89639c29f88db1798de66066a4a95759c0 (diff)
Throw a type error when trying to destructure null or undefined
Change-Id: Id1bba1a729124bccb8a90dcf40252fe5c69d27a3 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp3
-rw-r--r--src/qml/compiler/qv4codegen.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp3
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/jit/qv4baselinejit.cpp11
-rw-r--r--src/qml/jit/qv4baselinejit_p.h1
-rw-r--r--src/qml/jit/qv4jithelpers.cpp6
-rw-r--r--src/qml/jit/qv4jithelpers_p.h1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp7
9 files changed, 38 insertions, 0 deletions
diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp
index 3a3f4a6adb..5b836c2e9c 100644
--- a/src/qml/compiler/qv4bytecodehandler.cpp
+++ b/src/qml/compiler/qv4bytecodehandler.cpp
@@ -528,6 +528,9 @@ std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint
COLLECTOR_BEGIN_INSTR(InitializeBlockDeadTemporalZone)
COLLECTOR_END_INSTR(InitializeBlockDeadTemporalZone)
+ COLLECTOR_BEGIN_INSTR(ThrowOnNullOrUndefined)
+ COLLECTOR_END_INSTR(ThrowOnNullOrUndefined)
+
COLLECTOR_BEGIN_INSTR(LoadQmlContext)
COLLECTOR_END_INSTR(LoadQmlContext)
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 1d6e8819f5..2415142df4 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -619,6 +619,10 @@ void Codegen::destructurePropertyList(const Codegen::Reference &object, PatternP
{
RegisterScope scope(this);
+ object.loadInAccumulator();
+ Instruction::ThrowOnNullOrUndefined t;
+ bytecodeGenerator->addInstruction(t);
+
for (PatternPropertyList *it = bindingList; it; it = it->next) {
PatternProperty *p = it->property;
RegisterScope scope(this);
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index b09f1d09d0..00a1e8470b 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -702,6 +702,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << dumpRegister(firstReg, nFormals) << ", " << count;
MOTH_END_INSTR(InitializeBlockDeadTemporalZone)
+ MOTH_BEGIN_INSTR(ThrowOnNullOrUndefined)
+ MOTH_END_INSTR(ThrowOnNullOrUndefined)
+
MOTH_BEGIN_INSTR(LoadQmlContext)
d << dumpRegister(result, nFormals);
MOTH_END_INSTR(LoadQmlContext)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 40313551e8..34c80db0e8 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -195,6 +195,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_LoadQmlContext(op) INSTRUCTION(op, LoadQmlContext, 1, result)
#define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result)
#define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count)
+#define INSTR_ThrowOnNullOrUndefined(op) INSTRUCTION(op, ThrowOnNullOrUndefined, 0)
#define FOR_EACH_MOTH_INSTR_ALL(F) \
F(Nop) \
@@ -332,6 +333,7 @@ QT_BEGIN_NAMESPACE
F(PushScriptContext) \
F(PopScriptContext) \
F(InitializeBlockDeadTemporalZone) \
+ F(ThrowOnNullOrUndefined) \
F(Debug) \
#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::Debug_Wide) + 1)
diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp
index d0ac169e4f..baaab75158 100644
--- a/src/qml/jit/qv4baselinejit.cpp
+++ b/src/qml/jit/qv4baselinejit.cpp
@@ -956,6 +956,17 @@ void BaselineJIT::generate_InitializeBlockDeadTemporalZone(int firstReg, int cou
as->storeReg(i);
}
+void BaselineJIT::generate_ThrowOnNullOrUndefined()
+{
+ STORE_ACC();
+ as->prepareCallWithArgCount(2);
+ as->passAccumulatorAsArg(1);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::throwOnNullOrUndefined, CallResultDestination::Ignore);
+ as->checkException();
+}
+
+
void BaselineJIT::startInstruction(Instr::Type /*instr*/)
{
if (hasLabel())
diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h
index 7e3fcfa5e6..f9c876a1e9 100644
--- a/src/qml/jit/qv4baselinejit_p.h
+++ b/src/qml/jit/qv4baselinejit_p.h
@@ -211,6 +211,7 @@ public:
void generate_LoadQmlContext(int result) override;
void generate_LoadQmlImportedScripts(int result) override;
void generate_InitializeBlockDeadTemporalZone(int firstReg, int count) override;
+ void generate_ThrowOnNullOrUndefined() override;
void startInstruction(Moth::Instr::Type instr) override;
void endInstruction(Moth::Instr::Type instr) override;
diff --git a/src/qml/jit/qv4jithelpers.cpp b/src/qml/jit/qv4jithelpers.cpp
index 7bac5d968d..427356e5ed 100644
--- a/src/qml/jit/qv4jithelpers.cpp
+++ b/src/qml/jit/qv4jithelpers.cpp
@@ -146,6 +146,12 @@ ReturnedValue deleteName(Function *function, int name)
}
}
+void throwOnNullOrUndefined(ExecutionEngine *engine, const Value &v)
+{
+ if (v.isNullOrUndefined())
+ engine->throwTypeError();
+}
+
} // Helpers namespace
} // JIT namespace
} // QV4 namespace
diff --git a/src/qml/jit/qv4jithelpers_p.h b/src/qml/jit/qv4jithelpers_p.h
index bb10d5722b..dd68452e7f 100644
--- a/src/qml/jit/qv4jithelpers_p.h
+++ b/src/qml/jit/qv4jithelpers_p.h
@@ -76,6 +76,7 @@ void pushScriptContext(Value *stack, ExecutionEngine *engine, int index);
void popScriptContext(Value *stack, ExecutionEngine *engine);
ReturnedValue deleteProperty(QV4::Function *function, const QV4::Value &base, const QV4::Value &index);
ReturnedValue deleteName(Function *function, int name);
+void throwOnNullOrUndefined(ExecutionEngine *engine, const Value &v);
} // Helpers namespace
} // JIT namespace
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index f38bd7b48e..6ed371bbf2 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -1344,6 +1344,13 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
STACK_VALUE(i) = acc;
MOTH_END_INSTR(InitializeBlockDeadTemporalZone)
+ MOTH_BEGIN_INSTR(ThrowOnNullOrUndefined)
+ if (Primitive::fromReturnedValue(acc).isNullOrUndefined()) {
+ engine->throwTypeError();
+ goto handleUnwind;
+ }
+ MOTH_END_INSTR(ThrowOnNullOrUndefined)
+
MOTH_BEGIN_INSTR(Debug)
#if QT_CONFIG(qml_debug)
STORE_IP();