diff options
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 3 | ||||
-rw-r--r-- | src/qml/jit/qv4baselinejit.cpp | 2 | ||||
-rw-r--r-- | src/qml/jit/qv4jithelpers.cpp | 10 | ||||
-rw-r--r-- | src/qml/jit/qv4jithelpers_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 15 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtimeapi_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 1 |
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 |