Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qv4generatorobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include <qv4symbol_p.h>
6#include <qv4iterator_p.h>
7#include <qv4jscall_p.h>
8#include <qv4vme_moth_p.h>
9
10using namespace QV4;
11
15
17{
18 Heap::FunctionObject::init(engine, QStringLiteral("GeneratorFunction"));
19}
20
22{
23 ExecutionEngine *engine = f->engine();
24
25 QQmlRefPointer<ExecutableCompilationUnit> compilationUnit = parse(engine, argv, argc, Type_Generator);
27 return Encode::undefined();
28
29 Function *vmf = compilationUnit->rootFunction();
32
33 if (!newTarget)
34 return o;
35 Scope scope(engine);
36 ScopedObject obj(scope, o);
37 obj->setProtoFromNewTarget(newTarget);
38 return obj->asReturnedValue();
39}
40
41// 15.3.1: This is equivalent to new Function(...)
43{
44 return virtualCallAsConstructor(f, argv, argc, f);
45}
46
48{
50 Scoped<GeneratorFunction> g(scope, context->engine()->memoryManager->allocate<GeneratorFunction>(context, function));
51 ScopedObject proto(scope, scope.engine->newObject());
52 proto->setPrototypeOf(scope.engine->generatorPrototype());
53 g->defineDefaultProperty(scope.engine->id_prototype(), proto, Attr_NotConfigurable|Attr_NotEnumerable);
54 g->setPrototypeOf(ScopedObject(scope, scope.engine->generatorFunctionCtor()->get(scope.engine->id_prototype())));
55 return g->d();
56}
57
58ReturnedValue GeneratorFunction::virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
59{
60 const GeneratorFunction *gf = static_cast<const GeneratorFunction *>(f);
61 Function *function = gf->function();
62 ExecutionEngine *engine = gf->engine();
63
64 Scope scope(gf);
66 g->setPrototypeOf(ScopedObject(scope, gf->get(scope.engine->id_prototype())));
67
68 // We need to set up a separate JSFrame for the generator, as it's being re-entered
69 Heap::GeneratorObject *gp = g->d();
70 gp->values.set(engine, engine->newArrayObject(argc));
71 gp->jsFrame.set(engine, engine->newArrayObject(
73
74 // copy original arguments
75 for (int i = 0; i < argc; i++)
76 gp->values->arrayData->setArrayData(engine, i, argv[i]);
77
78 gp->cppFrame.init(function, gp->values->arrayData->values.values, argc);
79 gp->cppFrame.setupJSFrame(gp->jsFrame->arrayData->values.values, *gf, gf->scope(),
80 thisObject ? *thisObject : Value::undefinedValue(),
82
83 gp->cppFrame.push(engine);
84
85 Moth::VME::interpret(&gp->cppFrame, engine, function->codeData);
87
88 gp->cppFrame.pop(engine);
89 return g->asReturnedValue();
90}
91
92
94{
95 Heap::FunctionObject::init();
96}
97
98
100{
101 Scope scope(engine);
102 ScopedValue v(scope);
103
104 Scoped<InternalClass> ic(scope, engine->newInternalClass(
105 Object::staticVTable(), engine->functionPrototype()));
106 ScopedObject ctorProto(scope, engine->newObject(ic->d()));
107
108 ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(1));
109 ctor->defineReadonlyProperty(engine->id_prototype(), ctorProto);
110
111 ctorProto->defineDefaultProperty(QStringLiteral("constructor"), (v = ctor), Attr_ReadOnly_ButConfigurable);
112 ctorProto->defineDefaultProperty(engine->symbol_toStringTag(), (v = engine->newIdentifier(QStringLiteral("GeneratorFunction"))), Attr_ReadOnly_ButConfigurable);
113 ctorProto->defineDefaultProperty(engine->id_prototype(), (v = this), Attr_ReadOnly_ButConfigurable);
114
117 defineDefaultProperty(QStringLiteral("next"), method_next, 1);
118 defineDefaultProperty(QStringLiteral("return"), method_return, 1);
119 defineDefaultProperty(QStringLiteral("throw"), method_throw, 1);
121}
122
123ReturnedValue GeneratorPrototype::method_next(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
124{
125 ExecutionEngine *engine = f->engine();
126 const GeneratorObject *g = thisObject->as<GeneratorObject>();
127 if (!g || g->d()->state == GeneratorState::Executing)
128 return engine->throwTypeError();
129 Heap::GeneratorObject *gp = g->d();
130
131 if (gp->state == GeneratorState::Completed)
133
134 return g->resume(engine, argc ? argv[0] : Value::undefinedValue());
135}
136
137ReturnedValue GeneratorPrototype::method_return(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
138{
139 ExecutionEngine *engine = f->engine();
140 const GeneratorObject *g = thisObject->as<GeneratorObject>();
141 if (!g || g->d()->state == GeneratorState::Executing)
142 return engine->throwTypeError();
143
144 Heap::GeneratorObject *gp = g->d();
145
148
149 if (gp->state == GeneratorState::Completed)
151
152 // the bytecode interpreter interprets an exception with empty value as
153 // a yield called with return()
155
156 return g->resume(engine, argc ? argv[0] : Value::undefinedValue());
157}
158
159ReturnedValue GeneratorPrototype::method_throw(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
160{
161 ExecutionEngine *engine = f->engine();
162 const GeneratorObject *g = thisObject->as<GeneratorObject>();
163 if (!g || g->d()->state == GeneratorState::Executing)
164 return engine->throwTypeError();
165
166 Heap::GeneratorObject *gp = g->d();
167
168 engine->throwError(argc ? argv[0] : Value::undefinedValue());
169
172 return Encode::undefined();
173 }
174
175 return g->resume(engine, Value::undefinedValue());
176}
177
179{
180 Heap::GeneratorObject *gp = d();
182 gp->cppFrame.setParentFrame(engine->currentStackFrame);
183 engine->currentStackFrame = &gp->cppFrame;
184
185 Q_ASSERT(gp->cppFrame.yield() != nullptr);
186 const char *code = gp->cppFrame.yield();
187 gp->cppFrame.setYield(nullptr);
188 gp->cppFrame.jsFrame->accumulator = arg;
189 gp->cppFrame.setYieldIsIterator(false);
190
191 Scope scope(engine);
192 ScopedValue result(scope, Moth::VME::interpret(&gp->cppFrame, engine, code));
193
194 engine->currentStackFrame = gp->cppFrame.parentFrame();
195
196 bool done = (gp->cppFrame.yield() == nullptr);
198 if (engine->hasException)
199 return Encode::undefined();
200 if (gp->cppFrame.yieldIsIterator())
201 return result->asReturnedValue();
203}
204
206
207Heap::FunctionObject *MemberGeneratorFunction::create(ExecutionContext *context, Function *function, Object *homeObject, String *name)
208{
210 Scoped<MemberGeneratorFunction> g(scope, context->engine()->memoryManager->allocate<MemberGeneratorFunction>(context, function, name));
211 g->d()->homeObject.set(scope.engine, homeObject->d());
212 ScopedObject proto(scope, scope.engine->newObject());
213 proto->setPrototypeOf(scope.engine->generatorPrototype());
214 g->defineDefaultProperty(scope.engine->id_prototype(), proto, Attr_NotConfigurable|Attr_NotEnumerable);
215 g->setPrototypeOf(ScopedObject(scope, scope.engine->generatorFunctionCtor()->get(scope.engine->id_prototype())));
216 return g->d();
217}
218
219ReturnedValue MemberGeneratorFunction::virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
220{
221 return GeneratorFunction::virtualCall(f, thisObject, argv, argc);
222}
ManagedType::Data * allocManaged(std::size_t size, Heap::InternalClass *ic)
Definition qv4mm_p.h:199
static QV4::ReturnedValue interpret(JSTypesStackFrame *frame, ExecutionEngine *engine, const char *codeEntry)
quint64 ReturnedValue
Scoped< Object > ScopedObject
@ Attr_NotConfigurable
@ Attr_NotEnumerable
@ Attr_ReadOnly_ButConfigurable
static void * context
GLsizei const GLfloat * v
[13]
GLfloat GLfloat f
GLboolean GLboolean g
GLuint name
GLhandleARB obj
[2]
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int void * arg
#define QStringLiteral(str)
#define gp
#define DEFINE_OBJECT_VTABLE(classname)
QJSValue global
QJSEngine engine
[0]
static constexpr ReturnedValue undefined()
Heap::InternalClass * classes[NClasses]
MemoryManager * memoryManager
Object * iteratorPrototype() const
String * id_length() const
ReturnedValue throwError(const Value &value)
String * id_prototype() const
Heap::Object * newObject()
Symbol * symbol_toStringTag() const
Heap::String * newString(char16_t c)
Heap::String * newIdentifier(const QString &text)
ExecutionContext * scriptContext() const
Object * functionPrototype() const
Heap::ArrayObject * newArrayObject(int count=0)
ReturnedValue throwTypeError()
Heap::InternalClass * newInternalClass(const VTable *vtable, Object *prototype)
static Heap::FunctionObject * create(ExecutionContext *scope, Function *function)
ReturnedValue resume(ExecutionEngine *engine, const Value &arg) const
static ReturnedValue method_next(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_return(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_throw(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
void init(ExecutionEngine *engine)
static ReturnedValue createIterResultObject(ExecutionEngine *engine, const Value &value, bool done)
uint requiredJSStackFrameSize() const
V4_NEEDS_DESTROY Heap::ExecutionContext * scope() const
ExecutionEngine * engine() const
static Heap::FunctionObject * create(ExecutionContext *scope, Function *function, Object *homeObject, String *name)
void defineDefaultProperty(StringOrSymbol *name, const Value &value, PropertyAttributes attributes=Attr_Data|Attr_NotEnumerable)
bool setPrototypeOf(const Object *p)
static constexpr VTable::CallAsConstructor virtualCallAsConstructor
static constexpr VTable::Call virtualCall
static constexpr Value fromInt32(int i)
Definition qv4value_p.h:187
static constexpr Value undefinedValue()
Definition qv4value_p.h:191
const T * as() const
Definition qv4value_p.h:132
static constexpr Value emptyValue()
Definition qv4value_p.h:179