diff options
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 10 | ||||
-rw-r--r-- | src/qml/compiler/qqmlirbuilder_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 70 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 1 |
5 files changed, 80 insertions, 8 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 9021fd0284..2421e8c1ea 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1835,8 +1835,9 @@ JSCodeGen::JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator * , _scopeObject(nullptr) , _qmlContextSlot(-1) , _importedScriptsSlot(-1) - , m_globalNames(globalNames) { + m_globalNames = globalNames; + _module = jsModule; _fileNameIsUrl = true; } @@ -2306,15 +2307,10 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n return Reference::fromQmlContextObject(base, data->coreIndex(), data->notifyIndex(), capturePolicy); } } - - Reference r = Reference::fromName(this, name); - if (m_globalNames.contains(name)) - r.global = true; - return r; #else Q_UNUSED(name) - return Reference(); #endif // V4_BOOTSTRAP + return Reference(); } #ifndef V4_BOOTSTRAP diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index d1e2b17bb7..3dde929cc4 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -640,7 +640,6 @@ private: QQmlPropertyCache *_scopeObject; int _qmlContextSlot; int _importedScriptsSlot; - QSet<QString> m_globalNames; }; struct Q_QML_PRIVATE_EXPORT IRLoader { diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 54aef16970..21fb03c1a4 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -102,6 +102,62 @@ Codegen::Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict) jsUnitGenerator->codeGeneratorName = QStringLiteral("moth"); } +const char *globalNames[] = { + "isNaN", + "parseFloat", + "String", + "EvalError", + "URIError", + "Math", + "encodeURIComponent", + "RangeError", + "eval", + "isFinite", + "ReferenceError", + "Infinity", + "Function", + "RegExp", + "Number", + "parseInt", + "Object", + "decodeURI", + "TypeError", + "Boolean", + "encodeURI", + "NaN", + "Error", + "decodeURIComponent", + "Date", + "Array", + "Symbol", + "escape", + "unescape", + "SyntaxError", + "undefined", + "JSON", + "ArrayBuffer", + "SharedArrayBuffer", + "DataView", + "Int8Array", + "Uint8Array", + "Uint8ClampedArray", + "Int16Array", + "Uint16Array", + "Int32Array", + "Uint32Array", + "Float32Array", + "Float64Array", + "WeakSet", + "Set", + "WeakMap", + "Map", + "Reflect", + "Proxy", + "Atomics", + "Promise", + nullptr +}; + void Codegen::generateFromProgram(const QString &fileName, const QString &finalUrl, const QString &sourceCode, @@ -118,6 +174,18 @@ void Codegen::generateFromProgram(const QString &fileName, _module->fileName = fileName; _module->finalUrl = finalUrl; + if (contextType == ContextType::ScriptImportedByQML) { + // the global object is frozen, so we know that members of it are + // pointing to the global object. This is important so that references + // to Math etc. do not go through the expensive path in the context wrapper + // that tries to see whether we have a matching type + // + // Since this can be called from the loader thread we can't get the list + // directly from the engine, so let's hardcode the most important ones here + for (const char **g = globalNames; *g != nullptr; ++g) + m_globalNames << QString::fromLatin1(*g); + } + ScanFunctions scan(this, sourceCode, contextType); scan(node); @@ -2350,6 +2418,8 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs, co Reference r = Reference::fromName(this, name); r.global = useFastLookups && (resolved.type == Context::ResolvedName::Global); + if (!r.global && m_globalNames.contains(name)) + r.global = true; return r; } diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index e6e7d2e9fb..7630a1f71d 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -708,6 +708,11 @@ public: return *_returnLabel; } + void setGlobalNames(const QSet<QString>& globalNames) { + m_globalNames = globalNames; + } + + protected: friend class ScanFunctions; friend struct ControlFlow; @@ -730,6 +735,7 @@ protected: bool inFormalParameterList = false; bool functionEndsWithReturn = false; bool _tailCallsAreAllowed = true; + QSet<QString> m_globalNames; ControlFlow *controlFlow = nullptr; diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 951675b468..3d8c037910 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -241,6 +241,7 @@ Script *Script::createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlCo QmlIR::Document::removeScriptPragmas(sourceCode); auto result = new QV4::Script(engine, qmlContext, sourceCode, originalUrl.toString()); + result->contextType = QV4::Compiler::ContextType::ScriptImportedByQML; result->parse(); return result; } |