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