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
qv4module.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
4
5#include "qv4module_p.h"
6
7#include <private/qv4context_p.h>
8#include <private/qv4identifiertable_p.h>
9#include <private/qv4mm_p.h>
10#include <private/qv4stackframe_p.h>
11#include <private/qv4symbol_p.h>
12#include <private/qv4vme_moth_p.h>
13
14#include <QtCore/qscopeguard.h>
15
16using namespace QV4;
17
19
20void Heap::Module::init(ExecutionEngine *engine, ExecutableCompilationUnit *moduleUnit)
21{
22 Object::init();
23
24 // This is a back pointer and there is no need to call addref() on the unit, because the unit
25 // owns this object instead.
26 unit = moduleUnit;
27 self.set(engine, this);
28
29 Function *moduleFunction = unit->runtimeFunctions[unit->unitData()->indexOfRootFunction];
30
31 const uint locals = moduleFunction->compiledFunction->nLocals;
32 const size_t requiredMemory = sizeof(QV4::CallContext::Data) - sizeof(Value) + sizeof(Value) * locals;
33 scope.set(engine, engine->memoryManager->allocManaged<QV4::CallContext>(requiredMemory, moduleFunction->internalClass));
34 scope->init();
35 scope->outer.set(engine, engine->rootContext()->d());
36 scope->locals.size = locals;
37 scope->locals.alloc = locals;
38 scope->nArgs = 0;
39
40 // Prepare the temporal dead zone
41 scope->setupLocalTemporalDeadZone(moduleFunction->compiledFunction);
42
43 Scope valueScope(engine);
44
45 // It's possible for example to re-export an import, for example:
46 // import * as foo from "./bar.js"
47 // export { foo }
48 // Since we don't add imports to the locals, it won't be found typically.
49 // Except now we add imports at the end of the internal class in the index
50 // space past the locals, so that resolveExport can find it.
51 {
52 Scoped<QV4::InternalClass> ic(valueScope, scope->internalClass);
53
54 for (uint i = 0; i < unit->unitData()->importEntryTableSize; ++i) {
55 const CompiledData::ImportEntry &import = unit->unitData()->importEntryTable()[i];
56 ic = ic->addMember(engine->identifierTable->asPropertyKey(unit->runtimeStrings[import.localName]), Attr_NotConfigurable);
57 }
58 scope->internalClass.set(engine, ic->d());
59 }
60
61
62 Scoped<QV4::Module> This(valueScope, this);
63 ScopedString name(valueScope, engine->newString(QStringLiteral("Module")));
64 This->insertMember(engine->symbol_toStringTag(), name, Attr_ReadOnly);
65 This->setPrototypeUnchecked(nullptr);
66}
67
68void Module::evaluate()
69{
70 if (d()->evaluated)
71 return;
72 d()->evaluated = true;
73
74 ExecutableCompilationUnit *unit = d()->unit;
75
77
78 ExecutionEngine *v4 = engine();
79 Function *moduleFunction = unit->runtimeFunctions[unit->unitData()->indexOfRootFunction];
81 frame.init(moduleFunction, nullptr, 0);
82 frame.setupJSFrame(v4->jsStackTop, Value::undefinedValue(), d()->scope,
84
85 frame.push(v4);
86 v4->jsStackTop += frame.requiredJSStackFrameSize();
87 auto frameCleanup = qScopeGuard([&frame, v4]() {
88 frame.pop(v4);
89 });
91}
92
94{
95 if (d()->unit->isESModule()) {
96 if (!id.isString())
97 return nullptr;
98 Scope scope(engine());
99 ScopedString name(scope, id.asStringOrSymbol());
100 return d()->unit->resolveExport(name);
101 } else {
102 InternalClassEntry entry = d()->scope->internalClass->find(id);
103 if (entry.isValid())
104 return &d()->scope->locals[entry.index];
105 return nullptr;
106 }
107}
108
109ReturnedValue Module::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
110{
111 if (id.isSymbol())
112 return Object::virtualGet(m, id, receiver, hasProperty);
113
114 const Module *module = static_cast<const Module *>(m);
115 const Value *v = module->resolveExport(id);
116 if (hasProperty)
117 *hasProperty = v != nullptr;
118 if (!v)
119 return Encode::undefined();
120 if (v->isEmpty()) {
121 Scope scope(m->engine());
122 ScopedValue propName(scope, id.toStringOrSymbol(scope.engine));
123 return scope.engine->throwReferenceError(propName);
124 }
125 return v->asReturnedValue();
126}
127
129{
130 if (id.isSymbol())
131 return Object::virtualGetOwnProperty(m, id, p);
132
133 const Module *module = static_cast<const Module *>(m);
134 const Value *v = module->resolveExport(id);
135 if (!v) {
136 if (p)
138 return Attr_Invalid;
139 }
140 if (p)
141 p->value = v->isEmpty() ? Encode::undefined() : v->asReturnedValue();
142 if (v->isEmpty()) {
143 Scope scope(m->engine());
144 ScopedValue propName(scope, id.toStringOrSymbol(scope.engine));
145 scope.engine->throwReferenceError(propName);
146 }
148}
149
151{
152 if (id.isSymbol())
153 return Object::virtualHasProperty(m, id);
154
155 const Module *module = static_cast<const Module *>(m);
156 const Value *v = module->resolveExport(id);
157 return v != nullptr;
158}
159
161{
162 return true;
163}
164
169
171{
172 return false;
173}
174
176{
177 if (id.isSymbol())
179 const Module *module = static_cast<const Module *>(m);
180 const Value *v = module->resolveExport(id);
181 if (v)
182 return false;
183 return true;
184}
185
187{
189 int exportIndex = 0;
190 ModuleNamespaceIterator(const QStringList &names) : exportedNames(names) {}
191 ~ModuleNamespaceIterator() override = default;
192 PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
193
194};
195
197{
198 const Module *module = static_cast<const Module *>(o);
199 if (exportIndex < exportedNames.size()) {
200 if (attrs)
201 *attrs = Attr_Data;
202 Scope scope(module->engine());
203 ScopedString exportName(scope, scope.engine->newString(exportedNames.at(exportIndex)));
204 exportIndex++;
205 const Value *v = module->resolveExport(exportName->toPropertyKey());
206 if (pd) {
207 if (v->isEmpty())
208 scope.engine->throwReferenceError(exportName);
209 else
210 pd->value = *v;
211 }
212 return exportName->toPropertyKey();
213 }
215}
216
218{
219 const Module *module = static_cast<const Module *>(o);
220 *target = *o;
221
223 if (module->d()->unit->isESModule()) {
224 names = module->d()->unit->exportedNames();
225 } else {
226 QV4::Scope scope(module->engine());
227 QV4::Scoped<InternalClass> scopeClass(scope, module->d()->scope->internalClass);
228 for (uint i = 0, end = scopeClass->d()->size; i < end; ++i) {
229 QV4::ScopedValue key(scope, scopeClass->d()->keyAt(i));
230 names << key->toQString();
231 }
232 }
233
234 return new ModuleNamespaceIterator(names);
235}
236
238{
239 return nullptr;
240}
241
243{
244 return proto == nullptr;
245}
246
248{
249 return false;
250}
\inmodule QtCore
const CompiledData::Unit * unitData() const
static void exec(MetaTypesStackFrame *frame, ExecutionEngine *engine)
short next
Definition keywords.cpp:445
quint64 ReturnedValue
Scoped< String > ScopedString
@ Attr_Invalid
@ Attr_NotConfigurable
@ Attr_Data
@ Attr_ReadOnly
static struct AttrInfo attrs[]
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLuint64 key
GLuint GLuint end
GLenum target
GLuint name
GLuint GLuint * names
GLuint entry
GLfloat GLfloat p
[1]
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
#define QStringLiteral(str)
unsigned int uint
Definition qtypes.h:34
#define DEFINE_OBJECT_VTABLE(classname)
QFrame frame
[0]
QJSEngine engine
[0]
~ModuleNamespaceIterator() override=default
PropertyKey next(const Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
ModuleNamespaceIterator(const QStringList &names)
static constexpr ReturnedValue undefined()
ReturnedValue throwReferenceError(const Value &value)
Heap::String * newString(char16_t c)
ExecutionEngine * engine() const
const Value * resolveExport(PropertyKey key) const
Definition qv4module.cpp:93
PropertyKey next(const Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
bool hasProperty(PropertyKey id) const
ExecutionEngine * engine
QV4_NEARLY_ALWAYS_INLINE constexpr quint32 value() const
static constexpr VTable::SetPrototypeOf virtualSetPrototypeOf
static constexpr VTable::DefineOwnProperty virtualDefineOwnProperty
static constexpr VTable::OwnPropertyKeys virtualOwnPropertyKeys
static constexpr VTable::GetOwnProperty virtualGetOwnProperty
static constexpr VTable::PreventExtensions virtualPreventExtensions
static constexpr VTable::GetPrototypeOf virtualGetPrototypeOf
static constexpr VTable::DeleteProperty virtualDeleteProperty
static constexpr VTable::Get virtualGet
static constexpr VTable::HasProperty virtualHasProperty
static constexpr VTable::Put virtualPut
static constexpr VTable::IsExtensible virtualIsExtensible
bool isString() const
Definition qv4value_p.h:284
static constexpr Value undefinedValue()
Definition qv4value_p.h:191
bool isSymbol() const
Definition qv4value_p.h:296