aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2018-08-06 14:19:35 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2018-08-14 17:45:33 +0000
commite9f41fdf19749dda82c8005515c9941b757750c5 (patch)
treef015b35d04be96283ce5a7157445458339502963
parentbae423474b51fd0651aaea7cb18071a2206109b1 (diff)
Implement initial support for import namespaces
The import via import * as foo from "./bar.js" allows accessing all exports via the special namespace object. This is conceptually quite similar to the existing import of .js files in QtQuick. Change-Id: Ia6d79342f0884a89dfe4dc07316570ca7789cac0 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/qml/compiler/qv4compileddata.cpp3
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp3
-rw-r--r--src/qml/jsruntime/qv4module.cpp118
-rw-r--r--src/qml/jsruntime/qv4module_p.h14
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations30
5 files changed, 134 insertions, 34 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 4e7674a67a..33e463c76a 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -469,6 +469,9 @@ const Value *CompilationUnit::resolveExportRecursively(QV4::String *exportName,
(*resolveSet) << ResolveSetEntry(this, exportName);
+ if (exportName->toQString() == QLatin1String("*"))
+ return &m_module->self;
+
Scope scope(engine);
if (auto localExport = lookupNameInExportTable(data->localExportEntryTable(), data->localExportEntryTableSize, exportName)) {
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 8f16f9a362..f47643826f 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -251,9 +251,6 @@ bool ScanFunctions::visit(ImportDeclaration *declaration)
entry.importName = QStringLiteral("*");
entry.localName = import->nameSpaceImport->importedBinding.toString();
_context->importEntries << entry;
-
- _cg->throwSyntaxError(import->nameSpaceImport->importedBindingToken, QStringLiteral("* imports are currently not supported."));
- return false;
}
if (import->namedImports) {
diff --git a/src/qml/jsruntime/qv4module.cpp b/src/qml/jsruntime/qv4module.cpp
index ed7df459b6..4a7d0c19c4 100644
--- a/src/qml/jsruntime/qv4module.cpp
+++ b/src/qml/jsruntime/qv4module.cpp
@@ -43,6 +43,7 @@
#include <private/qv4mm_p.h>
#include <private/qv4vme_moth_p.h>
#include <private/qv4context_p.h>
+#include <private/qv4symbol_p.h>
using namespace QV4;
@@ -55,6 +56,7 @@ void Heap::Module::init(ExecutionEngine *engine, CompiledData::CompilationUnit *
// This is a back pointer and there is no need to call addref() on the unit, because the unit
// owns this object instead.
unit = moduleUnit;
+ self.set(engine, this);
Function *moduleFunction = unit->runtimeFunctions[unit->unitData()->indexOfRootFunction];
@@ -66,4 +68,120 @@ void Heap::Module::init(ExecutionEngine *engine, CompiledData::CompilationUnit *
scope->locals.size = locals;
scope->locals.alloc = locals;
scope->nArgs = 0;
+
+ Scope valueScope(engine);
+ Scoped<QV4::Module> This(valueScope, this);
+ ScopedString name(valueScope, engine->newString(QStringLiteral("Module")));
+ This->insertMember(engine->symbol_toStringTag(), name, Attr_ReadOnly);
+ This->setPrototypeUnchecked(nullptr);
+}
+
+ReturnedValue Module::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
+{
+ if (id.isSymbol())
+ return Object::virtualGet(m, id, receiver, hasProperty);
+
+ const Module *module = static_cast<const Module *>(m);
+ Scope scope(m->engine());
+ ScopedString expectedName(scope, id.toStringOrSymbol(scope.engine));
+ const Value *v = module->d()->unit->resolveExport(expectedName);
+ if (hasProperty)
+ *hasProperty = v != nullptr;
+ if (!v)
+ return Encode::undefined();
+ return v->asReturnedValue();
+}
+
+PropertyAttributes Module::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p)
+{
+ if (id.isSymbol())
+ return Object::virtualGetOwnProperty(m, id, p);
+
+ const Module *module = static_cast<const Module *>(m);
+ Scope scope(m->engine());
+ ScopedString expectedName(scope, id.toStringOrSymbol(scope.engine));
+ const Value *v = module->d()->unit->resolveExport(expectedName);
+ if (!v) {
+ if (p)
+ p->value = Encode::undefined();
+ return Attr_Invalid;
+ }
+ if (p)
+ p->value = v->asReturnedValue();
+ return Attr_Data;
+}
+
+bool Module::virtualPreventExtensions(Managed *)
+{
+ return true;
+}
+
+bool Module::virtualDefineOwnProperty(Managed *, PropertyKey, const Property *, PropertyAttributes)
+{
+ return false;
+}
+
+bool Module::virtualPut(Managed *, PropertyKey, const Value &, Value *)
+{
+ return false;
+}
+
+bool Module::virtualDeleteProperty(Managed *m, PropertyKey id)
+{
+ if (id.isSymbol())
+ return Object::virtualDeleteProperty(m, id);
+ const Module *module = static_cast<const Module *>(m);
+ Scope scope(m->engine());
+ ScopedString expectedName(scope, id.toStringOrSymbol(scope.engine));
+ if (!expectedName)
+ return true;
+ const Value *v = module->d()->unit->resolveExport(expectedName);
+ if (v)
+ return false;
+ return true;
+}
+
+struct ModuleNamespaceIterator : ObjectOwnPropertyKeyIterator
+{
+ uint exportIndex = 0;
+ ~ModuleNamespaceIterator() override = default;
+ PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+
+};
+
+PropertyKey ModuleNamespaceIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
+{
+ const Module *module = static_cast<const Module *>(o);
+ if (exportIndex < module->d()->unit->unitData()->localExportEntryTableSize) {
+ if (attrs)
+ *attrs = Attr_Data;
+ if (pd) {
+ const CompiledData::ExportEntry &entry = module->d()->unit->unitData()->localExportEntryTable()[exportIndex];
+ Scope scope(module->engine());
+ ScopedString exportName(scope, module->d()->unit->runtimeStrings[entry.exportName]);
+ pd->value = *module->d()->unit->resolveExport(exportName);
+ }
+ exportIndex++;
+ }
+ return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
+}
+
+OwnPropertyKeyIterator *Module::virtualOwnPropertyKeys(const Object *)
+{
+ return new ModuleNamespaceIterator;
+}
+
+Heap::Object *Module::virtualGetPrototypeOf(const Managed *)
+{
+ return nullptr;
+}
+
+bool Module::virtualSetPrototypeOf(Managed *, const Object *proto)
+{
+ return proto == nullptr;
+}
+
+bool Module::virtualIsExtensible(const Managed *)
+{
+ return false;
}
diff --git a/src/qml/jsruntime/qv4module_p.h b/src/qml/jsruntime/qv4module_p.h
index 1958258ef0..c22e6cd1c3 100644
--- a/src/qml/jsruntime/qv4module_p.h
+++ b/src/qml/jsruntime/qv4module_p.h
@@ -61,7 +61,8 @@ namespace Heap {
#define ModuleMembers(class, Member) \
Member(class, NoMark, CompiledData::CompilationUnit *, unit) \
- Member(class, Pointer, CallContext *, scope)
+ Member(class, Pointer, CallContext *, scope) \
+ Member(class, HeapValue, HeapValue, self)
DECLARE_EXPORTED_HEAP_OBJECT(Module, Object) {
DECLARE_MARKOBJECTS(Module)
@@ -73,6 +74,17 @@ DECLARE_EXPORTED_HEAP_OBJECT(Module, Object) {
struct Q_QML_EXPORT Module : public Object {
V4_OBJECT2(Module, Object)
+
+ static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
+ static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
+ static bool virtualPreventExtensions(Managed *);
+ static bool virtualDefineOwnProperty(Managed *, PropertyKey, const Property *, PropertyAttributes);
+ static bool virtualPut(Managed *, PropertyKey, const Value &, Value *);
+ static bool virtualDeleteProperty(Managed *m, PropertyKey id);
+ static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *);
+ static Heap::Object *virtualGetPrototypeOf(const Managed *);
+ static bool virtualSetPrototypeOf(Managed *, const Object *proto);
+ static bool virtualIsExtensible(const Managed *);
};
}
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 7a4a585501..f9bcd62d3d 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -2160,9 +2160,7 @@ language/literals/regexp/y-assertion-start.js fails
language/module-code/eval-export-dflt-cls-anon.js strictFails
language/module-code/eval-gtbndng-indirect-update-as.js strictFails
language/module-code/eval-gtbndng-indirect-update-dflt.js strictFails
-language/module-code/eval-rqstd-once.js strictFails
language/module-code/eval-rqstd-order.js strictFails
-language/module-code/eval-self-once.js strictFails
language/module-code/instn-iee-bndng-cls.js strictFails
language/module-code/instn-iee-bndng-const.js strictFails
language/module-code/instn-iee-bndng-let.js strictFails
@@ -2187,52 +2185,24 @@ language/module-code/instn-named-bndng-dflt-star.js strictFails
language/module-code/instn-named-bndng-let.js strictFails
language/module-code/instn-named-id-name.js strictFails
language/module-code/instn-named-star-cycle.js strictFails
-language/module-code/instn-once.js strictFails
language/module-code/instn-same-global.js strictFails
language/module-code/instn-star-ambiguous.js strictFails
-language/module-code/instn-star-binding.js strictFails
language/module-code/instn-star-equality.js strictFails
-language/module-code/instn-star-id-name.js strictFails
-language/module-code/instn-star-iee-cycle.js strictFails
language/module-code/instn-star-props-circular.js strictFails
-language/module-code/instn-star-props-dflt-keep-indirect.js strictFails
-language/module-code/instn-star-props-dflt-keep-local.js strictFails
language/module-code/instn-star-props-dflt-skip.js strictFails
language/module-code/instn-star-props-nrml.js strictFails
language/module-code/instn-star-star-cycle.js strictFails
-language/module-code/namespace/Symbol.iterator.js strictFails
-language/module-code/namespace/Symbol.toStringTag.js strictFails
language/module-code/namespace/internals/define-own-property.js strictFails
-language/module-code/namespace/internals/delete-exported-init.js strictFails
language/module-code/namespace/internals/delete-exported-uninit.js strictFails
-language/module-code/namespace/internals/delete-non-exported.js strictFails
language/module-code/namespace/internals/enumerate-binding-uninit.js strictFails
language/module-code/namespace/internals/get-own-property-str-found-init.js strictFails
language/module-code/namespace/internals/get-own-property-str-found-uninit.js strictFails
-language/module-code/namespace/internals/get-own-property-str-not-found.js strictFails
-language/module-code/namespace/internals/get-own-property-sym.js strictFails
-language/module-code/namespace/internals/get-prototype-of.js strictFails
-language/module-code/namespace/internals/get-str-found-init.js strictFails
language/module-code/namespace/internals/get-str-found-uninit.js strictFails
-language/module-code/namespace/internals/get-str-initialize.js strictFails
-language/module-code/namespace/internals/get-str-not-found.js strictFails
-language/module-code/namespace/internals/get-str-update.js strictFails
-language/module-code/namespace/internals/get-sym-found.js strictFails
-language/module-code/namespace/internals/get-sym-not-found.js strictFails
-language/module-code/namespace/internals/has-property-str-found-init.js strictFails
-language/module-code/namespace/internals/has-property-str-found-uninit.js strictFails
-language/module-code/namespace/internals/has-property-str-not-found.js strictFails
-language/module-code/namespace/internals/has-property-sym-found.js strictFails
-language/module-code/namespace/internals/has-property-sym-not-found.js strictFails
-language/module-code/namespace/internals/is-extensible.js strictFails
language/module-code/namespace/internals/object-hasOwnProperty-binding-uninit.js strictFails
language/module-code/namespace/internals/object-keys-binding-uninit.js strictFails
language/module-code/namespace/internals/object-propertyIsEnumerable-binding-uninit.js strictFails
language/module-code/namespace/internals/own-property-keys-binding-types.js strictFails
language/module-code/namespace/internals/own-property-keys-sort.js strictFails
-language/module-code/namespace/internals/prevent-extensions.js strictFails
-language/module-code/namespace/internals/set-prototype-of-null.js strictFails
-language/module-code/namespace/internals/set-prototype-of.js strictFails
language/module-code/namespace/internals/set.js strictFails
language/statements/async-function/cptn-decl.js fails
language/statements/async-function/declaration-returns-promise.js fails