diff options
author | Yulong Bai <yulong.bai@qt.io> | 2018-06-15 14:44:19 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-06-26 10:03:56 +0000 |
commit | 74f4065caa7254b0e30afa955aa59092024decdb (patch) | |
tree | b9b5555807ebfb2e7b6a80a56aec8785b4066ae1 /src/qml/jsruntime/qv4runtime.cpp | |
parent | c9fa5b8071f4a32afd05cc9fa5cd8ab28e60dc55 (diff) |
Add basic support for EcmaScript classes
Most of the class creation is done inside the runtime
in the CreateClass method. Added a corresponding
instruction to the interpreter and jit.
The compiled data now contains an array of classes
containing the compile time generated layout of the class.
Currently, classes without an explicit constructor and
classes with inheritance are not supported.
Done-with: Yulong Bai <yulong.bai@qt.io>
Change-Id: I0185dcc1e3b0b8f44deff74e44a8262fc646aa9e
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4runtime.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 64efaa9a86..bae8a9d332 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1482,6 +1482,67 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId return o.asReturnedValue(); } +ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classIndex, const Value &heritage, const Value *computedNames) +{ + const CompiledData::CompilationUnit *unit = engine->currentStackFrame->v4Function->compilationUnit; + const QV4::CompiledData::Class *cls = unit->data->classAt(classIndex); + + if (!heritage.isEmpty()) { + // #### + return engine->throwTypeError(QStringLiteral("classes with heritage not yet supported.")); + } + + Scope scope(engine); + ScopedString name(scope, unit->runtimeStrings[cls->nameIndex]); + // ### fix heritage + ScopedObject protoParent(scope, engine->objectPrototype()); + ScopedObject constructorParent(scope, engine->functionPrototype()); + + ScopedObject proto(scope, engine->newObject()); + proto->setPrototypeUnchecked(protoParent); + ExecutionContext *current = static_cast<ExecutionContext *>(&engine->currentStackFrame->jsFrame->context); + + ScopedFunctionObject constructor(scope); + if (cls->constructorFunction != UINT_MAX) { + QV4::Function *f = unit->runtimeFunctions[cls->constructorFunction]; + Q_ASSERT(f); + constructor = FunctionObject::createConstructorFunction(current, f)->asReturnedValue(); + } else { + // #### + return engine->throwTypeError(QStringLiteral("default constructor not implemented")); + } + constructor->setPrototypeUnchecked(constructorParent); + constructor->defineDefaultProperty(engine->id_prototype(), proto); + proto->defineDefaultProperty(engine->id_constructor(), constructor); + + + ScopedFunctionObject function(scope); + for (uint i = 0; i < cls->nStaticMethods; ++i) { + name = unit->runtimeStrings[cls->nameTable()[i]]; + QV4::Function *f = unit->runtimeFunctions[cls->methodTable()[i]]; + Q_ASSERT(f); + function = FunctionObject::createScriptFunction(current, f)->asReturnedValue(); + constructor->defineDefaultProperty(name, function); + } + + for (uint i = 0; i < cls->nMethods; ++i) { + name = unit->runtimeStrings[cls->nameTable()[i + cls->nStaticMethods]]; + name->makeIdentifier(); + if (name->identifier() == engine->id_empty()->identifier()) { + name = computedNames->toPropertyKey(engine); + if (engine->hasException) + return Encode::undefined(); + ++computedNames; + } + QV4::Function *f = unit->runtimeFunctions[cls->methodTable()[i + cls->nStaticMethods]]; + Q_ASSERT(f); + function = FunctionObject::createScriptFunction(current, f)->asReturnedValue(); + proto->defineDefaultProperty(name, function); + } + + return constructor->asReturnedValue(); +} + QV4::ReturnedValue Runtime::method_createMappedArgumentsObject(ExecutionEngine *engine) { Q_ASSERT(engine->currentContext()->d()->type == Heap::ExecutionContext::Type_CallContext); |