aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4codegen_p.h3
-rw-r--r--src/qml/jit/qv4baselinejit.cpp2
-rw-r--r--src/qml/jit/qv4jithelpers.cpp10
-rw-r--r--src/qml/jit/qv4jithelpers_p.h1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp15
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp7
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations1
9 files changed, 23 insertions, 21 deletions
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 1fc3c2180b..761b353066 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -338,6 +338,9 @@ public:
static Reference fromThis(Codegen *cg) {
Reference r = fromStackSlot(cg, CallData::This);
r.isReadonly = true;
+ // ### Optimize this. Functions that are not derived constructors or arrow functions can't have an
+ // empty this object
+ r.requiresTDZCheck = true;
return r;
}
diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp
index e9f85a5c6b..36375461f9 100644
--- a/src/qml/jit/qv4baselinejit.cpp
+++ b/src/qml/jit/qv4baselinejit.cpp
@@ -815,7 +815,7 @@ void BaselineJIT::generate_LoadSuperConstructor()
as->prepareCallWithArgCount(2);
as->passJSSlotAsArg(CallData::Function, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::loadSuperConstructor, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadSuperConstructor, CallResultDestination::InAccumulator);
as->checkException();
}
diff --git a/src/qml/jit/qv4jithelpers.cpp b/src/qml/jit/qv4jithelpers.cpp
index 9e057dd33d..7bac5d968d 100644
--- a/src/qml/jit/qv4jithelpers.cpp
+++ b/src/qml/jit/qv4jithelpers.cpp
@@ -70,16 +70,6 @@ ReturnedValue loadGlobalLookup(ExecutionEngine *engine, Function *f, int index)
return l->globalGetter(l, engine);
}
-ReturnedValue loadSuperConstructor(ExecutionEngine *engine, const Value *t)
-{
- const FunctionObject *f = t->as<FunctionObject>();
- if (!f || !f->isConstructor()) {
- engine->throwTypeError();
- return Encode::undefined();
- }
- return static_cast<const Object *>(t)->getPrototypeOf()->asReturnedValue();
-}
-
ReturnedValue toObject(ExecutionEngine *engine, const Value &obj)
{
if (obj.isObject())
diff --git a/src/qml/jit/qv4jithelpers_p.h b/src/qml/jit/qv4jithelpers_p.h
index e0dfdc47d9..bb10d5722b 100644
--- a/src/qml/jit/qv4jithelpers_p.h
+++ b/src/qml/jit/qv4jithelpers_p.h
@@ -66,7 +66,6 @@ namespace Helpers {
void convertThisToObject(ExecutionEngine *engine, Value *t);
ReturnedValue loadGlobalLookup(ExecutionEngine *engine, Function *f, int index);
-ReturnedValue loadSuperConstructor(ExecutionEngine *engine, const Value *t);
ReturnedValue toObject(ExecutionEngine *engine, const Value &obj);
ReturnedValue exp(const Value &base, const Value &exp);
ReturnedValue getLookup(ExecutionEngine *engine, Function *f, int index, const Value &base);
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index a5dc0ba567..f7bea9a5f0 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -556,7 +556,7 @@ ReturnedValue ConstructorFunction::virtualCallAsConstructor(const FunctionObject
CppStackFrame frame;
frame.init(v4, f->function(), argv, argc);
frame.setupJSFrame(v4->jsStackTop, *f, f->scope(),
- Primitive::undefinedValue(),
+ Primitive::emptyValue(),
newTarget ? *newTarget : Primitive::undefinedValue());
frame.push();
@@ -570,7 +570,7 @@ ReturnedValue ConstructorFunction::virtualCallAsConstructor(const FunctionObject
return Encode::undefined();
else if (Value::fromReturnedValue(result).isObject())
return result;
- else if (!Value::fromReturnedValue(result).isUndefined())
+ else if (!Value::fromReturnedValue(result).isUndefined() || frame.jsFrame->thisObject.isEmpty())
return v4->throwTypeError();
return frame.jsFrame->thisObject.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index bf79b369d2..edaa0a8e63 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -911,6 +911,21 @@ void Runtime::method_storeSuperProperty(ExecutionEngine *engine, const Value &pr
engine->throwTypeError();
}
+ReturnedValue Runtime::method_loadSuperConstructor(ExecutionEngine *engine, const Value &t)
+{
+ if (engine->currentStackFrame->thisObject() != Primitive::emptyValue().asReturnedValue()) {
+ return engine->throwReferenceError(QStringLiteral("super() already called."), QString(), 0, 0); // ### fix line number
+ }
+ const FunctionObject *f = t.as<FunctionObject>();
+ if (!f || !f->isConstructor()) {
+ engine->throwTypeError();
+ return Encode::undefined();
+ }
+ return static_cast<const Object &>(t).getPrototypeOf()->asReturnedValue();
+}
+
+
+
#endif // V4_BOOTSTRAP
uint RuntimeHelpers::equalHelper(const Value &x, const Value &y)
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index 182cc393ea..5dafeee6ce 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -115,6 +115,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(ReturnedValue, loadElement, (ExecutionEngine *engine, const Value &object, const Value &index)) \
F(ReturnedValue, loadSuperProperty, (ExecutionEngine *engine, const Value &property)) \
F(void, storeSuperProperty, (ExecutionEngine *engine, const Value &property, const Value &value)) \
+ F(ReturnedValue, loadSuperConstructor, (ExecutionEngine *engine, const Value &t)) \
\
/* typeof */ \
F(ReturnedValue, typeofValue, (ExecutionEngine *engine, const Value &val)) \
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 3570453525..fd2328beaa 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -958,12 +958,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(ConvertThisToObject)
MOTH_BEGIN_INSTR(LoadSuperConstructor)
- const FunctionObject *f = stack[CallData::Function].as<FunctionObject>();
- if (!f || !f->isConstructor()) {
- engine->throwTypeError();
- } else {
- acc = static_cast<const Object *>(f)->getPrototypeOf()->asReturnedValue();
- }
+ acc = Runtime::method_loadSuperConstructor(engine, stack[CallData::Function]);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadSuperConstructor)
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index c114b65f44..10690e3891 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -943,7 +943,6 @@ language/expressions/prefix-increment/S11.4.4_A5_T3.js sloppyFails
language/expressions/prefix-increment/S11.4.4_A5_T4.js sloppyFails
language/expressions/prefix-increment/S11.4.4_A5_T5.js fails
language/expressions/prefix-increment/S11.4.4_A6_T3.js fails
-language/expressions/super/call-bind-this-value-twice.js fails
language/expressions/super/call-construct-invocation.js fails
language/expressions/super/call-proto-not-ctor.js fails
language/expressions/super/prop-dot-cls-null-proto.js fails