aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp8
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h4
-rw-r--r--src/qml/compiler/qv4codegen.cpp31
-rw-r--r--src/qml/compiler/qv4compilationunitmapper_win.cpp8
-rw-r--r--src/qml/compiler/qv4compileddata.cpp7
-rw-r--r--src/qml/compiler/qv4compileddata_p.h2
-rw-r--r--src/qml/compiler/qv4ssa.cpp2
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h2
-rw-r--r--src/qml/doc/src/examples.qdoc36
-rw-r--r--src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc8
-rw-r--r--src/qml/doc/src/qmltypereference.qdoc4
-rw-r--r--src/qml/jit/qv4assembler.cpp182
-rw-r--r--src/qml/jit/qv4assembler_p.h4
-rw-r--r--src/qml/jit/qv4binop.cpp86
-rw-r--r--src/qml/jit/qv4binop_p.h98
-rw-r--r--src/qml/jit/qv4isel_masm.cpp178
-rw-r--r--src/qml/jit/qv4regalloc.cpp14
-rw-r--r--src/qml/jsapi/qjsvalue.cpp3
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp10
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp69
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h8
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp10
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp675
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h48
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp26
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4context.cpp34
-rw-r--r--src/qml/jsruntime/qv4context_p.h24
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp133
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h18
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp475
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h102
-rw-r--r--src/qml/jsruntime/qv4engine.cpp2
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp25
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp134
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h32
-rw-r--r--src/qml/jsruntime/qv4global_p.h9
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp146
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h20
-rw-r--r--src/qml/jsruntime/qv4include.cpp19
-rw-r--r--src/qml/jsruntime/qv4include_p.h2
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp32
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h2
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp23
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp186
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h38
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp7
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp160
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h16
-rw-r--r--src/qml/jsruntime/qv4object.cpp53
-rw-r--r--src/qml/jsruntime/qv4object_p.h14
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp412
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h52
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp65
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h4
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp97
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h18
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp1
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h32
-rw-r--r--src/qml/jsruntime/qv4script.cpp2
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp64
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h6
-rw-r--r--src/qml/jsruntime/qv4string.cpp12
-rw-r--r--src/qml/jsruntime/qv4string_p.h6
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp395
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h46
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp101
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h12
-rw-r--r--src/qml/jsruntime/qv4value_p.h2
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp47
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h8
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp4
-rw-r--r--src/qml/memory/memory.pri4
-rw-r--r--src/qml/memory/qv4heap_p.h43
-rw-r--r--src/qml/memory/qv4mm.cpp938
-rw-r--r--src/qml/memory/qv4mm_p.h212
-rw-r--r--src/qml/memory/qv4mmdefs_p.h262
-rw-r--r--src/qml/qml.pro2
-rw-r--r--src/qml/qml/qqmlabstractbinding.cpp2
-rw-r--r--src/qml/qml/qqmlabstracturlinterceptor.h1
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp15
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp9
-rw-r--r--src/qml/qml/qqmlcomponent.cpp74
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp2
-rw-r--r--src/qml/qml/qqmldelayedcallqueue.cpp10
-rw-r--r--src/qml/qml/qqmldelayedcallqueue_p.h2
-rw-r--r--src/qml/qml/qqmldirparser.cpp9
-rw-r--r--src/qml/qml/qqmlengine.cpp31
-rw-r--r--src/qml/qml/qqmlerror.cpp72
-rw-r--r--src/qml/qml/qqmlerror.h3
-rw-r--r--src/qml/qml/qqmlextensionplugin.cpp10
-rw-r--r--src/qml/qml/qqmlimport.cpp168
-rw-r--r--src/qml/qml/qqmlincubator.cpp17
-rw-r--r--src/qml/qml/qqmlincubator_p.h5
-rw-r--r--src/qml/qml/qqmlinfo.cpp127
-rw-r--r--src/qml/qml/qqmlinfo.h16
-rw-r--r--src/qml/qml/qqmllist.cpp5
-rw-r--r--src/qml/qml/qqmllocale.cpp485
-rw-r--r--src/qml/qml/qqmllocale_p.h82
-rw-r--r--src/qml/qml/qqmlloggingcategory.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp32
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h1
-rw-r--r--src/qml/qml/qqmlplatform.cpp4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp100
-rw-r--r--src/qml/qml/qqmltypeloader_p.h10
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp12
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlvme.cpp12
-rw-r--r--src/qml/qml/qqmlvme_p.h1
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp9
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp496
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp865
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h118
-rw-r--r--src/qml/qml/v8/qv4domerrors_p.h5
-rw-r--r--src/qml/types/qqmlbind.cpp4
-rw-r--r--src/qml/types/qqmlconnections.cpp6
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp147
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h6
-rw-r--r--src/qml/types/qqmllistmodel.cpp50
-rw-r--r--src/qml/types/qqmlobjectmodel.cpp6
-rw-r--r--src/qml/types/qquickworkerscript.cpp13
124 files changed, 5034 insertions, 4104 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index ab2b0553a9..85267225be 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -57,12 +57,12 @@
QT_BEGIN_NAMESPACE
QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData,
- QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &importCache,
+ QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
: resolvedTypes(resolvedTypeCache)
, engine(engine)
, typeData(typeData)
- , importCache(importCache)
+ , typeNameCache(typeNameCache)
, document(parsedQML)
{
}
@@ -138,7 +138,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
sss.scan();
}
- QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, importCache, &document->jsGenerator.stringTable);
+ QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable);
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
if (!jsCodeGen.generateCodeForComponents())
return nullptr;
@@ -164,7 +164,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
QV4::CompiledData::CompilationUnit *compilationUnit = document->javaScriptCompilationUnit;
compilationUnit = document->javaScriptCompilationUnit;
- compilationUnit->importCache = importCache;
+ compilationUnit->typeNameCache = typeNameCache;
compilationUnit->resolvedTypes = resolvedTypes;
compilationUnit->propertyCaches = std::move(m_propertyCaches);
Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast<int>(compilationUnit->data->nObjects));
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index de6abb4ced..2b59e7e42f 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -89,7 +89,7 @@ struct QQmlTypeCompiler
{
Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler)
public:
- QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer<QQmlTypeNameCache> &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
+ QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
// --- interface used by QQmlPropertyCacheCreator
typedef QmlIR::Object CompiledObject;
@@ -139,7 +139,7 @@ private:
QList<QQmlError> errors;
QQmlEnginePrivate *engine;
QQmlTypeData *typeData;
- QQmlRefPointer<QQmlTypeNameCache> importCache;
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
QmlIR::Document *document;
// index is string index of type name (use obj->inheritedTypeNameIndex)
QHash<int, QQmlCustomParser*> customParsers;
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index e0def1021b..7d3ad38f97 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -526,21 +526,21 @@ IR::Expr *Codegen::subscript(IR::Expr *base, IR::Expr *index)
if (hasError)
return 0;
- if (! base->asTemp() || base->asArgLocal()) {
+ if (! base->asTemp() && !base->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), base);
base = _block->TEMP(t);
}
- if (! index->asTemp() || index->asArgLocal()) {
+ if (! index->asTemp() && !index->asArgLocal() && !index->asConst()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), index);
index = _block->TEMP(t);
}
Q_ASSERT(base->asTemp() || base->asArgLocal());
- Q_ASSERT(index->asTemp() || index->asArgLocal());
- return _block->SUBSCRIPT(base->asTemp(), index->asTemp());
+ Q_ASSERT(index->asTemp() || index->asArgLocal() || index->asConst());
+ return _block->SUBSCRIPT(base, index);
}
IR::Expr *Codegen::argument(IR::Expr *expr)
@@ -611,7 +611,7 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right, const AS
if (IR::Const *c1 = left->asConst()) {
if (IR::Const *c2 = right->asConst()) {
- if (c1->type == IR::NumberType && c2->type == IR::NumberType) {
+ if ((c1->type & IR::NumberType) && (c2->type & IR::NumberType)) {
switch (op) {
case IR::OpAdd: return _block->CONST(IR::NumberType, c1->value + c2->value);
case IR::OpAnd: return _block->CONST(IR::BoolType, c1->value ? c2->value : 0);
@@ -659,20 +659,20 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right, const AS
}
}
- if (!left->asTemp() && !left->asArgLocal()) {
+ if (!left->asTemp() && !left->asArgLocal() && !left->asConst()) {
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), left), loc);
left = _block->TEMP(t);
}
- if (!right->asTemp() && !right->asArgLocal()) {
+ if (!right->asTemp() && !right->asArgLocal() && !right->asConst()) {
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), right), loc);
right = _block->TEMP(t);
}
- Q_ASSERT(left->asTemp() || left->asArgLocal());
- Q_ASSERT(right->asTemp() || right->asArgLocal());
+ Q_ASSERT(left->asTemp() || left->asArgLocal() || left->asConst());
+ Q_ASSERT(right->asTemp() || right->asArgLocal() || right->asConst());
return _block->BINOP(op, left, right);
}
@@ -842,9 +842,16 @@ void Codegen::variableDeclaration(VariableDeclaration *ast)
Q_ASSERT(expr.code);
initializer = *expr;
- int initialized = _block->newTemp();
- move(_block->TEMP(initialized), initializer);
- move(identifier(ast->name.toString(), ast->identifierToken.startLine, ast->identifierToken.startColumn), _block->TEMP(initialized));
+ IR::Expr *lhs = identifier(ast->name.toString(), ast->identifierToken.startLine,
+ ast->identifierToken.startColumn);
+
+ if (lhs->asArgLocal()) {
+ move(lhs, initializer);
+ } else {
+ int initialized = _block->newTemp();
+ move(_block->TEMP(initialized), initializer);
+ move(lhs, _block->TEMP(initialized));
+ }
}
void Codegen::variableDeclarationList(VariableDeclarationList *ast)
diff --git a/src/qml/compiler/qv4compilationunitmapper_win.cpp b/src/qml/compiler/qv4compilationunitmapper_win.cpp
index 457b702ac3..37cac846a0 100644
--- a/src/qml/compiler/qv4compilationunitmapper_win.cpp
+++ b/src/qml/compiler/qv4compilationunitmapper_win.cpp
@@ -75,7 +75,6 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
CloseHandle(handle);
});
-#if !defined(Q_OS_WINRT) || _MSC_VER >= 1900
CompiledData::Unit header;
DWORD bytesRead;
if (!ReadFile(handle, reinterpret_cast<char *>(&header), sizeof(header), &bytesRead, nullptr)) {
@@ -115,19 +114,12 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
}
return reinterpret_cast<CompiledData::Unit*>(dataPtr);
-#else
- Q_UNUSED(sourcePath);
- *errorString = QStringLiteral("Compilation unit mapping not supported on WinRT 8.1");
- return nullptr;
-#endif
}
void CompilationUnitMapper::close()
{
-#if !defined(Q_OS_WINRT) || _MSC_VER >= 1900
if (dataPtr != nullptr)
UnmapViewOfFile(dataPtr);
-#endif
dataPtr = nullptr;
}
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 8586c84c3d..25b090f555 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -207,7 +207,7 @@ void CompilationUnit::unlink()
dependentScripts.at(ii)->release();
dependentScripts.clear();
- importCache = nullptr;
+ typeNameCache = nullptr;
qDeleteAll(resolvedTypes);
resolvedTypes.clear();
@@ -407,6 +407,11 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory
const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr;
QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit);
+ if (sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
+ *errorString = QStringLiteral("QML source file has moved to a different location.");
+ return false;
+ }
+
{
const QString foundArchitecture = stringAt(data->architectureIndex);
const QString expectedArchitecture = QSysInfo::buildAbi();
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 2682365182..97623b4d86 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -855,7 +855,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
QQmlPropertyCacheVector propertyCaches;
QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(data->indexOfRootObject); }
- QQmlRefPointer<QQmlTypeNameCache> importCache;
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
// index is object index. This allows fast access to the
// property data when initializing bindings, avoiding expensive
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 943700de44..1d512711b8 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -2758,7 +2758,7 @@ public:
visit(s);
}
- foreach (const Conversion &conversion, _conversions) {
+ for (const Conversion &conversion : qAsConst(_conversions)) {
IR::Move *move = conversion.stmt->asMove();
// Note: isel only supports move into member when source is a temp, so convert
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 3a507bef74..41fb2c5b7b 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -73,7 +73,7 @@ struct QQmlProfiler {};
struct QQmlBindingProfiler
{
- QQmlBindingProfiler(quintptr, QQmlBinding *, QV4::FunctionObject *) {}
+ QQmlBindingProfiler(quintptr, QV4::Function *) {}
};
struct QQmlHandlingSignalProfiler
diff --git a/src/qml/doc/src/examples.qdoc b/src/qml/doc/src/examples.qdoc
index f3550ae199..4f12d42f48 100644
--- a/src/qml/doc/src/examples.qdoc
+++ b/src/qml/doc/src/examples.qdoc
@@ -32,4 +32,40 @@
The list of examples demonstrating how to extend C++ to QML or the other way
around.
+
+\noautolist
+
+\table
+ \row
+ \li \l {Extending QML - Adding Types Example}
+ \li Exporting C++ Classes
+ \row
+ \li \l {Extending QML - Object and List Property Types Example}
+ \li Exporting C++ Properties
+ \row
+ \li \l {Extending QML - Extension Objects Example}
+ \li Extension Objects
+ \row
+ \li \l {Extending QML - Inheritance and Coercion Example}
+ \li C++ Inheritance and Coercion
+ \row
+ \li \l {Extending QML - Methods Example}
+ \li Methods Support
+ \row
+ \li \l {Extending QML - Attached Properties Example}
+ \li Attached Properties
+ \row
+ \li \l {Extending QML - Signal Support Example}
+ \li Signal Support
+ \row
+ \li \l {Extending QML - Property Value Source Example}
+ \li Property Value Source
+ \row
+ \li \l {Extending QML - Default Property Example}
+ \li Default Property
+ \row
+ \li \l {Extending QML - Grouped Properties Example}
+ \li Grouped Properties
+\endtable
+
*/
diff --git a/src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc b/src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc
index 7fa271c2d9..5cfd80f8a0 100644
--- a/src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc
+++ b/src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc
@@ -48,12 +48,8 @@ Image {
}
\endqml
-Network transparency is supported throughout QML, for example:
-
-\list
-\li Fonts - the \c source property of FontLoader is a URL
-\li WebViews - the \c url property of WebView (obviously!)
-\endlist
+Network transparency is supported throughout QML, for example, both the FontLoader
+and Image elements support loading resources from a remote server.
Even QML types themselves can be on the network - if the \l {Prototyping with qmlscene} is used to load
\tt http://example.com/mystuff/Hello.qml and that content refers to a type "World", the engine
diff --git a/src/qml/doc/src/qmltypereference.qdoc b/src/qml/doc/src/qmltypereference.qdoc
index f32574fcc1..b2bb9ebd18 100644
--- a/src/qml/doc/src/qmltypereference.qdoc
+++ b/src/qml/doc/src/qmltypereference.qdoc
@@ -89,7 +89,7 @@ provided:
\ingroup qtquickbasictypes
\brief a date value.
-The \c date type refers to a date value.
+The \c date type refers to a date value, including the time of the day.
To create a \c date value, specify it as a "YYYY-MM-DD" string:
@@ -100,7 +100,7 @@ MyDatePicker { minDate: "2000-01-01"; maxDate: "2020-12-31" }
To read a date value returned from a C++ extension class, use
\l{QtQml::Qt::formatDate()}{Qt.formatDate()} and \l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}.
-When integrating with C++, note that any QDate value
+When integrating with C++, note that any QDate or QDateTime value
\l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically
converted into a \c date value, and vice-versa.
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index e1acc33f82..018396318e 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -52,6 +52,8 @@
#include <WTFStubs.h>
#include <iostream>
+#include <QBuffer>
+#include <QCoreApplication>
#if ENABLE(ASSEMBLER)
@@ -146,11 +148,11 @@ bool CompilationUnit::memoryMapCode(QString *errorString)
const Assembler::VoidType Assembler::Void;
-Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator)
+Assembler::Assembler(QV4::Compiler::JSUnitGenerator *jsGenerator, IR::Function* function, QV4::ExecutableAllocator *executableAllocator)
: _function(function)
, _nextBlock(0)
, _executableAllocator(executableAllocator)
- , _isel(isel)
+ , _jsGenerator(jsGenerator)
{
_addrs.resize(_function->basicBlockCount());
_patches.resize(_function->basicBlockCount());
@@ -301,7 +303,7 @@ Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &s
loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::Heap::ExecutionContext, compilationUnit)), Assembler::ScratchRegister);
loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg);
- const int id = _isel->registerString(string);
+ const int id = _jsGenerator->registerString(string);
return Pointer(reg, id * sizeof(QV4::String*));
}
@@ -314,13 +316,13 @@ Assembler::Address Assembler::loadConstant(const Primitive &v, RegisterID baseRe
{
loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), baseReg);
loadPtr(Address(baseReg, qOffsetOf(QV4::Heap::ExecutionContext, constantTable)), baseReg);
- const int index = _isel->jsUnitGenerator()->registerConstant(v.asReturnedValue());
+ const int index = _jsGenerator->registerConstant(v.asReturnedValue());
return Address(baseReg, index * sizeof(QV4::Value));
}
void Assembler::loadStringRef(RegisterID reg, const QString &string)
{
- const int id = _isel->registerString(string);
+ const int id = _jsGenerator->registerString(string);
move(TrustedImm32(id), reg);
}
@@ -496,4 +498,174 @@ void Assembler::setStackLayout(int maxArgCountForBuiltins, int regularRegistersT
_stackLayout.reset(new StackLayout(_function, maxArgCountForBuiltins, regularRegistersToSave, fpRegistersToSave));
}
+
+namespace {
+class QIODevicePrintStream: public FilePrintStream
+{
+ Q_DISABLE_COPY(QIODevicePrintStream)
+
+public:
+ explicit QIODevicePrintStream(QIODevice *dest)
+ : FilePrintStream(0)
+ , dest(dest)
+ , buf(4096, '0')
+ {
+ Q_ASSERT(dest);
+ }
+
+ ~QIODevicePrintStream()
+ {}
+
+ void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0)
+ {
+ const int written = qvsnprintf(buf.data(), buf.size(), format, argList);
+ if (written > 0)
+ dest->write(buf.constData(), written);
+ memset(buf.data(), 0, qMin(written, buf.size()));
+ }
+
+ void flush()
+ {}
+
+private:
+ QIODevice *dest;
+ QByteArray buf;
+};
+} // anonymous namespace
+
+static void printDisassembledOutputWithCalls(QByteArray processedOutput, const QHash<void*, const char*>& functions)
+{
+ for (QHash<void*, const char*>::ConstIterator it = functions.begin(), end = functions.end();
+ it != end; ++it) {
+ const QByteArray ptrString = "0x" + QByteArray::number(quintptr(it.key()), 16);
+ int idx = processedOutput.indexOf(ptrString);
+ if (idx < 0)
+ continue;
+ idx = processedOutput.lastIndexOf('\n', idx);
+ if (idx < 0)
+ continue;
+ processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; call ") + it.value());
+ }
+
+ qDebug("%s", processedOutput.constData());
+}
+
+#if defined(Q_OS_LINUX)
+static FILE *pmap;
+
+static void qt_closePmap()
+{
+ if (pmap) {
+ fclose(pmap);
+ pmap = 0;
+ }
+}
+
+#endif
+
+JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
+{
+ Label endOfCode = label();
+
+ {
+ for (size_t i = 0, ei = _patches.size(); i != ei; ++i) {
+ Label target = _addrs.at(i);
+ Q_ASSERT(target.isSet());
+ for (Jump jump : qAsConst(_patches.at(i)))
+ jump.linkTo(target, this);
+ }
+ }
+
+ JSC::JSGlobalData dummy(_executableAllocator);
+ JSC::LinkBuffer linkBuffer(dummy, this, 0);
+
+ for (const DataLabelPatch &p : qAsConst(_dataLabelPatches))
+ linkBuffer.patch(p.dataLabel, linkBuffer.locationOf(p.target));
+
+ // link exception handlers
+ for (Jump jump : qAsConst(exceptionPropagationJumps))
+ linkBuffer.link(jump, linkBuffer.locationOf(exceptionReturnLabel));
+
+ {
+ for (size_t i = 0, ei = _labelPatches.size(); i != ei; ++i) {
+ Label target = _addrs.at(i);
+ Q_ASSERT(target.isSet());
+ for (DataLabelPtr label : _labelPatches.at(i))
+ linkBuffer.patch(label, linkBuffer.locationOf(target));
+ }
+ }
+
+ *codeSize = linkBuffer.offsetOf(endOfCode);
+
+ QByteArray name;
+
+ JSC::MacroAssemblerCodeRef codeRef;
+
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM");
+ if (showCode) {
+ QHash<void*, const char*> functions;
+#ifndef QT_NO_DEBUG
+ for (CallInfo call : qAsConst(_callInfos))
+ functions[linkBuffer.locationOf(call.label).dataLocation()] = call.functionName;
+#endif
+
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ WTF::setDataFile(new QIODevicePrintStream(&buf));
+
+ name = _function->name->toUtf8();
+ if (name.isEmpty())
+ name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')';
+ codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data());
+
+ WTF::setDataFile(stderr);
+ printDisassembledOutputWithCalls(buf.data(), functions);
+ } else {
+ codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
+ }
+
+#if defined(Q_OS_LINUX)
+ // This implements writing of JIT'd addresses so that perf can find the
+ // symbol names.
+ //
+ // Perf expects the mapping to be in a certain place and have certain
+ // content, for more information, see:
+ // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt
+ static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP");
+ static bool profileInitialized = false;
+ if (doProfile && !profileInitialized) {
+ profileInitialized = true;
+
+ char pname[PATH_MAX];
+ snprintf(pname, PATH_MAX - 1, "/tmp/perf-%lu.map",
+ (unsigned long)QCoreApplication::applicationPid());
+
+ pmap = fopen(pname, "w");
+ if (!pmap)
+ qWarning("QV4: Can't write %s, call stacks will not contain JavaScript function names", pname);
+
+ // make sure we clean up nicely
+ std::atexit(qt_closePmap);
+ }
+
+ if (pmap) {
+ // this may have been pre-populated, if QV4_SHOW_ASM was on
+ if (name.isEmpty()) {
+ name = _function->name->toUtf8();
+ if (name.isEmpty())
+ name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')';
+ }
+
+ fprintf(pmap, "%llx %x %.*s\n",
+ (long long unsigned int)codeRef.code().executableAddress(),
+ *codeSize,
+ name.length(),
+ name.constData());
+ fflush(pmap);
+ }
+#endif
+
+ return codeRef;
+}
+
#endif
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 94478cd9cd..de9c246ed6 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -111,7 +111,7 @@ class Assembler : public JSC::MacroAssembler, public TargetPlatform
Q_DISABLE_COPY(Assembler)
public:
- Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator);
+ Assembler(QV4::Compiler::JSUnitGenerator *jsGenerator, IR::Function* function, QV4::ExecutableAllocator *executableAllocator);
// Explicit type to allow distinguishing between
// pushing an address itself or the value it points
@@ -1092,7 +1092,7 @@ private:
IR::BasicBlock *_nextBlock;
QV4::ExecutableAllocator *_executableAllocator;
- InstructionSelection *_isel;
+ QV4::Compiler::JSUnitGenerator *_jsGenerator;
};
template <typename Result, typename Source>
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index 9c535bb0bb..d2758c4a47 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -112,7 +112,7 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
return;
}
- Assembler::Jump done;
+ Jump done;
if (lhs->type != IR::StringType && rhs->type != IR::StringType)
done = genInlineBinop(lhs, rhs, target);
@@ -129,13 +129,13 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
RuntimeCall context(info.contextImplementation);
if (fallBack.isValid()) {
as->generateFunctionCallImp(info.needsExceptionCheck, target, info.name, fallBack,
- Assembler::PointerToValue(lhs),
- Assembler::PointerToValue(rhs));
+ PointerToValue(lhs),
+ PointerToValue(rhs));
} else if (context.isValid()) {
as->generateFunctionCallImp(info.needsExceptionCheck, target, info.name, context,
Assembler::EngineRegister,
- Assembler::PointerToValue(lhs),
- Assembler::PointerToValue(rhs));
+ PointerToValue(lhs),
+ PointerToValue(rhs));
} else {
Q_ASSERT(!"unreachable");
}
@@ -148,9 +148,9 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
{
IR::Temp *targetTemp = target->asTemp();
- Assembler::FPRegisterID targetReg;
+ FPRegisterID targetReg;
if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
- targetReg = (Assembler::FPRegisterID) targetTemp->index;
+ targetReg = (FPRegisterID) targetTemp->index;
else
targetReg = Assembler::FPGpr0;
@@ -162,7 +162,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X + constant -> Y = X; Y += [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
- Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
+ Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->addDouble(addr, targetReg);
break;
}
@@ -184,7 +184,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X * constant -> Y = X; Y *= [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
- Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
+ Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->mulDouble(addr, targetReg);
break;
}
@@ -203,7 +203,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X - constant -> Y = X; Y -= [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
- Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
+ Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->subDouble(addr, targetReg);
break;
}
@@ -231,7 +231,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X / constant -> Y = X; Y /= [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
- Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
+ Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->divDouble(addr, targetReg);
break;
}
@@ -258,9 +258,9 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
default: {
Q_ASSERT(target->type == IR::BoolType);
- Assembler::Jump trueCase = as->branchDouble(false, op, lhs, rhs);
+ Jump trueCase = as->branchDouble(false, op, lhs, rhs);
as->storeBool(false, target);
- Assembler::Jump done = as->jump();
+ Jump done = as->jump();
trueCase.link(as);
as->storeBool(true, target);
done.link(as);
@@ -305,13 +305,13 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
bool inplaceOpWithAddress = false;
IR::Temp *targetTemp = target->asTemp();
- Assembler::RegisterID targetReg = Assembler::ReturnValueRegister;
+ RegisterID targetReg = Assembler::ReturnValueRegister;
if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
IR::Temp *rhs = rightSource->asTemp();
if (!rhs || rhs->kind != IR::Temp::PhysicalRegister || rhs->index != targetTemp->index) {
// We try to load leftSource into the target's register, but we can't do that if
// the target register is the same as rightSource.
- targetReg = (Assembler::RegisterID) targetTemp->index;
+ targetReg = (RegisterID) targetTemp->index;
} else if (rhs && rhs->kind == IR::Temp::PhysicalRegister && targetTemp->index == rhs->index) {
// However, if the target register is the same as the rightSource register, we can flip
// the operands for certain operations.
@@ -323,7 +323,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
case IR::OpMul:
// X = Y op X -> X = X op Y (or rephrased: X op= Y (so an in-place operation))
std::swap(leftSource, rightSource);
- targetReg = (Assembler::RegisterID) targetTemp->index;
+ targetReg = (RegisterID) targetTemp->index;
break;
case IR::OpLShift:
@@ -368,7 +368,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
&& targetTemp->kind == IR::Temp::PhysicalRegister
&& targetTemp->index == rightSource->asTemp()->index) {
// X = Y - X -> Tmp = X; X = Y; X -= Tmp
- targetReg = (Assembler::RegisterID) targetTemp->index;
+ targetReg = (RegisterID) targetTemp->index;
as->move(targetReg, Assembler::ScratchRegister);
as->move(as->toInt32Register(leftSource, targetReg), targetReg);
as->sub32(Assembler::ScratchRegister, targetReg);
@@ -384,7 +384,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
case IR::OpURShift:
if (IR::Const *c = rightSource->asConst()) {
if ((QV4::Primitive::toUInt32(c->value) & 0x1f) == 0) {
- Assembler::RegisterID r = as->toInt32Register(leftSource, targetReg);
+ RegisterID r = as->toInt32Register(leftSource, targetReg);
as->storeInt32(r, target);
return true;
}
@@ -395,10 +395,10 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
break;
}
- Assembler::RegisterID l = as->toInt32Register(leftSource, targetReg);
+ RegisterID l = as->toInt32Register(leftSource, targetReg);
if (IR::Const *c = rightSource->asConst()) { // All cases of Y = X op Const
- Assembler::TrustedImm32 r(int(c->value));
- Assembler::TrustedImm32 ur(QV4::Primitive::toUInt32(c->value) & 0x1f);
+ TrustedImm32 r(int(c->value));
+ TrustedImm32 ur(QV4::Primitive::toUInt32(c->value) & 0x1f);
switch (op) {
case IR::OpBitAnd: as->and32(r, l, targetReg); break;
@@ -419,7 +419,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
return false;
}
} else if (inplaceOpWithAddress) { // All cases of X = X op [address-of-Y]
- Assembler::Pointer rhsAddr = as->loadAddress(Assembler::ScratchRegister, rightSource);
+ Pointer rhsAddr = as->loadAddress(Assembler::ScratchRegister, rightSource);
switch (op) {
case IR::OpBitAnd: as->and32(rhsAddr, targetReg); break;
case IR::OpBitOr: as->or32 (rhsAddr, targetReg); break;
@@ -433,7 +433,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
return false;
}
} else { // All cases of Z = X op Y
- Assembler::RegisterID r = as->toInt32Register(rightSource, Assembler::ScratchRegister);
+ RegisterID r = as->toInt32Register(rightSource, Assembler::ScratchRegister);
switch (op) {
case IR::OpBitAnd: as->and32(l, r, targetReg); break;
case IR::OpBitOr: as->or32 (l, r, targetReg); break;
@@ -452,10 +452,10 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta
// Not all CPUs accept shifts over more than 31 bits, and some CPUs (like ARM) will do
// surprising stuff when shifting over 0 bits.
#define CHECK_RHS(op) { \
- as->and32(Assembler::TrustedImm32(0x1f), r, Assembler::ScratchRegister); \
- Assembler::Jump notZero = as->branch32(Assembler::NotEqual, Assembler::ScratchRegister, Assembler::TrustedImm32(0)); \
+ as->and32(TrustedImm32(0x1f), r, Assembler::ScratchRegister); \
+ Jump notZero = as->branch32(RelationalCondition::NotEqual, Assembler::ScratchRegister, TrustedImm32(0)); \
as->move(l, targetReg); \
- Assembler::Jump done = as->jump(); \
+ Jump done = as->jump(); \
notZero.link(as); \
op; \
done.link(as); \
@@ -493,7 +493,7 @@ static inline Assembler::FPRegisterID getFreeFPReg(IR::Expr *shouldNotOverlap, u
Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
- Assembler::Jump done;
+ Jump done;
// Try preventing a call for a few common binary operations. This is used in two cases:
// - no register allocation was performed (not available for the platform, or the IR was
@@ -505,10 +505,10 @@ Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSourc
// register.
switch (op) {
case IR::OpAdd: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
- Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
- Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
+ FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ FPRegisterID rReg = getFreeFPReg(leftSource, 4);
+ Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
+ Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
as->addDouble(rReg, lReg);
as->storeDouble(lReg, target);
@@ -520,10 +520,10 @@ Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSourc
rightIsNoDbl.link(as);
} break;
case IR::OpMul: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
- Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
- Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
+ FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ FPRegisterID rReg = getFreeFPReg(leftSource, 4);
+ Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
+ Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
as->mulDouble(rReg, lReg);
as->storeDouble(lReg, target);
@@ -535,10 +535,10 @@ Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSourc
rightIsNoDbl.link(as);
} break;
case IR::OpSub: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
- Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
- Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
+ FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ FPRegisterID rReg = getFreeFPReg(leftSource, 4);
+ Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
+ Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
as->subDouble(rReg, lReg);
as->storeDouble(lReg, target);
@@ -550,10 +550,10 @@ Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSourc
rightIsNoDbl.link(as);
} break;
case IR::OpDiv: {
- Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2);
- Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4);
- Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
- Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
+ FPRegisterID lReg = getFreeFPReg(rightSource, 2);
+ FPRegisterID rReg = getFreeFPReg(leftSource, 4);
+ Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg);
+ Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg);
as->divDouble(rReg, lReg);
as->storeDouble(lReg, target);
diff --git a/src/qml/jit/qv4binop_p.h b/src/qml/jit/qv4binop_p.h
index 37601f54ba..3742e99e5a 100644
--- a/src/qml/jit/qv4binop_p.h
+++ b/src/qml/jit/qv4binop_p.h
@@ -67,13 +67,23 @@ struct Binop {
, op(operation)
{}
+ using Jump = Assembler::Jump;
+ using Address = Assembler::Address;
+ using RegisterID = Assembler::RegisterID;
+ using FPRegisterID = Assembler::FPRegisterID;
+ using TrustedImm32 = Assembler::TrustedImm32;
+ using ResultCondition = Assembler::ResultCondition;
+ using RelationalCondition = Assembler::RelationalCondition;
+ using Pointer = Assembler::Pointer;
+ using PointerToValue = Assembler::PointerToValue;
+
void generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target);
void doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target);
bool int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
- Assembler::Jump genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
+ Jump genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
- typedef Assembler::Jump (Binop::*MemRegOp)(Assembler::Address, Assembler::RegisterID);
- typedef Assembler::Jump (Binop::*ImmRegOp)(Assembler::TrustedImm32, Assembler::RegisterID);
+ typedef Jump (Binop::*MemRegOp)(Address, RegisterID);
+ typedef Jump (Binop::*ImmRegOp)(TrustedImm32, RegisterID);
struct OpInfo {
const char *name;
@@ -88,97 +98,97 @@ struct Binop {
static const OpInfo &operation(IR::AluOp operation)
{ return operations[operation]; }
- Assembler::Jump inline_add32(Assembler::Address addr, Assembler::RegisterID reg)
+ Jump inline_add32(Address addr, RegisterID reg)
{
#if HAVE(ALU_OPS_WITH_MEM_OPERAND)
- return as->branchAdd32(Assembler::Overflow, addr, reg);
+ return as->branchAdd32(ResultCondition::Overflow, addr, reg);
#else
as->load32(addr, Assembler::ScratchRegister);
- return as->branchAdd32(Assembler::Overflow, Assembler::ScratchRegister, reg);
+ return as->branchAdd32(ResultCondition::Overflow, Assembler::ScratchRegister, reg);
#endif
}
- Assembler::Jump inline_add32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg)
+ Jump inline_add32(TrustedImm32 imm, RegisterID reg)
{
- return as->branchAdd32(Assembler::Overflow, imm, reg);
+ return as->branchAdd32(ResultCondition::Overflow, imm, reg);
}
- Assembler::Jump inline_sub32(Assembler::Address addr, Assembler::RegisterID reg)
+ Jump inline_sub32(Address addr, RegisterID reg)
{
#if HAVE(ALU_OPS_WITH_MEM_OPERAND)
- return as->branchSub32(Assembler::Overflow, addr, reg);
+ return as->branchSub32(ResultCondition::Overflow, addr, reg);
#else
as->load32(addr, Assembler::ScratchRegister);
- return as->branchSub32(Assembler::Overflow, Assembler::ScratchRegister, reg);
+ return as->branchSub32(ResultCondition::Overflow, Assembler::ScratchRegister, reg);
#endif
}
- Assembler::Jump inline_sub32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg)
+ Jump inline_sub32(TrustedImm32 imm, RegisterID reg)
{
- return as->branchSub32(Assembler::Overflow, imm, reg);
+ return as->branchSub32(ResultCondition::Overflow, imm, reg);
}
- Assembler::Jump inline_mul32(Assembler::Address addr, Assembler::RegisterID reg)
+ Jump inline_mul32(Address addr, RegisterID reg)
{
#if HAVE(ALU_OPS_WITH_MEM_OPERAND)
return as->branchMul32(Assembler::Overflow, addr, reg);
#else
as->load32(addr, Assembler::ScratchRegister);
- return as->branchMul32(Assembler::Overflow, Assembler::ScratchRegister, reg);
+ return as->branchMul32(ResultCondition::Overflow, Assembler::ScratchRegister, reg);
#endif
}
- Assembler::Jump inline_mul32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg)
+ Jump inline_mul32(TrustedImm32 imm, RegisterID reg)
{
- return as->branchMul32(Assembler::Overflow, imm, reg, reg);
+ return as->branchMul32(ResultCondition::Overflow, imm, reg, reg);
}
- Assembler::Jump inline_shl32(Assembler::Address addr, Assembler::RegisterID reg)
+ Jump inline_shl32(Address addr, RegisterID reg)
{
as->load32(addr, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
+ as->and32(TrustedImm32(0x1f), Assembler::ScratchRegister);
as->lshift32(Assembler::ScratchRegister, reg);
- return Assembler::Jump();
+ return Jump();
}
- Assembler::Jump inline_shl32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg)
+ Jump inline_shl32(TrustedImm32 imm, RegisterID reg)
{
imm.m_value &= 0x1f;
as->lshift32(imm, reg);
- return Assembler::Jump();
+ return Jump();
}
- Assembler::Jump inline_shr32(Assembler::Address addr, Assembler::RegisterID reg)
+ Jump inline_shr32(Address addr, RegisterID reg)
{
as->load32(addr, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
+ as->and32(TrustedImm32(0x1f), Assembler::ScratchRegister);
as->rshift32(Assembler::ScratchRegister, reg);
- return Assembler::Jump();
+ return Jump();
}
- Assembler::Jump inline_shr32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg)
+ Jump inline_shr32(TrustedImm32 imm, RegisterID reg)
{
imm.m_value &= 0x1f;
as->rshift32(imm, reg);
- return Assembler::Jump();
+ return Jump();
}
- Assembler::Jump inline_ushr32(Assembler::Address addr, Assembler::RegisterID reg)
+ Jump inline_ushr32(Address addr, RegisterID reg)
{
as->load32(addr, Assembler::ScratchRegister);
- as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister);
+ as->and32(TrustedImm32(0x1f), Assembler::ScratchRegister);
as->urshift32(Assembler::ScratchRegister, reg);
- return as->branchTest32(Assembler::Signed, reg, reg);
+ return as->branchTest32(ResultCondition::Signed, reg, reg);
}
- Assembler::Jump inline_ushr32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg)
+ Jump inline_ushr32(TrustedImm32 imm, RegisterID reg)
{
imm.m_value &= 0x1f;
as->urshift32(imm, reg);
- return as->branchTest32(Assembler::Signed, reg, reg);
+ return as->branchTest32(ResultCondition::Signed, reg, reg);
}
- Assembler::Jump inline_and32(Assembler::Address addr, Assembler::RegisterID reg)
+ Jump inline_and32(Address addr, RegisterID reg)
{
#if HAVE(ALU_OPS_WITH_MEM_OPERAND)
as->and32(addr, reg);
@@ -186,16 +196,16 @@ struct Binop {
as->load32(addr, Assembler::ScratchRegister);
as->and32(Assembler::ScratchRegister, reg);
#endif
- return Assembler::Jump();
+ return Jump();
}
- Assembler::Jump inline_and32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg)
+ Jump inline_and32(TrustedImm32 imm, RegisterID reg)
{
as->and32(imm, reg);
- return Assembler::Jump();
+ return Jump();
}
- Assembler::Jump inline_or32(Assembler::Address addr, Assembler::RegisterID reg)
+ Jump inline_or32(Address addr, RegisterID reg)
{
#if HAVE(ALU_OPS_WITH_MEM_OPERAND)
as->or32(addr, reg);
@@ -203,16 +213,16 @@ struct Binop {
as->load32(addr, Assembler::ScratchRegister);
as->or32(Assembler::ScratchRegister, reg);
#endif
- return Assembler::Jump();
+ return Jump();
}
- Assembler::Jump inline_or32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg)
+ Jump inline_or32(TrustedImm32 imm, RegisterID reg)
{
as->or32(imm, reg);
- return Assembler::Jump();
+ return Jump();
}
- Assembler::Jump inline_xor32(Assembler::Address addr, Assembler::RegisterID reg)
+ Jump inline_xor32(Address addr, RegisterID reg)
{
#if HAVE(ALU_OPS_WITH_MEM_OPERAND)
as->xor32(addr, reg);
@@ -220,13 +230,13 @@ struct Binop {
as->load32(addr, Assembler::ScratchRegister);
as->xor32(Assembler::ScratchRegister, reg);
#endif
- return Assembler::Jump();
+ return Jump();
}
- Assembler::Jump inline_xor32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg)
+ Jump inline_xor32(TrustedImm32 imm, RegisterID reg)
{
as->xor32(imm, reg);
- return Assembler::Jump();
+ return Jump();
}
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index c5d612ae65..279ccabf81 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -68,175 +68,6 @@ using namespace QV4;
using namespace QV4::JIT;
-namespace {
-class QIODevicePrintStream: public FilePrintStream
-{
- Q_DISABLE_COPY(QIODevicePrintStream)
-
-public:
- explicit QIODevicePrintStream(QIODevice *dest)
- : FilePrintStream(0)
- , dest(dest)
- , buf(4096, '0')
- {
- Q_ASSERT(dest);
- }
-
- ~QIODevicePrintStream()
- {}
-
- void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0)
- {
- const int written = qvsnprintf(buf.data(), buf.size(), format, argList);
- if (written > 0)
- dest->write(buf.constData(), written);
- memset(buf.data(), 0, qMin(written, buf.size()));
- }
-
- void flush()
- {}
-
-private:
- QIODevice *dest;
- QByteArray buf;
-};
-} // anonymous namespace
-
-static void printDisassembledOutputWithCalls(QByteArray processedOutput, const QHash<void*, const char*>& functions)
-{
- for (QHash<void*, const char*>::ConstIterator it = functions.begin(), end = functions.end();
- it != end; ++it) {
- const QByteArray ptrString = "0x" + QByteArray::number(quintptr(it.key()), 16);
- int idx = processedOutput.indexOf(ptrString);
- if (idx < 0)
- continue;
- idx = processedOutput.lastIndexOf('\n', idx);
- if (idx < 0)
- continue;
- processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; call ") + it.value());
- }
-
- qDebug("%s", processedOutput.constData());
-}
-
-#if defined(Q_OS_LINUX)
-static FILE *pmap;
-
-static void qt_closePmap()
-{
- if (pmap) {
- fclose(pmap);
- pmap = 0;
- }
-}
-
-#endif
-
-JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
-{
- Label endOfCode = label();
-
- {
- for (size_t i = 0, ei = _patches.size(); i != ei; ++i) {
- Label target = _addrs.at(i);
- Q_ASSERT(target.isSet());
- for (Jump jump : qAsConst(_patches.at(i)))
- jump.linkTo(target, this);
- }
- }
-
- JSC::JSGlobalData dummy(_executableAllocator);
- JSC::LinkBuffer linkBuffer(dummy, this, 0);
-
- for (const DataLabelPatch &p : qAsConst(_dataLabelPatches))
- linkBuffer.patch(p.dataLabel, linkBuffer.locationOf(p.target));
-
- // link exception handlers
- for (Jump jump : qAsConst(exceptionPropagationJumps))
- linkBuffer.link(jump, linkBuffer.locationOf(exceptionReturnLabel));
-
- {
- for (size_t i = 0, ei = _labelPatches.size(); i != ei; ++i) {
- Label target = _addrs.at(i);
- Q_ASSERT(target.isSet());
- for (DataLabelPtr label : _labelPatches.at(i))
- linkBuffer.patch(label, linkBuffer.locationOf(target));
- }
- }
-
- *codeSize = linkBuffer.offsetOf(endOfCode);
-
- QByteArray name;
-
- JSC::MacroAssemblerCodeRef codeRef;
-
- static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM");
- if (showCode) {
- QHash<void*, const char*> functions;
-#ifndef QT_NO_DEBUG
- for (CallInfo call : qAsConst(_callInfos))
- functions[linkBuffer.locationOf(call.label).dataLocation()] = call.functionName;
-#endif
-
- QBuffer buf;
- buf.open(QIODevice::WriteOnly);
- WTF::setDataFile(new QIODevicePrintStream(&buf));
-
- name = _function->name->toUtf8();
- if (name.isEmpty())
- name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')';
- codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data());
-
- WTF::setDataFile(stderr);
- printDisassembledOutputWithCalls(buf.data(), functions);
- } else {
- codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
- }
-
-#if defined(Q_OS_LINUX)
- // This implements writing of JIT'd addresses so that perf can find the
- // symbol names.
- //
- // Perf expects the mapping to be in a certain place and have certain
- // content, for more information, see:
- // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt
- static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP");
- static bool profileInitialized = false;
- if (doProfile && !profileInitialized) {
- profileInitialized = true;
-
- char pname[PATH_MAX];
- snprintf(pname, PATH_MAX - 1, "/tmp/perf-%lu.map",
- (unsigned long)QCoreApplication::applicationPid());
-
- pmap = fopen(pname, "w");
- if (!pmap)
- qWarning("QV4: Can't write %s, call stacks will not contain JavaScript function names", pname);
-
- // make sure we clean up nicely
- std::atexit(qt_closePmap);
- }
-
- if (pmap) {
- // this may have been pre-populated, if QV4_SHOW_ASM was on
- if (name.isEmpty()) {
- name = _function->name->toUtf8();
- if (name.isEmpty())
- name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')';
- }
-
- fprintf(pmap, "%llx %x %.*s\n",
- (long long unsigned int)codeRef.code().executableAddress(),
- *codeSize,
- name.length(),
- name.constData());
- fflush(pmap);
- }
-#endif
-
- return codeRef;
-}
-
InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory)
: EvalInstructionSelection(execAllocator, module, jsGenerator, iselFactory)
, _block(0)
@@ -278,7 +109,7 @@ void InstructionSelection::run(int functionIndex)
qSwap(_removableJumps, removableJumps);
Assembler* oldAssembler = _as;
- _as = new Assembler(this, _function, executableAllocator);
+ _as = new Assembler(jsGenerator, _function, executableAllocator);
_as->setStackLayout(6, // 6 == max argc for calls to built-ins with an argument array
regularRegistersToSave.size(),
fpRegistersToSave.size());
@@ -1881,6 +1712,13 @@ bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock
// neither operands are statically typed as bool, so bail out.
return false;
}
+ if (otherSrc->type == IR::UnknownType) {
+ // Ok, we really need to call into the runtime.
+ // (This case doesn't happen when the optimizer ran, because everything will be typed (yes,
+ // possibly as "var" meaning anything), but it does happen for $0===true, which is generated
+ // for things where the optimizer didn't run (like functions with a try block).)
+ return false;
+ }
Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
: Assembler::NotEqual;
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index 63d542b5c8..f2ae7e117a 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -973,7 +973,15 @@ private:
break;
Q_ASSERT(!i->isFixedInterval());
- _liveIntervals.push_back(i);
+ auto it = _liveIntervals.begin();
+ for (; it != _liveIntervals.end(); ++it) {
+ if ((*it)->temp() == i->temp()) {
+ *it = i;
+ break;
+ }
+ }
+ if (it == _liveIntervals.end())
+ _liveIntervals.push_back(i);
// qDebug() << "-- Activating interval for temp" << i->temp().index;
_unprocessedReverseOrder.removeLast();
@@ -1087,12 +1095,12 @@ private:
if (_info->def(it->temp()) != successorStart && !it->isSplitFromInterval()) {
const int successorEnd = successor->terminator()->id();
const int idx = successor->in.indexOf(predecessor);
- foreach (const Use &use, _info->uses(it->temp())) {
+ for (const Use &use : _info->uses(it->temp)) {
if (use.pos == static_cast<unsigned>(successorStart)) {
// only check the current edge, not all other possible ones. This is
// important for phi nodes: they have uses that are only valid when
// coming in over a specific edge.
- foreach (Stmt *s, successor->statements()) {
+ for (Stmt *s : successor->statements()) {
if (Phi *phi = s->asPhi()) {
Q_ASSERT(it->temp().index != phi->targetTemp->index);
Q_ASSERT(phi->d->incoming[idx]->asTemp() == 0
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index b473e96286..bab2e633a7 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -73,7 +73,8 @@
For the object-based types (including Date and RegExp), use the
newT() functions in QJSEngine (e.g. QJSEngine::newObject())
to create a QJSValue of the desired type. For the primitive types,
- use one of the QJSValue constructor overloads.
+ use one of the QJSValue constructor overloads. For other types, e.g.
+ registered gadget types such as QPoint, you can use QJSEngine::toScriptValue.
The methods named isT() (e.g. isBool(), isUndefined()) can be
used to test if a value is of a certain type. The methods named
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 5a190d6690..9354bcb1a3 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -88,10 +88,12 @@ void ArgumentsObject::fullyCreate()
Scope scope(engine());
Scoped<MemberData> md(scope, d()->mappedArguments);
- d()->mappedArguments = md->allocate(engine(), numAccessors);
- for (uint i = 0; i < numAccessors; ++i) {
- d()->mappedArguments->data[i] = context()->callData->args[i];
- arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor);
+ if (numAccessors) {
+ d()->mappedArguments = md->allocate(engine(), numAccessors);
+ for (uint i = 0; i < numAccessors; ++i) {
+ d()->mappedArguments->data[i] = context()->callData->args[i];
+ arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor);
+ }
}
arrayPut(numAccessors, context()->callData->args + numAccessors, argCount - numAccessors);
for (uint i = numAccessors; i < argCount; ++i)
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index 23075aa78c..ffe9aa846f 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -81,16 +81,19 @@ void ArrayBufferCtor::call(const Managed *that, Scope &scope, CallData *callData
construct(that, scope, callData);
}
-ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx)
+void ArrayBufferCtor::method_isView(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<TypedArray> a(scope, ctx->argument(0));
- if (!!a)
- return Encode(true);
- QV4::Scoped<DataView> v(scope, ctx->argument(0));
- if (!!v)
- return Encode(true);
- return Encode(false);
+ QV4::Scoped<TypedArray> a(scope, callData->argument(0));
+ if (!!a) {
+ scope.result = Encode(true);
+ return;
+ }
+ QV4::Scoped<DataView> v(scope, callData->argument(0));
+ if (!!v) {
+ scope.result = Encode(true);
+ return;
+ }
+ scope.result = Encode(false);
}
@@ -160,54 +163,48 @@ void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("toString"), method_toString, 0);
}
-ReturnedValue ArrayBufferPrototype::method_get_byteLength(CallContext *ctx)
+void ArrayBufferPrototype::method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<ArrayBuffer> v(scope, ctx->thisObject());
+ Scoped<ArrayBuffer> v(scope, callData->thisObject);
if (!v)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(v->d()->data->size);
+ scope.result = Encode(v->d()->data->size);
}
-ReturnedValue ArrayBufferPrototype::method_slice(CallContext *ctx)
+void ArrayBufferPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<ArrayBuffer> a(scope, ctx->thisObject());
+ Scoped<ArrayBuffer> a(scope, callData->thisObject);
if (!a)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- double start = ctx->argc() > 0 ? ctx->args()[0].toInteger() : 0;
- double end = (ctx->argc() < 2 || ctx->args()[1].isUndefined()) ?
- a->d()->data->size : ctx->args()[1].toInteger();
- if (scope.engine->hasException)
- return Encode::undefined();
+ double start = callData->argc > 0 ? callData->args[0].toInteger() : 0;
+ double end = (callData->argc < 2 || callData->args[1].isUndefined()) ?
+ a->d()->data->size : callData->args[1].toInteger();
+ CHECK_EXCEPTION();
double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size);
double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size);
ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedCallData callData(scope, 1);
+ ScopedCallData cData(scope, 1);
double newLen = qMax(final - first, 0.);
- callData->args[0] = QV4::Encode(newLen);
- constructor->construct(scope, callData);
- QV4::Scoped<ArrayBuffer> newBuffer(scope, scope.result.asReturnedValue());
+ cData->args[0] = QV4::Encode(newLen);
+ constructor->construct(scope, cData);
+ QV4::Scoped<ArrayBuffer> newBuffer(scope, scope.result);
if (!newBuffer || newBuffer->d()->data->size < (int)newLen)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
memcpy(newBuffer->d()->data->data(), a->d()->data->data() + (uint)first, newLen);
-
- return newBuffer.asReturnedValue();
}
-ReturnedValue ArrayBufferPrototype::method_toString(CallContext *ctx)
+void ArrayBufferPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<ArrayBuffer> a(scope, ctx->thisObject());
+ Scoped<ArrayBuffer> a(scope, callData->thisObject);
if (!a)
- return Encode::undefined();
- return Encode(ctx->engine()->newString(QString::fromUtf8(a->asByteArray())));
+ RETURN_UNDEFINED();
+ scope.result = scope.engine->newString(QString::fromUtf8(a->asByteArray()));
}
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index bc56d1ea31..4f7926d3dc 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -81,7 +81,7 @@ struct ArrayBufferCtor: FunctionObject
static void construct(const Managed *m, Scope &scope, CallData *callData);
static void call(const Managed *that, Scope &scope, CallData *callData);
- static ReturnedValue method_isView(CallContext *ctx);
+ static void method_isView(const BuiltinFunction *, Scope &scope, CallData *callData);
};
@@ -104,9 +104,9 @@ struct ArrayBufferPrototype: Object
{
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_get_byteLength(CallContext *ctx);
- static ReturnedValue method_slice(CallContext *ctx);
- static ReturnedValue method_toString(CallContext *ctx);
+ static void method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_slice(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index bfeb3d4699..d8a7de5466 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -237,8 +237,14 @@ void ArrayData::ensureAttributes(Object *o)
void SimpleArrayData::markObjects(Heap::Base *d, ExecutionEngine *e)
{
Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(d);
- for (uint i = 0; i < dd->len; ++i)
- dd->arrayData[dd->mappedIndex(i)].mark(e);
+ uint end = dd->offset + dd->len;
+ if (end > dd->alloc) {
+ for (uint i = 0; i < end - dd->alloc; ++i)
+ dd->arrayData[i].mark(e);
+ end = dd->alloc;
+ }
+ for (uint i = dd->offset; i < end; ++i)
+ dd->arrayData[i].mark(e);
}
ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 20ba11fd75..759354f4e2 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -44,6 +44,7 @@
#include "qv4argumentsobject_p.h"
#include "qv4runtime_p.h"
#include "qv4string_p.h"
+#include <QtCore/qscopedvaluerollback.h>
using namespace QV4;
@@ -118,42 +119,40 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("reduceRight"), method_reduceRight, 1);
}
-ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx)
+void ArrayPrototype::method_isArray(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- bool isArray = ctx->argc() && ctx->args()[0].as<ArrayObject>();
- return Encode(isArray);
+ bool isArray = callData->argc && callData->args[0].as<ArrayObject>();
+ scope.result = Encode(isArray);
}
-ReturnedValue ArrayPrototype::method_toString(CallContext *ctx)
+void ArrayPrototype::method_toString(const BuiltinFunction *builtin, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->thisObject(), ScopedObject::Convert);
- if (ctx->d()->engine->hasException)
- return Encode::undefined();
- ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("join")));
+ ScopedObject o(scope, callData->thisObject, ScopedObject::Convert);
+ CHECK_EXCEPTION();
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("join")));
ScopedFunctionObject f(scope, o->get(s));
if (!!f) {
ScopedCallData d(scope, 0);
- d->thisObject = ctx->thisObject();
+ d->thisObject = callData->thisObject;
f->call(scope, d);
- return scope.result.asReturnedValue();
+ return;
}
- return ObjectPrototype::method_toString(ctx);
+ ObjectPrototype::method_toString(builtin, scope, callData);
}
-ReturnedValue ArrayPrototype::method_toLocaleString(CallContext *ctx)
+void ArrayPrototype::method_toLocaleString(const BuiltinFunction *builtin, Scope &scope, CallData *callData)
{
- return method_toString(ctx);
+ return method_toString(builtin, scope, callData);
}
-ReturnedValue ArrayPrototype::method_concat(CallContext *ctx)
+void ArrayPrototype::method_concat(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject result(scope, ctx->d()->engine->newArrayObject());
-
- ScopedObject thisObject(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject thisObject(scope, callData->thisObject.toObject(scope.engine));
if (!thisObject)
- return Encode::undefined();
+ RETURN_UNDEFINED();
+
+ ScopedArrayObject result(scope, scope.engine->newArrayObject());
+
if (thisObject->isArrayObject()) {
result->copyArrayData(thisObject);
} else {
@@ -163,9 +162,9 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx)
ScopedArrayObject elt(scope);
ScopedObject eltAsObj(scope);
ScopedValue entry(scope);
- for (int i = 0; i < ctx->argc(); ++i) {
- eltAsObj = ctx->args()[i];
- elt = ctx->args()[i];
+ for (int i = 0; i < callData->argc; ++i) {
+ eltAsObj = callData->args[i];
+ elt = callData->args[i];
if (elt) {
uint n = elt->getLength();
uint newLen = ArrayData::append(result, elt, n);
@@ -177,95 +176,90 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx)
result->putIndexed(startIndex + i, entry);
}
} else {
- result->arraySet(result->getLength(), ctx->args()[i]);
+ result->arraySet(result->getLength(), callData->args[i]);
}
}
- return result.asReturnedValue();
+ scope.result = result;
}
-ReturnedValue ArrayPrototype::method_find(CallContext *ctx)
+void ArrayPrototype::method_find(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedFunctionObject callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, callData->argument(0));
if (!callback)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedCallData callData(scope, 3);
- callData->thisObject = ctx->argument(1);
- callData->args[2] = instance;
+ ScopedCallData cData(scope, 3);
+ cData->thisObject = callData->argument(1);
+ cData->args[2] = instance;
ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
v = instance->getIndexed(k);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
- callData->args[0] = v;
- callData->args[1] = Primitive::fromDouble(k);
- callback->call(scope, callData);
+ cData->args[0] = v;
+ cData->args[1] = Primitive::fromDouble(k);
+ callback->call(scope, cData);
- if (scope.hasException())
- return Encode::undefined();
- else if (scope.result.toBoolean())
- return v->asReturnedValue();
+ CHECK_EXCEPTION();
+ if (scope.result.toBoolean())
+ RETURN_RESULT(v);
}
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-ReturnedValue ArrayPrototype::method_findIndex(CallContext *ctx)
+void ArrayPrototype::method_findIndex(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedFunctionObject callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, callData->argument(0));
if (!callback)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedCallData callData(scope, 3);
- callData->thisObject = ctx->argument(1);
- callData->args[2] = instance;
+ ScopedCallData cData(scope, 3);
+ cData->thisObject = callData->argument(1);
+ cData->args[2] = instance;
ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
v = instance->getIndexed(k);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
- callData->args[0] = v;
- callData->args[1] = Primitive::fromDouble(k);
- callback->call(scope, callData);
+ cData->args[0] = v;
+ cData->args[1] = Primitive::fromDouble(k);
+ callback->call(scope, cData);
- if (scope.hasException())
- return Encode::undefined();
- else if (scope.result.toBoolean())
- return Encode(k);
+ CHECK_EXCEPTION();
+ if (scope.result.toBoolean())
+ RETURN_RESULT(Encode(k));
}
- return Encode(-1);
+ RETURN_RESULT(Encode(-1));
}
-ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
+void ArrayPrototype::method_join(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedValue arg(scope, ctx->argument(0));
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedValue arg(scope, callData->argument(0));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
- if (!instance)
- return ctx->d()->engine->newString()->asReturnedValue();
+ if (!instance) {
+ scope.result = scope.engine->newString();
+ return;
+ }
QString r4;
if (arg->isUndefined())
@@ -273,11 +267,13 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
else
r4 = arg->toQString();
- ScopedValue length(scope, instance->get(ctx->d()->engine->id_length()));
+ ScopedValue length(scope, instance->get(scope.engine->id_length()));
const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32();
- if (!r2)
- return ctx->d()->engine->newString()->asReturnedValue();
+ if (!r2) {
+ scope.result = scope.engine->newString();
+ return;
+ }
QString R;
@@ -289,8 +285,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
R += r4;
e = a->getIndexed(i);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (!e->isNullOrUndefined())
R += e->toQString();
}
@@ -298,7 +293,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
//
// crazy!
//
- ScopedString name(scope, ctx->d()->engine->newString(QStringLiteral("0")));
+ ScopedString name(scope, scope.engine->newString(QStringLiteral("0")));
ScopedValue r6(scope, instance->get(name));
if (!r6->isNullOrUndefined())
R = r6->toQString();
@@ -309,99 +304,98 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
name = Primitive::fromDouble(k).toString(scope.engine);
r12 = instance->get(name);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (!r12->isNullOrUndefined())
R += r12->toQString();
}
}
- return ctx->d()->engine->newString(R)->asReturnedValue();
+ scope.result = scope.engine->newString(R);
}
-ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
+void ArrayPrototype::method_pop(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
+
uint len = instance->getLength();
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
- return Encode::undefined();
+ instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
+ RETURN_UNDEFINED();
}
ScopedValue result(scope, instance->getIndexed(len - 1));
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
instance->deleteIndexedProperty(len - 1);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
+
if (instance->isArrayObject())
instance->setArrayLength(len - 1);
else
- instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
- return result->asReturnedValue();
+ instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ scope.result = result;
}
-ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
+void ArrayPrototype::method_push(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
instance->arrayCreate();
Q_ASSERT(instance->arrayData());
uint len = instance->getLength();
- if (len + ctx->argc() < len) {
+ if (len + callData->argc < len) {
// ughh...
double l = len;
ScopedString s(scope);
- for (int i = 0; i < ctx->argc(); ++i) {
+ for (int i = 0; i < callData->argc; ++i) {
s = Primitive::fromDouble(l + i).toString(scope.engine);
- instance->put(s, ctx->args()[i]);
+ instance->put(s, callData->args[i]);
}
- double newLen = l + ctx->argc();
+ double newLen = l + callData->argc;
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
else {
- ScopedString str(scope, ctx->d()->engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
- return ctx->engine()->throwRangeError(str);
+ ScopedString str(scope, scope.engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
+ scope.result = scope.engine->throwRangeError(str);
+ return;
}
- return Encode(newLen);
+ scope.result = Encode(newLen);
+ return;
}
- if (!ctx->argc())
+ if (!callData->argc)
;
else if (!instance->protoHasArray() && instance->arrayData()->length() <= len && instance->arrayData()->type == Heap::ArrayData::Simple) {
- instance->arrayData()->vtable()->putArray(instance, len, ctx->args(), ctx->argc());
+ instance->arrayData()->vtable()->putArray(instance, len, callData->args, callData->argc);
len = instance->arrayData()->length();
} else {
- for (int i = 0; i < ctx->argc(); ++i)
- instance->putIndexed(len + i, ctx->args()[i]);
- len += ctx->argc();
+ for (int i = 0; i < callData->argc; ++i)
+ instance->putIndexed(len + i, callData->args[i]);
+ len += callData->argc;
}
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len);
else
- instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len)));
+ instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len)));
- return Encode(len);
+ scope.result = Encode(len);
}
-ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx)
+void ArrayPrototype::method_reverse(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
+
uint length = instance->getLength();
int lo = 0, hi = length - 1;
@@ -412,28 +406,25 @@ ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx)
bool loExists, hiExists;
lval = instance->getIndexed(lo, &loExists);
hval = instance->getIndexed(hi, &hiExists);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (hiExists)
instance->putIndexed(lo, hval);
else
instance->deleteIndexedProperty(lo);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (loExists)
instance->putIndexed(hi, lval);
else
instance->deleteIndexedProperty(hi);
}
- return instance.asReturnedValue();
+ scope.result = instance;
}
-ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
+void ArrayPrototype::method_shift(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
instance->arrayCreate();
Q_ASSERT(instance->arrayData());
@@ -442,54 +433,46 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
- return Encode::undefined();
+ instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
+ RETURN_UNDEFINED();
}
- ScopedValue result(scope);
-
if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len && instance->arrayData()->type != Heap::ArrayData::Custom) {
- result = instance->arrayData()->vtable()->pop_front(instance);
+ scope.result = instance->arrayData()->vtable()->pop_front(instance);
} else {
- result = instance->getIndexed(0);
- if (scope.hasException())
- return Encode::undefined();
+ scope.result = instance->getIndexed(0);
+ CHECK_EXCEPTION();
ScopedValue v(scope);
// do it the slow way
for (uint k = 1; k < len; ++k) {
bool exists;
v = instance->getIndexed(k, &exists);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (exists)
instance->putIndexed(k - 1, v);
else
instance->deleteIndexedProperty(k - 1);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
}
instance->deleteIndexedProperty(len - 1);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
}
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len - 1);
else
- instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
- return result->asReturnedValue();
+ instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
}
-ReturnedValue ArrayPrototype::method_slice(CallContext *ctx)
+void ArrayPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject o(scope, callData->thisObject.toObject(scope.engine));
if (!o)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- ScopedArrayObject result(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject result(scope, scope.engine->newArrayObject());
uint len = o->getLength();
- double s = ScopedValue(scope, ctx->argument(0))->toInteger();
+ double s = ScopedValue(scope, callData->argument(0))->toInteger();
uint start;
if (s < 0)
start = (uint)qMax(len + s, 0.);
@@ -498,8 +481,8 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx)
else
start = (uint) s;
uint end = len;
- if (ctx->argc() > 1 && !ctx->args()[1].isUndefined()) {
- double e = ctx->args()[1].toInteger();
+ if (callData->argc > 1 && !callData->args[1].isUndefined()) {
+ double e = callData->args[1].toInteger();
if (e < 0)
end = (uint)qMax(len + e, 0.);
else if (e > len)
@@ -513,115 +496,107 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx)
for (uint i = start; i < end; ++i) {
bool exists;
v = o->getIndexed(i, &exists);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (exists)
result->arraySet(n, v);
++n;
}
- return result.asReturnedValue();
+ scope.result = result;
}
-ReturnedValue ArrayPrototype::method_sort(CallContext *ctx)
+void ArrayPrototype::method_sort(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedValue comparefn(scope, ctx->argument(0));
+ ScopedValue comparefn(scope, callData->argument(0));
ArrayData::sort(scope.engine, instance, comparefn, len);
- return ctx->thisObject().asReturnedValue();
+ scope.result = callData->thisObject;
}
-ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
+void ArrayPrototype::method_splice(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
+
uint len = instance->getLength();
- ScopedArrayObject newArray(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject newArray(scope, scope.engine->newArrayObject());
- double rs = ScopedValue(scope, ctx->argument(0))->toInteger();
+ double rs = ScopedValue(scope, callData->argument(0))->toInteger();
uint start;
if (rs < 0)
start = (uint) qMax(0., len + rs);
else
start = (uint) qMin(rs, (double)len);
- uint deleteCount = (uint)qMin(qMax(ScopedValue(scope, ctx->argument(1))->toInteger(), 0.), (double)(len - start));
+ uint deleteCount = (uint)qMin(qMax(ScopedValue(scope, callData->argument(1))->toInteger(), 0.), (double)(len - start));
newArray->arrayReserve(deleteCount);
ScopedValue v(scope);
for (uint i = 0; i < deleteCount; ++i) {
bool exists;
v = instance->getIndexed(start + i, &exists);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (exists)
newArray->arrayPut(i, v);
}
newArray->setArrayLengthUnchecked(deleteCount);
- uint itemCount = ctx->argc() < 2 ? 0 : ctx->argc() - 2;
+ uint itemCount = callData->argc < 2 ? 0 : callData->argc - 2;
if (itemCount < deleteCount) {
for (uint k = start; k < len - deleteCount; ++k) {
bool exists;
v = instance->getIndexed(k + deleteCount, &exists);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (exists)
instance->putIndexed(k + itemCount, v);
else
instance->deleteIndexedProperty(k + itemCount);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
}
for (uint k = len; k > len - deleteCount + itemCount; --k) {
instance->deleteIndexedProperty(k - 1);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
}
} else if (itemCount > deleteCount) {
uint k = len - deleteCount;
while (k > start) {
bool exists;
v = instance->getIndexed(k + deleteCount - 1, &exists);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (exists)
instance->putIndexed(k + itemCount - 1, v);
else
instance->deleteIndexedProperty(k + itemCount - 1);
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
--k;
}
}
for (uint i = 0; i < itemCount; ++i) {
- instance->putIndexed(start + i, ctx->args()[i + 2]);
- if (scope.hasException())
- return Encode::undefined();
+ instance->putIndexed(start + i, callData->args[i + 2]);
+ CHECK_EXCEPTION();
}
- ctx->d()->strictMode = true;
- instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
+ bool wasStrict = scope.engine->current->strictMode;
+ scope.engine->current->strictMode = true;
+ instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
- return newArray.asReturnedValue();
+ scope.result = newArray;
+ scope.engine->current->strictMode = wasStrict;
}
-ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
+void ArrayPrototype::method_unshift(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
instance->arrayCreate();
Q_ASSERT(instance->arrayData());
@@ -630,50 +605,52 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len &&
instance->arrayData()->type != Heap::ArrayData::Custom) {
- instance->arrayData()->vtable()->push_front(instance, ctx->args(), ctx->argc());
+ instance->arrayData()->vtable()->push_front(instance, callData->args, callData->argc);
} else {
ScopedValue v(scope);
for (uint k = len; k > 0; --k) {
bool exists;
v = instance->getIndexed(k - 1, &exists);
if (exists)
- instance->putIndexed(k + ctx->argc() - 1, v);
+ instance->putIndexed(k + callData->argc - 1, v);
else
- instance->deleteIndexedProperty(k + ctx->argc() - 1);
+ instance->deleteIndexedProperty(k + callData->argc - 1);
}
- for (int i = 0; i < ctx->argc(); ++i)
- instance->putIndexed(i, ctx->args()[i]);
+ for (int i = 0; i < callData->argc; ++i)
+ instance->putIndexed(i, callData->args[i]);
}
- uint newLen = len + ctx->argc();
+ uint newLen = len + callData->argc;
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(newLen);
else
- instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
- return Encode(newLen);
+ scope.result = Encode(newLen);
}
-ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
+void ArrayPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
-
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
+
uint len = instance->getLength();
- if (!len)
- return Encode(-1);
+ if (!len) {
+ scope.result = Encode(-1);
+ return;
+ }
- ScopedValue searchValue(scope, ctx->argument(0));
+ ScopedValue searchValue(scope, callData->argument(0));
uint fromIndex = 0;
- if (ctx->argc() >= 2) {
- double f = ctx->args()[1].toInteger();
- if (scope.hasException())
- return Encode::undefined();
- if (f >= len)
- return Encode(-1);
+ if (callData->argc >= 2) {
+ double f = callData->args[1].toInteger();
+ CHECK_EXCEPTION();
+ if (f >= len) {
+ scope.result = Encode(-1);
+ return;
+ }
if (f < 0)
f = qMax(len + f, 0.);
fromIndex = (uint) f;
@@ -684,10 +661,13 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
for (uint k = fromIndex; k < len; ++k) {
bool exists;
v = instance->getIndexed(k, &exists);
- if (exists && RuntimeHelpers::strictEqual(v, searchValue))
- return Encode(k);
+ if (exists && RuntimeHelpers::strictEqual(v, searchValue)) {
+ scope.result = Encode(k);
+ return;
+ }
}
- return Encode(-1);
+ scope.result = Encode(-1);
+ return;
}
ScopedValue value(scope);
@@ -698,13 +678,15 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
for (uint i = fromIndex; i < len; ++i) {
bool exists;
value = instance->getIndexed(i, &exists);
- if (scope.hasException())
- return Encode::undefined();
- if (exists && RuntimeHelpers::strictEqual(value, searchValue))
- return Encode(i);
+ CHECK_EXCEPTION();
+ if (exists && RuntimeHelpers::strictEqual(value, searchValue)) {
+ scope.result = Encode(i);
+ return;
+ }
}
} else if (!instance->arrayData()) {
- return Encode(-1);
+ scope.result = Encode(-1);
+ return;
} else {
Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex);
Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>();
@@ -713,45 +695,48 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
uint idx = fromIndex;
while (idx < len) {
value = sa->data(idx);
- if (scope.hasException())
- return Encode::undefined();
- if (RuntimeHelpers::strictEqual(value, searchValue))
- return Encode(idx);
+ CHECK_EXCEPTION();
+ if (RuntimeHelpers::strictEqual(value, searchValue)) {
+ scope.result = Encode(idx);
+ return;
+ }
++idx;
}
}
- return Encode(-1);
+ scope.result = Encode(-1);
}
-ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx)
+void ArrayPrototype::method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
-
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
+
uint len = instance->getLength();
- if (!len)
- return Encode(-1);
+ if (!len) {
+ scope.result = Encode(-1);
+ return;
+ }
ScopedValue searchValue(scope);
uint fromIndex = len;
- if (ctx->argc() >= 1)
- searchValue = ctx->argument(0);
+ if (callData->argc >= 1)
+ searchValue = callData->argument(0);
else
searchValue = Primitive::undefinedValue();
- if (ctx->argc() >= 2) {
- double f = ctx->args()[1].toInteger();
- if (scope.hasException())
- return Encode::undefined();
+ if (callData->argc >= 2) {
+ double f = callData->args[1].toInteger();
+ CHECK_EXCEPTION();
if (f > 0)
f = qMin(f, (double)(len - 1));
else if (f < 0) {
f = len + f;
- if (f < 0)
- return Encode(-1);
+ if (f < 0) {
+ scope.result = Encode(-1);
+ return;
+ }
}
fromIndex = (uint) f + 1;
}
@@ -761,30 +746,30 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx)
--k;
bool exists;
v = instance->getIndexed(k, &exists);
- if (scope.hasException())
- return Encode::undefined();
- if (exists && RuntimeHelpers::strictEqual(v, searchValue))
- return Encode(k);
+ CHECK_EXCEPTION();
+ if (exists && RuntimeHelpers::strictEqual(v, searchValue)) {
+ scope.result = Encode(k);
+ return;
+ }
}
- return Encode(-1);
+ scope.result = Encode(-1);
}
-ReturnedValue ArrayPrototype::method_every(CallContext *ctx)
+void ArrayPrototype::method_every(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedFunctionObject callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, callData->argument(0));
if (!callback)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedCallData callData(scope, 3);
- callData->args[2] = instance;
- callData->thisObject = ctx->argument(1);
+ ScopedCallData cData(scope, 3);
+ cData->args[2] = instance;
+ cData->thisObject = callData->argument(1);
ScopedValue v(scope);
bool ok = true;
@@ -794,30 +779,29 @@ ReturnedValue ArrayPrototype::method_every(CallContext *ctx)
if (!exists)
continue;
- callData->args[0] = v;
- callData->args[1] = Primitive::fromDouble(k);
- callback->call(scope, callData);
+ cData->args[0] = v;
+ cData->args[1] = Primitive::fromDouble(k);
+ callback->call(scope, cData);
ok = scope.result.toBoolean();
}
- return Encode(ok);
+ scope.result = Encode(ok);
}
-ReturnedValue ArrayPrototype::method_some(CallContext *ctx)
+void ArrayPrototype::method_some(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedFunctionObject callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, callData->argument(0));
if (!callback)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedCallData callData(scope, 3);
- callData->thisObject = ctx->argument(1);
- callData->args[2] = instance;
+ ScopedCallData cData(scope, 3);
+ cData->thisObject = callData->argument(1);
+ cData->args[2] = instance;
ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
@@ -826,31 +810,32 @@ ReturnedValue ArrayPrototype::method_some(CallContext *ctx)
if (!exists)
continue;
- callData->args[0] = v;
- callData->args[1] = Primitive::fromDouble(k);
- callback->call(scope, callData);
- if (scope.result.toBoolean())
- return Encode(true);
+ cData->args[0] = v;
+ cData->args[1] = Primitive::fromDouble(k);
+ callback->call(scope, cData);
+ if (scope.result.toBoolean()) {
+ scope.result = Encode(true);
+ return;
+ }
}
- return Encode(false);
+ scope.result = Encode(false);
}
-ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx)
+void ArrayPrototype::method_forEach(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedFunctionObject callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, callData->argument(0));
if (!callback)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedCallData callData(scope, 3);
- callData->thisObject = ctx->argument(1);
- callData->args[2] = instance;
+ ScopedCallData cData(scope, 3);
+ cData->thisObject = callData->argument(1);
+ cData->args[2] = instance;
ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
@@ -859,33 +844,32 @@ ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx)
if (!exists)
continue;
- callData->args[0] = v;
- callData->args[1] = Primitive::fromDouble(k);
- callback->call(scope, callData);
+ cData->args[0] = v;
+ cData->args[1] = Primitive::fromDouble(k);
+ callback->call(scope, cData);
}
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-ReturnedValue ArrayPrototype::method_map(CallContext *ctx)
+void ArrayPrototype::method_map(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedFunctionObject callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, callData->argument(0));
if (!callback)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedArrayObject a(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject a(scope, scope.engine->newArrayObject());
a->arrayReserve(len);
a->setArrayLengthUnchecked(len);
- ScopedCallData callData(scope, 3);
- callData->thisObject = ctx->argument(1);
- callData->args[2] = instance;
+ ScopedCallData cData(scope, 3);
+ cData->thisObject = callData->argument(1);
+ cData->args[2] = instance;
ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
@@ -894,33 +878,32 @@ ReturnedValue ArrayPrototype::method_map(CallContext *ctx)
if (!exists)
continue;
- callData->args[0] = v;
- callData->args[1] = Primitive::fromDouble(k);
- callback->call(scope, callData);
+ cData->args[0] = v;
+ cData->args[1] = Primitive::fromDouble(k);
+ callback->call(scope, cData);
a->arraySet(k, scope.result);
}
- return a.asReturnedValue();
+ scope.result = a.asReturnedValue();
}
-ReturnedValue ArrayPrototype::method_filter(CallContext *ctx)
+void ArrayPrototype::method_filter(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedFunctionObject callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, callData->argument(0));
if (!callback)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedArrayObject a(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject a(scope, scope.engine->newArrayObject());
a->arrayReserve(len);
- ScopedCallData callData(scope, 3);
- callData->thisObject = ctx->argument(1);
- callData->args[2] = instance;
+ ScopedCallData cData(scope, 3);
+ cData->thisObject = callData->argument(1);
+ cData->args[2] = instance;
ScopedValue v(scope);
@@ -931,35 +914,34 @@ ReturnedValue ArrayPrototype::method_filter(CallContext *ctx)
if (!exists)
continue;
- callData->args[0] = v;
- callData->args[1] = Primitive::fromDouble(k);
- callback->call(scope, callData);
+ cData->args[0] = v;
+ cData->args[1] = Primitive::fromDouble(k);
+ callback->call(scope, cData);
if (scope.result.toBoolean()) {
a->arraySet(to, v);
++to;
}
}
- return a.asReturnedValue();
+ scope.result = a.asReturnedValue();
}
-ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx)
+void ArrayPrototype::method_reduce(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedFunctionObject callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, callData->argument(0));
if (!callback)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
uint k = 0;
ScopedValue v(scope);
- if (ctx->argc() > 1) {
- scope.result = ctx->argument(1);
+ if (callData->argc > 1) {
+ scope.result = callData->argument(1);
} else {
bool kPresent = false;
while (k < len && !kPresent) {
@@ -969,51 +951,50 @@ ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx)
++k;
}
if (!kPresent)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
}
- ScopedCallData callData(scope, 4);
- callData->thisObject = Primitive::undefinedValue();
- callData->args[0] = scope.result;
- callData->args[3] = instance;
+ ScopedCallData cData(scope, 4);
+ cData->thisObject = Primitive::undefinedValue();
+ cData->args[0] = scope.result;
+ cData->args[3] = instance;
while (k < len) {
bool kPresent;
v = instance->getIndexed(k, &kPresent);
if (kPresent) {
- callData->args[0] = scope.result;
- callData->args[1] = v;
- callData->args[2] = Primitive::fromDouble(k);
- callback->call(scope, callData);
+ cData->args[0] = scope.result;
+ cData->args[1] = v;
+ cData->args[2] = Primitive::fromDouble(k);
+ callback->call(scope, cData);
}
++k;
}
- return scope.result.asReturnedValue();
}
-ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx)
+void ArrayPrototype::method_reduceRight(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject instance(scope, callData->thisObject.toObject(scope.engine));
if (!instance)
- return Encode::undefined();
+ RETURN_UNDEFINED();
uint len = instance->getLength();
- ScopedFunctionObject callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, callData->argument(0));
if (!callback)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (len == 0) {
- if (ctx->argc() == 1)
- return ctx->engine()->throwTypeError();
- return ctx->argument(1);
+ if (callData->argc == 1)
+ THROW_TYPE_ERROR();
+ scope.result = callData->argument(1);
+ return;
}
uint k = len;
ScopedValue v(scope);
- if (ctx->argc() > 1) {
- scope.result = ctx->argument(1);
+ if (callData->argc > 1) {
+ scope.result = callData->argument(1);
} else {
bool kPresent = false;
while (k > 0 && !kPresent) {
@@ -1023,24 +1004,24 @@ ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx)
--k;
}
if (!kPresent)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
}
- ScopedCallData callData(scope, 4);
- callData->thisObject = Primitive::undefinedValue();
- callData->args[3] = instance;
+ ScopedCallData cData(scope, 4);
+ cData->thisObject = Primitive::undefinedValue();
+ cData->args[3] = instance;
while (k > 0) {
bool kPresent;
v = instance->getIndexed(k - 1, &kPresent);
if (kPresent) {
- callData->args[0] = scope.result;
- callData->args[1] = v;
- callData->args[2] = Primitive::fromDouble(k - 1);
- callback->call(scope, callData);
+ cData->args[0] = scope.result;
+ cData->args[1] = v;
+ cData->args[2] = Primitive::fromDouble(k - 1);
+ callback->call(scope, cData);
}
--k;
}
- return scope.result.asReturnedValue();
+ scope.result = scope.result.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index f00c0c0249..689752433b 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -78,30 +78,30 @@ struct ArrayPrototype: ArrayObject
{
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_isArray(CallContext *ctx);
- static ReturnedValue method_toString(CallContext *ctx);
- static ReturnedValue method_toLocaleString(CallContext *ctx);
- static ReturnedValue method_concat(CallContext *ctx);
- static ReturnedValue method_find(CallContext *ctx);
- static ReturnedValue method_findIndex(CallContext *ctx);
- static ReturnedValue method_join(CallContext *ctx);
- static ReturnedValue method_pop(CallContext *ctx);
- static ReturnedValue method_push(CallContext *ctx);
- static ReturnedValue method_reverse(CallContext *ctx);
- static ReturnedValue method_shift(CallContext *ctx);
- static ReturnedValue method_slice(CallContext *ctx);
- static ReturnedValue method_sort(CallContext *ctx);
- static ReturnedValue method_splice(CallContext *ctx);
- static ReturnedValue method_unshift(CallContext *ctx);
- static ReturnedValue method_indexOf(CallContext *ctx);
- static ReturnedValue method_lastIndexOf(CallContext *ctx);
- static ReturnedValue method_every(CallContext *ctx);
- static ReturnedValue method_some(CallContext *ctx);
- static ReturnedValue method_forEach(CallContext *ctx);
- static ReturnedValue method_map(CallContext *ctx);
- static ReturnedValue method_filter(CallContext *ctx);
- static ReturnedValue method_reduce(CallContext *ctx);
- static ReturnedValue method_reduceRight(CallContext *ctx);
+ static void method_isArray(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_toString(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_toLocaleString(const BuiltinFunction *builtin, Scope &, CallData *callData);
+ static void method_concat(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_find(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_findIndex(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_join(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_pop(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_push(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_reverse(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_shift(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_slice(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_sort(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_splice(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_unshift(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_indexOf(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_lastIndexOf(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_every(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_some(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_forEach(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_map(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_filter(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_reduce(const BuiltinFunction *, Scope &, CallData *callData);
+ static void method_reduceRight(const BuiltinFunction *, Scope &, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 8047993266..601066110f 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -73,29 +73,31 @@ void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(engine->id_valueOf(), method_valueOf);
}
-ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
+void BooleanPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
bool result;
- if (ctx->thisObject().isBoolean()) {
- result = ctx->thisObject().booleanValue();
+ if (callData->thisObject.isBoolean()) {
+ result = callData->thisObject.booleanValue();
} else {
- const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = callData->thisObject.as<BooleanObject>();
if (!thisObject)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
result = thisObject->value();
}
- return Encode(ctx->d()->engine->newString(QLatin1String(result ? "true" : "false")));
+ scope.result = scope.engine->newString(QLatin1String(result ? "true" : "false"));
}
-ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx)
+void BooleanPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->thisObject().isBoolean())
- return ctx->thisObject().asReturnedValue();
+ if (callData->thisObject.isBoolean()) {
+ scope.result = callData->thisObject.asReturnedValue();
+ return;
+ }
- const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = callData->thisObject.as<BooleanObject>();
if (!thisObject)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(thisObject->value());
+ scope.result = Encode(thisObject->value());
}
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 4c2f3c09e7..9c8b1d67f1 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -78,8 +78,8 @@ struct BooleanPrototype: BooleanObject
{
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_toString(CallContext *ctx);
- static ReturnedValue method_valueOf(CallContext *ctx);
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 544d39339b..60b90e4bf0 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -95,6 +95,17 @@ Heap::CallContext *ExecutionContext::newCallContext(Function *function, CallData
return c;
}
+Heap::CallContext *Heap::CallContext::createSimpleContext(ExecutionEngine *v4)
+{
+ Heap::CallContext *ctxt = v4->memoryManager->allocSimpleCallContext(v4);
+ return ctxt;
+}
+
+void Heap::CallContext::freeSimpleCallContext()
+{
+ engine->memoryManager->freeSimpleCallContext();
+}
+
Heap::WithContext *ExecutionContext::newWithContext(Heap::Object *with)
{
return d()->engine->memoryManager->alloc<WithContext>(d(), with);
@@ -325,26 +336,27 @@ void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Functio
ExecutionContextSaver ctxSaver(scope);
- CallContext::Data ctx = CallContext::Data::createOnStack(scope.engine);
+ CallContext::Data *ctx = scope.engine->memoryManager->allocSimpleCallContext(scope.engine);
- ctx.strictMode = function->isStrict();
- ctx.callData = callData;
- ctx.v4Function = function;
- ctx.compilationUnit = function->compilationUnit;
- ctx.lookups = function->compilationUnit->runtimeLookups;
- ctx.constantTable = function->compilationUnit->constants;
- ctx.outer = this->d();
- ctx.locals = scope.alloc(function->compiledFunction->nLocals);
+ ctx->strictMode = function->isStrict();
+ ctx->callData = callData;
+ ctx->v4Function = function;
+ ctx->compilationUnit = function->compilationUnit;
+ ctx->lookups = function->compilationUnit->runtimeLookups;
+ ctx->constantTable = function->compilationUnit->constants;
+ ctx->outer = this->d();
+ ctx->locals = scope.alloc(function->compiledFunction->nLocals);
for (int i = callData->argc; i < (int)function->nFormals; ++i)
callData->args[i] = Encode::undefined();
- scope.engine->pushContext(&ctx);
- Q_ASSERT(scope.engine->current == &ctx);
+ scope.engine->pushContext(ctx);
+ Q_ASSERT(scope.engine->current == ctx);
scope.result = Q_V4_PROFILE(scope.engine, function);
if (function->hasQmlDependencies)
QQmlPropertyCapture::registerQmlDependencies(function->compiledFunction, scope);
+ scope.engine->memoryManager->freeSimpleCallContext();
}
void ExecutionContext::setProperty(String *name, const Value &value)
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index c985fdb24d..bcfee2e1f8 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -109,14 +109,8 @@ struct ExecutionContext : Base {
{
Base::init();
- callData = nullptr;
this->engine = engine;
- outer = nullptr;
- lookups = nullptr;
- constantTable = nullptr;
- compilationUnit = nullptr;
type = t;
- strictMode = false;
lineNumber = -1;
}
@@ -135,15 +129,12 @@ struct ExecutionContext : Base {
V4_ASSERT_IS_TRIVIAL(ExecutionContext)
struct CallContext : ExecutionContext {
- static CallContext createOnStack(ExecutionEngine *v4);
+ static CallContext *createSimpleContext(ExecutionEngine *v4);
+ void freeSimpleCallContext();
void init(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext)
{
ExecutionContext::init(engine, t);
- function = 0;
- v4Function = 0;
- locals = 0;
- activation = 0;
}
inline unsigned int formalParameterCount() const;
@@ -247,6 +238,7 @@ struct Q_QML_EXPORT CallContext : public ExecutionContext
inline ReturnedValue argument(int i) const;
bool needsOwnArguments() const;
+
};
inline ReturnedValue CallContext::argument(int i) const {
@@ -289,16 +281,6 @@ inline const WithContext *ExecutionContext::asWithContext() const
return d()->type == Heap::ExecutionContext::Type_WithContext ? static_cast<const WithContext *>(this) : 0;
}
-inline Heap::CallContext Heap::CallContext::createOnStack(ExecutionEngine *v4)
-{
- Heap::CallContext ctxt;
- memset(&ctxt, 0, sizeof(Heap::CallContext));
- ctxt.mm_data = 0;
- ctxt.setVtable(QV4::CallContext::staticVTable());
- ctxt.init(v4);
- return ctxt;
-}
-
} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index db8376272d..a810b38f24 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -129,90 +129,84 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0);
}
-ReturnedValue DataViewPrototype::method_get_buffer(CallContext *ctx)
+void DataViewPrototype::method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DataView> v(scope, ctx->thisObject());
+ Scoped<DataView> v(scope, callData->thisObject);
if (!v)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(v->d()->buffer->asReturnedValue());
+ scope.result = v->d()->buffer;
}
-ReturnedValue DataViewPrototype::method_get_byteLength(CallContext *ctx)
+void DataViewPrototype::method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DataView> v(scope, ctx->thisObject());
+ Scoped<DataView> v(scope, callData->thisObject);
if (!v)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(v->d()->byteLength);
+ scope.result = Encode(v->d()->byteLength);
}
-ReturnedValue DataViewPrototype::method_get_byteOffset(CallContext *ctx)
+void DataViewPrototype::method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DataView> v(scope, ctx->thisObject());
+ Scoped<DataView> v(scope, callData->thisObject);
if (!v)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(v->d()->byteOffset);
+ scope.result = Encode(v->d()->byteOffset);
}
template <typename T>
-ReturnedValue DataViewPrototype::method_getChar(CallContext *ctx)
+void DataViewPrototype::method_getChar(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DataView> v(scope, ctx->thisObject());
- if (!v || ctx->argc() < 1)
- return scope.engine->throwTypeError();
- double l = ctx->args()[0].toNumber();
+ Scoped<DataView> v(scope, callData->thisObject);
+ if (!v || callData->argc < 1)
+ THROW_TYPE_ERROR();
+ double l = callData->args[0].toNumber();
uint idx = (uint)l;
if (l != idx || idx + sizeof(T) > v->d()->byteLength)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
idx += v->d()->byteOffset;
T t = T(v->d()->buffer->data->data()[idx]);
- return Encode((int)t);
+ scope.result = Encode((int)t);
}
template <typename T>
-ReturnedValue DataViewPrototype::method_get(CallContext *ctx)
+void DataViewPrototype::method_get(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DataView> v(scope, ctx->thisObject());
- if (!v || ctx->argc() < 1)
- return scope.engine->throwTypeError();
- double l = ctx->args()[0].toNumber();
+ Scoped<DataView> v(scope, callData->thisObject);
+ if (!v || callData->argc < 1)
+ THROW_TYPE_ERROR();
+ double l = callData->args[0].toNumber();
uint idx = (uint)l;
if (l != idx || idx + sizeof(T) > v->d()->byteLength)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
idx += v->d()->byteOffset;
- bool littleEndian = ctx->argc() < 2 ? false : ctx->args()[1].toBoolean();
+ bool littleEndian = callData->argc < 2 ? false : callData->args[1].toBoolean();
T t = littleEndian
? qFromLittleEndian<T>((uchar *)v->d()->buffer->data->data() + idx)
: qFromBigEndian<T>((uchar *)v->d()->buffer->data->data() + idx);
- return Encode(t);
+ scope.result = Encode(t);
}
template <typename T>
-ReturnedValue DataViewPrototype::method_getFloat(CallContext *ctx)
+void DataViewPrototype::method_getFloat(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DataView> v(scope, ctx->thisObject());
- if (!v || ctx->argc() < 1)
- return scope.engine->throwTypeError();
- double l = ctx->args()[0].toNumber();
+ Scoped<DataView> v(scope, callData->thisObject);
+ if (!v || callData->argc < 1)
+ THROW_TYPE_ERROR();
+ double l = callData->args[0].toNumber();
uint idx = (uint)l;
if (l != idx || idx + sizeof(T) > v->d()->byteLength)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
idx += v->d()->byteOffset;
- bool littleEndian = ctx->argc() < 2 ? false : ctx->args()[1].toBoolean();
+ bool littleEndian = callData->argc < 2 ? false : callData->args[1].toBoolean();
if (sizeof(T) == 4) {
// float
@@ -223,7 +217,7 @@ ReturnedValue DataViewPrototype::method_getFloat(CallContext *ctx)
u.i = littleEndian
? qFromLittleEndian<uint>((uchar *)v->d()->buffer->data->data() + idx)
: qFromBigEndian<uint>((uchar *)v->d()->buffer->data->data() + idx);
- return Encode(u.f);
+ scope.result = Encode(u.f);
} else {
Q_ASSERT(sizeof(T) == 8);
union {
@@ -233,69 +227,66 @@ ReturnedValue DataViewPrototype::method_getFloat(CallContext *ctx)
u.i = littleEndian
? qFromLittleEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx)
: qFromBigEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx);
- return Encode(u.d);
+ scope.result = Encode(u.d);
}
}
template <typename T>
-ReturnedValue DataViewPrototype::method_setChar(CallContext *ctx)
+void DataViewPrototype::method_setChar(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DataView> v(scope, ctx->thisObject());
- if (!v || ctx->argc() < 1)
- return scope.engine->throwTypeError();
- double l = ctx->args()[0].toNumber();
+ Scoped<DataView> v(scope, callData->thisObject);
+ if (!v || callData->argc < 1)
+ THROW_TYPE_ERROR();
+ double l = callData->args[0].toNumber();
uint idx = (uint)l;
if (l != idx || idx + sizeof(T) > v->d()->byteLength)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
idx += v->d()->byteOffset;
- int val = ctx->argc() >= 2 ? ctx->args()[1].toInt32() : 0;
+ int val = callData->argc >= 2 ? callData->args[1].toInt32() : 0;
v->d()->buffer->data->data()[idx] = (char)val;
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
template <typename T>
-ReturnedValue DataViewPrototype::method_set(CallContext *ctx)
+void DataViewPrototype::method_set(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DataView> v(scope, ctx->thisObject());
- if (!v || ctx->argc() < 1)
- return scope.engine->throwTypeError();
- double l = ctx->args()[0].toNumber();
+ Scoped<DataView> v(scope, callData->thisObject);
+ if (!v || callData->argc < 1)
+ THROW_TYPE_ERROR();
+ double l = callData->args[0].toNumber();
uint idx = (uint)l;
if (l != idx || idx + sizeof(T) > v->d()->byteLength)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
idx += v->d()->byteOffset;
- int val = ctx->argc() >= 2 ? ctx->args()[1].toInt32() : 0;
+ int val = callData->argc >= 2 ? callData->args[1].toInt32() : 0;
- bool littleEndian = ctx->argc() < 3 ? false : ctx->args()[2].toBoolean();
+ bool littleEndian = callData->argc < 3 ? false : callData->args[2].toBoolean();
if (littleEndian)
qToLittleEndian<T>(val, (uchar *)v->d()->buffer->data->data() + idx);
else
qToBigEndian<T>(val, (uchar *)v->d()->buffer->data->data() + idx);
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
template <typename T>
-ReturnedValue DataViewPrototype::method_setFloat(CallContext *ctx)
+void DataViewPrototype::method_setFloat(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DataView> v(scope, ctx->thisObject());
- if (!v || ctx->argc() < 1)
- return scope.engine->throwTypeError();
- double l = ctx->args()[0].toNumber();
+ Scoped<DataView> v(scope, callData->thisObject);
+ if (!v || callData->argc < 1)
+ THROW_TYPE_ERROR();
+ double l = callData->args[0].toNumber();
uint idx = (uint)l;
if (l != idx || idx + sizeof(T) > v->d()->byteLength)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
idx += v->d()->byteOffset;
- double val = ctx->argc() >= 2 ? ctx->args()[1].toNumber() : qt_qnan();
- bool littleEndian = ctx->argc() < 3 ? false : ctx->args()[2].toBoolean();
+ double val = callData->argc >= 2 ? callData->args[1].toNumber() : qt_qnan();
+ bool littleEndian = callData->argc < 3 ? false : callData->args[2].toBoolean();
if (sizeof(T) == 4) {
// float
@@ -320,5 +311,5 @@ ReturnedValue DataViewPrototype::method_setFloat(CallContext *ctx)
else
qToBigEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx);
}
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index 246124394a..11cc0a6bd9 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -92,21 +92,21 @@ struct DataViewPrototype: Object
{
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_get_buffer(CallContext *ctx);
- static ReturnedValue method_get_byteLength(CallContext *ctx);
- static ReturnedValue method_get_byteOffset(CallContext *ctx);
+ static void method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData);
template <typename T>
- static ReturnedValue method_getChar(CallContext *ctx);
+ static void method_getChar(const BuiltinFunction *, Scope &scope, CallData *callData);
template <typename T>
- static ReturnedValue method_get(CallContext *ctx);
+ static void method_get(const BuiltinFunction *, Scope &scope, CallData *callData);
template <typename T>
- static ReturnedValue method_getFloat(CallContext *ctx);
+ static void method_getFloat(const BuiltinFunction *, Scope &scope, CallData *callData);
template <typename T>
- static ReturnedValue method_setChar(CallContext *ctx);
+ static void method_setChar(const BuiltinFunction *, Scope &scope, CallData *callData);
template <typename T>
- static ReturnedValue method_set(CallContext *ctx);
+ static void method_set(const BuiltinFunction *, Scope &scope, CallData *callData);
template <typename T>
- static ReturnedValue method_setFloat(CallContext *ctx);
+ static void method_setFloat(const BuiltinFunction *, Scope &scope, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 8cc6a25fea..b90c335b1c 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -780,435 +780,435 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("toJSON"), method_toJSON, 1);
}
-double DatePrototype::getThisDate(ExecutionContext *ctx)
+double DatePrototype::getThisDate(Scope &scope, CallData *callData)
{
- if (DateObject *thisObject = ctx->thisObject().as<DateObject>())
+ if (DateObject *thisObject = callData->thisObject.as<DateObject>())
return thisObject->date();
else {
- ctx->engine()->throwTypeError();
+ scope.engine->throwTypeError();
return 0;
}
}
-ReturnedValue DatePrototype::method_parse(CallContext *ctx)
+void DatePrototype::method_parse(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (!ctx->argc())
- return Encode(qt_qnan());
- return Encode(ParseString(ctx->args()[0].toQString()));
+ if (!callData->argc)
+ scope.result = Encode(qt_qnan());
+ else
+ scope.result = Encode(ParseString(callData->args[0].toQString()));
}
-ReturnedValue DatePrototype::method_UTC(CallContext *ctx)
+void DatePrototype::method_UTC(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- const int numArgs = ctx->argc();
+ const int numArgs = callData->argc;
if (numArgs >= 2) {
- double year = ctx->args()[0].toNumber();
- double month = ctx->args()[1].toNumber();
- double day = numArgs >= 3 ? ctx->args()[2].toNumber() : 1;
- double hours = numArgs >= 4 ? ctx->args()[3].toNumber() : 0;
- double mins = numArgs >= 5 ? ctx->args()[4].toNumber() : 0;
- double secs = numArgs >= 6 ? ctx->args()[5].toNumber() : 0;
- double ms = numArgs >= 7 ? ctx->args()[6].toNumber() : 0;
+ double year = callData->args[0].toNumber();
+ double month = callData->args[1].toNumber();
+ double day = numArgs >= 3 ? callData->args[2].toNumber() : 1;
+ double hours = numArgs >= 4 ? callData->args[3].toNumber() : 0;
+ double mins = numArgs >= 5 ? callData->args[4].toNumber() : 0;
+ double secs = numArgs >= 6 ? callData->args[5].toNumber() : 0;
+ double ms = numArgs >= 7 ? callData->args[6].toNumber() : 0;
if (year >= 0 && year <= 99)
year += 1900;
double t = MakeDate(MakeDay(year, month, day),
MakeTime(hours, mins, secs, ms));
- return Encode(TimeClip(t));
+ scope.result = Encode(TimeClip(t));
+ return;
}
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-ReturnedValue DatePrototype::method_now(CallContext *ctx)
+void DatePrototype::method_now(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Q_UNUSED(ctx);
+ Q_UNUSED(callData);
double t = currentTime();
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_toString(CallContext *ctx)
+void DatePrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- return ctx->d()->engine->newString(ToString(t))->asReturnedValue();
+ double t = getThisDate(scope, callData);
+ scope.result = scope.engine->newString(ToString(t));
}
-ReturnedValue DatePrototype::method_toDateString(CallContext *ctx)
+void DatePrototype::method_toDateString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- return ctx->d()->engine->newString(ToDateString(t))->asReturnedValue();
+ double t = getThisDate(scope, callData);
+ scope.result = scope.engine->newString(ToDateString(t));
}
-ReturnedValue DatePrototype::method_toTimeString(CallContext *ctx)
+void DatePrototype::method_toTimeString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- return ctx->d()->engine->newString(ToTimeString(t))->asReturnedValue();
+ double t = getThisDate(scope, callData);
+ scope.result = scope.engine->newString(ToTimeString(t));
}
-ReturnedValue DatePrototype::method_toLocaleString(CallContext *ctx)
+void DatePrototype::method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- return ctx->d()->engine->newString(ToLocaleString(t))->asReturnedValue();
+ double t = getThisDate(scope, callData);
+ scope.result = scope.engine->newString(ToLocaleString(t));
}
-ReturnedValue DatePrototype::method_toLocaleDateString(CallContext *ctx)
+void DatePrototype::method_toLocaleDateString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- return ctx->d()->engine->newString(ToLocaleDateString(t))->asReturnedValue();
+ double t = getThisDate(scope, callData);
+ scope.result = scope.engine->newString(ToLocaleDateString(t));
}
-ReturnedValue DatePrototype::method_toLocaleTimeString(CallContext *ctx)
+void DatePrototype::method_toLocaleTimeString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- return ctx->d()->engine->newString(ToLocaleTimeString(t))->asReturnedValue();
+ double t = getThisDate(scope, callData);
+ scope.result = scope.engine->newString(ToLocaleTimeString(t));
}
-ReturnedValue DatePrototype::method_valueOf(CallContext *ctx)
+void DatePrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- return Encode(t);
+ double t = getThisDate(scope, callData);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getTime(CallContext *ctx)
+void DatePrototype::method_getTime(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- return Encode(t);
+ double t = getThisDate(scope, callData);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getYear(CallContext *ctx)
+void DatePrototype::method_getYear(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = YearFromTime(LocalTime(t)) - 1900;
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getFullYear(CallContext *ctx)
+void DatePrototype::method_getFullYear(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = YearFromTime(LocalTime(t));
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getUTCFullYear(CallContext *ctx)
+void DatePrototype::method_getUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = YearFromTime(t);
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getMonth(CallContext *ctx)
+void DatePrototype::method_getMonth(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = MonthFromTime(LocalTime(t));
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getUTCMonth(CallContext *ctx)
+void DatePrototype::method_getUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = MonthFromTime(t);
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getDate(CallContext *ctx)
+void DatePrototype::method_getDate(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = DateFromTime(LocalTime(t));
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getUTCDate(CallContext *ctx)
+void DatePrototype::method_getUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = DateFromTime(t);
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getDay(CallContext *ctx)
+void DatePrototype::method_getDay(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = WeekDay(LocalTime(t));
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getUTCDay(CallContext *ctx)
+void DatePrototype::method_getUTCDay(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = WeekDay(t);
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getHours(CallContext *ctx)
+void DatePrototype::method_getHours(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = HourFromTime(LocalTime(t));
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getUTCHours(CallContext *ctx)
+void DatePrototype::method_getUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = HourFromTime(t);
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getMinutes(CallContext *ctx)
+void DatePrototype::method_getMinutes(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = MinFromTime(LocalTime(t));
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getUTCMinutes(CallContext *ctx)
+void DatePrototype::method_getUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = MinFromTime(t);
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getSeconds(CallContext *ctx)
+void DatePrototype::method_getSeconds(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = SecFromTime(LocalTime(t));
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getUTCSeconds(CallContext *ctx)
+void DatePrototype::method_getUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = SecFromTime(t);
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getMilliseconds(CallContext *ctx)
+void DatePrototype::method_getMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = msFromTime(LocalTime(t));
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getUTCMilliseconds(CallContext *ctx)
+void DatePrototype::method_getUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = msFromTime(t);
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_getTimezoneOffset(CallContext *ctx)
+void DatePrototype::method_getTimezoneOffset(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double t = getThisDate(ctx);
- if (! std::isnan(t))
+ double t = getThisDate(scope, callData);
+ if (!std::isnan(t))
t = (t - LocalTime(t)) / msPerMinute;
- return Encode(t);
+ scope.result = Encode(t);
}
-ReturnedValue DatePrototype::method_setTime(CallContext *ctx)
+void DatePrototype::method_setTime(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DateObject> self(scope, ctx->thisObject());
+ Scoped<DateObject> self(scope, callData->thisObject);
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- double t = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
+ double t = callData->argc ? callData->args[0].toNumber() : qt_qnan();
self->setDate(TimeClip(t));
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
+void DatePrototype::method_setMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<DateObject> self(scope, ctx->thisObject());
+ Scoped<DateObject> self(scope, callData->thisObject);
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = LocalTime(self->date());
- double ms = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
+ double ms = callData->argc ? callData->args[0].toNumber() : qt_qnan();
self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx)
+void DatePrototype::method_setUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
- double ms = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
+ double ms = callData->argc ? callData->args[0].toNumber() : qt_qnan();
self->setDate(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx)
+void DatePrototype::method_setSeconds(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = LocalTime(self->date());
- double sec = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
+ double sec = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double ms = (callData->argc < 2) ? msFromTime(t) : callData->args[1].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx)
+void DatePrototype::method_setUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
- double sec = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
+ double sec = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double ms = (callData->argc < 2) ? msFromTime(t) : callData->args[1].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx)
+void DatePrototype::method_setMinutes(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = LocalTime(self->date());
- double min = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
- double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
+ double min = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double sec = (callData->argc < 2) ? SecFromTime(t) : callData->args[1].toNumber();
+ double ms = (callData->argc < 3) ? msFromTime(t) : callData->args[2].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx)
+void DatePrototype::method_setUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
- double min = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
- double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
+ double min = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double sec = (callData->argc < 2) ? SecFromTime(t) : callData->args[1].toNumber();
+ double ms = (callData->argc < 3) ? msFromTime(t) : callData->args[2].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setHours(CallContext *ctx)
+void DatePrototype::method_setHours(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = LocalTime(self->date());
- double hour = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
- double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
- double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
+ double hour = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double min = (callData->argc < 2) ? MinFromTime(t) : callData->args[1].toNumber();
+ double sec = (callData->argc < 3) ? SecFromTime(t) : callData->args[2].toNumber();
+ double ms = (callData->argc < 4) ? msFromTime(t) : callData->args[3].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx)
+void DatePrototype::method_setUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
- double hour = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
- double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
- double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
+ double hour = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double min = (callData->argc < 2) ? MinFromTime(t) : callData->args[1].toNumber();
+ double sec = (callData->argc < 3) ? SecFromTime(t) : callData->args[2].toNumber();
+ double ms = (callData->argc < 4) ? msFromTime(t) : callData->args[3].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms)));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setDate(CallContext *ctx)
+void DatePrototype::method_setDate(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = LocalTime(self->date());
- double date = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
+ double date = callData->argc ? callData->args[0].toNumber() : qt_qnan();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx)
+void DatePrototype::method_setUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
- double date = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
+ double date = callData->argc ? callData->args[0].toNumber() : qt_qnan();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setMonth(CallContext *ctx)
+void DatePrototype::method_setMonth(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = LocalTime(self->date());
- double month = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
+ double month = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double date = (callData->argc < 2) ? DateFromTime(t) : callData->args[1].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx)
+void DatePrototype::method_setUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
- double month = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
+ double month = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double date = (callData->argc < 2) ? DateFromTime(t) : callData->args[1].toNumber();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
+void DatePrototype::method_setYear(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
if (std::isnan(t))
t = 0;
else
t = LocalTime(t);
- double year = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
+ double year = callData->argc ? callData->args[0].toNumber() : qt_qnan();
double r;
if (std::isnan(year)) {
r = qt_qnan();
@@ -1220,49 +1220,49 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
r = TimeClip(r);
}
self->setDate(r);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx)
+void DatePrototype::method_setUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
- double year = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
- double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
+ double year = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double month = (callData->argc < 2) ? MonthFromTime(t) : callData->args[1].toNumber();
+ double date = (callData->argc < 3) ? DateFromTime(t) : callData->args[2].toNumber();
t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx)
+void DatePrototype::method_setFullYear(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = LocalTime(self->date());
if (std::isnan(t))
t = 0;
- double year = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
- double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
+ double year = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double month = (callData->argc < 2) ? MonthFromTime(t) : callData->args[1].toNumber();
+ double date = (callData->argc < 3) ? DateFromTime(t) : callData->args[2].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
self->setDate(t);
- return Encode(self->date());
+ scope.result = Encode(self->date());
}
-ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx)
+void DatePrototype::method_toUTCString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
- return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue();
+ scope.result = scope.engine->newString(ToUTCString(t));
}
static void addZeroPrefixedInt(QString &str, int num, int nDigits)
@@ -1278,21 +1278,21 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits)
}
}
-ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
+void DatePrototype::method_toISOString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- DateObject *self = ctx->thisObject().as<DateObject>();
+ DateObject *self = callData->thisObject.as<DateObject>();
if (!self)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
double t = self->date();
if (!std::isfinite(t))
- return ctx->engine()->throwRangeError(ctx->thisObject());
+ RETURN_RESULT(scope.engine->throwRangeError(callData->thisObject));
QString result;
int year = (int)YearFromTime(t);
if (year < 0 || year > 9999) {
if (qAbs(year) >= 1000000)
- return ctx->d()->engine->newString(QStringLiteral("Invalid Date"))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(QStringLiteral("Invalid Date")));
result += year < 0 ? QLatin1Char('-') : QLatin1Char('+');
year = qAbs(year);
addZeroPrefixedInt(result, year, 6);
@@ -1313,32 +1313,29 @@ ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
addZeroPrefixedInt(result, msFromTime(t), 3);
result += QLatin1Char('Z');
- return ctx->d()->engine->newString(result)->asReturnedValue();
+ scope.result = scope.engine->newString(result);
}
-ReturnedValue DatePrototype::method_toJSON(CallContext *ctx)
+void DatePrototype::method_toJSON(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject O(scope, ctx->thisObject().toObject(scope.engine));
- if (scope.hasException())
- return Encode::undefined();
+ ScopedObject O(scope, callData->thisObject.toObject(scope.engine));
+ CHECK_EXCEPTION();
ScopedValue tv(scope, RuntimeHelpers::toPrimitive(O, NUMBER_HINT));
if (tv->isNumber() && !std::isfinite(tv->toNumber()))
- return Encode::null();
+ RETURN_RESULT(Encode::null());
- ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString")));
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("toISOString")));
ScopedValue v(scope, O->get(s));
FunctionObject *toIso = v->as<FunctionObject>();
if (!toIso)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedCallData callData(scope);
- callData->thisObject = ctx->thisObject();
- toIso->call(scope, callData);
- return scope.result.asReturnedValue();
+ ScopedCallData cData(scope);
+ cData->thisObject = callData->thisObject;
+ toIso->call(scope, cData);
}
void DatePrototype::timezoneUpdated()
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 835f6adbe0..a56d17f9b1 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -116,57 +116,57 @@ struct DatePrototype: DateObject
{
void init(ExecutionEngine *engine, Object *ctor);
- static double getThisDate(ExecutionContext *ctx);
-
- static ReturnedValue method_parse(CallContext *ctx);
- static ReturnedValue method_UTC(CallContext *ctx);
- static ReturnedValue method_now(CallContext *ctx);
-
- static ReturnedValue method_toString(CallContext *ctx);
- static ReturnedValue method_toDateString(CallContext *ctx);
- static ReturnedValue method_toTimeString(CallContext *ctx);
- static ReturnedValue method_toLocaleString(CallContext *ctx);
- static ReturnedValue method_toLocaleDateString(CallContext *ctx);
- static ReturnedValue method_toLocaleTimeString(CallContext *ctx);
- static ReturnedValue method_valueOf(CallContext *ctx);
- static ReturnedValue method_getTime(CallContext *ctx);
- static ReturnedValue method_getYear(CallContext *ctx);
- static ReturnedValue method_getFullYear(CallContext *ctx);
- static ReturnedValue method_getUTCFullYear(CallContext *ctx);
- static ReturnedValue method_getMonth(CallContext *ctx);
- static ReturnedValue method_getUTCMonth(CallContext *ctx);
- static ReturnedValue method_getDate(CallContext *ctx);
- static ReturnedValue method_getUTCDate(CallContext *ctx);
- static ReturnedValue method_getDay(CallContext *ctx);
- static ReturnedValue method_getUTCDay(CallContext *ctx);
- static ReturnedValue method_getHours(CallContext *ctx);
- static ReturnedValue method_getUTCHours(CallContext *ctx);
- static ReturnedValue method_getMinutes(CallContext *ctx);
- static ReturnedValue method_getUTCMinutes(CallContext *ctx);
- static ReturnedValue method_getSeconds(CallContext *ctx);
- static ReturnedValue method_getUTCSeconds(CallContext *ctx);
- static ReturnedValue method_getMilliseconds(CallContext *ctx);
- static ReturnedValue method_getUTCMilliseconds(CallContext *ctx);
- static ReturnedValue method_getTimezoneOffset(CallContext *ctx);
- static ReturnedValue method_setTime(CallContext *ctx);
- static ReturnedValue method_setMilliseconds(CallContext *ctx);
- static ReturnedValue method_setUTCMilliseconds(CallContext *ctx);
- static ReturnedValue method_setSeconds(CallContext *ctx);
- static ReturnedValue method_setUTCSeconds(CallContext *ctx);
- static ReturnedValue method_setMinutes(CallContext *ctx);
- static ReturnedValue method_setUTCMinutes(CallContext *ctx);
- static ReturnedValue method_setHours(CallContext *ctx);
- static ReturnedValue method_setUTCHours(CallContext *ctx);
- static ReturnedValue method_setDate(CallContext *ctx);
- static ReturnedValue method_setUTCDate(CallContext *ctx);
- static ReturnedValue method_setMonth(CallContext *ctx);
- static ReturnedValue method_setUTCMonth(CallContext *ctx);
- static ReturnedValue method_setYear(CallContext *ctx);
- static ReturnedValue method_setFullYear(CallContext *ctx);
- static ReturnedValue method_setUTCFullYear(CallContext *ctx);
- static ReturnedValue method_toUTCString(CallContext *ctx);
- static ReturnedValue method_toISOString(CallContext *ctx);
- static ReturnedValue method_toJSON(CallContext *ctx);
+ static double getThisDate(Scope &scope, CallData *callData);
+
+ static void method_parse(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_UTC(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_now(const BuiltinFunction *, Scope &scope, CallData *callData);
+
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toDateString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toTimeString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toLocaleDateString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toLocaleTimeString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getTime(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getYear(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getFullYear(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getMonth(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getDate(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getDay(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getUTCDay(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getHours(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getMinutes(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getSeconds(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getTimezoneOffset(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setTime(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setSeconds(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setMinutes(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setHours(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setDate(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setMonth(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setYear(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setFullYear(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_setUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toUTCString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toISOString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toJSON(const BuiltinFunction *, Scope &scope, CallData *callData);
static void timezoneUpdated();
};
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 8f2c5174da..a11f7f0875 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -158,8 +158,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
}
Q_ASSERT(maxCallDepth > 0);
- MemoryManager::GCBlocker gcBlocker(memoryManager);
-
if (!factory) {
#if QT_CONFIG(qml_interpreter)
bool jitDisabled = true;
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 597ded6ae1..f290bc5136 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -153,12 +153,11 @@ const char *ErrorObject::className(Heap::ErrorObject::ErrorType t)
Q_UNREACHABLE();
}
-ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
+void ErrorObject::method_get_stack(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<ErrorObject> This(scope, ctx->thisObject());
+ Scoped<ErrorObject> This(scope, callData->thisObject);
if (!This)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (!This->d()->stack) {
QString trace;
for (int i = 0; i < This->d()->stackTrace->count(); ++i) {
@@ -169,9 +168,9 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
if (frame.line >= 0)
trace += QLatin1Char(':') + QString::number(frame.line);
}
- This->d()->stack = ctx->d()->engine->newString(trace);
+ This->d()->stack = scope.engine->newString(trace);
}
- return This->d()->stack->asReturnedValue();
+ scope.result = This->d()->stack;
}
void ErrorObject::markObjects(Heap::Base *that, ExecutionEngine *e)
@@ -335,22 +334,20 @@ void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, He
obj->defineDefaultProperty(engine->id_toString(), method_toString, 0);
}
-ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
+void ErrorPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
-
- Object *o = ctx->thisObject().as<Object>();
+ Object *o = callData->thisObject.as<Object>();
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedValue name(scope, o->get(ctx->d()->engine->id_name()));
+ ScopedValue name(scope, o->get(scope.engine->id_name()));
QString qname;
if (name->isUndefined())
qname = QStringLiteral("Error");
else
qname = name->toQString();
- ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("message")));
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("message")));
ScopedValue message(scope, o->get(s));
QString qmessage;
if (!message->isUndefined())
@@ -365,5 +362,5 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
str = qname + QLatin1String(": ") + qmessage;
}
- return ctx->d()->engine->newString(str)->asReturnedValue();
+ scope.result = scope.engine->newString(str)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 2b3ab25e2d..9ba9f05234 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -172,7 +172,7 @@ struct ErrorObject: Object {
static const char *className(Heap::ErrorObject::ErrorType t);
- static ReturnedValue method_get_stack(CallContext *ctx);
+ static void method_get_stack(const BuiltinFunction *, Scope &scope, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
@@ -282,7 +282,7 @@ struct ErrorPrototype : ErrorObject
void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this, Heap::ErrorObject::Error); }
static void init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t);
- static ReturnedValue method_toString(CallContext *ctx);
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
};
struct EvalErrorPrototype : ErrorObject
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 64f7b98618..b2d89220ea 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -270,23 +270,22 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
}
-ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
+void FunctionPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- FunctionObject *fun = ctx->thisObject().as<FunctionObject>();
+ FunctionObject *fun = callData->thisObject.as<FunctionObject>();
if (!fun)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return ctx->d()->engine->newString(QStringLiteral("function() { [code] }"))->asReturnedValue();
+ scope.result = scope.engine->newString(QStringLiteral("function() { [code] }"));
}
-ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
+void FunctionPrototype::method_apply(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- FunctionObject *o = ctx->thisObject().as<FunctionObject>();
+ FunctionObject *o = callData->thisObject.as<FunctionObject>();
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- Scope scope(ctx);
- ScopedValue arg(scope, ctx->argument(1));
+ ScopedValue arg(scope, callData->argument(1));
ScopedObject arr(scope, arg);
@@ -294,75 +293,71 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
if (!arr) {
len = 0;
if (!arg->isNullOrUndefined())
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
} else {
len = arr->getLength();
}
- ScopedCallData callData(scope, len);
+ ScopedCallData cData(scope, len);
if (len) {
if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast<ArgumentsObject>()->fullyCreated()) {
QV4::ArgumentsObject *a = arr->cast<ArgumentsObject>();
int l = qMin(len, (uint)a->d()->context->callData->argc);
- memcpy(callData->args, a->d()->context->callData->args, l*sizeof(Value));
+ memcpy(cData->args, a->d()->context->callData->args, l*sizeof(Value));
for (quint32 i = l; i < len; ++i)
- callData->args[i] = Primitive::undefinedValue();
+ cData->args[i] = Primitive::undefinedValue();
} else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) {
auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData());
uint alen = sad ? sad->len : 0;
if (alen > len)
alen = len;
for (uint i = 0; i < alen; ++i)
- callData->args[i] = sad->data(i);
+ cData->args[i] = sad->data(i);
for (quint32 i = alen; i < len; ++i)
- callData->args[i] = Primitive::undefinedValue();
+ cData->args[i] = Primitive::undefinedValue();
} else {
for (quint32 i = 0; i < len; ++i)
- callData->args[i] = arr->getIndexed(i);
+ cData->args[i] = arr->getIndexed(i);
}
}
- callData->thisObject = ctx->argument(0);
- o->call(scope, callData);
- return scope.result.asReturnedValue();
+ cData->thisObject = callData->argument(0);
+ o->call(scope, cData);
}
-ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
+void FunctionPrototype::method_call(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- FunctionObject *o = ctx->thisObject().as<FunctionObject>();
+ FunctionObject *o = callData->thisObject.as<FunctionObject>();
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- Scope scope(ctx);
- ScopedCallData callData(scope, ctx->argc() ? ctx->argc() - 1 : 0);
- if (ctx->argc()) {
- for (int i = 1; i < ctx->argc(); ++i)
- callData->args[i - 1] = ctx->args()[i];
+ ScopedCallData cData(scope, callData->argc ? callData->argc - 1 : 0);
+ if (callData->argc) {
+ for (int i = 1; i < callData->argc; ++i)
+ cData->args[i - 1] = callData->args[i];
}
- callData->thisObject = ctx->argument(0);
+ cData->thisObject = callData->argument(0);
- o->call(scope, callData);
- return scope.result.asReturnedValue();
+ o->call(scope, cData);
}
-ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
+void FunctionPrototype::method_bind(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- FunctionObject *target = ctx->thisObject().as<FunctionObject>();
+ FunctionObject *target = callData->thisObject.as<FunctionObject>();
if (!target)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- Scope scope(ctx);
- ScopedValue boundThis(scope, ctx->argument(0));
+ ScopedValue boundThis(scope, callData->argument(0));
Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0);
- if (ctx->argc() > 1) {
- boundArgs = MemberData::allocate(scope.engine, ctx->argc() - 1);
- boundArgs->d()->size = ctx->argc() - 1;
- memcpy(boundArgs->data(), ctx->args() + 1, (ctx->argc() - 1)*sizeof(Value));
+ if (callData->argc > 1) {
+ boundArgs = MemberData::allocate(scope.engine, callData->argc - 1);
+ boundArgs->d()->size = callData->argc - 1;
+ memcpy(boundArgs->data(), callData->args + 1, (callData->argc - 1)*sizeof(Value));
}
ExecutionContext *global = scope.engine->rootContext();
- return BoundFunction::create(global, target, boundThis, boundArgs)->asReturnedValue();
+ scope.result = BoundFunction::create(global, target, boundThis, boundArgs);
}
DEFINE_OBJECT_VTABLE(ScriptFunction);
@@ -459,22 +454,22 @@ Heap::Object *ScriptFunction::protoForConstructor() const
-DEFINE_OBJECT_VTABLE(BuiltinFunction);
+DEFINE_OBJECT_VTABLE(OldBuiltinFunction);
-void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *))
+void Heap::OldBuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *))
{
Heap::FunctionObject::init(scope, name);
this->code = code;
}
-void BuiltinFunction::construct(const Managed *f, Scope &scope, CallData *)
+void OldBuiltinFunction::construct(const Managed *f, Scope &scope, CallData *)
{
- scope.result = static_cast<const BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
+ scope.result = static_cast<const OldBuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
}
-void BuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData)
+void OldBuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData)
{
- const BuiltinFunction *f = static_cast<const BuiltinFunction *>(that);
+ const OldBuiltinFunction *f = static_cast<const OldBuiltinFunction *>(that);
ExecutionEngine *v4 = scope.engine;
if (v4->hasException) {
scope.result = Encode::undefined();
@@ -484,15 +479,41 @@ void BuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData
ExecutionContextSaver ctxSaver(scope);
- CallContext::Data ctx = CallContext::Data::createOnStack(v4);
- ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
- ctx.callData = callData;
- v4->pushContext(&ctx);
- Q_ASSERT(v4->current == &ctx);
+ CallContext::Data *ctx = v4->memoryManager->allocSimpleCallContext(v4);
+ ctx->strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
+ ctx->callData = callData;
+ v4->pushContext(ctx);
+ Q_ASSERT(v4->current == ctx);
scope.result = f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext));
+ v4->memoryManager->freeSimpleCallContext();
+}
+
+DEFINE_OBJECT_VTABLE(BuiltinFunction);
+
+void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *))
+{
+ Heap::FunctionObject::init(scope, name);
+ this->code = code;
+}
+
+void BuiltinFunction::construct(const Managed *f, Scope &scope, CallData *)
+{
+ scope.result = static_cast<const BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
+}
+
+void BuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData)
+{
+ const BuiltinFunction *f = static_cast<const BuiltinFunction *>(that);
+ ExecutionEngine *v4 = scope.engine;
+ if (v4->hasException) {
+ scope.result = Encode::undefined();
+ return;
+ }
+ f->d()->code(f, scope, callData);
}
+
void IndexedBuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData)
{
const IndexedBuiltinFunction *f = static_cast<const IndexedBuiltinFunction *>(that);
@@ -505,13 +526,14 @@ void IndexedBuiltinFunction::call(const Managed *that, Scope &scope, CallData *c
ExecutionContextSaver ctxSaver(scope);
- CallContext::Data ctx = CallContext::Data::createOnStack(v4);
- ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
- ctx.callData = callData;
- v4->pushContext(&ctx);
- Q_ASSERT(v4->current == &ctx);
+ CallContext::Data *ctx = v4->memoryManager->allocSimpleCallContext(v4);
+ ctx->strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
+ ctx->callData = callData;
+ v4->pushContext(ctx);
+ Q_ASSERT(v4->current == ctx);
scope.result = f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext), f->d()->index);
+ v4->memoryManager->freeSimpleCallContext();
}
DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index a02e89e883..45d7485f1b 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -61,6 +61,8 @@ struct QQmlSourceLocation;
namespace QV4 {
+struct BuiltinFunction;
+
namespace Heap {
struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
@@ -93,11 +95,16 @@ struct FunctionPrototype : FunctionObject {
void init();
};
-struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
+struct Q_QML_EXPORT OldBuiltinFunction : FunctionObject {
void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *));
ReturnedValue (*code)(QV4::CallContext *);
};
+struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
+ void init(QV4::ExecutionContext *scope, QV4::String *name, void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *));
+ void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *);
+};
+
struct IndexedBuiltinFunction : FunctionObject {
inline void init(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(QV4::CallContext *ctx, uint index));
ReturnedValue (*code)(QV4::CallContext *, uint index);
@@ -177,16 +184,27 @@ struct FunctionPrototype: FunctionObject
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_toString(CallContext *ctx);
- static ReturnedValue method_apply(CallContext *ctx);
- static ReturnedValue method_call(CallContext *ctx);
- static ReturnedValue method_bind(CallContext *ctx);
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_apply(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_call(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_bind(const BuiltinFunction *, Scope &scope, CallData *callData);
};
-struct Q_QML_EXPORT BuiltinFunction: FunctionObject {
+struct Q_QML_EXPORT OldBuiltinFunction : FunctionObject {
+ V4_OBJECT2(OldBuiltinFunction, FunctionObject)
+
+ static void construct(const Managed *, Scope &scope, CallData *);
+ static void call(const Managed *that, Scope &scope, CallData *callData);
+};
+
+struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
V4_OBJECT2(BuiltinFunction, FunctionObject)
- static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
+ static Heap::OldBuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
+ {
+ return scope->engine()->memoryManager->allocObject<OldBuiltinFunction>(scope, name, code);
+ }
+ static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *))
{
return scope->engine()->memoryManager->allocObject<BuiltinFunction>(scope, name, code);
}
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index c37ad1668d..66861bf697 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -97,19 +97,19 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
//
// NOTE: This should match the logic in qv4targetplatform_p.h!
-#if defined(Q_PROCESSOR_X86) && !defined(__ILP32__) \
+#if defined(Q_PROCESSOR_X86) && (QT_POINTER_SIZE == 4) \
&& (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD))
# define V4_ENABLE_JIT
-#elif defined(Q_PROCESSOR_X86_64) && !defined(__ILP32__) \
+#elif defined(Q_PROCESSOR_X86_64) && (QT_POINTER_SIZE == 8) \
&& (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
# define V4_ENABLE_JIT
-#elif defined(Q_PROCESSOR_ARM_32)
+#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4)
# if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4)
# define V4_ENABLE_JIT
# elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2 // clang 3.5 and later will set this if the core supports the Thumb-2 ISA.
# define V4_ENABLE_JIT
# endif
-#elif defined(Q_PROCESSOR_ARM_64)
+#elif defined(Q_PROCESSOR_ARM_64) && (QT_POINTER_SIZE == 8)
# if defined(Q_OS_LINUX)
# define V4_ENABLE_JIT
# endif
@@ -208,6 +208,7 @@ struct StringObject;
struct ArrayObject;
struct DateObject;
struct FunctionObject;
+struct BuiltinFunction;
struct ErrorObject;
struct ArgumentsObject;
struct Managed;
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index af92ce1ad8..1bc91f832b 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -423,18 +423,15 @@ static inline int toInt(const QChar &qc, int R)
}
// parseInt [15.1.2.2]
-ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx)
+void GlobalFunctions::method_parseInt(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedValue inputString(scope, ctx->argument(0));
- ScopedValue radix(scope, ctx->argument(1));
+ ScopedValue inputString(scope, callData->argument(0));
+ ScopedValue radix(scope, callData->argument(1));
int R = radix->isUndefined() ? 0 : radix->toInt32();
// [15.1.2.2] step by step:
QString trimmed = inputString->toQString().trimmed(); // 1 + 2
-
- if (ctx->d()->engine->hasException)
- return Encode::undefined();
+ CHECK_EXCEPTION();
const QChar *pos = trimmed.constData();
const QChar *end = pos + trimmed.length();
@@ -449,7 +446,7 @@ ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx)
bool stripPrefix = true; // 7
if (R) { // 8
if (R < 2 || R > 36)
- return Encode(std::numeric_limits<double>::quiet_NaN()); // 8a
+ RETURN_RESULT(Encode(std::numeric_limits<double>::quiet_NaN())); // 8a
if (R != 16)
stripPrefix = false; // 8b
} else { // 9
@@ -466,13 +463,13 @@ ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx)
// 11: Z is progressively built below
// 13: this is handled by the toInt function
if (pos == end) // 12
- return Encode(std::numeric_limits<double>::quiet_NaN());
+ RETURN_RESULT(Encode(std::numeric_limits<double>::quiet_NaN()));
bool overflow = false;
qint64 v_overflow = 0;
unsigned overflow_digit_count = 0;
int d = toInt(*pos++, R);
if (d == -1)
- return Encode(std::numeric_limits<double>::quiet_NaN());
+ RETURN_RESULT(Encode(std::numeric_limits<double>::quiet_NaN()));
qint64 v = d;
while (pos != end) {
d = toInt(*pos++, R);
@@ -499,155 +496,148 @@ ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx)
if (overflow) {
double result = (double) v_overflow * pow(static_cast<double>(R), static_cast<double>(overflow_digit_count));
result += v;
- return Encode(sign * result);
+ RETURN_RESULT(Encode(sign * result));
} else {
- return Encode(sign * (double) v); // 15
+ RETURN_RESULT(Encode(sign * (double) v)); // 15
}
}
// parseFloat [15.1.2.3]
-ReturnedValue GlobalFunctions::method_parseFloat(CallContext *ctx)
+void GlobalFunctions::method_parseFloat(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
-
// [15.1.2.3] step by step:
- ScopedString inputString(scope, ctx->argument(0), ScopedString::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
+ ScopedString inputString(scope, callData->argument(0), ScopedString::Convert);
+ CHECK_EXCEPTION();
QString trimmed = inputString->toQString().trimmed(); // 2
// 4:
if (trimmed.startsWith(QLatin1String("Infinity"))
|| trimmed.startsWith(QLatin1String("+Infinity")))
- return Encode(Q_INFINITY);
+ RETURN_RESULT(Encode(Q_INFINITY));
if (trimmed.startsWith(QLatin1String("-Infinity")))
- return Encode(-Q_INFINITY);
+ RETURN_RESULT(Encode(-Q_INFINITY));
QByteArray ba = trimmed.toLatin1();
bool ok;
const char *begin = ba.constData();
const char *end = 0;
double d = qstrtod(begin, &end, &ok);
if (end - begin == 0)
- return Encode(std::numeric_limits<double>::quiet_NaN()); // 3
+ RETURN_RESULT(Encode(std::numeric_limits<double>::quiet_NaN())); // 3
else
- return Encode(d);
+ RETURN_RESULT(Encode(d));
}
/// isNaN [15.1.2.4]
-ReturnedValue GlobalFunctions::method_isNaN(CallContext *ctx)
+void GlobalFunctions::method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (!ctx->argc())
+ if (!callData->argc)
// undefined gets converted to NaN
- return Encode(true);
+ RETURN_RESULT(Encode(true));
- if (ctx->args()[0].integerCompatible())
- return Encode(false);
+ if (callData->args[0].integerCompatible())
+ RETURN_RESULT(Encode(false));
- double d = ctx->args()[0].toNumber();
- return Encode((bool)std::isnan(d));
+ double d = callData->args[0].toNumber();
+ RETURN_RESULT(Encode((bool)std::isnan(d)));
}
/// isFinite [15.1.2.5]
-ReturnedValue GlobalFunctions::method_isFinite(CallContext *ctx)
+void GlobalFunctions::method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (!ctx->argc())
+ if (!callData->argc)
// undefined gets converted to NaN
- return Encode(false);
+ RETURN_RESULT(Encode(false));
- if (ctx->args()[0].integerCompatible())
- return Encode(true);
+ if (callData->args[0].integerCompatible())
+ RETURN_RESULT(Encode(true));
- double d = ctx->args()[0].toNumber();
- return Encode((bool)std::isfinite(d));
+ double d = callData->args[0].toNumber();
+ RETURN_RESULT(Encode((bool)std::isfinite(d)));
}
/// decodeURI [15.1.3.1]
-ReturnedValue GlobalFunctions::method_decodeURI(CallContext *context)
+void GlobalFunctions::method_decodeURI(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (context->argc() == 0)
- return Encode::undefined();
+ if (callData->argc == 0)
+ RETURN_UNDEFINED();
- QString uriString = context->args()[0].toQString();
+ QString uriString = callData->args[0].toQString();
bool ok;
QString out = decode(uriString, DecodeNonReserved, &ok);
if (!ok) {
- Scope scope(context);
- ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
- return context->engine()->throwURIError(s);
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence")));
+ RETURN_RESULT(scope.engine->throwURIError(s));
}
- return context->d()->engine->newString(out)->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(out));
}
/// decodeURIComponent [15.1.3.2]
-ReturnedValue GlobalFunctions::method_decodeURIComponent(CallContext *context)
+void GlobalFunctions::method_decodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (context->argc() == 0)
- return Encode::undefined();
+ if (callData->argc == 0)
+ RETURN_UNDEFINED();
- QString uriString = context->args()[0].toQString();
+ QString uriString = callData->args[0].toQString();
bool ok;
QString out = decode(uriString, DecodeAll, &ok);
if (!ok) {
- Scope scope(context);
- ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
- return context->engine()->throwURIError(s);
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence")));
+ RETURN_RESULT(scope.engine->throwURIError(s));
}
- return context->d()->engine->newString(out)->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(out));
}
/// encodeURI [15.1.3.3]
-ReturnedValue GlobalFunctions::method_encodeURI(CallContext *context)
+void GlobalFunctions::method_encodeURI(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (context->argc() == 0)
- return Encode::undefined();
+ if (callData->argc == 0)
+ RETURN_UNDEFINED();
- QString uriString = context->args()[0].toQString();
+ QString uriString = callData->args[0].toQString();
bool ok;
QString out = encode(uriString, uriUnescapedReserved, &ok);
if (!ok) {
- Scope scope(context);
- ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
- return context->engine()->throwURIError(s);
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence")));
+ RETURN_RESULT(scope.engine->throwURIError(s));
}
- return context->d()->engine->newString(out)->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(out));
}
/// encodeURIComponent [15.1.3.4]
-ReturnedValue GlobalFunctions::method_encodeURIComponent(CallContext *context)
+void GlobalFunctions::method_encodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (context->argc() == 0)
- return Encode::undefined();
+ if (callData->argc == 0)
+ RETURN_UNDEFINED();
- QString uriString = context->args()[0].toQString();
+ QString uriString = callData->args[0].toQString();
bool ok;
QString out = encode(uriString, uriUnescaped, &ok);
if (!ok) {
- Scope scope(context);
- ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
- return context->engine()->throwURIError(s);
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence")));
+ RETURN_RESULT(scope.engine->throwURIError(s));
}
- return context->d()->engine->newString(out)->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(out));
}
-ReturnedValue GlobalFunctions::method_escape(CallContext *context)
+void GlobalFunctions::method_escape(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (!context->argc())
- return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue();
+ if (!callData->argc)
+ RETURN_RESULT(scope.engine->newString(QStringLiteral("undefined")));
- QString str = context->args()[0].toQString();
- return context->d()->engine->newString(escape(str))->asReturnedValue();
+ QString str = callData->args[0].toQString();
+ RETURN_RESULT(scope.engine->newString(escape(str)));
}
-ReturnedValue GlobalFunctions::method_unescape(CallContext *context)
+void GlobalFunctions::method_unescape(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (!context->argc())
- return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue();
+ if (!callData->argc)
+ RETURN_RESULT(scope.engine->newString(QStringLiteral("undefined")));
- QString str = context->args()[0].toQString();
- return context->d()->engine->newString(unescape(str))->asReturnedValue();
+ QString str = callData->args[0].toQString();
+ RETURN_RESULT(scope.engine->newString(unescape(str)));
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index e8b3a92d34..273f1ba7ea 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -76,16 +76,16 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject
struct GlobalFunctions
{
- static ReturnedValue method_parseInt(CallContext *context);
- static ReturnedValue method_parseFloat(CallContext *context);
- static ReturnedValue method_isNaN(CallContext *context);
- static ReturnedValue method_isFinite(CallContext *ctx);
- static ReturnedValue method_decodeURI(CallContext *context);
- static ReturnedValue method_decodeURIComponent(CallContext *context);
- static ReturnedValue method_encodeURI(CallContext *context);
- static ReturnedValue method_encodeURIComponent(CallContext *context);
- static ReturnedValue method_escape(CallContext *context);
- static ReturnedValue method_unescape(CallContext *context);
+ static void method_parseInt(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_parseFloat(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_decodeURI(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_decodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_encodeURI(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_encodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_escape(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_unescape(const BuiltinFunction *, Scope &scope, CallData *callData);
};
}
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 1d393cf0aa..f033eb2d2d 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -195,23 +195,22 @@ void QV4Include::finished()
/*
Documented in qv8engine.cpp
*/
-QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
+void QV4Include::method_include(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- if (!ctx->argc())
- return QV4::Encode::undefined();
+ if (!callData->argc)
+ RETURN_UNDEFINED();
- QV4::Scope scope(ctx->engine());
QQmlContextData *context = scope.engine->callingQmlContext();
if (!context || !context->isJSContext)
- V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
+ RETURN_RESULT(scope.engine->throwError(QString::fromUtf8("Qt.include(): Can only be called from JavaScript files")));
QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue());
- if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>())
- callbackFunction = ctx->args()[1];
+ if (callData->argc >= 2 && callData->args[1].as<QV4::FunctionObject>())
+ callbackFunction = callData->args[1];
#if QT_CONFIG(qml_network)
- QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow()));
+ QUrl url(scope.engine->resolvedUrl(callData->args[0].toQStringNoThrow()));
if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor())
url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
@@ -261,12 +260,12 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
callback(callbackFunction, result);
}
- return result->asReturnedValue();
+ scope.result = result;
#else
QV4::ScopedValue result(scope);
result = resultValue(scope.engine, NetworkError);
callback(callbackFunction, result);
- return result->asReturnedValue();
+ scope.result = result;
#endif
}
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 4c601a5e7b..5908d6bfde 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -77,7 +77,7 @@ public:
Exception = 3
};
- static QV4::ReturnedValue method_include(QV4::CallContext *ctx);
+ static void method_include(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
private Q_SLOTS:
void finished();
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index d17da9af0c..bac71b4537 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -128,48 +128,22 @@ InternalClass::InternalClass(const QV4::InternalClass &other)
static void insertHoleIntoPropertyData(Object *object, int idx)
{
- int inlineSize = object->d()->inlineMemberSize;
int icSize = object->internalClass()->size;
- int from = qMax(idx, inlineSize);
+ int from = idx;
int to = from + 1;
- if (from < icSize) {
+ if (from < icSize)
memmove(object->propertyData(to), object->propertyData(from),
(icSize - from - 1) * sizeof(Value));
- }
- if (from == idx)
- return;
- if (inlineSize < icSize)
- *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1);
- from = idx;
- to = from + 1;
- if (from < inlineSize - 1) {
- memmove(object->propertyData(to), object->propertyData(from),
- (inlineSize - from - 1) * sizeof(Value));
- }
}
static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
{
- int inlineSize = object->d()->inlineMemberSize;
int delta = (accessor ? 2 : 1);
int oldSize = object->internalClass()->size + delta;
int to = idx;
int from = to + delta;
- if (from < inlineSize) {
- memmove(object->propertyData(to), object->d()->propertyData(from), (inlineSize - from)*sizeof(Value));
- to = inlineSize - delta;
- from = inlineSize;
- }
- if (to < inlineSize && from < oldSize) {
- Q_ASSERT(from >= inlineSize);
- memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value));
- to = inlineSize;
- from = inlineSize + delta;
- }
- if (from < oldSize) {
- Q_ASSERT(to >= inlineSize && from > to);
+ if (from < oldSize)
memmove(object->propertyData(to), object->d()->propertyData(from), (oldSize - to)*sizeof(Value));
- }
}
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index dcda949c97..1d8ef4b0fb 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -234,7 +234,7 @@ struct InternalClassTransition
{ return id == other.id && flags == other.flags; }
bool operator<(const InternalClassTransition &other) const
- { return id < other.id; }
+ { return id < other.id || (id == other.id && flags < other.flags); }
};
struct InternalClass : public QQmlJS::Managed {
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index d79e6242ba..1d571f53f3 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -883,10 +883,9 @@ void Heap::JsonObject::init()
}
-ReturnedValue JsonObject::method_parse(CallContext *ctx)
+void JsonObject::method_parse(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedValue v(scope, ctx->argument(0));
+ ScopedValue v(scope, callData->argument(0));
QString jtext = v->toQString();
DEBUG << "parsing source = " << jtext;
@@ -895,19 +894,17 @@ ReturnedValue JsonObject::method_parse(CallContext *ctx)
ScopedValue result(scope, parser.parse(&error));
if (error.error != QJsonParseError::NoError) {
DEBUG << "parse error" << error.errorString();
- return ctx->engine()->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"));
+ RETURN_RESULT(scope.engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error")));
}
- return result->asReturnedValue();
+ scope.result = result;
}
-ReturnedValue JsonObject::method_stringify(CallContext *ctx)
+void JsonObject::method_stringify(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
-
Stringify stringify(scope.engine);
- ScopedObject o(scope, ctx->argument(1));
+ ScopedObject o(scope, callData->argument(1));
if (o) {
stringify.replacerFunction = o->as<FunctionObject>();
if (o->isArrayObject()) {
@@ -932,7 +929,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
}
}
- ScopedValue s(scope, ctx->argument(2));
+ ScopedValue s(scope, callData->argument(2));
if (NumberObject *n = s->as<NumberObject>())
s = Encode(n->value());
else if (StringObject *so = s->as<StringObject>())
@@ -945,11 +942,11 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
}
- ScopedValue arg0(scope, ctx->argument(0));
+ ScopedValue arg0(scope, callData->argument(0));
QString result = stringify.Str(QString(), arg0);
if (result.isEmpty() || scope.engine->hasException)
- return Encode::undefined();
- return ctx->d()->engine->newString(result)->asReturnedValue();
+ RETURN_UNDEFINED();
+ scope.result = scope.engine->newString(result);
}
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 43248a214d..a73ce1c74e 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -88,8 +88,8 @@ private:
typedef QSet<ObjectItem> V4ObjectSet;
public:
- static ReturnedValue method_parse(CallContext *ctx);
- static ReturnedValue method_stringify(CallContext *ctx);
+ static void method_parse(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_stringify(const BuiltinFunction *, Scope &scope, CallData *callData);
static ReturnedValue fromJsonValue(ExecutionEngine *engine, const QJsonValue &value);
static ReturnedValue fromJsonObject(ExecutionEngine *engine, const QJsonObject &object);
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index e03b2762cc..2d9d81c64b 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -92,160 +92,160 @@ static Q_ALWAYS_INLINE double copySign(double x, double y)
return ::copysign(x, y);
}
-ReturnedValue MathObject::method_abs(CallContext *context)
+void MathObject::method_abs(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (!context->argc())
- return Encode(qt_qnan());
+ if (!callData->argc)
+ RETURN_RESULT(Encode(qt_qnan()));
- if (context->args()[0].isInteger()) {
- int i = context->args()[0].integerValue();
- return Encode(i < 0 ? - i : i);
+ if (callData->args[0].isInteger()) {
+ int i = callData->args[0].integerValue();
+ RETURN_RESULT(Encode(i < 0 ? - i : i));
}
- double v = context->args()[0].toNumber();
+ double v = callData->args[0].toNumber();
if (v == 0) // 0 | -0
- return Encode(0);
+ RETURN_RESULT(Encode(0));
- return Encode(v < 0 ? -v : v);
+ RETURN_RESULT(Encode(v < 0 ? -v : v));
}
-ReturnedValue MathObject::method_acos(CallContext *context)
+void MathObject::method_acos(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : 2;
+ double v = callData->argc ? callData->args[0].toNumber() : 2;
if (v > 1)
- return Encode(qt_qnan());
+ RETURN_RESULT(Encode(qt_qnan()));
- return Encode(std::acos(v));
+ RETURN_RESULT(Encode(std::acos(v)));
}
-ReturnedValue MathObject::method_asin(CallContext *context)
+void MathObject::method_asin(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : 2;
+ double v = callData->argc ? callData->args[0].toNumber() : 2;
if (v > 1)
- return Encode(qt_qnan());
+ RETURN_RESULT(Encode(qt_qnan()));
else
- return Encode(std::asin(v));
+ RETURN_RESULT(Encode(std::asin(v)));
}
-ReturnedValue MathObject::method_atan(CallContext *context)
+void MathObject::method_atan(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
if (v == 0.0)
- return Encode(v);
+ RETURN_RESULT(Encode(v));
else
- return Encode(std::atan(v));
+ RETURN_RESULT(Encode(std::atan(v)));
}
-ReturnedValue MathObject::method_atan2(CallContext *context)
+void MathObject::method_atan2(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v1 = context->argc() ? context->args()[0].toNumber() : qt_qnan();
- double v2 = context->argc() > 1 ? context->args()[1].toNumber() : qt_qnan();
+ double v1 = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ double v2 = callData->argc > 1 ? callData->args[1].toNumber() : qt_qnan();
if ((v1 < 0) && qt_is_finite(v1) && qt_is_inf(v2) && (copySign(1.0, v2) == 1.0))
- return Encode(copySign(0, -1.0));
+ RETURN_RESULT(Encode(copySign(0, -1.0)));
if ((v1 == 0.0) && (v2 == 0.0)) {
if ((copySign(1.0, v1) == 1.0) && (copySign(1.0, v2) == -1.0)) {
- return Encode(M_PI);
+ RETURN_RESULT(Encode(M_PI));
} else if ((copySign(1.0, v1) == -1.0) && (copySign(1.0, v2) == -1.0)) {
- return Encode(-M_PI);
+ RETURN_RESULT(Encode(-M_PI));
}
}
- return Encode(std::atan2(v1, v2));
+ RETURN_RESULT(Encode(std::atan2(v1, v2)));
}
-ReturnedValue MathObject::method_ceil(CallContext *context)
+void MathObject::method_ceil(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
if (v < 0.0 && v > -1.0)
- return Encode(copySign(0, -1.0));
+ RETURN_RESULT(Encode(copySign(0, -1.0)));
else
- return Encode(std::ceil(v));
+ RETURN_RESULT(Encode(std::ceil(v)));
}
-ReturnedValue MathObject::method_cos(CallContext *context)
+void MathObject::method_cos(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
- return Encode(std::cos(v));
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ RETURN_RESULT(Encode(std::cos(v)));
}
-ReturnedValue MathObject::method_exp(CallContext *context)
+void MathObject::method_exp(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
if (qt_is_inf(v)) {
if (copySign(1.0, v) == -1.0)
- return Encode(0);
+ RETURN_RESULT(Encode(0));
else
- return Encode(qt_inf());
+ RETURN_RESULT(Encode(qt_inf()));
} else {
- return Encode(std::exp(v));
+ RETURN_RESULT(Encode(std::exp(v)));
}
}
-ReturnedValue MathObject::method_floor(CallContext *context)
+void MathObject::method_floor(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
- return Encode(std::floor(v));
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ RETURN_RESULT(Encode(std::floor(v)));
}
-ReturnedValue MathObject::method_log(CallContext *context)
+void MathObject::method_log(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
if (v < 0)
- return Encode(qt_qnan());
+ RETURN_RESULT(Encode(qt_qnan()));
else
- return Encode(std::log(v));
+ RETURN_RESULT(Encode(std::log(v)));
}
-ReturnedValue MathObject::method_max(CallContext *context)
+void MathObject::method_max(const BuiltinFunction *, Scope &scope, CallData *callData)
{
double mx = -qt_inf();
- for (int i = 0; i < context->argc(); ++i) {
- double x = context->args()[i].toNumber();
+ for (int i = 0; i < callData->argc; ++i) {
+ double x = callData->args[i].toNumber();
if (x > mx || std::isnan(x))
mx = x;
}
- return Encode(mx);
+ RETURN_RESULT(Encode(mx));
}
-ReturnedValue MathObject::method_min(CallContext *context)
+void MathObject::method_min(const BuiltinFunction *, Scope &scope, CallData *callData)
{
double mx = qt_inf();
- for (int i = 0; i < context->argc(); ++i) {
- double x = context->args()[i].toNumber();
+ for (int i = 0; i < callData->argc; ++i) {
+ double x = callData->args[i].toNumber();
if ((x == 0 && mx == x && copySign(1.0, x) == -1.0)
|| (x < mx) || std::isnan(x)) {
mx = x;
}
}
- return Encode(mx);
+ RETURN_RESULT(Encode(mx));
}
-ReturnedValue MathObject::method_pow(CallContext *context)
+void MathObject::method_pow(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double x = context->argc() > 0 ? context->args()[0].toNumber() : qt_qnan();
- double y = context->argc() > 1 ? context->args()[1].toNumber() : qt_qnan();
+ double x = callData->argc > 0 ? callData->args[0].toNumber() : qt_qnan();
+ double y = callData->argc > 1 ? callData->args[1].toNumber() : qt_qnan();
if (std::isnan(y))
- return Encode(qt_qnan());
+ RETURN_RESULT(Encode(qt_qnan()));
if (y == 0) {
- return Encode(1);
+ RETURN_RESULT(Encode(1));
} else if (((x == 1) || (x == -1)) && std::isinf(y)) {
- return Encode(qt_qnan());
+ RETURN_RESULT(Encode(qt_qnan()));
} else if (((x == 0) && copySign(1.0, x) == 1.0) && (y < 0)) {
- return Encode(qInf());
+ RETURN_RESULT(Encode(qInf()));
} else if ((x == 0) && copySign(1.0, x) == -1.0) {
if (y < 0) {
if (std::fmod(-y, 2.0) == 1.0)
- return Encode(-qt_inf());
+ RETURN_RESULT(Encode(-qt_inf()));
else
- return Encode(qt_inf());
+ RETURN_RESULT(Encode(qt_inf()));
} else if (y > 0) {
if (std::fmod(y, 2.0) == 1.0)
- return Encode(copySign(0, -1.0));
+ RETURN_RESULT(Encode(copySign(0, -1.0)));
else
- return Encode(0);
+ RETURN_RESULT(Encode(0));
}
}
@@ -253,78 +253,78 @@ ReturnedValue MathObject::method_pow(CallContext *context)
else if (qt_is_inf(x) && copySign(1.0, x) == -1.0) {
if (y > 0) {
if (std::fmod(y, 2.0) == 1.0)
- return Encode(-qt_inf());
+ RETURN_RESULT(Encode(-qt_inf()));
else
- return Encode(qt_inf());
+ RETURN_RESULT(Encode(qt_inf()));
} else if (y < 0) {
if (std::fmod(-y, 2.0) == 1.0)
- return Encode(copySign(0, -1.0));
+ RETURN_RESULT(Encode(copySign(0, -1.0)));
else
- return Encode(0);
+ RETURN_RESULT(Encode(0));
}
}
#endif
else {
- return Encode(std::pow(x, y));
+ RETURN_RESULT(Encode(std::pow(x, y)));
}
// ###
- return Encode(qt_qnan());
+ RETURN_RESULT(Encode(qt_qnan()));
}
Q_GLOBAL_STATIC(QThreadStorage<bool *>, seedCreatedStorage);
-ReturnedValue MathObject::method_random(CallContext *context)
+void MathObject::method_random(const BuiltinFunction *, Scope &scope, CallData *)
{
if (!seedCreatedStorage()->hasLocalData()) {
int msecs = QTime(0,0,0).msecsTo(QTime::currentTime());
Q_ASSERT(msecs >= 0);
- qsrand(uint(uint(msecs) ^ reinterpret_cast<quintptr>(context)));
+ qsrand(uint(uint(msecs) ^ reinterpret_cast<quintptr>(scope.engine)));
seedCreatedStorage()->setLocalData(new bool(true));
}
// rand()/qrand() return a value where the upperbound is RAND_MAX inclusive. So, instead of
// dividing by RAND_MAX (which would return 0..RAND_MAX inclusive), we divide by RAND_MAX + 1.
qint64 upperLimit = qint64(RAND_MAX) + 1;
- return Encode(qrand() / double(upperLimit));
+ RETURN_RESULT(Encode(qrand() / double(upperLimit)));
}
-ReturnedValue MathObject::method_round(CallContext *context)
+void MathObject::method_round(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
v = copySign(std::floor(v + 0.5), v);
- return Encode(v);
+ RETURN_RESULT(Encode(v));
}
-ReturnedValue MathObject::method_sign(CallContext *context)
+void MathObject::method_sign(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
if (std::isnan(v))
- return Encode(qt_qnan());
+ RETURN_RESULT(Encode(qt_qnan()));
if (qIsNull(v))
- return v;
+ RETURN_RESULT(Encode(v));
- return Encode(std::signbit(v) ? -1 : 1);
+ RETURN_RESULT(Encode(std::signbit(v) ? -1 : 1));
}
-ReturnedValue MathObject::method_sin(CallContext *context)
+void MathObject::method_sin(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
- return Encode(std::sin(v));
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ RETURN_RESULT(Encode(std::sin(v)));
}
-ReturnedValue MathObject::method_sqrt(CallContext *context)
+void MathObject::method_sqrt(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
- return Encode(std::sqrt(v));
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
+ RETURN_RESULT(Encode(std::sqrt(v)));
}
-ReturnedValue MathObject::method_tan(CallContext *context)
+void MathObject::method_tan(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- double v = context->argc() ? context->args()[0].toNumber() : qt_qnan();
+ double v = callData->argc ? callData->args[0].toNumber() : qt_qnan();
if (v == 0.0)
- return Encode(v);
+ RETURN_RESULT(Encode(v));
else
- return Encode(std::tan(v));
+ RETURN_RESULT(Encode(std::tan(v)));
}
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index f6b1a4395f..e617712905 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -69,25 +69,25 @@ struct MathObject: Object
V4_OBJECT2(MathObject, Object)
Q_MANAGED_TYPE(MathObject)
- static ReturnedValue method_abs(CallContext *context);
- static ReturnedValue method_acos(CallContext *context);
- static ReturnedValue method_asin(CallContext *context);
- static ReturnedValue method_atan(CallContext *context);
- static ReturnedValue method_atan2(CallContext *context);
- static ReturnedValue method_ceil(CallContext *context);
- static ReturnedValue method_cos(CallContext *context);
- static ReturnedValue method_exp(CallContext *context);
- static ReturnedValue method_floor(CallContext *context);
- static ReturnedValue method_log(CallContext *context);
- static ReturnedValue method_max(CallContext *context);
- static ReturnedValue method_min(CallContext *context);
- static ReturnedValue method_pow(CallContext *context);
- static ReturnedValue method_random(CallContext *context);
- static ReturnedValue method_round(CallContext *context);
- static ReturnedValue method_sign(CallContext *context);
- static ReturnedValue method_sin(CallContext *context);
- static ReturnedValue method_sqrt(CallContext *context);
- static ReturnedValue method_tan(CallContext *context);
+ static void method_abs(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_acos(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_asin(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_atan(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_atan2(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_ceil(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_cos(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_exp(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_floor(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_log(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_max(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_min(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_pow(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_random(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_round(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_sign(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_sin(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_sqrt(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_tan(const BuiltinFunction *, Scope &scope, CallData *callData);
};
}
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index d5f75415cc..db45c77472 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -55,13 +55,14 @@ void MemberData::markObjects(Heap::Base *that, ExecutionEngine *e)
Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberData *old)
{
Q_ASSERT(!old || old->size < n);
+ Q_ASSERT(n);
- uint alloc = sizeof(Heap::MemberData) + (n)*sizeof(Value);
+ size_t alloc = MemoryManager::align(sizeof(Heap::MemberData) + (n - 1)*sizeof(Value));
Heap::MemberData *m = e->memoryManager->allocManaged<MemberData>(alloc);
if (old)
- memcpy(m, old, sizeof(Heap::MemberData) + old->size * sizeof(Value));
+ memcpy(m, old, sizeof(Heap::MemberData) + (old->size - 1)* sizeof(Value));
else
m->init();
- m->size = n;
+ m->size = static_cast<uint>((alloc - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value));
return m;
}
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 3a6b9da763..09644c161d 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -120,61 +120,71 @@ QT_WARNING_POP
defineDefaultProperty(QStringLiteral("toPrecision"), method_toPrecision);
}
-inline ReturnedValue thisNumberValue(ExecutionContext *ctx)
+inline ReturnedValue thisNumberValue(Scope &scope, CallData *callData)
{
- if (ctx->thisObject().isNumber())
- return ctx->thisObject().asReturnedValue();
- NumberObject *n = ctx->thisObject().as<NumberObject>();
- if (!n)
- return ctx->engine()->throwTypeError();
+ if (callData->thisObject.isNumber())
+ return callData->thisObject.asReturnedValue();
+ NumberObject *n = callData->thisObject.as<NumberObject>();
+ if (!n) {
+ scope.engine->throwTypeError();
+ return Encode::undefined();
+ }
return Encode(n->value());
}
-inline double thisNumber(ExecutionContext *ctx)
+inline double thisNumber(Scope &scope, CallData *callData)
{
- if (ctx->thisObject().isNumber())
- return ctx->thisObject().asDouble();
- NumberObject *n = ctx->thisObject().as<NumberObject>();
- if (!n)
- return ctx->engine()->throwTypeError();
+ if (callData->thisObject.isNumber())
+ return callData->thisObject.asDouble();
+ NumberObject *n = callData->thisObject.as<NumberObject>();
+ if (!n) {
+ scope.engine->throwTypeError();
+ return 0;
+ }
return n->value();
}
-ReturnedValue NumberPrototype::method_isFinite(CallContext *ctx)
+void NumberPrototype::method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (!ctx->argc())
- return Encode(false);
+ if (!callData->argc) {
+ scope.result = Encode(false);
+ return;
+ }
- double v = ctx->args()[0].toNumber();
- return Encode(!std::isnan(v) && !qt_is_inf(v));
+ double v = callData->args[0].toNumber();
+ scope.result = Encode(!std::isnan(v) && !qt_is_inf(v));
}
-ReturnedValue NumberPrototype::method_isNaN(CallContext *ctx)
+void NumberPrototype::method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (!ctx->argc())
- return Encode(false);
+ if (!callData->argc) {
+ scope.result = Encode(false);
+ return;
+ }
- double v = ctx->args()[0].toNumber();
- return Encode(std::isnan(v));
+ double v = callData->args[0].toNumber();
+ scope.result = Encode(std::isnan(v));
}
-ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
+void NumberPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- double num = thisNumber(ctx);
- if (scope.engine->hasException)
- return Encode::undefined();
+ double num = thisNumber(scope, callData);
+ CHECK_EXCEPTION();
- if (ctx->argc() && !ctx->args()[0].isUndefined()) {
- int radix = ctx->args()[0].toInt32();
- if (radix < 2 || radix > 36)
- return ctx->engine()->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix")
+ if (callData->argc && !callData->args[0].isUndefined()) {
+ int radix = callData->args[0].toInt32();
+ if (radix < 2 || radix > 36) {
+ scope.result = scope.engine->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix")
.arg(radix));
+ return;
+ }
if (std::isnan(num)) {
- return scope.engine->newString(QStringLiteral("NaN"))->asReturnedValue();
+ scope.result = scope.engine->newString(QStringLiteral("NaN"));
+ return;
} else if (qt_is_inf(num)) {
- return scope.engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"))->asReturnedValue();
+ scope.result = scope.engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"));
+ return;
}
if (radix != 10) {
@@ -204,45 +214,43 @@ ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
}
if (negative)
str.prepend(QLatin1Char('-'));
- return scope.engine->newString(str)->asReturnedValue();
+ scope.result = scope.engine->newString(str);
+ return;
}
}
- return Primitive::fromDouble(num).toString(scope.engine)->asReturnedValue();
+ scope.result = Primitive::fromDouble(num).toString(scope.engine);
}
-ReturnedValue NumberPrototype::method_toLocaleString(CallContext *ctx)
+void NumberPrototype::method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedValue v(scope, thisNumberValue(ctx));
- ScopedString str(scope, v->toString(scope.engine));
- if (scope.engine->hasException)
- return Encode::undefined();
- return str.asReturnedValue();
+ ScopedValue v(scope, thisNumberValue(scope, callData));
+ scope.result = v->toString(scope.engine);
+ CHECK_EXCEPTION();
}
-ReturnedValue NumberPrototype::method_valueOf(CallContext *ctx)
+void NumberPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- return thisNumberValue(ctx);
+ scope.result = thisNumberValue(scope, callData);
}
-ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
+void NumberPrototype::method_toFixed(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- double v = thisNumber(ctx);
- if (scope.engine->hasException)
- return Encode::undefined();
+ double v = thisNumber(scope, callData);
+ CHECK_EXCEPTION();
double fdigits = 0;
- if (ctx->argc() > 0)
- fdigits = ctx->args()[0].toInteger();
+ if (callData->argc > 0)
+ fdigits = callData->args[0].toInteger();
if (std::isnan(fdigits))
fdigits = 0;
- if (fdigits < 0 || fdigits > 20)
- return ctx->engine()->throwRangeError(ctx->thisObject());
+ if (fdigits < 0 || fdigits > 20) {
+ scope.result = scope.engine->throwRangeError(callData->thisObject);
+ return;
+ }
QString str;
if (std::isnan(v))
@@ -251,48 +259,50 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
str = QString::fromLatin1(v < 0 ? "-Infinity" : "Infinity");
else if (v < 1.e21)
str = NumberLocale::instance()->toString(v, 'f', int(fdigits));
- else
- return RuntimeHelpers::stringFromNumber(ctx->engine(), v)->asReturnedValue();
- return scope.engine->newString(str)->asReturnedValue();
+ else {
+ scope.result = RuntimeHelpers::stringFromNumber(scope.engine, v);
+ return;
+ }
+ scope.result = scope.engine->newString(str);
}
-ReturnedValue NumberPrototype::method_toExponential(CallContext *ctx)
+void NumberPrototype::method_toExponential(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- double d = thisNumber(ctx);
- if (scope.engine->hasException)
- return Encode::undefined();
+ double d = thisNumber(scope, callData);
+ CHECK_EXCEPTION();
int fdigits = NumberLocale::instance()->defaultDoublePrecision;
- if (ctx->argc() && !ctx->args()[0].isUndefined()) {
- fdigits = ctx->args()[0].toInt32();
+ if (callData->argc && !callData->args[0].isUndefined()) {
+ fdigits = callData->args[0].toInt32();
if (fdigits < 0 || fdigits > 20) {
ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range")));
- return ctx->engine()->throwRangeError(error);
+ scope.result = scope.engine->throwRangeError(error);
+ return;
}
}
QString result = NumberLocale::instance()->toString(d, 'e', fdigits);
- return scope.engine->newString(result)->asReturnedValue();
+ scope.result = scope.engine->newString(result);
}
-ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx)
+void NumberPrototype::method_toPrecision(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedValue v(scope, thisNumberValue(ctx));
- if (scope.engine->hasException)
- return Encode::undefined();
+ ScopedValue v(scope, thisNumberValue(scope, callData));
+ CHECK_EXCEPTION();
- if (!ctx->argc() || ctx->args()[0].isUndefined())
- return Encode(v->toString(scope.engine));
+ if (!callData->argc || callData->args[0].isUndefined()) {
+ scope.result = v->toString(scope.engine);
+ return;
+ }
- int precision = ctx->args()[0].toInt32();
+ int precision = callData->args[0].toInt32();
if (precision < 1 || precision > 21) {
ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range")));
- return ctx->engine()->throwRangeError(error);
+ scope.result = scope.engine->throwRangeError(error);
+ return;
}
QString result = NumberLocale::instance()->toString(v->asDouble(), 'g', precision);
- return scope.engine->newString(result)->asReturnedValue();
+ scope.result = scope.engine->newString(result);
}
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 6022b3a029..364b866a16 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -87,14 +87,14 @@ struct NumberPrototype: NumberObject
{
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_isFinite(CallContext *ctx);
- static ReturnedValue method_isNaN(CallContext *ctx);
- static ReturnedValue method_toString(CallContext *ctx);
- static ReturnedValue method_toLocaleString(CallContext *ctx);
- static ReturnedValue method_valueOf(CallContext *ctx);
- static ReturnedValue method_toFixed(CallContext *ctx);
- static ReturnedValue method_toExponential(CallContext *ctx);
- static ReturnedValue method_toPrecision(CallContext *ctx);
+ static void method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toFixed(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toExponential(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toPrecision(const BuiltinFunction *, Scope &scope, CallData *callData);
};
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 8acca16dd0..eb9cb80cee 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -61,9 +61,8 @@ DEFINE_OBJECT_VTABLE(Object);
void Object::setInternalClass(InternalClass *ic)
{
d()->internalClass = ic;
- if ((ic->size > d()->inlineMemberSize && !d()->memberData) ||
- (d()->memberData && d()->memberData->size < ic->size - d()->inlineMemberSize))
- d()->memberData = MemberData::allocate(ic->engine, ic->size - d()->inlineMemberSize, d()->memberData);
+ if ((!d()->memberData && ic->size) || (d()->memberData->size < ic->size))
+ d()->memberData = MemberData::allocate(ic->engine, ic->size, d()->memberData);
}
void Object::getProperty(uint index, Property *p, PropertyAttributes *attrs) const
@@ -167,6 +166,17 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
defineDefaultProperty(s, function);
}
+void Object::defineDefaultProperty(const QString &name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount)
+{
+ ExecutionEngine *e = engine();
+ Scope scope(e);
+ ScopedString s(scope, e->newIdentifier(name));
+ ExecutionContext *global = e->rootContext();
+ ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
+ defineDefaultProperty(s, function);
+}
+
void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallContext *), int argumentCount)
{
ExecutionEngine *e = engine();
@@ -177,6 +187,16 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallConte
defineDefaultProperty(name, function);
}
+void Object::defineDefaultProperty(String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount)
+{
+ ExecutionEngine *e = engine();
+ Scope scope(e);
+ ExecutionContext *global = e->rootContext();
+ ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
+ defineDefaultProperty(name, function);
+}
+
void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *))
{
ExecutionEngine *e = engine();
@@ -196,6 +216,27 @@ void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallCo
insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
+void Object::defineAccessorProperty(const QString &name, void (*getter)(const BuiltinFunction *, Scope &, CallData *),
+ void (*setter)(const BuiltinFunction *, Scope &, CallData *))
+{
+ ExecutionEngine *e = engine();
+ Scope scope(e);
+ ScopedString s(scope, e->newIdentifier(name));
+ defineAccessorProperty(s, getter, setter);
+}
+
+void Object::defineAccessorProperty(String *name, void (*getter)(const BuiltinFunction *, Scope &, CallData *),
+ void (*setter)(const BuiltinFunction *, Scope &, CallData *))
+{
+ ExecutionEngine *v4 = engine();
+ QV4::Scope scope(v4);
+ ScopedProperty p(scope);
+ ExecutionContext *global = v4->rootContext();
+ p->setGetter(ScopedFunctionObject(scope, (getter ? BuiltinFunction::create(global, name, getter) : 0)));
+ p->setSetter(ScopedFunctionObject(scope, (setter ? BuiltinFunction::create(global, name, setter) : 0)));
+ insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+}
+
void Object::defineReadonlyProperty(const QString &name, const Value &value)
{
QV4::ExecutionEngine *e = engine();
@@ -213,12 +254,6 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
{
Heap::Object *o = static_cast<Heap::Object *>(that);
- if (o->inlineMemberSize) {
- Value *v = o->propertyData(0);
- for (uint i = 0; i < o->inlineMemberSize; ++i)
- v[i].mark(e);
- }
-
if (o->memberData)
o->memberData->mark(e);
if (o->arrayData)
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 6c679deb10..4a78690f47 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -63,17 +63,17 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+struct BuiltinFunction;
+
namespace Heap {
struct Object : Base {
void init() { Base::init(); }
void destroy() { Base::destroy(); }
- const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast<const Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
- Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast<Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
+ const Value *propertyData(uint index) const { return memberData->data + index; }
+ Value *propertyData(uint index) { return memberData->data + index; }
- uint inlineMemberOffset;
- uint inlineMemberSize;
InternalClass *internalClass;
Pointer<Object> prototype;
Pointer<MemberData> memberData;
@@ -238,9 +238,15 @@ struct Q_QML_EXPORT Object: Managed {
}
void defineDefaultProperty(const QString &name, const Value &value);
void defineDefaultProperty(const QString &name, ReturnedValue (*code)(CallContext *), int argumentCount = 0);
+ void defineDefaultProperty(const QString &name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount = 0);
void defineDefaultProperty(String *name, ReturnedValue (*code)(CallContext *), int argumentCount = 0);
+ void defineDefaultProperty(String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount = 0);
void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *));
void defineAccessorProperty(String *name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *));
+ void defineAccessorProperty(const QString &name, void (*getter)(const BuiltinFunction *, Scope &, CallData *),
+ void (*setter)(const BuiltinFunction *, Scope &, CallData *));
+ void defineAccessorProperty(String *name, void (*getter)(const BuiltinFunction *, Scope &, CallData *),
+ void (*setter)(const BuiltinFunction *, Scope &, CallData *));
/* Fixed: Writable: false, Enumerable: false, Configurable: false */
void defineReadonlyProperty(const QString &name, const Value &value);
void defineReadonlyProperty(String *name, const Value &value);
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 8191083544..97dbe24339 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -121,100 +121,100 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
insertMember(v4->id___proto__(), p, Attr_Accessor|Attr_NotEnumerable);
}
-ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx)
+void ObjectPrototype::method_getPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->argument(0));
+ ScopedObject o(scope, callData->argument(0));
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
ScopedObject p(scope, o->prototype());
- return !!p ? p->asReturnedValue() : Encode::null();
+ scope.result = !!p ? p->asReturnedValue() : Encode::null();
}
-ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
+void ObjectPrototype::method_getOwnPropertyDescriptor(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject O(scope, ctx->argument(0));
- if (!O)
- return ctx->engine()->throwTypeError();
+ ScopedObject O(scope, callData->argument(0));
+ if (!O) {
+ scope.result = scope.engine->throwTypeError();
+ return;
+ }
if (ArgumentsObject::isNonStrictArgumentsObject(O))
static_cast<ArgumentsObject *>(O.getPointer())->fullyCreate();
- ScopedValue v(scope, ctx->argument(1));
+ ScopedValue v(scope, callData->argument(1));
ScopedString name(scope, v->toString(scope.engine));
- if (scope.hasException())
- return Encode::undefined();
+ CHECK_EXCEPTION();
+
PropertyAttributes attrs;
ScopedProperty desc(scope);
O->getOwnProperty(name, &attrs, desc);
- return fromPropertyDescriptor(scope.engine, desc, attrs);
+ scope.result = fromPropertyDescriptor(scope.engine, desc, attrs);
}
-ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context)
+void ObjectPrototype::method_getOwnPropertyNames(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(context);
- ScopedObject O(scope, context->argument(0));
- if (!O)
- return context->engine()->throwTypeError();
+ ScopedObject O(scope, callData->argument(0));
+ if (!O) {
+ scope.result = scope.engine->throwTypeError();
+ return;
+ }
- ScopedArrayObject array(scope, getOwnPropertyNames(context->d()->engine, context->args()[0]));
- return array.asReturnedValue();
+ scope.result = getOwnPropertyNames(scope.engine, callData->args[0]);
}
-ReturnedValue ObjectPrototype::method_create(CallContext *ctx)
+void ObjectPrototype::method_create(const BuiltinFunction *builtin, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedValue O(scope, ctx->argument(0));
- if (!O->isObject() && !O->isNull())
- return ctx->engine()->throwTypeError();
+ ScopedValue O(scope, callData->argument(0));
+ if (!O->isObject() && !O->isNull()) {
+ scope.result = scope.engine->throwTypeError();
+ return;
+ }
- ScopedObject newObject(scope, ctx->d()->engine->newObject());
+ ScopedObject newObject(scope, scope.engine->newObject());
newObject->setPrototype(O->as<Object>());
- if (ctx->argc() > 1 && !ctx->args()[1].isUndefined()) {
- ctx->d()->callData->args[0] = newObject.asReturnedValue();
- return method_defineProperties(ctx);
+ if (callData->argc > 1 && !callData->args[1].isUndefined()) {
+ callData->args[0] = newObject;
+ method_defineProperties(builtin, scope, callData);
+ return;
}
- return newObject.asReturnedValue();
+ scope.result = newObject;
}
-ReturnedValue ObjectPrototype::method_defineProperty(CallContext *ctx)
+void ObjectPrototype::method_defineProperty(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject O(scope, ctx->argument(0));
- if (!O)
- return ctx->engine()->throwTypeError();
+ ScopedObject O(scope, callData->argument(0));
+ if (!O) {
+ scope.result = scope.engine->throwTypeError();
+ return;
+ }
- ScopedString name(scope, ctx->argument(1), ScopedString::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
+ ScopedString name(scope, callData->argument(1), ScopedString::Convert);
+ CHECK_EXCEPTION();
- ScopedValue attributes(scope, ctx->argument(2));
+ ScopedValue attributes(scope, callData->argument(2));
ScopedProperty pd(scope);
PropertyAttributes attrs;
toPropertyDescriptor(scope.engine, attributes, pd, &attrs);
- if (scope.engine->hasException)
- return Encode::undefined();
+ CHECK_EXCEPTION();
if (!O->__defineOwnProperty__(scope.engine, name, pd, attrs))
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return O.asReturnedValue();
+ scope.result = O;
}
-ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
+void ObjectPrototype::method_defineProperties(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject O(scope, ctx->argument(0));
+ ScopedObject O(scope, callData->argument(0));
if (!O)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
+
+ ScopedObject o(scope, callData->argument(1), ScopedObject::Convert);
+ CHECK_EXCEPTION();
- ScopedObject o(scope, ctx->argument(1), ScopedObject::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
ScopedValue val(scope);
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
@@ -230,26 +230,24 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
PropertyAttributes nattrs;
val = o->getValue(pd->value, attrs);
toPropertyDescriptor(scope.engine, val, n, &nattrs);
- if (scope.engine->hasException)
- return Encode::undefined();
+ CHECK_EXCEPTION();
bool ok;
if (name)
ok = O->__defineOwnProperty__(scope.engine, name, n, nattrs);
else
ok = O->__defineOwnProperty__(scope.engine, index, n, nattrs);
if (!ok)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
}
- return O.asReturnedValue();
+ scope.result = O;
}
-ReturnedValue ObjectPrototype::method_seal(CallContext *ctx)
+void ObjectPrototype::method_seal(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->argument(0));
+ ScopedObject o(scope, callData->argument(0));
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
o->setInternalClass(o->internalClass()->sealed());
@@ -261,15 +259,14 @@ ReturnedValue ObjectPrototype::method_seal(CallContext *ctx)
}
}
- return o.asReturnedValue();
+ scope.result = o;
}
-ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx)
+void ObjectPrototype::method_freeze(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->argument(0));
+ ScopedObject o(scope, callData->argument(0));
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (ArgumentsObject::isNonStrictArgumentsObject(o))
static_cast<ArgumentsObject *>(o.getPointer())->fullyCreate();
@@ -285,96 +282,111 @@ ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx)
o->arrayData()->attrs[i].setWritable(false);
}
}
- return o.asReturnedValue();
+ scope.result = o;
}
-ReturnedValue ObjectPrototype::method_preventExtensions(CallContext *ctx)
+void ObjectPrototype::method_preventExtensions(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->argument(0));
+ ScopedObject o(scope, callData->argument(0));
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
o->setInternalClass(o->internalClass()->nonExtensible());
- return o.asReturnedValue();
+ scope.result = o;
}
-ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx)
+void ObjectPrototype::method_isSealed(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->argument(0));
+ ScopedObject o(scope, callData->argument(0));
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- if (o->isExtensible())
- return Encode(false);
+ if (o->isExtensible()) {
+ scope.result = Encode(false);
+ return;
+ }
- if (o->internalClass() != o->internalClass()->sealed())
- return Encode(false);
+ if (o->internalClass() != o->internalClass()->sealed()) {
+ scope.result = Encode(false);
+ return;
+ }
- if (!o->arrayData() || !o->arrayData()->length())
- return Encode(true);
+ if (!o->arrayData() || !o->arrayData()->length()) {
+ scope.result = Encode(true);
+ return;
+ }
Q_ASSERT(o->arrayData() && o->arrayData()->length());
- if (!o->arrayData()->attrs)
- return Encode(false);
+ if (!o->arrayData()->attrs) {
+ scope.result = Encode(false);
+ return;
+ }
for (uint i = 0; i < o->arrayData()->alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
- if (o->arrayData()->attributes(i).isConfigurable())
- return Encode(false);
+ if (o->arrayData()->attributes(i).isConfigurable()) {
+ scope.result = Encode(false);
+ return;
+ }
}
- return Encode(true);
+ scope.result = Encode(true);
}
-ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx)
+void ObjectPrototype::method_isFrozen(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->argument(0));
+ ScopedObject o(scope, callData->argument(0));
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- if (o->isExtensible())
- return Encode(false);
+ if (o->isExtensible()) {
+ scope.result = Encode(false);
+ return;
+ }
- if (o->internalClass() != o->internalClass()->frozen())
- return Encode(false);
+ if (o->internalClass() != o->internalClass()->frozen()) {
+ scope.result = Encode(false);
+ return;
+ }
- if (!o->arrayData() || !o->arrayData()->length())
- return Encode(true);
+ if (!o->arrayData() || !o->arrayData()->length()) {
+ scope.result = Encode(true);
+ return;
+ }
Q_ASSERT(o->arrayData() && o->arrayData()->length());
- if (!o->arrayData()->attrs)
- return Encode(false);
+ if (!o->arrayData()->attrs) {
+ scope.result = Encode(false);
+ return;
+ }
for (uint i = 0; i < o->arrayData()->alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
- if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable())
- return Encode(false);
+ if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) {
+ scope.result = Encode(false);
+ return;
+ }
}
- return Encode(true);
+ scope.result = Encode(true);
}
-ReturnedValue ObjectPrototype::method_isExtensible(CallContext *ctx)
+void ObjectPrototype::method_isExtensible(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->argument(0));
+ ScopedObject o(scope, callData->argument(0));
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode((bool)o->isExtensible());
+ scope.result = Encode((bool)o->isExtensible());
}
-ReturnedValue ObjectPrototype::method_keys(CallContext *ctx)
+void ObjectPrototype::method_keys(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->argument(0));
+ ScopedObject o(scope, callData->argument(0));
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedArrayObject a(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject a(scope, scope.engine->newArrayObject());
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -385,175 +397,159 @@ ReturnedValue ObjectPrototype::method_keys(CallContext *ctx)
a->push_back(name);
}
- return a.asReturnedValue();
+ scope.result = a;
}
-ReturnedValue ObjectPrototype::method_toString(CallContext *ctx)
+void ObjectPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- if (ctx->thisObject().isUndefined()) {
- return ctx->d()->engine->newString(QStringLiteral("[object Undefined]"))->asReturnedValue();
- } else if (ctx->thisObject().isNull()) {
- return ctx->d()->engine->newString(QStringLiteral("[object Null]"))->asReturnedValue();
+ if (callData->thisObject.isUndefined()) {
+ scope.result = scope.engine->newString(QStringLiteral("[object Undefined]"));
+ } else if (callData->thisObject.isNull()) {
+ scope.result = scope.engine->newString(QStringLiteral("[object Null]"));
} else {
- ScopedObject obj(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject obj(scope, callData->thisObject.toObject(scope.engine));
QString className = obj->className();
- return ctx->d()->engine->newString(QStringLiteral("[object %1]").arg(className))->asReturnedValue();
+ scope.result = scope.engine->newString(QStringLiteral("[object %1]").arg(className));
}
}
-ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx)
+void ObjectPrototype::method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->thisObject().toObject(scope.engine));
+ ScopedObject o(scope, callData->thisObject.toObject(scope.engine));
if (!o)
- return Encode::undefined();
- ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString()));
+ RETURN_UNDEFINED();
+
+ ScopedFunctionObject f(scope, o->get(scope.engine->id_toString()));
if (!f)
- return ctx->engine()->throwTypeError();
- ScopedCallData callData(scope);
- callData->thisObject = o;
+ THROW_TYPE_ERROR();
+ ScopedCallData cData(scope);
+ cData->thisObject = o;
f->call(scope, callData);
- return scope.result.asReturnedValue();
}
-ReturnedValue ObjectPrototype::method_valueOf(CallContext *ctx)
+void ObjectPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedValue v(scope, ctx->thisObject().toObject(scope.engine));
- if (ctx->d()->engine->hasException)
- return Encode::undefined();
- return v->asReturnedValue();
+ scope.result = callData->thisObject.toObject(scope.engine);
}
-ReturnedValue ObjectPrototype::method_hasOwnProperty(CallContext *ctx)
+void ObjectPrototype::method_hasOwnProperty(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedString P(scope, ctx->argument(0), ScopedString::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
- ScopedObject O(scope, ctx->thisObject(), ScopedObject::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
+ ScopedString P(scope, callData->argument(0), ScopedString::Convert);
+ CHECK_EXCEPTION();
+ ScopedObject O(scope, callData->thisObject, ScopedObject::Convert);
+ CHECK_EXCEPTION();
bool r = O->hasOwnProperty(P);
if (!r)
r = !O->query(P).isEmpty();
- return Encode(r);
+ scope.result = Encode(r);
}
-ReturnedValue ObjectPrototype::method_isPrototypeOf(CallContext *ctx)
+void ObjectPrototype::method_isPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject V(scope, ctx->argument(0));
- if (!V)
- return Encode(false);
+ ScopedObject V(scope, callData->argument(0));
+ if (!V) {
+ scope.result = Encode(false);
+ return;
+ }
- ScopedObject O(scope, ctx->thisObject(), ScopedObject::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
+ ScopedObject O(scope, callData->thisObject, ScopedObject::Convert);
+ CHECK_EXCEPTION();
ScopedObject proto(scope, V->prototype());
while (proto) {
- if (O->d() == proto->d())
- return Encode(true);
+ if (O->d() == proto->d()) {
+ scope.result = Encode(true);
+ return;
+ }
proto = proto->prototype();
}
- return Encode(false);
+ scope.result = Encode(false);
}
-ReturnedValue ObjectPrototype::method_propertyIsEnumerable(CallContext *ctx)
+void ObjectPrototype::method_propertyIsEnumerable(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedString p(scope, ctx->argument(0), ScopedString::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
+ ScopedString p(scope, callData->argument(0), ScopedString::Convert);
+ CHECK_EXCEPTION();
- ScopedObject o(scope, ctx->thisObject(), ScopedObject::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
+ ScopedObject o(scope, callData->thisObject, ScopedObject::Convert);
+ CHECK_EXCEPTION();
PropertyAttributes attrs;
o->getOwnProperty(p, &attrs);
- return Encode(attrs.isEnumerable());
+ scope.result = Encode(attrs.isEnumerable());
}
-ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
+void ObjectPrototype::method_defineGetter(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 2)
- return ctx->engine()->throwTypeError();
+ if (callData->argc < 2)
+ THROW_TYPE_ERROR();
- Scope scope(ctx);
- ScopedFunctionObject f(scope, ctx->argument(1));
+ ScopedFunctionObject f(scope, callData->argument(1));
if (!f)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedString prop(scope, ctx->argument(0), ScopedString::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
+ ScopedString prop(scope, callData->argument(0), ScopedString::Convert);
+ CHECK_EXCEPTION();
- ScopedObject o(scope, ctx->thisObject());
+ ScopedObject o(scope, callData->thisObject);
if (!o) {
- if (!ctx->thisObject().isUndefined())
- return Encode::undefined();
- o = ctx->d()->engine->globalObject;
+ if (!callData->thisObject.isUndefined())
+ RETURN_UNDEFINED();
+ o = scope.engine->globalObject;
}
ScopedProperty pd(scope);
pd->value = f;
pd->set = Primitive::emptyValue();
o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor);
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
+void ObjectPrototype::method_defineSetter(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 2)
- return ctx->engine()->throwTypeError();
+ if (callData->argc < 2)
+ THROW_TYPE_ERROR();
- Scope scope(ctx);
- ScopedFunctionObject f(scope, ctx->argument(1));
+ ScopedFunctionObject f(scope, callData->argument(1));
if (!f)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedString prop(scope, ctx->argument(0), ScopedString::Convert);
- if (scope.engine->hasException)
- return Encode::undefined();
+ ScopedString prop(scope, callData->argument(0), ScopedString::Convert);
+ CHECK_EXCEPTION();
- ScopedObject o(scope, ctx->thisObject());
+ ScopedObject o(scope, callData->thisObject);
if (!o) {
- if (!ctx->thisObject().isUndefined())
- return Encode::undefined();
- o = ctx->d()->engine->globalObject;
+ if (!callData->thisObject.isUndefined())
+ RETURN_UNDEFINED();
+ o = scope.engine->globalObject;
}
ScopedProperty pd(scope);
pd->value = Primitive::emptyValue();
pd->set = f;
o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor);
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx)
+void ObjectPrototype::method_get_proto(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->thisObject().as<Object>());
+ ScopedObject o(scope, callData->thisObject.as<Object>());
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return o->prototype()->asReturnedValue();
+ scope.result = o->prototype();
}
-ReturnedValue ObjectPrototype::method_set_proto(CallContext *ctx)
+void ObjectPrototype::method_set_proto(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedObject o(scope, ctx->thisObject());
- if (!o || !ctx->argc())
- return ctx->engine()->throwTypeError();
+ ScopedObject o(scope, callData->thisObject);
+ if (!o || !callData->argc)
+ THROW_TYPE_ERROR();
- if (ctx->args()[0].isNull()) {
+ if (callData->args[0].isNull()) {
o->setPrototype(0);
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
- ScopedObject p(scope, ctx->args()[0]);
+ ScopedObject p(scope, callData->args[0]);
bool ok = false;
if (!!p) {
if (o->prototype() == p->d()) {
@@ -562,9 +558,11 @@ ReturnedValue ObjectPrototype::method_set_proto(CallContext *ctx)
ok = o->setPrototype(p);
}
}
- if (!ok)
- return ctx->engine()->throwTypeError(QStringLiteral("Cyclic __proto__ value"));
- return Encode::undefined();
+ if (!ok) {
+ scope.result = scope.engine->throwTypeError(QStringLiteral("Cyclic __proto__ value"));
+ return;
+ }
+ RETURN_UNDEFINED();
}
void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value &v, Property *desc, PropertyAttributes *attrs)
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index e3d85782d5..1db8615511 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -78,32 +78,32 @@ struct ObjectPrototype: Object
{
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_getPrototypeOf(CallContext *ctx);
- static ReturnedValue method_getOwnPropertyDescriptor(CallContext *ctx);
- static ReturnedValue method_getOwnPropertyNames(CallContext *context);
- static ReturnedValue method_create(CallContext *ctx);
- static ReturnedValue method_defineProperty(CallContext *ctx);
- static ReturnedValue method_defineProperties(CallContext *ctx);
- static ReturnedValue method_seal(CallContext *ctx);
- static ReturnedValue method_freeze(CallContext *ctx);
- static ReturnedValue method_preventExtensions(CallContext *ctx);
- static ReturnedValue method_isSealed(CallContext *ctx);
- static ReturnedValue method_isFrozen(CallContext *ctx);
- static ReturnedValue method_isExtensible(CallContext *ctx);
- static ReturnedValue method_keys(CallContext *ctx);
-
- static ReturnedValue method_toString(CallContext *ctx);
- static ReturnedValue method_toLocaleString(CallContext *ctx);
- static ReturnedValue method_valueOf(CallContext *ctx);
- static ReturnedValue method_hasOwnProperty(CallContext *ctx);
- static ReturnedValue method_isPrototypeOf(CallContext *ctx);
- static ReturnedValue method_propertyIsEnumerable(CallContext *ctx);
-
- static ReturnedValue method_defineGetter(CallContext *ctx);
- static ReturnedValue method_defineSetter(CallContext *ctx);
-
- static ReturnedValue method_get_proto(CallContext *ctx);
- static ReturnedValue method_set_proto(CallContext *ctx);
+ static void method_getPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getOwnPropertyDescriptor(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_getOwnPropertyNames(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_create(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_defineProperty(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_defineProperties(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_seal(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_freeze(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_preventExtensions(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_isSealed(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_isFrozen(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_isExtensible(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_keys(const BuiltinFunction *, Scope &scope, CallData *callData);
+
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_hasOwnProperty(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_isPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_propertyIsEnumerable(const BuiltinFunction *, Scope &scope, CallData *callData);
+
+ static void method_defineGetter(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_defineSetter(const BuiltinFunction *, Scope &scope, CallData *callData);
+
+ static void method_get_proto(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_set_proto(const BuiltinFunction *, Scope &scope, CallData *callData);
static void toPropertyDescriptor(ExecutionEngine *engine, const Value &v, Property *desc, PropertyAttributes *attrs);
static ReturnedValue fromPropertyDescriptor(ExecutionEngine *engine, const Property *desc, PropertyAttributes attrs);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 77dbb18b50..7260e71fab 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -826,40 +826,39 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
} // namespace QV4
-ReturnedValue QObjectWrapper::method_connect(CallContext *ctx)
+void QObjectWrapper::method_connect(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() == 0)
- V4THROW_ERROR("Function.prototype.connect: no arguments given");
+ if (callData->argc == 0)
+ THROW_GENERIC_ERROR("Function.prototype.connect: no arguments given");
- QPair<QObject *, int> signalInfo = extractQtSignal(ctx->thisObject());
+ QPair<QObject *, int> signalInfo = extractQtSignal(callData->thisObject);
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second; // in method range, not signal range!
if (signalIndex < 0)
- V4THROW_ERROR("Function.prototype.connect: this object is not a signal");
+ THROW_GENERIC_ERROR("Function.prototype.connect: this object is not a signal");
if (!signalObject)
- V4THROW_ERROR("Function.prototype.connect: cannot connect to deleted QObject");
+ THROW_GENERIC_ERROR("Function.prototype.connect: cannot connect to deleted QObject");
if (signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
- V4THROW_ERROR("Function.prototype.connect: this object is not a signal");
+ THROW_GENERIC_ERROR("Function.prototype.connect: this object is not a signal");
- QV4::Scope scope(ctx);
QV4::ScopedFunctionObject f(scope);
QV4::ScopedValue thisObject (scope, QV4::Encode::undefined());
- if (ctx->argc() == 1) {
- f = ctx->args()[0];
- } else if (ctx->argc() >= 2) {
- thisObject = ctx->args()[0];
- f = ctx->args()[1];
+ if (callData->argc == 1) {
+ f = callData->args[0];
+ } else if (callData->argc >= 2) {
+ thisObject = callData->args[0];
+ f = callData->args[1];
}
if (!f)
- V4THROW_ERROR("Function.prototype.connect: target is not a function");
+ THROW_GENERIC_ERROR("Function.prototype.connect: target is not a function");
if (!thisObject->isUndefined() && !thisObject->isObject())
- V4THROW_ERROR("Function.prototype.connect: target this is not an object");
+ THROW_GENERIC_ERROR("Function.prototype.connect: target this is not an object");
QV4::QObjectSlotDispatcher *slot = new QV4::QObjectSlotDispatcher;
slot->signalIndex = signalIndex;
@@ -874,49 +873,47 @@ ReturnedValue QObjectWrapper::method_connect(CallContext *ctx)
}
QObjectPrivate::connect(signalObject, signalIndex, slot, Qt::AutoConnection);
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx)
+void QObjectWrapper::method_disconnect(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() == 0)
- V4THROW_ERROR("Function.prototype.disconnect: no arguments given");
-
- QV4::Scope scope(ctx);
+ if (callData->argc == 0)
+ THROW_GENERIC_ERROR("Function.prototype.disconnect: no arguments given");
- QPair<QObject *, int> signalInfo = extractQtSignal(ctx->thisObject());
+ QPair<QObject *, int> signalInfo = extractQtSignal(callData->thisObject);
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second;
if (signalIndex == -1)
- V4THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
+ THROW_GENERIC_ERROR("Function.prototype.disconnect: this object is not a signal");
if (!signalObject)
- V4THROW_ERROR("Function.prototype.disconnect: cannot disconnect from deleted QObject");
+ THROW_GENERIC_ERROR("Function.prototype.disconnect: cannot disconnect from deleted QObject");
if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
- V4THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
+ THROW_GENERIC_ERROR("Function.prototype.disconnect: this object is not a signal");
QV4::ScopedFunctionObject functionValue(scope);
QV4::ScopedValue functionThisValue(scope, QV4::Encode::undefined());
- if (ctx->argc() == 1) {
- functionValue = ctx->args()[0];
- } else if (ctx->argc() >= 2) {
- functionThisValue = ctx->args()[0];
- functionValue = ctx->args()[1];
+ if (callData->argc == 1) {
+ functionValue = callData->args[0];
+ } else if (callData->argc >= 2) {
+ functionThisValue = callData->args[0];
+ functionValue = callData->args[1];
}
if (!functionValue)
- V4THROW_ERROR("Function.prototype.disconnect: target is not a function");
+ THROW_GENERIC_ERROR("Function.prototype.disconnect: target is not a function");
if (!functionThisValue->isUndefined() && !functionThisValue->isObject())
- V4THROW_ERROR("Function.prototype.disconnect: target this is not an object");
+ THROW_GENERIC_ERROR("Function.prototype.disconnect: target this is not an object");
QPair<QObject *, int> functionData = QObjectMethod::extractQtMethod(functionValue);
void *a[] = {
- ctx->d()->engine,
+ scope.engine,
functionValue.ptr,
functionThisValue.ptr,
functionData.first,
@@ -925,7 +922,7 @@ ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx)
QObjectPrivate::disconnect(signalObject, signalIndex, reinterpret_cast<void**>(&a));
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
static void markChildQObjectsRecursively(QObject *parent, QV4::ExecutionEngine *e)
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index c7c4f4dd77..b09e06cec5 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -197,8 +197,8 @@ protected:
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
- static ReturnedValue method_connect(CallContext *ctx);
- static ReturnedValue method_disconnect(CallContext *ctx);
+ static void method_connect(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_disconnect(const BuiltinFunction *, Scope &scope, CallData *callData);
private:
Q_NEVER_INLINE static ReturnedValue wrap_slowPath(ExecutionEngine *engine, QObject *object);
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 218695624b..40682aaa4b 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -307,7 +307,8 @@ void RegExpCtor::markObjects(Heap::Base *that, ExecutionEngine *e)
{
RegExpCtor::Data *This = static_cast<RegExpCtor::Data *>(that);
This->lastMatch.mark(e);
- This->lastInput->mark(e);
+ if (This->lastInput)
+ This->lastInput->mark(e);
FunctionObject::markObjects(that, e);
}
@@ -348,34 +349,33 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
defineDefaultProperty(QStringLiteral("compile"), method_compile, 2);
}
-ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
+void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<RegExpObject> r(scope, ctx->thisObject().as<RegExpObject>());
+ Scoped<RegExpObject> r(scope, callData->thisObject.as<RegExpObject>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedValue arg(scope, ctx->argument(0));
+ ScopedValue arg(scope, callData->argument(0));
ScopedString str(scope, arg->toString(scope.engine));
if (scope.hasException())
- return Encode::undefined();
+ RETURN_UNDEFINED();
QString s = str->toQString();
int offset = r->global() ? r->lastIndexProperty()->toInt32() : 0;
if (offset < 0 || offset > s.length()) {
*r->lastIndexProperty() = Primitive::fromInt32(0);
- return Encode::null();
+ RETURN_RESULT(Encode::null());
}
uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint));
const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
+ Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor());
regExpCtor->d()->clearLastMatch();
if (result == -1) {
*r->lastIndexProperty() = Primitive::fromInt32(0);
- return Encode::null();
+ RETURN_RESULT(Encode::null());
}
// fill in result data
@@ -386,7 +386,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
for (int i = 0; i < len; ++i) {
int start = matchOffsets[i * 2];
int end = matchOffsets[i * 2 + 1];
- v = (start != -1) ? ctx->d()->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
+ v = (start != -1) ? scope.engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
@@ -402,84 +402,75 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
if (r->global())
*r->lastIndexProperty() = Primitive::fromInt32(matchOffsets[1]);
- return array.asReturnedValue();
+ scope.result = array;
}
-ReturnedValue RegExpPrototype::method_test(CallContext *ctx)
+void RegExpPrototype::method_test(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedValue r(scope, method_exec(ctx));
- return Encode(!r->isNull());
+ method_exec(b, scope, callData);
+ scope.result = Encode(!scope.result.isNull());
}
-ReturnedValue RegExpPrototype::method_toString(CallContext *ctx)
+void RegExpPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<RegExpObject> r(scope, ctx->thisObject().as<RegExpObject>());
+ Scoped<RegExpObject> r(scope, callData->thisObject.as<RegExpObject>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return ctx->d()->engine->newString(r->toString())->asReturnedValue();
+ scope.result = scope.engine->newString(r->toString());
}
-ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
+void RegExpPrototype::method_compile(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<RegExpObject> r(scope, ctx->thisObject().as<RegExpObject>());
+ Scoped<RegExpObject> r(scope, callData->thisObject.as<RegExpObject>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- ScopedCallData callData(scope, ctx->argc());
- memcpy(callData->args, ctx->args(), ctx->argc()*sizeof(Value));
+ ScopedCallData cData(scope, callData->argc);
+ memcpy(cData->args, callData->args, callData->argc*sizeof(Value));
- ctx->d()->engine->regExpCtor()->as<FunctionObject>()->construct(scope, callData);
+ scope.engine->regExpCtor()->as<FunctionObject>()->construct(scope, cData);
Scoped<RegExpObject> re(scope, scope.result.asReturnedValue());
r->d()->value = re->value();
r->d()->global = re->global();
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
template <int index>
-ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
+void RegExpPrototype::method_get_lastMatch_n(const BuiltinFunction *, Scope &scope, CallData *)
{
- Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
- ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
- if (result->isUndefined())
- return ctx->d()->engine->newString()->asReturnedValue();
- return result->asReturnedValue();
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch());
+ scope.result = lastMatch ? lastMatch->getIndexed(index) : Encode::undefined();
+ if (scope.result.isUndefined())
+ scope.result = scope.engine->newString();
}
-ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
+void RegExpPrototype::method_get_lastParen(const BuiltinFunction *, Scope &scope, CallData *)
{
- Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
- ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
- if (result->isUndefined())
- return ctx->d()->engine->newString()->asReturnedValue();
- return result->asReturnedValue();
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch());
+ scope.result = lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined();
+ if (scope.result.isUndefined())
+ scope.result = scope.engine->newString();
}
-ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx)
+void RegExpPrototype::method_get_input(const BuiltinFunction *, Scope &scope, CallData *)
{
- return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastInput()->asReturnedValue();
+ scope.result = static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastInput();
}
-ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
+void RegExpPrototype::method_get_leftContext(const BuiltinFunction *, Scope &scope, CallData *)
{
- Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
+ Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
- return ctx->d()->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue();
+ scope.result = scope.engine->newString(lastInput.left(regExpCtor->lastMatchStart()));
}
-ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx)
+void RegExpPrototype::method_get_rightContext(const BuiltinFunction *, Scope &scope, CallData *)
{
- Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
+ Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
- return ctx->d()->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue();
+ scope.result = scope.engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()));
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 2c82cfdfd1..c0c7dfa78a 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -149,17 +149,17 @@ struct RegExpPrototype: RegExpObject
{
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_exec(CallContext *ctx);
- static ReturnedValue method_test(CallContext *ctx);
- static ReturnedValue method_toString(CallContext *ctx);
- static ReturnedValue method_compile(CallContext *ctx);
+ static void method_exec(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_test(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_compile(const BuiltinFunction *, Scope &scope, CallData *callData);
template <int index>
- static ReturnedValue method_get_lastMatch_n(CallContext *ctx);
- static ReturnedValue method_get_lastParen(CallContext *ctx);
- static ReturnedValue method_get_input(CallContext *ctx);
- static ReturnedValue method_get_leftContext(CallContext *ctx);
- static ReturnedValue method_get_rightContext(CallContext *ctx);
+ static void method_get_lastMatch_n(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_lastParen(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_input(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_leftContext(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_rightContext(const BuiltinFunction *, Scope &scope, CallData *callData);
};
}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index d6c55926b1..023a739e33 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -499,6 +499,7 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val
{
Scope scope(engine);
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(value, STRING_HINT));
+ Q_ASSERT(!prim->isManaged() || prim->isString());
return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 4e627e003f..6775028272 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -68,6 +68,38 @@ namespace QV4 {
struct ScopedValue;
+#define CHECK_EXCEPTION() \
+ do { \
+ if (scope.hasException()) { \
+ scope.result = QV4::Encode::undefined(); \
+ return; \
+ } \
+ } while (false)
+
+#define RETURN_UNDEFINED() \
+ do { \
+ scope.result = QV4::Encode::undefined(); \
+ return; \
+ } while (false)
+
+#define RETURN_RESULT(r) \
+ do { \
+ scope.result = r; \
+ return; \
+ } while (false)
+
+#define THROW_TYPE_ERROR() \
+ do { \
+ scope.result = scope.engine->throwTypeError(); \
+ return; \
+ } while (false)
+
+#define THROW_GENERIC_ERROR(str) \
+ do { \
+ scope.result = scope.engine->throwError(QString::fromUtf8(str)); \
+ return; \
+ } while (false)
+
struct Scope {
inline Scope(ExecutionContext *ctx)
: engine(ctx->d()->engine)
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index b54177bee9..62145f36cc 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -88,8 +88,6 @@ void Script::parse()
ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
- MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
-
IR::Module module(v4->debugger() != 0);
QQmlJS::Engine ee, *engine = &ee;
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 58da7b9f68..8ce10e326d 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -404,28 +404,28 @@ public:
struct CompareFunctor
{
- CompareFunctor(QV4::ExecutionContext *ctx, const QV4::Value &compareFn)
- : m_ctx(ctx), m_compareFn(&compareFn)
+ CompareFunctor(QV4::ExecutionEngine *v4, const QV4::Value &compareFn)
+ : m_v4(v4), m_compareFn(&compareFn)
{}
bool operator()(typename Container::value_type lhs, typename Container::value_type rhs)
{
- QV4::Scope scope(m_ctx);
+ QV4::Scope scope(m_v4);
ScopedObject compare(scope, m_compareFn);
ScopedCallData callData(scope, 2);
- callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs);
- callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs);
- callData->thisObject = this->m_ctx->d()->engine->globalObject;
+ callData->args[0] = convertElementToValue(m_v4, lhs);
+ callData->args[1] = convertElementToValue(m_v4, rhs);
+ callData->thisObject = m_v4->globalObject;
compare->call(scope, callData);
return scope.result.toNumber() < 0;
}
private:
- QV4::ExecutionContext *m_ctx;
+ QV4::ExecutionEngine *m_v4;
const QV4::Value *m_compareFn;
};
- void sort(QV4::CallContext *ctx)
+ void sort(const BuiltinFunction *, Scope &scope, CallData *callData)
{
if (d()->isReference) {
if (!d()->object)
@@ -433,9 +433,8 @@ public:
loadReference();
}
- QV4::Scope scope(ctx);
- if (ctx->argc() == 1 && ctx->args()[0].as<FunctionObject>()) {
- CompareFunctor cf(ctx, ctx->args()[0]);
+ if (callData->argc == 1 && callData->args[0].as<FunctionObject>()) {
+ CompareFunctor cf(scope.engine, callData->args[0]);
std::sort(d()->container->begin(), d()->container->end(), cf);
} else {
DefaultCompareFunctor cf;
@@ -446,45 +445,43 @@ public:
storeReference();
}
- static QV4::ReturnedValue method_get_length(QV4::CallContext *ctx)
+ static void method_get_length(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->thisObject().as<QQmlSequence<Container> >());
+ QV4::Scoped<QQmlSequence<Container> > This(scope, callData->thisObject.as<QQmlSequence<Container> >());
if (!This)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (This->d()->isReference) {
if (!This->d()->object)
- return QV4::Encode(0);
+ RETURN_RESULT(Encode(0));
This->loadReference();
}
- return QV4::Encode(This->d()->container->count());
+ RETURN_RESULT(Encode(This->d()->container->count()));
}
- static QV4::ReturnedValue method_set_length(QV4::CallContext* ctx)
+ static void method_set_length(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->thisObject().as<QQmlSequence<Container> >());
+ QV4::Scoped<QQmlSequence<Container> > This(scope, callData->thisObject.as<QQmlSequence<Container> >());
if (!This)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- quint32 newLength = ctx->args()[0].toUInt32();
+ quint32 newLength = callData->args[0].toUInt32();
/* Qt containers have int (rather than uint) allowable indexes. */
if (newLength > INT_MAX) {
generateWarning(scope.engine, QLatin1String("Index out of range during length set"));
- return QV4::Encode::undefined();
+ RETURN_UNDEFINED();
}
/* Read the sequence from the QObject property if we're a reference */
if (This->d()->isReference) {
if (!This->d()->object)
- return QV4::Encode::undefined();
+ RETURN_UNDEFINED();
This->loadReference();
}
/* Determine whether we need to modify the sequence */
qint32 newCount = static_cast<qint32>(newLength);
qint32 count = This->d()->container->count();
if (newCount == count) {
- return QV4::Encode::undefined();
+ RETURN_UNDEFINED();
} else if (newCount > count) {
/* according to ECMA262r3 we need to insert */
/* undefined values increasing length to newLength. */
@@ -506,7 +503,7 @@ public:
/* write back. already checked that object is non-null, so skip that check here. */
This->storeReference();
}
- return QV4::Encode::undefined();
+ RETURN_UNDEFINED();
}
QVariant toVariant() const
@@ -625,26 +622,25 @@ void SequencePrototype::init()
}
#undef REGISTER_QML_SEQUENCE_METATYPE
-QV4::ReturnedValue SequencePrototype::method_sort(QV4::CallContext *ctx)
+void SequencePrototype::method_sort(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::ScopedObject o(scope, ctx->thisObject());
+ QV4::ScopedObject o(scope, callData->thisObject);
if (!o || !o->isListType())
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- if (ctx->argc() >= 2)
- return o.asReturnedValue();
+ if (callData->argc >= 2)
+ RETURN_RESULT(o);
#define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \
if (QQml##SequenceElementTypeName##List *s = o->as<QQml##SequenceElementTypeName##List>()) { \
- s->sort(ctx); \
+ s->sort(b, scope, callData); \
} else
FOREACH_QML_SEQUENCE_TYPE(CALL_SORT)
#undef CALL_SORT
{}
- return o.asReturnedValue();
+ RETURN_RESULT(o);
}
#define IS_SEQUENCE(unused1, unused2, SequenceType, unused3) \
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index c0416ad639..6f96b9f760 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -67,12 +67,12 @@ struct SequencePrototype : public QV4::Object
{
void init();
- static ReturnedValue method_valueOf(QV4::CallContext *ctx)
+ static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- return ctx->thisObject().toString(ctx->engine())->asReturnedValue();
+ scope.result = callData->thisObject.toString(scope.engine);
}
- static ReturnedValue method_sort(QV4::CallContext *ctx);
+ static void method_sort(const BuiltinFunction *, Scope &scope, CallData *callData);
static bool isSequenceType(int sequenceTypeId);
static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 1efd8cb714..cde2131aab 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -102,6 +102,7 @@ void Heap::String::init(MemoryManager *mm, String *l, String *r)
stringHash = UINT_MAX;
largestSubLength = qMax(l->largestSubLength, r->largestSubLength);
len = l->len + r->len;
+ Q_ASSERT(largestSubLength <= len);
if (!l->largestSubLength && l->len > largestSubLength)
largestSubLength = l->len;
@@ -113,6 +114,15 @@ void Heap::String::init(MemoryManager *mm, String *l, String *r)
simplifyString();
}
+void Heap::String::destroy() {
+ if (!largestSubLength) {
+ mm->changeUnmanagedHeapSizeUsage(qptrdiff(-text->size) * (int)sizeof(QChar));
+ if (!text->ref.deref())
+ QStringData::deallocate(text);
+ }
+ Base::destroy();
+}
+
uint String::toUInt(bool *ok) const
{
*ok = true;
@@ -151,7 +161,7 @@ void Heap::String::simplifyString() const
text->ref.ref();
identifier = 0;
largestSubLength = 0;
- mm->growUnmanagedHeapSizeUsage(size_t(text->size) * sizeof(QChar));
+ mm->changeUnmanagedHeapSizeUsage(qptrdiff(text->size) * (qptrdiff)sizeof(QChar));
}
void Heap::String::append(const String *data, QChar *ch)
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 4890a85724..5b0fd292d6 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -73,11 +73,7 @@ struct Q_QML_PRIVATE_EXPORT String : Base {
#ifndef V4_BOOTSTRAP
void init(MemoryManager *mm, const QString &text);
void init(MemoryManager *mm, String *l, String *n);
- void destroy() {
- if (!largestSubLength && !text->ref.deref())
- QStringData::deallocate(text);
- Base::destroy();
- }
+ void destroy();
void simplifyString() const;
int length() const {
Q_ASSERT((largestSubLength &&
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 6fbf1c3c85..3c6a24e035 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -214,10 +214,9 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("trim"), method_trim);
}
-static QString getThisString(ExecutionContext *ctx)
+static QString getThisString(Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- ScopedValue t(scope, ctx->thisObject());
+ ScopedValue t(scope, callData->thisObject);
if (String *s = t->stringValue())
return s->toQString();
if (StringObject *thisString = t->as<StringObject>())
@@ -229,158 +228,146 @@ static QString getThisString(ExecutionContext *ctx)
return t->toQString();
}
-ReturnedValue StringPrototype::method_toString(CallContext *context)
+void StringPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (context->thisObject().isString())
- return context->thisObject().asReturnedValue();
+ if (callData->thisObject.isString())
+ RETURN_RESULT(callData->thisObject);
- StringObject *o = context->thisObject().as<StringObject>();
+ StringObject *o = callData->thisObject.as<StringObject>();
if (!o)
- return context->engine()->throwTypeError();
- return Encode(o->d()->string);
+ THROW_TYPE_ERROR();
+ scope.result = o->d()->string;
}
-ReturnedValue StringPrototype::method_charAt(CallContext *context)
+void StringPrototype::method_charAt(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- const QString str = getThisString(context);
- if (context->d()->engine->hasException)
- return Encode::undefined();
+ const QString str = getThisString(scope, callData);
+ CHECK_EXCEPTION();
int pos = 0;
- if (context->argc() > 0)
- pos = (int) context->args()[0].toInteger();
+ if (callData->argc > 0)
+ pos = (int) callData->args[0].toInteger();
QString result;
if (pos >= 0 && pos < str.length())
result += str.at(pos);
- return context->d()->engine->newString(result)->asReturnedValue();
+ scope.result = scope.engine->newString(result);
}
-ReturnedValue StringPrototype::method_charCodeAt(CallContext *context)
+void StringPrototype::method_charCodeAt(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- const QString str = getThisString(context);
- if (context->d()->engine->hasException)
- return Encode::undefined();
+ const QString str = getThisString(scope, callData);
+ CHECK_EXCEPTION();
int pos = 0;
- if (context->argc() > 0)
- pos = (int) context->args()[0].toInteger();
+ if (callData->argc > 0)
+ pos = (int) callData->args[0].toInteger();
if (pos >= 0 && pos < str.length())
- return Encode(str.at(pos).unicode());
+ RETURN_RESULT(Encode(str.at(pos).unicode()));
- return Encode(qt_qnan());
+ scope.result = Encode(qt_qnan());
}
-ReturnedValue StringPrototype::method_concat(CallContext *context)
+void StringPrototype::method_concat(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(context);
-
- QString value = getThisString(context);
- if (scope.engine->hasException)
- return Encode::undefined();
+ QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
ScopedString s(scope);
- for (int i = 0; i < context->argc(); ++i) {
- s = context->args()[i].toString(scope.engine);
- if (scope.hasException())
- return Encode::undefined();
+ for (int i = 0; i < callData->argc; ++i) {
+ s = callData->args[i].toString(scope.engine);
+ CHECK_EXCEPTION();
+
Q_ASSERT(s->isString());
value += s->toQString();
}
- return context->d()->engine->newString(value)->asReturnedValue();
+ scope.result = scope.engine->newString(value);
}
-ReturnedValue StringPrototype::method_endsWith(CallContext *context)
+void StringPrototype::method_endsWith(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QString value = getThisString(context);
- if (context->d()->engine->hasException)
- return Encode::undefined();
+ QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
QString searchString;
- if (context->argc()) {
- if (context->args()[0].as<RegExpObject>())
- return context->engine()->throwTypeError();
- searchString = context->args()[0].toQString();
+ if (callData->argc) {
+ if (callData->args[0].as<RegExpObject>())
+ THROW_TYPE_ERROR();
+ searchString = callData->args[0].toQString();
}
int pos = value.length();
- if (context->argc() > 1)
- pos = (int) context->args()[1].toInteger();
+ if (callData->argc > 1)
+ pos = (int) callData->args[1].toInteger();
if (pos == value.length())
- return Encode(value.endsWith(searchString));
+ RETURN_RESULT(Encode(value.endsWith(searchString)));
QStringRef stringToSearch = value.leftRef(pos);
- return Encode(stringToSearch.endsWith(searchString));
+ scope.result = Encode(stringToSearch.endsWith(searchString));
}
-ReturnedValue StringPrototype::method_indexOf(CallContext *context)
+void StringPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QString value = getThisString(context);
- if (context->d()->engine->hasException)
- return Encode::undefined();
+ QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
QString searchString;
- if (context->argc())
- searchString = context->args()[0].toQString();
+ if (callData->argc)
+ searchString = callData->args[0].toQString();
int pos = 0;
- if (context->argc() > 1)
- pos = (int) context->args()[1].toInteger();
+ if (callData->argc > 1)
+ pos = (int) callData->args[1].toInteger();
int index = -1;
if (! value.isEmpty())
index = value.indexOf(searchString, qMin(qMax(pos, 0), value.length()));
- return Encode(index);
+ scope.result = Encode(index);
}
-ReturnedValue StringPrototype::method_includes(CallContext *context)
+void StringPrototype::method_includes(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QString value = getThisString(context);
- if (context->d()->engine->hasException)
- return Encode::undefined();
+ QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
QString searchString;
- if (context->argc()) {
- if (context->args()[0].as<RegExpObject>())
- return context->engine()->throwTypeError();
- searchString = context->args()[0].toQString();
+ if (callData->argc) {
+ if (callData->args[0].as<RegExpObject>())
+ THROW_TYPE_ERROR();
+ searchString = callData->args[0].toQString();
}
int pos = 0;
- if (context->argc() > 1) {
- Scope scope(context);
- ScopedValue posArg(scope, context->argument(1));
+ if (callData->argc > 1) {
+ ScopedValue posArg(scope, callData->argument(1));
pos = (int) posArg->toInteger();
if (!posArg->isInteger() && posArg->isNumber() && qIsInf(posArg->toNumber()))
pos = value.length();
}
if (pos == 0)
- return Encode(value.contains(searchString));
+ RETURN_RESULT(Encode(value.contains(searchString)));
QStringRef stringToSearch = value.midRef(pos);
- return Encode(stringToSearch.contains(searchString));
+ scope.result = Encode(stringToSearch.contains(searchString));
}
-ReturnedValue StringPrototype::method_lastIndexOf(CallContext *context)
+void StringPrototype::method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(context);
-
- const QString value = getThisString(context);
- if (scope.engine->hasException)
- return Encode::undefined();
+ const QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
QString searchString;
- if (context->argc())
- searchString = context->args()[0].toQString();
+ if (callData->argc)
+ searchString = callData->args[0].toQString();
- ScopedValue posArg(scope, context->argument(1));
+ ScopedValue posArg(scope, callData->argument(1));
double position = RuntimeHelpers::toNumber(posArg);
if (std::isnan(position))
position = +qInf();
@@ -391,43 +378,40 @@ ReturnedValue StringPrototype::method_lastIndexOf(CallContext *context)
if (!searchString.isEmpty() && pos == value.length())
--pos;
if (searchString.isNull() && pos == 0)
- return Encode(-1);
+ RETURN_RESULT(Encode(-1));
int index = value.lastIndexOf(searchString, pos);
- return Encode(index);
+ scope.result = Encode(index);
}
-ReturnedValue StringPrototype::method_localeCompare(CallContext *context)
+void StringPrototype::method_localeCompare(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(context);
- const QString value = getThisString(context);
- if (scope.engine->hasException)
- return Encode::undefined();
+ const QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
- ScopedValue v(scope, context->argument(0));
+ ScopedValue v(scope, callData->argument(0));
const QString that = v->toQString();
- return Encode(QString::localeAwareCompare(value, that));
+ scope.result = Encode(QString::localeAwareCompare(value, that));
}
-ReturnedValue StringPrototype::method_match(CallContext *context)
+void StringPrototype::method_match(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (context->thisObject().isUndefined() || context->thisObject().isNull())
- return context->engine()->throwTypeError();
+ if (callData->thisObject.isUndefined() || callData->thisObject.isNull())
+ THROW_TYPE_ERROR();
- Scope scope(context);
- ScopedString s(scope, context->thisObject().toString(scope.engine));
+ ScopedString s(scope, callData->thisObject.toString(scope.engine));
- ScopedValue regexp(scope, context->argument(0));
+ ScopedValue regexp(scope, callData->argument(0));
Scoped<RegExpObject> rx(scope, regexp);
if (!rx) {
ScopedCallData callData(scope, 1);
callData->args[0] = regexp;
- context->d()->engine->regExpCtor()->construct(scope, callData);
+ scope.engine->regExpCtor()->construct(scope, callData);
rx = scope.result.asReturnedValue();
}
if (!rx)
// ### CHECK
- return context->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
bool global = rx->global();
@@ -435,24 +419,24 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec")));
ScopedFunctionObject exec(scope, scope.engine->regExpPrototype()->get(execString));
- ScopedCallData callData(scope, 1);
- callData->thisObject = rx;
- callData->args[0] = s;
+ ScopedCallData cData(scope, 1);
+ cData->thisObject = rx;
+ cData->args[0] = s;
if (!global) {
- exec->call(scope, callData);
- return scope.result.asReturnedValue();
+ exec->call(scope, cData);
+ return;
}
- ScopedString lastIndex(scope, context->d()->engine->newString(QStringLiteral("lastIndex")));
+ ScopedString lastIndex(scope, scope.engine->newString(QStringLiteral("lastIndex")));
rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0)));
- ScopedArrayObject a(scope, context->d()->engine->newArrayObject());
+ ScopedArrayObject a(scope, scope.engine->newArrayObject());
double previousLastIndex = 0;
uint n = 0;
ScopedValue matchStr(scope);
ScopedValue index(scope);
while (1) {
- exec->call(scope, callData);
+ exec->call(scope, cData);
if (scope.result.isNull())
break;
assert(scope.result.isObject());
@@ -469,10 +453,9 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
++n;
}
if (!n)
- return Encode::null();
-
- return a.asReturnedValue();
-
+ scope.result = Encode::null();
+ else
+ scope.result = a;
}
static void appendReplacementString(QString *result, const QString &input, const QString& replaceValue, uint* matchOffsets, int captureCount)
@@ -521,14 +504,13 @@ static void appendReplacementString(QString *result, const QString &input, const
}
}
-ReturnedValue StringPrototype::method_replace(CallContext *ctx)
+void StringPrototype::method_replace(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
QString string;
- if (StringObject *thisString = ctx->thisObject().as<StringObject>())
+ if (StringObject *thisString = callData->thisObject.as<StringObject>())
string = thisString->d()->string->toQString();
else
- string = ctx->thisObject().toQString();
+ string = callData->thisObject.toQString();
int numCaptures = 0;
int numStringMatches = 0;
@@ -537,7 +519,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
uint _matchOffsets[64];
uint *matchOffsets = _matchOffsets;
- ScopedValue searchValue(scope, ctx->argument(0));
+ ScopedValue searchValue(scope, callData->argument(0));
Scoped<RegExpObject> regExp(scope, searchValue);
if (regExp) {
uint offset = 0;
@@ -580,7 +562,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
}
QString result;
- ScopedValue replaceValue(scope, ctx->argument(1));
+ ScopedValue replaceValue(scope, callData->argument(1));
ScopedFunctionObject searchCallback(scope, replaceValue);
if (!!searchCallback) {
result.reserve(string.length() + 10*numStringMatches);
@@ -595,14 +577,14 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
uint end = matchOffsets[idx + 1];
entry = Primitive::undefinedValue();
if (start != JSC::Yarr::offsetNoMatch && end != JSC::Yarr::offsetNoMatch)
- entry = ctx->d()->engine->newString(string.mid(start, end - start));
+ entry = scope.engine->newString(string.mid(start, end - start));
callData->args[k] = entry;
}
uint matchStart = matchOffsets[i * numCaptures * 2];
Q_ASSERT(matchStart >= static_cast<uint>(lastEnd));
uint matchEnd = matchOffsets[i * numCaptures * 2 + 1];
callData->args[numCaptures] = Primitive::fromUInt32(matchStart);
- callData->args[numCaptures + 1] = ctx->d()->engine->newString(string);
+ callData->args[numCaptures + 1] = scope.engine->newString(string);
searchCallback->call(scope, callData);
result += string.midRef(lastEnd, matchStart - lastEnd);
@@ -632,23 +614,22 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
if (matchOffsets != _matchOffsets)
free(matchOffsets);
- return ctx->d()->engine->newString(result)->asReturnedValue();
+ scope.result = scope.engine->newString(result);
}
-ReturnedValue StringPrototype::method_search(CallContext *ctx)
+void StringPrototype::method_search(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- QString string = getThisString(ctx);
- scope.result = ctx->argument(0);
- if (scope.engine->hasException)
- return Encode::undefined();
+ QString string = getThisString(scope, callData);
+ scope.result = callData->argument(0);
+ CHECK_EXCEPTION();
+
Scoped<RegExpObject> regExp(scope, scope.result.as<RegExpObject>());
if (!regExp) {
ScopedCallData callData(scope, 1);
callData->args[0] = scope.result;
- ctx->d()->engine->regExpCtor()->construct(scope, callData);
- if (scope.engine->hasException)
- return Encode::undefined();
+ scope.engine->regExpCtor()->construct(scope, callData);
+ CHECK_EXCEPTION();
+
regExp = scope.result.as<RegExpObject>();
Q_ASSERT(regExp);
}
@@ -656,21 +637,21 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx)
uint* matchOffsets = (uint*)alloca(regExp->value()->captureCount() * 2 * sizeof(uint));
uint result = re->match(string, /*offset*/0, matchOffsets);
if (result == JSC::Yarr::offsetNoMatch)
- return Encode(-1);
- return Encode(result);
+ scope.result = Encode(-1);
+ else
+ scope.result = Encode(result);
}
-ReturnedValue StringPrototype::method_slice(CallContext *ctx)
+void StringPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- const QString text = getThisString(ctx);
- if (ctx->d()->engine->hasException)
- return Encode::undefined();
+ const QString text = getThisString(scope, callData);
+ CHECK_EXCEPTION();
const double length = text.length();
- double start = ctx->argc() ? ctx->args()[0].toInteger() : 0;
- double end = (ctx->argc() < 2 || ctx->args()[1].isUndefined())
- ? length : ctx->args()[1].toInteger();
+ double start = callData->argc ? callData->args[0].toInteger() : 0;
+ double end = (callData->argc < 2 || callData->args[1].isUndefined())
+ ? length : callData->args[1].toInteger();
if (start < 0)
start = qMax(length + start, 0.);
@@ -686,40 +667,38 @@ ReturnedValue StringPrototype::method_slice(CallContext *ctx)
const int intEnd = int(end);
int count = qMax(0, intEnd - intStart);
- return ctx->d()->engine->newString(text.mid(intStart, count))->asReturnedValue();
+ scope.result = scope.engine->newString(text.mid(intStart, count));
}
-ReturnedValue StringPrototype::method_split(CallContext *ctx)
+void StringPrototype::method_split(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- QString text = getThisString(ctx);
- if (scope.engine->hasException)
- return Encode::undefined();
+ QString text = getThisString(scope, callData);
+ CHECK_EXCEPTION();
- ScopedValue separatorValue(scope, ctx->argument(0));
- ScopedValue limitValue(scope, ctx->argument(1));
+ ScopedValue separatorValue(scope, callData->argument(0));
+ ScopedValue limitValue(scope, callData->argument(1));
- ScopedArrayObject array(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject array(scope, scope.engine->newArrayObject());
if (separatorValue->isUndefined()) {
if (limitValue->isUndefined()) {
- ScopedString s(scope, ctx->d()->engine->newString(text));
+ ScopedString s(scope, scope.engine->newString(text));
array->push_back(s);
- return array.asReturnedValue();
+ RETURN_RESULT(array);
}
- return ctx->d()->engine->newString(text.left(limitValue->toInteger()))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(text.left(limitValue->toInteger())));
}
uint limit = limitValue->isUndefined() ? UINT_MAX : limitValue->toUInt32();
if (limit == 0)
- return array.asReturnedValue();
+ RETURN_RESULT(array);
Scoped<RegExpObject> re(scope, separatorValue);
if (re) {
if (re->value()->pattern->isEmpty()) {
re = (RegExpObject *)0;
- separatorValue = ctx->d()->engine->newString();
+ separatorValue = scope.engine->newString();
}
}
@@ -733,7 +712,7 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
if (result == JSC::Yarr::offsetNoMatch)
break;
- array->push_back((s = ctx->d()->engine->newString(text.mid(offset, matchOffsets[0] - offset))));
+ array->push_back((s = scope.engine->newString(text.mid(offset, matchOffsets[0] - offset))));
offset = qMax(offset + 1, matchOffsets[1]);
if (array->getLength() >= limit)
@@ -742,72 +721,70 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
for (int i = 1; i < re->value()->captureCount(); ++i) {
uint start = matchOffsets[i * 2];
uint end = matchOffsets[i * 2 + 1];
- array->push_back((s = ctx->d()->engine->newString(text.mid(start, end - start))));
+ array->push_back((s = scope.engine->newString(text.mid(start, end - start))));
if (array->getLength() >= limit)
break;
}
}
if (array->getLength() < limit)
- array->push_back((s = ctx->d()->engine->newString(text.mid(offset))));
+ array->push_back((s = scope.engine->newString(text.mid(offset))));
} else {
QString separator = separatorValue->toQString();
if (separator.isEmpty()) {
for (uint i = 0; i < qMin(limit, uint(text.length())); ++i)
- array->push_back((s = ctx->d()->engine->newString(text.mid(i, 1))));
- return array.asReturnedValue();
+ array->push_back((s = scope.engine->newString(text.mid(i, 1))));
+ RETURN_RESULT(array);
}
int start = 0;
int end;
while ((end = text.indexOf(separator, start)) != -1) {
- array->push_back((s = ctx->d()->engine->newString(text.mid(start, end - start))));
+ array->push_back((s = scope.engine->newString(text.mid(start, end - start))));
start = end + separator.size();
if (array->getLength() >= limit)
break;
}
if (array->getLength() < limit && start != -1)
- array->push_back((s = ctx->d()->engine->newString(text.mid(start))));
+ array->push_back((s = scope.engine->newString(text.mid(start))));
}
- return array.asReturnedValue();
+ RETURN_RESULT(array);
}
-ReturnedValue StringPrototype::method_startsWith(CallContext *context)
+void StringPrototype::method_startsWith(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QString value = getThisString(context);
- if (context->d()->engine->hasException)
- return Encode::undefined();
+ QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
QString searchString;
- if (context->argc()) {
- if (context->args()[0].as<RegExpObject>())
- return context->engine()->throwTypeError();
- searchString = context->args()[0].toQString();
+ if (callData->argc) {
+ if (callData->args[0].as<RegExpObject>())
+ THROW_TYPE_ERROR();
+ searchString = callData->args[0].toQString();
}
int pos = 0;
- if (context->argc() > 1)
- pos = (int) context->args()[1].toInteger();
+ if (callData->argc > 1)
+ pos = (int) callData->args[1].toInteger();
if (pos == 0)
- return Encode(value.startsWith(searchString));
+ RETURN_RESULT(Encode(value.startsWith(searchString)));
QStringRef stringToSearch = value.midRef(pos);
- return Encode(stringToSearch.startsWith(searchString));
+ RETURN_RESULT(Encode(stringToSearch.startsWith(searchString)));
}
-ReturnedValue StringPrototype::method_substr(CallContext *context)
+void StringPrototype::method_substr(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- const QString value = getThisString(context);
- if (context->d()->engine->hasException)
- return Encode::undefined();
+ const QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
double start = 0;
- if (context->argc() > 0)
- start = context->args()[0].toInteger();
+ if (callData->argc > 0)
+ start = callData->args[0].toInteger();
double length = +qInf();
- if (context->argc() > 1)
- length = context->args()[1].toInteger();
+ if (callData->argc > 1)
+ length = callData->args[1].toInteger();
double count = value.length();
if (start < 0)
@@ -817,24 +794,23 @@ ReturnedValue StringPrototype::method_substr(CallContext *context)
qint32 x = Primitive::toInt32(start);
qint32 y = Primitive::toInt32(length);
- return context->d()->engine->newString(value.mid(x, y))->asReturnedValue();
+ scope.result = scope.engine->newString(value.mid(x, y));
}
-ReturnedValue StringPrototype::method_substring(CallContext *context)
+void StringPrototype::method_substring(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QString value = getThisString(context);
- if (context->d()->engine->hasException)
- return Encode::undefined();
+ QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
+
int length = value.length();
double start = 0;
double end = length;
- if (context->argc() > 0)
- start = context->args()[0].toInteger();
+ if (callData->argc > 0)
+ start = callData->args[0].toInteger();
- Scope scope(context);
- ScopedValue endValue(scope, context->argument(1));
+ ScopedValue endValue(scope, callData->argument(1));
if (!endValue->isUndefined())
end = endValue->toInteger();
@@ -858,51 +834,50 @@ ReturnedValue StringPrototype::method_substring(CallContext *context)
qint32 x = (int)start;
qint32 y = (int)(end - start);
- return context->d()->engine->newString(value.mid(x, y))->asReturnedValue();
+ scope.result = scope.engine->newString(value.mid(x, y));
}
-ReturnedValue StringPrototype::method_toLowerCase(CallContext *ctx)
+void StringPrototype::method_toLowerCase(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QString value = getThisString(ctx);
- if (ctx->d()->engine->hasException)
- return Encode::undefined();
- return ctx->d()->engine->newString(value.toLower())->asReturnedValue();
+ QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
+
+ scope.result = scope.engine->newString(value.toLower());
}
-ReturnedValue StringPrototype::method_toLocaleLowerCase(CallContext *ctx)
+void StringPrototype::method_toLocaleLowerCase(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- return method_toLowerCase(ctx);
+ method_toLowerCase(b, scope, callData);
}
-ReturnedValue StringPrototype::method_toUpperCase(CallContext *ctx)
+void StringPrototype::method_toUpperCase(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QString value = getThisString(ctx);
- if (ctx->d()->engine->hasException)
- return Encode::undefined();
- return ctx->d()->engine->newString(value.toUpper())->asReturnedValue();
+ QString value = getThisString(scope, callData);
+ CHECK_EXCEPTION();
+
+ scope.result = scope.engine->newString(value.toUpper());
}
-ReturnedValue StringPrototype::method_toLocaleUpperCase(CallContext *ctx)
+void StringPrototype::method_toLocaleUpperCase(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- return method_toUpperCase(ctx);
+ return method_toUpperCase(b, scope, callData);
}
-ReturnedValue StringPrototype::method_fromCharCode(CallContext *context)
+void StringPrototype::method_fromCharCode(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QString str(context->argc(), Qt::Uninitialized);
+ QString str(callData->argc, Qt::Uninitialized);
QChar *ch = str.data();
- for (int i = 0; i < context->argc(); ++i) {
- *ch = QChar(context->args()[i].toUInt16());
+ for (int i = 0; i < callData->argc; ++i) {
+ *ch = QChar(callData->args[i].toUInt16());
++ch;
}
- return context->d()->engine->newString(str)->asReturnedValue();
+ scope.result = scope.engine->newString(str);
}
-ReturnedValue StringPrototype::method_trim(CallContext *ctx)
+void StringPrototype::method_trim(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QString s = getThisString(ctx);
- if (ctx->d()->engine->hasException)
- return Encode::undefined();
+ QString s = getThisString(scope, callData);
+ CHECK_EXCEPTION();
const QChar *chars = s.constData();
int start, end;
@@ -915,5 +890,5 @@ ReturnedValue StringPrototype::method_trim(CallContext *ctx)
break;
}
- return ctx->d()->engine->newString(QString(chars + start, end - start + 1))->asReturnedValue();
+ scope.result = scope.engine->newString(QString(chars + start, end - start + 1));
}
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index b9f9d44fe8..0ee7a6ece9 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -111,29 +111,29 @@ struct StringPrototype: StringObject
{
void init(ExecutionEngine *engine, Object *ctor);
- static ReturnedValue method_toString(CallContext *context);
- static ReturnedValue method_charAt(CallContext *context);
- static ReturnedValue method_charCodeAt(CallContext *context);
- static ReturnedValue method_concat(CallContext *context);
- static ReturnedValue method_endsWith(CallContext *ctx);
- static ReturnedValue method_indexOf(CallContext *context);
- static ReturnedValue method_includes(CallContext *context);
- static ReturnedValue method_lastIndexOf(CallContext *context);
- static ReturnedValue method_localeCompare(CallContext *context);
- static ReturnedValue method_match(CallContext *context);
- static ReturnedValue method_replace(CallContext *ctx);
- static ReturnedValue method_search(CallContext *ctx);
- static ReturnedValue method_slice(CallContext *ctx);
- static ReturnedValue method_split(CallContext *ctx);
- static ReturnedValue method_startsWith(CallContext *ctx);
- static ReturnedValue method_substr(CallContext *context);
- static ReturnedValue method_substring(CallContext *context);
- static ReturnedValue method_toLowerCase(CallContext *ctx);
- static ReturnedValue method_toLocaleLowerCase(CallContext *ctx);
- static ReturnedValue method_toUpperCase(CallContext *ctx);
- static ReturnedValue method_toLocaleUpperCase(CallContext *ctx);
- static ReturnedValue method_fromCharCode(CallContext *context);
- static ReturnedValue method_trim(CallContext *ctx);
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_charAt(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_charCodeAt(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_concat(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_endsWith(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_indexOf(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_includes(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_localeCompare(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_match(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_replace(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_search(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_slice(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_split(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_startsWith(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_substr(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_substring(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toLowerCase(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toLocaleLowerCase(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toUpperCase(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toLocaleUpperCase(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_fromCharCode(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_trim(const BuiltinFunction *, Scope &scope, CallData *callData);
};
}
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 009c573bf8..cecd1e6958 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -438,79 +438,74 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
defineDefaultProperty(QStringLiteral("subarray"), method_subarray, 0);
}
-ReturnedValue TypedArrayPrototype::method_get_buffer(CallContext *ctx)
+void TypedArrayPrototype::method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<TypedArray> v(scope, ctx->thisObject());
+ Scoped<TypedArray> v(scope, callData->thisObject);
if (!v)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(v->d()->buffer->asReturnedValue());
+ scope.result = v->d()->buffer;
}
-ReturnedValue TypedArrayPrototype::method_get_byteLength(CallContext *ctx)
+void TypedArrayPrototype::method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<TypedArray> v(scope, ctx->thisObject());
+ Scoped<TypedArray> v(scope, callData->thisObject);
if (!v)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(v->d()->byteLength);
+ scope.result = Encode(v->d()->byteLength);
}
-ReturnedValue TypedArrayPrototype::method_get_byteOffset(CallContext *ctx)
+void TypedArrayPrototype::method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<TypedArray> v(scope, ctx->thisObject());
+ Scoped<TypedArray> v(scope, callData->thisObject);
if (!v)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(v->d()->byteOffset);
+ scope.result = Encode(v->d()->byteOffset);
}
-ReturnedValue TypedArrayPrototype::method_get_length(CallContext *ctx)
+void TypedArrayPrototype::method_get_length(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<TypedArray> v(scope, ctx->thisObject());
+ Scoped<TypedArray> v(scope, callData->thisObject);
if (!v)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(v->d()->byteLength/v->d()->type->bytesPerElement);
+ scope.result = Encode(v->d()->byteLength/v->d()->type->bytesPerElement);
}
-ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
+void TypedArrayPrototype::method_set(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<TypedArray> a(scope, ctx->thisObject());
+ Scoped<TypedArray> a(scope, callData->thisObject);
if (!a)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
Scoped<ArrayBuffer> buffer(scope, a->d()->buffer);
if (!buffer)
scope.engine->throwTypeError();
- double doffset = ctx->argc() >= 2 ? ctx->args()[1].toInteger() : 0;
+ double doffset = callData->argc >= 2 ? callData->args[1].toInteger() : 0;
if (scope.engine->hasException)
- return Encode::undefined();
+ RETURN_UNDEFINED();
if (doffset < 0 || doffset >= UINT_MAX)
- return scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"));
+ RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")));
uint offset = (uint)doffset;
uint elementSize = a->d()->type->bytesPerElement;
- Scoped<TypedArray> srcTypedArray(scope, ctx->args()[0]);
+ Scoped<TypedArray> srcTypedArray(scope, callData->args[0]);
if (!srcTypedArray) {
// src is a regular object
- ScopedObject o(scope, ctx->args()[0].toObject(scope.engine));
+ ScopedObject o(scope, callData->args[0].toObject(scope.engine));
if (scope.engine->hasException || !o)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
double len = ScopedValue(scope, o->get(scope.engine->id_length()))->toNumber();
uint l = (uint)len;
if (scope.engine->hasException || l != len)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
if (offset + l > a->length())
- return scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"));
+ RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")));
uint idx = 0;
char *b = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
@@ -519,28 +514,28 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
val = o->getIndexed(idx);
a->d()->type->write(scope.engine, b, 0, val);
if (scope.engine->hasException)
- return Encode::undefined();
+ RETURN_UNDEFINED();
++idx;
b += elementSize;
}
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
// src is a typed array
Scoped<ArrayBuffer> srcBuffer(scope, srcTypedArray->d()->buffer);
if (!srcBuffer)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
uint l = srcTypedArray->length();
if (offset + l > a->length())
- return scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"));
+ RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")));
char *dest = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
const char *src = srcBuffer->d()->data->data() + srcTypedArray->d()->byteOffset;
if (srcTypedArray->d()->type == a->d()->type) {
// same type of typed arrays, use memmove (as srcbuffer and buffer could be the same)
memmove(dest, src, srcTypedArray->d()->byteLength);
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
char *srcCopy = 0;
@@ -564,28 +559,27 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
if (srcCopy)
delete [] srcCopy;
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-ReturnedValue TypedArrayPrototype::method_subarray(CallContext *ctx)
+void TypedArrayPrototype::method_subarray(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<TypedArray> a(scope, ctx->thisObject());
+ Scoped<TypedArray> a(scope, callData->thisObject);
if (!a)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
Scoped<ArrayBuffer> buffer(scope, a->d()->buffer);
if (!buffer)
- return scope.engine->throwTypeError();
+ THROW_TYPE_ERROR();
int len = a->length();
- double b = ctx->argc() > 0 ? ctx->args()[0].toInteger() : 0;
+ double b = callData->argc > 0 ? callData->args[0].toInteger() : 0;
if (b < 0)
b = len + b;
uint begin = (uint)qBound(0., b, (double)len);
- double e = ctx->argc() < 2 || ctx->args()[1].isUndefined() ? len : ctx->args()[1].toInteger();
+ double e = callData->argc < 2 || callData->args[1].isUndefined() ? len : callData->args[1].toInteger();
if (e < 0)
e = len + e;
uint end = (uint)qBound(0., e, (double)len);
@@ -593,18 +587,17 @@ ReturnedValue TypedArrayPrototype::method_subarray(CallContext *ctx)
end = begin;
if (scope.engine->hasException)
- return Encode::undefined();
+ RETURN_UNDEFINED();
int newLen = end - begin;
ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
- return scope.engine->throwTypeError();
-
- ScopedCallData callData(scope, 3);
- callData->args[0] = buffer;
- callData->args[1] = Encode(a->d()->byteOffset + begin*a->d()->type->bytesPerElement);
- callData->args[2] = Encode(newLen);
- constructor->construct(scope, callData);
- return scope.result.asReturnedValue();
+ THROW_TYPE_ERROR();
+
+ ScopedCallData cData(scope, 3);
+ cData->args[0] = buffer;
+ cData->args[1] = Encode(a->d()->byteOffset + begin*a->d()->type->bytesPerElement);
+ cData->args[2] = Encode(newLen);
+ constructor->construct(scope, cData);
}
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 0112d2e4a1..eefed2db4b 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -151,13 +151,13 @@ struct TypedArrayPrototype : Object
void init(ExecutionEngine *engine, TypedArrayCtor *ctor);
- static ReturnedValue method_get_buffer(CallContext *ctx);
- static ReturnedValue method_get_byteLength(CallContext *ctx);
- static ReturnedValue method_get_byteOffset(CallContext *ctx);
- static ReturnedValue method_get_length(CallContext *ctx);
+ static void method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_length(const BuiltinFunction *, Scope &scope, CallData *callData);
- static ReturnedValue method_set(CallContext *ctx);
- static ReturnedValue method_subarray(CallContext *ctx);
+ static void method_set(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_subarray(const BuiltinFunction *, Scope &scope, CallData *callData);
};
inline void
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 816b8fb11b..64f0f3a86f 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -544,7 +544,7 @@ inline bool Value::asArrayIndex(uint &idx) const
}
double d = doubleValue();
idx = (uint)d;
- return (idx == d);
+ return (idx == d && idx != UINT_MAX);
}
#endif
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 455a7ccb65..5cab4c5386 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -113,67 +113,68 @@ void VariantPrototype::init()
defineDefaultProperty(engine()->id_toString(), method_toString, 0);
}
-QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx)
+void VariantPrototype::method_preserve(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>());
+ Scoped<VariantObject> o(scope, callData->thisObject.as<QV4::VariantObject>());
if (o && o->d()->isScarce())
o->d()->addVmePropertyReference();
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-QV4::ReturnedValue VariantPrototype::method_destroy(CallContext *ctx)
+void VariantPrototype::method_destroy(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>());
+ Scoped<VariantObject> o(scope, callData->thisObject.as<QV4::VariantObject>());
if (o) {
if (o->d()->isScarce())
o->d()->addVmePropertyReference();
o->d()->data() = QVariant();
}
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx)
+void VariantPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>());
+ Scoped<VariantObject> o(scope, callData->thisObject.as<QV4::VariantObject>());
if (!o)
- return Encode::undefined();
+ RETURN_UNDEFINED();
QString result = o->d()->data().toString();
if (result.isEmpty() && !o->d()->data().canConvert(QVariant::String)) {
result = QLatin1String("QVariant(")
+ QLatin1String(o->d()->data().typeName())
+ QLatin1Char(')');
}
- return Encode(ctx->d()->engine->newString(result));
+ scope.result = scope.engine->newString(result);
}
-QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx)
+void VariantPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>());
+ Scoped<VariantObject> o(scope, callData->thisObject.as<QV4::VariantObject>());
if (o) {
QVariant v = o->d()->data();
switch (v.type()) {
case QVariant::Invalid:
- return Encode::undefined();
+ scope.result = Encode::undefined();
+ return;
case QVariant::String:
- return Encode(ctx->d()->engine->newString(v.toString()));
+ scope.result = scope.engine->newString(v.toString());
+ return;
case QVariant::Int:
- return Encode(v.toInt());
+ scope.result = Encode(v.toInt());
+ return;
case QVariant::Double:
case QVariant::UInt:
- return Encode(v.toDouble());
+ scope.result = Encode(v.toDouble());
+ return;
case QVariant::Bool:
- return Encode(v.toBool());
+ scope.result = Encode(v.toBool());
+ return;
default:
if (QMetaType::typeFlags(v.userType()) & QMetaType::IsEnumeration)
- return Encode(v.toInt());
+ RETURN_RESULT(Encode(v.toInt()));
break;
}
}
- return ctx->thisObject().asReturnedValue();
+ scope.result = callData->thisObject;
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index 9a04069c12..ef51b6632d 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -107,10 +107,10 @@ struct VariantPrototype : VariantObject
public:
void init();
- static ReturnedValue method_preserve(CallContext *ctx);
- static ReturnedValue method_destroy(CallContext *ctx);
- static ReturnedValue method_toString(CallContext *ctx);
- static ReturnedValue method_valueOf(CallContext *ctx);
+ static void method_preserve(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_destroy(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData);
};
}
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 622359a7d9..b9183313cd 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -347,6 +347,10 @@ Param traceParam(const Param &param)
goto catchException; \
VALUE(param) = tmp; \
}
+// qv4scopedvalue_p.h also defines a CHECK_EXCEPTION macro
+#ifdef CHECK_EXCEPTION
+#undef CHECK_EXCEPTION
+#endif
#define CHECK_EXCEPTION \
if (engine->hasException) \
goto catchException
diff --git a/src/qml/memory/memory.pri b/src/qml/memory/memory.pri
index 04b7566ccc..38fadbf23f 100644
--- a/src/qml/memory/memory.pri
+++ b/src/qml/memory/memory.pri
@@ -6,8 +6,8 @@ SOURCES += \
$$PWD/qv4mm.cpp \
HEADERS += \
- $$PWD/qv4mm_p.h
-
+ $$PWD/qv4mm_p.h \
+ $$PWD/qv4mmdefs_p.h
}
HEADERS += \
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index 5a3797f397..8285ef4de7 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -52,6 +52,7 @@
#include <QtCore/QString>
#include <private/qv4global_p.h>
+#include <private/qv4mmdefs_p.h>
#include <QSharedPointer>
// To check if Heap::Base::init is called (meaning, all subclasses did their init and called their
@@ -90,43 +91,31 @@ namespace Heap {
struct Q_QML_EXPORT Base {
void *operator new(size_t) = delete;
- quintptr mm_data; // vtable and markbit
+ const VTable *vt;
inline ReturnedValue asReturnedValue() const;
inline void mark(QV4::ExecutionEngine *engine);
- enum {
- MarkBit = 0x1,
- NotInUse = 0x2,
- PointerMask = ~0x3
- };
-
- void setVtable(const VTable *v) {
- Q_ASSERT(!(mm_data & MarkBit));
- mm_data = reinterpret_cast<quintptr>(v);
- }
- VTable *vtable() const {
- return reinterpret_cast<VTable *>(mm_data & PointerMask);
- }
+ void setVtable(const VTable *v) { vt = v; }
+ const VTable *vtable() const { return vt; }
inline bool isMarked() const {
- return mm_data & MarkBit;
+ const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
+ Chunk *c = h->chunk();
+ Q_ASSERT(!Chunk::testBit(c->extendsBitmap, h - c->realBase()));
+ return Chunk::testBit(c->blackBitmap, h - c->realBase());
}
inline void setMarkBit() {
- mm_data |= MarkBit;
- }
- inline void clearMarkBit() {
- mm_data &= ~MarkBit;
+ const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
+ Chunk *c = h->chunk();
+ Q_ASSERT(!Chunk::testBit(c->extendsBitmap, h - c->realBase()));
+ return Chunk::setBit(c->blackBitmap, h - c->realBase());
}
inline bool inUse() const {
- return !(mm_data & NotInUse);
- }
-
- Base *nextFree() {
- return reinterpret_cast<Base *>(mm_data & PointerMask);
- }
- void setNextFree(Base *m) {
- mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
+ const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
+ Chunk *c = h->chunk();
+ Q_ASSERT(!Chunk::testBit(c->extendsBitmap, h - c->realBase()));
+ return Chunk::testBit(c->objectBitmap, h - c->realBase());
}
void *operator new(size_t, Managed *m) { return m; }
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 606d3ec162..6330ef6038 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -42,8 +42,12 @@
#include "qv4objectproto_p.h"
#include "qv4mm_p.h"
#include "qv4qobjectwrapper_p.h"
+#include <QtCore/qalgorithms.h>
+#include <QtCore/private/qnumeric_p.h>
#include <qqmlengine.h>
+#include "PageReservation.h"
#include "PageAllocation.h"
+#include "PageAllocationAligned.h"
#include "StdLibExtras.h"
#include <QElapsedTimer>
@@ -56,6 +60,14 @@
#include "qv4alloca_p.h"
#include "qv4profiling_p.h"
+#define MM_DEBUG 0
+
+#if MM_DEBUG
+#define DEBUG qDebug() << "MM:"
+#else
+#define DEBUG if (1) ; else qDebug() << "MM:"
+#endif
+
#ifdef V4_USE_VALGRIND
#include <valgrind/valgrind.h>
#include <valgrind/memcheck.h>
@@ -79,319 +91,616 @@ using namespace WTF;
QT_BEGIN_NAMESPACE
-static uint maxShiftValue()
-{
- static uint result = 0;
- if (!result) {
- result = 6;
- if (Q_UNLIKELY(qEnvironmentVariableIsSet(QV4_MM_MAXBLOCK_SHIFT))) {
- bool ok;
- const uint overrideValue = qgetenv(QV4_MM_MAXBLOCK_SHIFT).toUInt(&ok);
- if (ok && overrideValue <= 11 && overrideValue > 0)
- result = overrideValue;
+namespace QV4 {
+
+enum {
+ MinSlotsGCLimit = QV4::Chunk::AvailableSlots*16,
+ GCOverallocation = 200 /* Max overallocation by the GC in % */
+};
+
+struct MemorySegment {
+ enum {
+ NumChunks = 8*sizeof(quint64),
+ SegmentSize = NumChunks*Chunk::ChunkSize,
+ };
+
+ MemorySegment(size_t size)
+ {
+ size += Chunk::ChunkSize; // make sure we can get enough 64k aligment memory
+ if (size < SegmentSize)
+ size = SegmentSize;
+
+ pageReservation = PageReservation::reserve(size, OSAllocator::JSGCHeapPages);
+ base = reinterpret_cast<Chunk *>((reinterpret_cast<quintptr>(pageReservation.base()) + Chunk::ChunkSize - 1) & ~(Chunk::ChunkSize - 1));
+ nChunks = NumChunks;
+ if (base != pageReservation.base())
+ --nChunks;
+ }
+ MemorySegment(MemorySegment &&other) {
+ qSwap(pageReservation, other.pageReservation);
+ qSwap(base, other.base);
+ qSwap(nChunks, other.nChunks);
+ qSwap(allocatedMap, other.allocatedMap);
+ }
+
+ ~MemorySegment() {
+ if (base)
+ pageReservation.deallocate();
+ }
+
+ void setBit(size_t index) {
+ Q_ASSERT(index < nChunks);
+ quint64 bit = static_cast<quint64>(1) << index;
+// qDebug() << " setBit" << hex << index << (index & (Bits - 1)) << bit;
+ allocatedMap |= bit;
+ }
+ void clearBit(size_t index) {
+ Q_ASSERT(index < nChunks);
+ quint64 bit = static_cast<quint64>(1) << index;
+// qDebug() << " setBit" << hex << index << (index & (Bits - 1)) << bit;
+ allocatedMap &= ~bit;
+ }
+ bool testBit(size_t index) const {
+ Q_ASSERT(index < nChunks);
+ quint64 bit = static_cast<quint64>(1) << index;
+ return (allocatedMap & bit);
+ }
+
+ Chunk *allocate(size_t size);
+ void free(Chunk *chunk, size_t size) {
+ DEBUG << "freeing chunk" << chunk;
+ size_t index = static_cast<size_t>(chunk - base);
+ size_t end = index + (size - 1)/Chunk::ChunkSize + 1;
+ while (index < end) {
+ Q_ASSERT(testBit(index));
+ clearBit(index);
+ ++index;
}
+
+ size_t pageSize = WTF::pageSize();
+ size = (size + pageSize - 1) & ~(pageSize - 1);
+ pageReservation.decommit(chunk, size);
+ }
+
+ bool contains(Chunk *c) const {
+ return c >= base && c < base + nChunks;
}
- return result;
-}
-static std::size_t maxChunkSizeValue()
+ PageReservation pageReservation;
+ Chunk *base = 0;
+ quint64 allocatedMap = 0;
+ uint nChunks = 0;
+};
+
+Chunk *MemorySegment::allocate(size_t size)
{
- static std::size_t result = 0;
- if (!result) {
- result = 32 * 1024;
- if (Q_UNLIKELY(qEnvironmentVariableIsSet(QV4_MM_MAX_CHUNK_SIZE))) {
- bool ok;
- const std::size_t overrideValue = qgetenv(QV4_MM_MAX_CHUNK_SIZE).toUInt(&ok);
- if (ok)
- result = overrideValue;
+ size_t requiredChunks = (size + sizeof(Chunk) - 1)/sizeof(Chunk);
+ uint sequence = 0;
+ Chunk *candidate = 0;
+ for (uint i = 0; i < nChunks; ++i) {
+ if (!testBit(i)) {
+ if (!candidate)
+ candidate = base + i;
+ ++sequence;
+ } else {
+ candidate = 0;
+ sequence = 0;
+ }
+ if (sequence == requiredChunks) {
+ pageReservation.commit(candidate, size);
+ for (uint i = 0; i < requiredChunks; ++i)
+ setBit(candidate - base + i);
+ DEBUG << "allocated chunk " << candidate << hex << size;
+ return candidate;
}
}
- return result;
+ return 0;
}
-using namespace QV4;
-
-struct MemoryManager::Data
-{
- const size_t pageSize;
-
- struct ChunkHeader {
- Heap::Base freeItems;
- ChunkHeader *nextNonFull;
- char *itemStart;
- char *itemEnd;
- unsigned itemSize;
- };
+struct ChunkAllocator {
+ ChunkAllocator() {}
- ExecutionEngine *engine;
+ size_t requiredChunkSize(size_t size) {
+ size += Chunk::HeaderSize; // space required for the Chunk header
+ size_t pageSize = WTF::pageSize();
+ size = (size + pageSize - 1) & ~(pageSize - 1); // align to page sizes
+ if (size < Chunk::ChunkSize)
+ size = Chunk::ChunkSize;
+ return size;
+ }
- std::size_t maxChunkSize;
- std::vector<PageAllocation> heapChunks;
- std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items.
- std::size_t unmanagedHeapSizeGCLimit;
+ Chunk *allocate(size_t size = 0);
+ void free(Chunk *chunk, size_t size = 0);
- struct LargeItem {
- LargeItem *next;
- size_t size;
- void *data;
+ std::vector<MemorySegment> memorySegments;
+};
- Heap::Base *heapObject() {
- return reinterpret_cast<Heap::Base *>(&data);
+Chunk *ChunkAllocator::allocate(size_t size)
+{
+ size = requiredChunkSize(size);
+ for (auto &m : memorySegments) {
+ if (~m.allocatedMap) {
+ Chunk *c = m.allocate(size);
+ if (c)
+ return c;
}
- };
+ }
- LargeItem *largeItems;
- std::size_t totalLargeItemsAllocated;
+ // allocate a new segment
+ memorySegments.push_back(MemorySegment(size));
+ Chunk *c = memorySegments.back().allocate(size);
+ Q_ASSERT(c);
+ return c;
+}
- enum { MaxItemSize = 512 };
- ChunkHeader *nonFullChunks[MaxItemSize/16];
- uint nChunks[MaxItemSize/16];
- uint availableItems[MaxItemSize/16];
- uint allocCount[MaxItemSize/16];
- int totalItems;
- int totalAlloc;
- uint maxShift;
+void ChunkAllocator::free(Chunk *chunk, size_t size)
+{
+ size = requiredChunkSize(size);
+ for (auto &m : memorySegments) {
+ if (m.contains(chunk)) {
+ m.free(chunk, size);
+ return;
+ }
+ }
+ Q_ASSERT(false);
+}
- bool gcBlocked;
- bool aggressiveGC;
- bool gcStats;
- bool unused; // suppress padding warning
- // statistics:
-#ifdef DETAILED_MM_STATS
- QVector<unsigned> allocSizeCounters;
-#endif // DETAILED_MM_STATS
+void Chunk::sweep()
+{
+ // DEBUG << "sweeping chunk" << this << (*freeList);
+ HeapItem *o = realBase();
+ for (uint i = 0; i < Chunk::EntriesInBitmap; ++i) {
+ Q_ASSERT((grayBitmap[i] | blackBitmap[i]) == blackBitmap[i]); // check that we don't have gray only objects
+ quintptr toFree = objectBitmap[i] ^ blackBitmap[i];
+ Q_ASSERT((toFree & objectBitmap[i]) == toFree); // check all black objects are marked as being used
+ quintptr e = extendsBitmap[i];
+ // DEBUG << hex << " index=" << i << toFree;
+ while (toFree) {
+ uint index = qCountTrailingZeroBits(toFree);
+ quintptr bit = (static_cast<quintptr>(1) << index);
+
+ toFree ^= bit; // mask out freed slot
+ // DEBUG << " index" << hex << index << toFree;
+
+ // remove all extends slots that have been freed
+ // this is a bit of bit trickery.
+ quintptr mask = (bit << 1) - 1; // create a mask of 1's to the right of and up to the current bit
+ quintptr objmask = e | mask; // or'ing mask with e gives all ones until the end of the current object
+ quintptr result = objmask + 1;
+ Q_ASSERT(qCountTrailingZeroBits(result) - index != 0); // ensure we freed something
+ result |= mask; // ensure we don't clear stuff to the right of the current object
+ e &= result;
+
+ HeapItem *itemToFree = o + index;
+ Heap::Base *b = *itemToFree;
+ if (b->vtable()->destroy) {
+ b->vtable()->destroy(b);
+ b->_checkIsDestroyed();
+ }
+ }
+ objectBitmap[i] = blackBitmap[i];
+ blackBitmap[i] = 0;
+ extendsBitmap[i] = e;
+ o += Chunk::Bits;
+ }
+ // DEBUG << "swept chunk" << this << "freed" << slotsFreed << "slots.";
+}
- Data()
- : pageSize(WTF::pageSize())
- , engine(0)
- , maxChunkSize(maxChunkSizeValue())
- , unmanagedHeapSize(0)
- , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
- , largeItems(0)
- , totalLargeItemsAllocated(0)
- , totalItems(0)
- , totalAlloc(0)
- , maxShift(maxShiftValue())
- , gcBlocked(false)
- , aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC"))
- , gcStats(!qEnvironmentVariableIsEmpty(QV4_MM_STATS))
- {
- memset(nonFullChunks, 0, sizeof(nonFullChunks));
- memset(nChunks, 0, sizeof(nChunks));
- memset(availableItems, 0, sizeof(availableItems));
- memset(allocCount, 0, sizeof(allocCount));
+void Chunk::freeAll()
+{
+ // DEBUG << "sweeping chunk" << this << (*freeList);
+ HeapItem *o = realBase();
+ for (uint i = 0; i < Chunk::EntriesInBitmap; ++i) {
+ quintptr toFree = objectBitmap[i];
+ quintptr e = extendsBitmap[i];
+ // DEBUG << hex << " index=" << i << toFree;
+ while (toFree) {
+ uint index = qCountTrailingZeroBits(toFree);
+ quintptr bit = (static_cast<quintptr>(1) << index);
+
+ toFree ^= bit; // mask out freed slot
+ // DEBUG << " index" << hex << index << toFree;
+
+ // remove all extends slots that have been freed
+ // this is a bit of bit trickery.
+ quintptr mask = (bit << 1) - 1; // create a mask of 1's to the right of and up to the current bit
+ quintptr objmask = e | mask; // or'ing mask with e gives all ones until the end of the current object
+ quintptr result = objmask + 1;
+ Q_ASSERT(qCountTrailingZeroBits(result) - index != 0); // ensure we freed something
+ result |= mask; // ensure we don't clear stuff to the right of the current object
+ e &= result;
+
+ HeapItem *itemToFree = o + index;
+ Heap::Base *b = *itemToFree;
+ if (b->vtable()->destroy) {
+ b->vtable()->destroy(b);
+ b->_checkIsDestroyed();
+ }
+ }
+ objectBitmap[i] = 0;
+ blackBitmap[i] = 0;
+ extendsBitmap[i] = e;
+ o += Chunk::Bits;
}
+ // DEBUG << "swept chunk" << this << "freed" << slotsFreed << "slots.";
+}
- ~Data()
- {
- for (std::vector<PageAllocation>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
- Q_V4_PROFILE_DEALLOC(engine, i->size(), Profiling::HeapPage);
- i->deallocate();
+void Chunk::sortIntoBins(HeapItem **bins, uint nBins)
+{
+ HeapItem *base = realBase();
+#if QT_POINTER_SIZE == 8
+ const int start = 0;
+#else
+ const int start = 1;
+#endif
+ for (int i = start; i < EntriesInBitmap; ++i) {
+ quintptr usedSlots = (objectBitmap[i]|extendsBitmap[i]);
+#if QT_POINTER_SIZE == 8
+ if (!i)
+ usedSlots |= (static_cast<quintptr>(1) << (HeaderSize/SlotSize)) - 1;
+#endif
+ uint index = qCountTrailingZeroBits(usedSlots + 1);
+ if (index == Bits)
+ continue;
+ uint freeStart = i*Bits + index;
+ usedSlots &= ~((static_cast<quintptr>(1) << index) - 1);
+ while (i < EntriesInBitmap && !usedSlots) {
+ ++i;
+ usedSlots = (objectBitmap[i]|extendsBitmap[i]);
}
+ if (i == EntriesInBitmap)
+ usedSlots = 1;
+ HeapItem *freeItem = base + freeStart;
+
+ uint freeEnd = i*Bits + qCountTrailingZeroBits(usedSlots);
+ uint nSlots = freeEnd - freeStart;
+ Q_ASSERT(freeEnd > freeStart && freeEnd <= NumSlots);
+ freeItem->freeData.availableSlots = nSlots;
+ uint bin = qMin(nBins - 1, nSlots);
+ freeItem->freeData.next = bins[bin];
+ bins[bin] = freeItem;
+ // DEBUG << "binnig item" << freeItem << nSlots << bin << freeItem->freeData.availableSlots;
}
-};
+}
-namespace {
-bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, ExecutionEngine *engine, std::size_t *unmanagedHeapSize)
+template<typename T>
+StackAllocator<T>::StackAllocator(ChunkAllocator *chunkAlloc)
+ : chunkAllocator(chunkAlloc)
{
- Q_ASSERT(unmanagedHeapSize);
+ chunks.push_back(chunkAllocator->allocate());
+ firstInChunk = chunks.back()->first();
+ nextFree = firstInChunk;
+ lastInChunk = firstInChunk + (Chunk::AvailableSlots - 1)/requiredSlots*requiredSlots;
+}
- bool isEmpty = true;
- Heap::Base *tail = &header->freeItems;
-// qDebug("chunkStart @ %p, size=%x, pos=%x", header->itemStart, header->itemSize, header->itemSize>>4);
-#ifdef V4_USE_VALGRIND
- VALGRIND_DISABLE_ERROR_REPORTING;
-#endif
- for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
- Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
-// qDebug("chunk @ %p, in use: %s, mark bit: %s",
-// item, (m->inUse() ? "yes" : "no"), (m->isMarked() ? "true" : "false"));
-
- Q_ASSERT(qintptr(item) % 16 == 0);
-
- if (m->isMarked()) {
- Q_ASSERT(m->inUse());
- m->clearMarkBit();
- isEmpty = false;
- ++(*itemsInUse);
- } else {
- if (m->inUse()) {
-// qDebug() << "-- collecting it." << m << tail << m->nextFree();
-#ifdef V4_USE_VALGRIND
- VALGRIND_ENABLE_ERROR_REPORTING;
-#endif
- if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->vtable()->isString) {
- std::size_t heapBytes = static_cast<Heap::String *>(m)->retainedTextSize();
- Q_ASSERT(*unmanagedHeapSize >= heapBytes);
-// qDebug() << "-- it's a string holding on to" << heapBytes << "bytes";
- *unmanagedHeapSize -= heapBytes;
- }
+template<typename T>
+void StackAllocator<T>::freeAll()
+{
+ for (auto c : chunks)
+ chunkAllocator->free(c);
+}
- if (m->vtable()->destroy) {
- m->vtable()->destroy(m);
- m->_checkIsDestroyed();
- }
+template<typename T>
+void StackAllocator<T>::nextChunk() {
+ Q_ASSERT(nextFree == lastInChunk);
+ ++currentChunk;
+ if (currentChunk >= chunks.size()) {
+ Chunk *newChunk = chunkAllocator->allocate();
+ chunks.push_back(newChunk);
+ }
+ firstInChunk = chunks.at(currentChunk)->first();
+ nextFree = firstInChunk;
+ lastInChunk = firstInChunk + (Chunk::AvailableSlots - 1)/requiredSlots*requiredSlots;
+}
- memset(m, 0, sizeof(Heap::Base));
-#ifdef V4_USE_VALGRIND
- VALGRIND_DISABLE_ERROR_REPORTING;
- VALGRIND_MEMPOOL_FREE(engine->memoryManager, m);
+template<typename T>
+void QV4::StackAllocator<T>::prevChunk() {
+ Q_ASSERT(nextFree == firstInChunk);
+ Q_ASSERT(chunks.at(currentChunk) == nextFree->chunk());
+ Q_ASSERT(currentChunk > 0);
+ --currentChunk;
+ firstInChunk = chunks.at(currentChunk)->first();
+ lastInChunk = firstInChunk + (Chunk::AvailableSlots - 1)/requiredSlots*requiredSlots;
+ nextFree = lastInChunk;
+}
+
+template struct StackAllocator<Heap::CallContext>;
+
+
+HeapItem *BlockAllocator::allocate(size_t size, bool forceAllocation) {
+ Q_ASSERT((size % Chunk::SlotSize) == 0);
+ size_t slotsRequired = size >> Chunk::SlotSizeShift;
+#if MM_DEBUG
+ ++allocations[bin];
#endif
-#ifdef V4_USE_HEAPTRACK
- heaptrack_report_free(m);
+
+ HeapItem **last;
+
+ HeapItem *m;
+
+ if (slotsRequired < NumBins - 1) {
+ m = freeBins[slotsRequired];
+ if (m) {
+ freeBins[slotsRequired] = m->freeData.next;
+ goto done;
+ }
+ }
+#if 0
+ for (uint b = bin + 1; b < NumBins - 1; ++b) {
+ if ((m = freeBins[b])) {
+ Q_ASSERT(binForSlots(m->freeData.availableSlots) == b);
+ freeBins[b] = m->freeData.next;
+ // DEBUG << "looking for empty bin" << bin << "size" << size << "found" << b;
+ uint remainingSlots = m->freeData.availableSlots - slotsRequired;
+ // DEBUG << "found free slots of size" << m->freeData.availableSlots << m << "remaining" << remainingSlots;
+ if (remainingSlots < 2) {
+ // avoid too much fragmentation and rather mark the memory as used
+ size += remainingSlots*Chunk::SlotSize;
+ goto done;
+ }
+ HeapItem *remainder = m + slotsRequired;
+ remainder->freeData.availableSlots = remainingSlots;
+ uint binForRemainder = binForSlots(remainingSlots);
+ remainder->freeData.next = freeBins[binForRemainder];
+ freeBins[binForRemainder] = remainder;
+ goto done;
+ }
+ }
#endif
- Q_V4_PROFILE_DEALLOC(engine, header->itemSize, Profiling::SmallItem);
- ++(*itemsInUse);
+ if (nFree >= slotsRequired) {
+ // use bump allocation
+ Q_ASSERT(nextFree);
+ m = nextFree;
+ nextFree += slotsRequired;
+ nFree -= slotsRequired;
+ goto done;
+ }
+
+ // DEBUG << "No matching bin found for item" << size << bin;
+ // search last bin for a large enough item
+ last = &freeBins[NumBins - 1];
+ while ((m = *last)) {
+ if (m->freeData.availableSlots >= slotsRequired) {
+ *last = m->freeData.next; // take it out of the list
+
+ size_t remainingSlots = m->freeData.availableSlots - slotsRequired;
+ // DEBUG << "found large free slots of size" << m->freeData.availableSlots << m << "remaining" << remainingSlots;
+ if (remainingSlots < 2) {
+ // avoid too much fragmentation and rather mark the memory as used
+ size += remainingSlots*Chunk::SlotSize;
+ goto done;
+ }
+ HeapItem *remainder = m + slotsRequired;
+ if (remainingSlots >= 2*NumBins) {
+ if (nFree) {
+ size_t bin = binForSlots(nFree);
+ nextFree->freeData.next = freeBins[bin];
+ nextFree->freeData.availableSlots = nFree;
+ freeBins[bin] = nextFree;
+ }
+ nextFree = remainder;
+ nFree = remainingSlots;
+ } else {
+ remainder->freeData.availableSlots = remainingSlots;
+ size_t binForRemainder = binForSlots(remainingSlots);
+ remainder->freeData.next = freeBins[binForRemainder];
+ freeBins[binForRemainder] = remainder;
}
- // Relink all free blocks to rewrite references to any released chunk.
- tail->setNextFree(m);
- tail = m;
+ goto done;
}
+ last = &m->freeData.next;
}
- tail->setNextFree(0);
-#ifdef V4_USE_VALGRIND
- VALGRIND_ENABLE_ERROR_REPORTING;
+
+ if (!m) {
+ if (!forceAllocation)
+ return 0;
+ Chunk *newChunk = chunkAllocator->allocate();
+ chunks.push_back(newChunk);
+ nextFree = newChunk->first();
+ nFree = Chunk::AvailableSlots;
+ m = nextFree;
+ nextFree += slotsRequired;
+ nFree -= slotsRequired;
+ }
+
+done:
+ m->setAllocatedSlots(slotsRequired);
+ // DEBUG << " " << hex << m->chunk() << m->chunk()->objectBitmap[0] << m->chunk()->extendsBitmap[0] << (m - m->chunk()->realBase());
+ return m;
+}
+
+void BlockAllocator::sweep()
+{
+ nextFree = 0;
+ nFree = 0;
+ memset(freeBins, 0, sizeof(freeBins));
+
+// qDebug() << "BlockAlloc: sweep";
+ usedSlotsAfterLastSweep = 0;
+ for (auto c : chunks) {
+ c->sweep();
+ c->sortIntoBins(freeBins, NumBins);
+// qDebug() << "used slots in chunk" << c << ":" << c->nUsedSlots();
+ usedSlotsAfterLastSweep += c->nUsedSlots();
+ }
+}
+
+void BlockAllocator::freeAll()
+{
+ for (auto c : chunks) {
+ c->freeAll();
+ chunkAllocator->free(c);
+ }
+}
+
+#if MM_DEBUG
+void BlockAllocator::stats() {
+ DEBUG << "MM stats:";
+ QString s;
+ for (int i = 0; i < 10; ++i) {
+ uint c = 0;
+ HeapItem *item = freeBins[i];
+ while (item) {
+ ++c;
+ item = item->freeData.next;
+ }
+ s += QString::number(c) + QLatin1String(", ");
+ }
+ HeapItem *item = freeBins[NumBins - 1];
+ uint c = 0;
+ while (item) {
+ ++c;
+ item = item->freeData.next;
+ }
+ s += QLatin1String("..., ") + QString::number(c);
+ DEBUG << "bins:" << s;
+ QString a;
+ for (int i = 0; i < 10; ++i)
+ a += QString::number(allocations[i]) + QLatin1String(", ");
+ a += QLatin1String("..., ") + QString::number(allocations[NumBins - 1]);
+ DEBUG << "allocs:" << a;
+ memset(allocations, 0, sizeof(allocations));
+}
#endif
- return isEmpty;
+
+
+HeapItem *HugeItemAllocator::allocate(size_t size) {
+ Chunk *c = chunkAllocator->allocate(size);
+ chunks.push_back(HugeChunk{c, size});
+ Chunk::setBit(c->objectBitmap, c->first() - c->realBase());
+ return c->first();
+}
+
+static void freeHugeChunk(ChunkAllocator *chunkAllocator, const HugeItemAllocator::HugeChunk &c)
+{
+ HeapItem *itemToFree = c.chunk->first();
+ Heap::Base *b = *itemToFree;
+ if (b->vtable()->destroy) {
+ b->vtable()->destroy(b);
+ b->_checkIsDestroyed();
+ }
+ chunkAllocator->free(c.chunk, c.size);
+}
+
+void HugeItemAllocator::sweep() {
+ auto isBlack = [this] (const HugeChunk &c) {
+ bool b = c.chunk->first()->isBlack();
+ Chunk::clearBit(c.chunk->blackBitmap, c.chunk->first() - c.chunk->realBase());
+ if (!b)
+ freeHugeChunk(chunkAllocator, c);
+ return !b;
+ };
+
+ auto newEnd = std::remove_if(chunks.begin(), chunks.end(), isBlack);
+ chunks.erase(newEnd, chunks.end());
+}
+
+void HugeItemAllocator::freeAll()
+{
+ for (auto &c : chunks) {
+ freeHugeChunk(chunkAllocator, c);
+ }
}
-} // namespace
MemoryManager::MemoryManager(ExecutionEngine *engine)
: engine(engine)
- , m_d(new Data)
+ , chunkAllocator(new ChunkAllocator)
+ , stackAllocator(chunkAllocator)
+ , blockAllocator(chunkAllocator)
+ , hugeItemAllocator(chunkAllocator)
, m_persistentValues(new PersistentValueStorage(engine))
, m_weakValues(new PersistentValueStorage(engine))
+ , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
+ , aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC"))
+ , gcStats(!qEnvironmentVariableIsEmpty(QV4_MM_STATS))
{
#ifdef V4_USE_VALGRIND
VALGRIND_CREATE_MEMPOOL(this, 0, true);
#endif
- m_d->engine = engine;
}
-Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize)
+Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize)
{
- if (m_d->aggressiveGC)
+ if (aggressiveGC)
runGC();
-#ifdef DETAILED_MM_STATS
- willAllocate(size);
-#endif // DETAILED_MM_STATS
- Q_ASSERT(size >= 16);
- Q_ASSERT(size % 16 == 0);
-
-// qDebug() << "unmanagedHeapSize:" << m_d->unmanagedHeapSize << "limit:" << m_d->unmanagedHeapSizeGCLimit << "unmanagedSize:" << unmanagedSize;
- m_d->unmanagedHeapSize += unmanagedSize;
+ const size_t stringSize = align(sizeof(Heap::String));
+ unmanagedHeapSize += unmanagedSize;
bool didGCRun = false;
- if (m_d->unmanagedHeapSize > m_d->unmanagedHeapSizeGCLimit) {
+ if (unmanagedHeapSize > unmanagedHeapSizeGCLimit) {
runGC();
- if (3*m_d->unmanagedHeapSizeGCLimit <= 4*m_d->unmanagedHeapSize)
+ if (3*unmanagedHeapSizeGCLimit <= 4*unmanagedHeapSize)
// more than 75% full, raise limit
- m_d->unmanagedHeapSizeGCLimit = std::max(m_d->unmanagedHeapSizeGCLimit, m_d->unmanagedHeapSize) * 2;
- else if (m_d->unmanagedHeapSize * 4 <= m_d->unmanagedHeapSizeGCLimit)
+ unmanagedHeapSizeGCLimit = std::max(unmanagedHeapSizeGCLimit, unmanagedHeapSize) * 2;
+ else if (unmanagedHeapSize * 4 <= unmanagedHeapSizeGCLimit)
// less than 25% full, lower limit
- m_d->unmanagedHeapSizeGCLimit = qMax(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT, m_d->unmanagedHeapSizeGCLimit/2);
+ unmanagedHeapSizeGCLimit = qMax(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT, unmanagedHeapSizeGCLimit/2);
didGCRun = true;
}
- size_t pos = size >> 4;
-
- // doesn't fit into a small bucket
- if (size >= MemoryManager::Data::MaxItemSize) {
- if (!didGCRun && m_d->totalLargeItemsAllocated > 8 * 1024 * 1024)
+ HeapItem *m = blockAllocator.allocate(stringSize);
+ if (!m) {
+ if (!didGCRun && shouldRunGC())
runGC();
-
- // we use malloc for this
- const size_t totalSize = size + sizeof(MemoryManager::Data::LargeItem);
- Q_V4_PROFILE_ALLOC(engine, totalSize, Profiling::LargeItem);
- MemoryManager::Data::LargeItem *item =
- static_cast<MemoryManager::Data::LargeItem *>(malloc(totalSize));
- memset(item, 0, totalSize);
- item->next = m_d->largeItems;
- item->size = size;
- m_d->largeItems = item;
- m_d->totalLargeItemsAllocated += size;
- return item->heapObject();
+ m = blockAllocator.allocate(stringSize, true);
}
- Heap::Base *m = 0;
- Data::ChunkHeader *header = m_d->nonFullChunks[pos];
- if (header) {
- m = header->freeItems.nextFree();
- goto found;
- }
+ memset(m, 0, stringSize);
+ return *m;
+}
- // try to free up space, otherwise allocate
- if (!didGCRun && m_d->allocCount[pos] > (m_d->availableItems[pos] >> 1) && m_d->totalAlloc > (m_d->totalItems >> 1) && !m_d->aggressiveGC) {
+Heap::Base *MemoryManager::allocData(std::size_t size)
+{
+ if (aggressiveGC)
runGC();
- header = m_d->nonFullChunks[pos];
- if (header) {
- m = header->freeItems.nextFree();
- goto found;
- }
- }
+#ifdef DETAILED_MM_STATS
+ willAllocate(size);
+#endif // DETAILED_MM_STATS
- // no free item available, allocate a new chunk
- {
- // allocate larger chunks at a time to avoid excessive GC, but cap at maximum chunk size (2MB by default)
- uint shift = ++m_d->nChunks[pos];
- if (shift > m_d->maxShift)
- shift = m_d->maxShift;
- std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
- allocSize = roundUpToMultipleOf(m_d->pageSize, allocSize);
- Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage);
- PageAllocation allocation = PageAllocation::allocate(allocSize, OSAllocator::JSGCHeapPages);
- m_d->heapChunks.push_back(allocation);
-
- header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
- Q_ASSERT(size <= UINT_MAX);
- header->itemSize = unsigned(size);
- header->itemStart = reinterpret_cast<char *>(allocation.base()) + roundUpToMultipleOf(16, sizeof(Data::ChunkHeader));
- header->itemEnd = reinterpret_cast<char *>(allocation.base()) + allocation.size() - header->itemSize;
-
- header->nextNonFull = m_d->nonFullChunks[pos];
- m_d->nonFullChunks[pos] = header;
-
- Heap::Base *last = &header->freeItems;
- for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
- Heap::Base *o = reinterpret_cast<Heap::Base *>(item);
- last->setNextFree(o);
- last = o;
+ Q_ASSERT(size >= Chunk::SlotSize);
+ Q_ASSERT(size % Chunk::SlotSize == 0);
- }
- last->setNextFree(0);
- m = header->freeItems.nextFree();
- Q_ASSERT(header->itemEnd >= header->itemStart);
- const size_t increase = quintptr(header->itemEnd - header->itemStart) / header->itemSize;
- m_d->availableItems[pos] += uint(increase);
- m_d->totalItems += int(increase);
-#ifdef V4_USE_VALGRIND
- VALGRIND_MAKE_MEM_NOACCESS(allocation.base(), allocSize);
- VALGRIND_MEMPOOL_ALLOC(this, header, sizeof(Data::ChunkHeader));
-#endif
-#ifdef V4_USE_HEAPTRACK
- heaptrack_report_alloc(header, sizeof(Data::ChunkHeader));
-#endif
+// qDebug() << "unmanagedHeapSize:" << unmanagedHeapSize << "limit:" << unmanagedHeapSizeGCLimit << "unmanagedSize:" << unmanagedSize;
+
+ if (size > Chunk::DataSize)
+ return *hugeItemAllocator.allocate(size);
+
+ HeapItem *m = blockAllocator.allocate(size);
+ if (!m) {
+ if (shouldRunGC())
+ runGC();
+ m = blockAllocator.allocate(size, true);
}
- found:
-#ifdef V4_USE_VALGRIND
- VALGRIND_MEMPOOL_ALLOC(this, m, size);
-#endif
-#ifdef V4_USE_HEAPTRACK
- heaptrack_report_alloc(m, size);
-#endif
- Q_V4_PROFILE_ALLOC(engine, size, Profiling::SmallItem);
+ memset(m, 0, size);
+ return *m;
+}
- ++m_d->allocCount[pos];
- ++m_d->totalAlloc;
- header->freeItems.setNextFree(m->nextFree());
- if (!header->freeItems.nextFree())
- m_d->nonFullChunks[pos] = header->nextNonFull;
- return m;
+Heap::Object *MemoryManager::allocObjectWithMemberData(std::size_t size, uint nMembers)
+{
+ Heap::Object *o = static_cast<Heap::Object *>(allocData(size));
+
+ // ### Could optimize this and allocate both in one go through the block allocator
+ if (nMembers) {
+ std::size_t memberSize = align(sizeof(Heap::MemberData) + (nMembers - 1)*sizeof(Value));
+// qDebug() << "allocating member data for" << o << nMembers << memberSize;
+ Heap::Base *m;
+ if (memberSize > Chunk::DataSize)
+ m = *hugeItemAllocator.allocate(memberSize);
+ else
+ m = *blockAllocator.allocate(memberSize, true);
+ memset(m, 0, memberSize);
+ o->memberData = static_cast<Heap::MemberData *>(m);
+ o->memberData->setVtable(MemberData::staticVTable());
+ o->memberData->size = static_cast<uint>((memberSize - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value));
+ o->memberData->init();
+// qDebug() << " got" << o->memberData << o->memberData->size;
+ }
+ return o;
}
static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
@@ -495,98 +804,34 @@ void MemoryManager::sweep(bool lastSweep)
}
}
- bool *chunkIsEmpty = static_cast<bool *>(alloca(m_d->heapChunks.size() * sizeof(bool)));
- uint itemsInUse[MemoryManager::Data::MaxItemSize/16];
- memset(itemsInUse, 0, sizeof(itemsInUse));
- memset(m_d->nonFullChunks, 0, sizeof(m_d->nonFullChunks));
-
- for (size_t i = 0; i < m_d->heapChunks.size(); ++i) {
- Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(m_d->heapChunks[i].base());
- chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine, &m_d->unmanagedHeapSize);
- }
-
- std::vector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
- for (size_t i = 0; i < m_d->heapChunks.size(); ++i) {
- Q_ASSERT(chunkIter != m_d->heapChunks.end());
- Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(chunkIter->base());
- const size_t pos = header->itemSize >> 4;
- Q_ASSERT(header->itemEnd >= header->itemStart);
- const size_t decrease = quintptr(header->itemEnd - header->itemStart) / header->itemSize;
-
- // Release that chunk if it could have been spared since the last GC run without any difference.
- if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) {
- Q_V4_PROFILE_DEALLOC(engine, chunkIter->size(), Profiling::HeapPage);
-#ifdef V4_USE_VALGRIND
- VALGRIND_MEMPOOL_FREE(this, header);
-#endif
-#ifdef V4_USE_HEAPTRACK
- heaptrack_report_free(header);
-#endif
- --m_d->nChunks[pos];
- m_d->availableItems[pos] -= uint(decrease);
- m_d->totalItems -= int(decrease);
- chunkIter->deallocate();
- chunkIter = m_d->heapChunks.erase(chunkIter);
- continue;
- } else if (header->freeItems.nextFree()) {
- header->nextNonFull = m_d->nonFullChunks[pos];
- m_d->nonFullChunks[pos] = header;
- }
- ++chunkIter;
- }
-
- Data::LargeItem *i = m_d->largeItems;
- Data::LargeItem **last = &m_d->largeItems;
- while (i) {
- Heap::Base *m = i->heapObject();
- Q_ASSERT(m->inUse());
- if (m->isMarked()) {
- m->clearMarkBit();
- last = &i->next;
- i = i->next;
- continue;
- }
- if (m->vtable()->destroy)
- m->vtable()->destroy(m);
-
- *last = i->next;
- Q_V4_PROFILE_DEALLOC(engine, i->size + sizeof(Data::LargeItem), Profiling::LargeItem);
- free(i);
- i = *last;
- }
-
- // some execution contexts are allocated on the stack, make sure we clear their markBit as well
- if (!lastSweep) {
- QV4::ExecutionContext *ctx = engine->currentContext;
- while (ctx) {
- ctx->d()->clearMarkBit();
- ctx = engine->parentContext(ctx);
- }
- }
+ blockAllocator.sweep();
+ hugeItemAllocator.sweep();
}
-bool MemoryManager::isGCBlocked() const
+bool MemoryManager::shouldRunGC() const
{
- return m_d->gcBlocked;
+ size_t total = blockAllocator.totalSlots();
+ size_t usedSlots = blockAllocator.usedSlotsAfterLastSweep;
+ if (total > MinSlotsGCLimit && usedSlots * GCOverallocation < total * 100)
+ return true;
+ return false;
}
-void MemoryManager::setGCBlocked(bool blockGC)
-{
- m_d->gcBlocked = blockGC;
-}
void MemoryManager::runGC()
{
- if (m_d->gcBlocked) {
+ if (gcBlocked) {
// qDebug() << "Not running GC.";
return;
}
- QScopedValueRollback<bool> gcBlocker(m_d->gcBlocked, true);
+ QScopedValueRollback<bool> gcBlocker(gcBlocked, true);
- if (!m_d->gcStats) {
+ if (!gcStats) {
+// uint oldUsed = allocator.usedMem();
mark();
sweep();
+// DEBUG << "RUN GC: allocated:" << allocator.allocatedMem() << "used before" << oldUsed << "used now" << allocator.usedMem();
} else {
const size_t totalMem = getAllocatedMem();
@@ -596,7 +841,6 @@ void MemoryManager::runGC()
qint64 markTime = t.restart();
const size_t usedBefore = getUsedMem();
const size_t largeItemsBefore = getLargeItemsMem();
- size_t chunksBefore = m_d->heapChunks.size();
sweep();
const size_t usedAfter = getUsedMem();
const size_t largeItemsAfter = getLargeItemsMem();
@@ -605,56 +849,30 @@ void MemoryManager::runGC()
qDebug() << "========== GC ==========";
qDebug() << "Marked object in" << markTime << "ms.";
qDebug() << "Sweeped object in" << sweepTime << "ms.";
- qDebug() << "Allocated" << totalMem << "bytes in" << m_d->heapChunks.size() << "chunks.";
+ qDebug() << "Allocated" << totalMem << "bytes";
qDebug() << "Used memory before GC:" << usedBefore;
qDebug() << "Used memory after GC:" << usedAfter;
qDebug() << "Freed up bytes:" << (usedBefore - usedAfter);
- qDebug() << "Released chunks:" << (chunksBefore - m_d->heapChunks.size());
qDebug() << "Large item memory before GC:" << largeItemsBefore;
qDebug() << "Large item memory after GC:" << largeItemsAfter;
qDebug() << "Large item memory freed up:" << (largeItemsBefore - largeItemsAfter);
qDebug() << "======== End GC ========";
}
-
- memset(m_d->allocCount, 0, sizeof(m_d->allocCount));
- m_d->totalAlloc = 0;
- m_d->totalLargeItemsAllocated = 0;
}
size_t MemoryManager::getUsedMem() const
{
- size_t usedMem = 0;
- for (std::vector<PageAllocation>::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) {
- Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base());
- for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
- Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
- Q_ASSERT(qintptr(item) % 16 == 0);
- if (m->inUse())
- usedMem += header->itemSize;
- }
- }
- return usedMem;
+ return blockAllocator.usedMem();
}
size_t MemoryManager::getAllocatedMem() const
{
- size_t total = 0;
- for (size_t i = 0; i < m_d->heapChunks.size(); ++i)
- total += m_d->heapChunks.at(i).size();
- return total;
+ return blockAllocator.allocatedMem() + hugeItemAllocator.usedMem();
}
size_t MemoryManager::getLargeItemsMem() const
{
- size_t total = 0;
- for (const Data::LargeItem *i = m_d->largeItems; i != 0; i = i->next)
- total += i->size;
- return total;
-}
-
-void MemoryManager::growUnmanagedHeapSizeUsage(size_t delta)
-{
- m_d->unmanagedHeapSize += delta;
+ return hugeItemAllocator.usedMem();
}
MemoryManager::~MemoryManager()
@@ -662,23 +880,26 @@ MemoryManager::~MemoryManager()
delete m_persistentValues;
sweep(/*lastSweep*/true);
+ blockAllocator.freeAll();
+ hugeItemAllocator.freeAll();
+ stackAllocator.freeAll();
delete m_weakValues;
#ifdef V4_USE_VALGRIND
VALGRIND_DESTROY_MEMPOOL(this);
#endif
+ delete chunkAllocator;
}
-
void MemoryManager::dumpStats() const
{
#ifdef DETAILED_MM_STATS
std::cerr << "=================" << std::endl;
std::cerr << "Allocation stats:" << std::endl;
std::cerr << "Requests for each chunk size:" << std::endl;
- for (int i = 0; i < m_d->allocSizeCounters.size(); ++i) {
- if (unsigned count = m_d->allocSizeCounters[i]) {
+ for (int i = 0; i < allocSizeCounters.size(); ++i) {
+ if (unsigned count = allocSizeCounters[i]) {
std::cerr << "\t" << (i << 4) << " bytes chunks: " << count << std::endl;
}
}
@@ -689,7 +910,7 @@ void MemoryManager::dumpStats() const
void MemoryManager::willAllocate(std::size_t size)
{
unsigned alignedSize = (size + 15) >> 4;
- QVector<unsigned> &counters = m_d->allocSizeCounters;
+ QVector<unsigned> &counters = allocSizeCounters;
if ((unsigned) counters.size() < alignedSize + 1)
counters.resize(alignedSize + 1);
counters[alignedSize]++;
@@ -709,4 +930,7 @@ void MemoryManager::collectFromJSStack() const
++v;
}
}
+
+} // namespace QV4
+
QT_END_NAMESPACE
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index dfa0d85dff..00daf8a622 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -55,6 +55,7 @@
#include <private/qv4value_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4object_p.h>
+#include <private/qv4mmdefs_p.h>
#include <QVector>
//#define DETAILED_MM_STATS
@@ -63,55 +64,166 @@
#define QV4_MM_MAX_CHUNK_SIZE "QV4_MM_MAX_CHUNK_SIZE"
#define QV4_MM_STATS "QV4_MM_STATS"
+#define MM_DEBUG 0
+
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct GCDeletable;
+struct ChunkAllocator;
-class Q_QML_EXPORT MemoryManager
-{
- Q_DISABLE_COPY(MemoryManager);
+template<typename T>
+struct StackAllocator {
+ Q_STATIC_ASSERT(sizeof(T) < Chunk::DataSize);
+ static const uint requiredSlots = (sizeof(T) + sizeof(HeapItem) - 1)/sizeof(HeapItem);
-public:
- struct Data;
+ StackAllocator(ChunkAllocator *chunkAlloc);
- class GCBlocker
- {
- public:
- GCBlocker(MemoryManager *mm)
- : mm(mm)
- , wasBlocked(mm->isGCBlocked())
- {
- mm->setGCBlocked(true);
+ T *allocate() {
+ T *m = nextFree->as<T>();
+ if (Q_UNLIKELY(nextFree == lastInChunk)) {
+ nextChunk();
+ } else {
+ nextFree += requiredSlots;
}
-
- ~GCBlocker()
- {
- mm->setGCBlocked(wasBlocked);
+#if MM_DEBUG
+ Chunk *c = m->chunk();
+ Chunk::setBit(c->objectBitmap, m - c->realBase());
+#endif
+ return m;
+ }
+ void free() {
+#if MM_DEBUG
+ Chunk::clearBit(item->chunk()->objectBitmap, item - item->chunk()->realBase());
+#endif
+ if (Q_UNLIKELY(nextFree == firstInChunk)) {
+ prevChunk();
+ } else {
+ nextFree -= requiredSlots;
}
+ }
+
+ void nextChunk();
+ void prevChunk();
+
+ void freeAll();
+
+ ChunkAllocator *chunkAllocator;
+ HeapItem *nextFree = 0;
+ HeapItem *firstInChunk = 0;
+ HeapItem *lastInChunk = 0;
+ std::vector<Chunk *> chunks;
+ uint currentChunk = 0;
+};
+
+struct BlockAllocator {
+ BlockAllocator(ChunkAllocator *chunkAllocator)
+ : chunkAllocator(chunkAllocator)
+ {
+ memset(freeBins, 0, sizeof(freeBins));
+#if MM_DEBUG
+ memset(allocations, 0, sizeof(allocations));
+#endif
+ }
+
+ enum { NumBins = 8 };
+
+ static inline size_t binForSlots(size_t nSlots) {
+ return nSlots >= NumBins ? NumBins - 1 : nSlots;
+ }
+
+#if MM_DEBUG
+ void stats();
+#endif
+
+ HeapItem *allocate(size_t size, bool forceAllocation = false);
+
+ size_t totalSlots() const {
+ return Chunk::AvailableSlots*chunks.size();
+ }
+
+ size_t allocatedMem() const {
+ return chunks.size()*Chunk::DataSize;
+ }
+ size_t usedMem() const {
+ uint used = 0;
+ for (auto c : chunks)
+ used += c->nUsedSlots()*Chunk::SlotSize;
+ return used;
+ }
- private:
- MemoryManager *mm;
- bool wasBlocked;
+ void sweep();
+ void freeAll();
+
+ // bump allocations
+ HeapItem *nextFree = 0;
+ size_t nFree = 0;
+ size_t usedSlotsAfterLastSweep = 0;
+ HeapItem *freeBins[NumBins];
+ ChunkAllocator *chunkAllocator;
+ std::vector<Chunk *> chunks;
+#if MM_DEBUG
+ uint allocations[NumBins];
+#endif
+};
+
+struct HugeItemAllocator {
+ HugeItemAllocator(ChunkAllocator *chunkAllocator)
+ : chunkAllocator(chunkAllocator)
+ {}
+
+ HeapItem *allocate(size_t size);
+ void sweep();
+ void freeAll();
+
+ size_t usedMem() const {
+ size_t used = 0;
+ for (const auto &c : chunks)
+ used += c.size;
+ return used;
+ }
+
+ ChunkAllocator *chunkAllocator;
+ struct HugeChunk {
+ Chunk *chunk;
+ size_t size;
};
+ std::vector<HugeChunk> chunks;
+};
+
+
+class Q_QML_EXPORT MemoryManager
+{
+ Q_DISABLE_COPY(MemoryManager);
+
public:
MemoryManager(ExecutionEngine *engine);
~MemoryManager();
// TODO: this is only for 64bit (and x86 with SSE/AVX), so exend it for other architectures to be slightly more efficient (meaning, align on 8-byte boundaries).
// Note: all occurrences of "16" in alloc/dealloc are also due to the alignment.
- static inline std::size_t align(std::size_t size)
- { return (size + 15) & ~0xf; }
+ Q_DECL_CONSTEXPR static inline std::size_t align(std::size_t size)
+ { return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); }
+
+ QV4::Heap::CallContext *allocSimpleCallContext(QV4::ExecutionEngine *v4)
+ {
+ Heap::CallContext *ctxt = stackAllocator.allocate();
+ memset(ctxt, 0, sizeof(Heap::CallContext));
+ ctxt->setVtable(QV4::CallContext::staticVTable());
+ ctxt->init(v4);
+ return ctxt;
+
+ }
+ void freeSimpleCallContext()
+ { stackAllocator.free(); }
template<typename ManagedType>
- inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0)
+ inline typename ManagedType::Data *allocManaged(std::size_t size)
{
V4_ASSERT_IS_TRIVIAL(typename ManagedType::Data)
size = align(size);
- Heap::Base *o = allocData(size, unmanagedSize);
- memset(o, 0, size);
+ Heap::Base *o = allocData(size);
o->setVtable(ManagedType::staticVTable());
return static_cast<typename ManagedType::Data *>(o);
}
@@ -119,35 +231,31 @@ public:
template <typename ObjectType>
typename ObjectType::Data *allocateObject(InternalClass *ic)
{
- const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
- typename ObjectType::Data *o = allocManaged<ObjectType>(size + ic->size*sizeof(Value));
+ Heap::Object *o = allocObjectWithMemberData(align(sizeof(typename ObjectType::Data)), ic->size);
+ o->setVtable(ObjectType::staticVTable());
o->internalClass = ic;
- o->inlineMemberSize = ic->size;
- o->inlineMemberOffset = size/sizeof(Value);
- return o;
+ return static_cast<typename ObjectType::Data *>(o);
}
template <typename ObjectType>
typename ObjectType::Data *allocateObject()
{
InternalClass *ic = ObjectType::defaultInternalClass(engine);
- const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
- typename ObjectType::Data *o = allocManaged<ObjectType>(size + ic->size*sizeof(Value));
+ Heap::Object *o = allocObjectWithMemberData(align(sizeof(typename ObjectType::Data)), ic->size);
+ o->setVtable(ObjectType::staticVTable());
Object *prototype = ObjectType::defaultPrototype(engine);
o->internalClass = ic;
o->prototype = prototype->d();
- o->inlineMemberSize = ic->size;
- o->inlineMemberOffset = size/sizeof(Value);
- return o;
+ return static_cast<typename ObjectType::Data *>(o);
}
template <typename ManagedType, typename Arg1>
typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
{
- Scope scope(engine);
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
- t->d_unchecked()->init(this, arg1);
- return t->d();
+ typename ManagedType::Data *o = reinterpret_cast<typename ManagedType::Data *>(allocString(unmanagedSize));
+ o->setVtable(ManagedType::staticVTable());
+ o->init(this, arg1);
+ return o;
}
template <typename ObjectType>
@@ -309,8 +417,6 @@ public:
return t->d();
}
- bool isGCBlocked() const;
- void setGCBlocked(bool blockGC);
void runGC();
void dumpStats() const;
@@ -319,12 +425,15 @@ public:
size_t getAllocatedMem() const;
size_t getLargeItemsMem() const;
- void growUnmanagedHeapSizeUsage(size_t delta); // called when a JS object grows itself. Specifically: Heap::String::append
+ // called when a JS object grows itself. Specifically: Heap::String::append
+ void changeUnmanagedHeapSizeUsage(qptrdiff delta) { unmanagedHeapSize += delta; }
+
protected:
/// expects size to be aligned
- // TODO: try to inline
- Heap::Base *allocData(std::size_t size, std::size_t unmanagedSize);
+ Heap::Base *allocString(std::size_t unmanagedSize);
+ Heap::Base *allocData(std::size_t size);
+ Heap::Object *allocObjectWithMemberData(std::size_t size, uint nMembers);
#ifdef DETAILED_MM_STATS
void willAllocate(std::size_t size);
@@ -334,13 +443,24 @@ private:
void collectFromJSStack() const;
void mark();
void sweep(bool lastSweep = false);
+ bool shouldRunGC() const;
public:
QV4::ExecutionEngine *engine;
- QScopedPointer<Data> m_d;
+ ChunkAllocator *chunkAllocator;
+ StackAllocator<Heap::CallContext> stackAllocator;
+ BlockAllocator blockAllocator;
+ HugeItemAllocator hugeItemAllocator;
PersistentValueStorage *m_persistentValues;
PersistentValueStorage *m_weakValues;
QVector<Value *> m_pendingFreedObjectWrapperValue;
+
+ std::size_t unmanagedHeapSize = 0; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items.
+ std::size_t unmanagedHeapSizeGCLimit;
+
+ bool gcBlocked = false;
+ bool aggressiveGC = false;
+ bool gcStats = false;
};
}
diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h
new file mode 100644
index 0000000000..588ae21ee0
--- /dev/null
+++ b/src/qml/memory/qv4mmdefs_p.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4MMDEFS_P_H
+#define QV4MMDEFS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4global_p.h>
+#include <QtCore/qalgorithms.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+/*
+ * Chunks are the basic structure containing GC managed objects.
+ *
+ * Chunks are 64k aligned in memory, so that retrieving the Chunk pointer from a Heap object
+ * is a simple masking operation. Each Chunk has 4 bitmaps for managing purposes,
+ * and 32byte wide slots for the objects following afterwards.
+ *
+ * The gray and black bitmaps are used for mark/sweep.
+ * The object bitmap has a bit set if this location represents the start of a Heap object.
+ * The extends bitmap denotes the extend of an object. It has a cleared bit at the start of the object
+ * and a set bit for all following slots used by the object.
+ *
+ * Free memory has both used and extends bits set to 0.
+ *
+ * This gives the following operations when allocating an object of size s:
+ * Find s/Alignment consecutive free slots in the chunk. Set the object bit for the first
+ * slot to 1. Set the extends bits for all following slots to 1.
+ *
+ * All used slots can be found by object|extents.
+ *
+ * When sweeping, simply copy the black bits over to the object bits.
+ *
+ */
+struct HeapItem;
+struct Chunk {
+ enum {
+ ChunkSize = 64*1024,
+ ChunkShift = 16,
+ SlotSize = 32,
+ SlotSizeShift = 5,
+ NumSlots = ChunkSize/SlotSize,
+ BitmapSize = NumSlots/8,
+ HeaderSize = 4*BitmapSize,
+ DataSize = ChunkSize - HeaderSize,
+ AvailableSlots = DataSize/SlotSize,
+#if QT_POINTER_SIZE == 8
+ Bits = 64,
+ BitShift = 6,
+#else
+ Bits = 32,
+ BitShift = 5,
+#endif
+ EntriesInBitmap = BitmapSize/sizeof(quintptr)
+ };
+ quintptr grayBitmap[BitmapSize/sizeof(quintptr)];
+ quintptr blackBitmap[BitmapSize/sizeof(quintptr)];
+ quintptr objectBitmap[BitmapSize/sizeof(quintptr)];
+ quintptr extendsBitmap[BitmapSize/sizeof(quintptr)];
+ char data[ChunkSize - HeaderSize];
+
+ HeapItem *realBase();
+ HeapItem *first();
+
+ static void setBit(quintptr *bitmap, size_t index) {
+// Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize);
+ bitmap += index >> BitShift;
+ quintptr bit = static_cast<quintptr>(1) << (index & (Bits - 1));
+ *bitmap |= bit;
+ }
+ static void clearBit(quintptr *bitmap, size_t index) {
+// Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize);
+ bitmap += index >> BitShift;
+ quintptr bit = static_cast<quintptr>(1) << (index & (Bits - 1));
+ *bitmap &= ~bit;
+ }
+ static bool testBit(quintptr *bitmap, size_t index) {
+// Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize);
+ bitmap += index >> BitShift;
+ quintptr bit = static_cast<quintptr>(1) << (index & (Bits - 1));
+ return (*bitmap & bit);
+ }
+ static void setBits(quintptr *bitmap, size_t index, size_t nBits) {
+// Q_ASSERT(index >= HeaderSize/SlotSize && index + nBits <= ChunkSize/SlotSize);
+ if (!nBits)
+ return;
+ bitmap += index >> BitShift;
+ index &= (Bits - 1);
+ while (1) {
+ size_t bitsToSet = qMin(nBits, Bits - index);
+ quintptr mask = static_cast<quintptr>(-1) >> (Bits - bitsToSet) << index;
+ *bitmap |= mask;
+ nBits -= bitsToSet;
+ if (!nBits)
+ return;
+ index = 0;
+ ++bitmap;
+ }
+ }
+ static bool hasNonZeroBit(quintptr *bitmap) {
+ for (uint i = 0; i < EntriesInBitmap; ++i)
+ if (bitmap[i])
+ return true;
+ return false;
+ }
+ static uint lowestNonZeroBit(quintptr *bitmap) {
+ for (uint i = 0; i < EntriesInBitmap; ++i) {
+ if (bitmap[i]) {
+ quintptr b = bitmap[i];
+ return i*Bits + qCountTrailingZeroBits(b);
+ }
+ }
+ return 0;
+ }
+
+ uint nFreeSlots() const {
+ return AvailableSlots - nUsedSlots();
+ }
+ uint nUsedSlots() const {
+ uint usedSlots = 0;
+ for (uint i = 0; i < EntriesInBitmap; ++i) {
+ quintptr used = objectBitmap[i] | extendsBitmap[i];
+ usedSlots += qPopulationCount(used);
+ }
+ return usedSlots;
+ }
+
+ void sweep();
+ void freeAll();
+
+ void sortIntoBins(HeapItem **bins, uint nBins);
+};
+
+struct HeapItem {
+ union {
+ struct {
+ HeapItem *next;
+ size_t availableSlots;
+ } freeData;
+ quint64 payload[Chunk::SlotSize/sizeof(quint64)];
+ };
+ operator Heap::Base *() { return reinterpret_cast<Heap::Base *>(this); }
+
+ template<typename T>
+ T *as() { return static_cast<T *>(reinterpret_cast<Heap::Base *>(this)); }
+
+ Chunk *chunk() const {
+ return reinterpret_cast<Chunk *>(reinterpret_cast<quintptr>(this) >> Chunk::ChunkShift << Chunk::ChunkShift);
+ }
+
+ bool isGray() const {
+ Chunk *c = chunk();
+ uint index = this - c->realBase();
+ return Chunk::testBit(c->grayBitmap, index);
+ }
+ bool isBlack() const {
+ Chunk *c = chunk();
+ uint index = this - c->realBase();
+ return Chunk::testBit(c->blackBitmap, index);
+ }
+ bool isInUse() const {
+ Chunk *c = chunk();
+ uint index = this - c->realBase();
+ return Chunk::testBit(c->objectBitmap, index);
+ }
+
+ void setAllocatedSlots(size_t nSlots) {
+// Q_ASSERT(size && !(size % sizeof(HeapItem)));
+ Chunk *c = chunk();
+ size_t index = this - c->realBase();
+// Q_ASSERT(!Chunk::testBit(c->objectBitmap, index));
+ Chunk::setBit(c->objectBitmap, index);
+ Chunk::setBits(c->extendsBitmap, index + 1, nSlots - 1);
+// for (uint i = index + 1; i < nBits - 1; ++i)
+// Q_ASSERT(Chunk::testBit(c->extendsBitmap, i));
+// Q_ASSERT(!Chunk::testBit(c->extendsBitmap, index));
+ }
+
+ // Doesn't report correctly for huge items
+ size_t size() const {
+ Chunk *c = chunk();
+ uint index = this - c->realBase();
+ Q_ASSERT(Chunk::testBit(c->objectBitmap, index));
+ // ### optimize me
+ uint end = index + 1;
+ while (end < Chunk::NumSlots && Chunk::testBit(c->extendsBitmap, end))
+ ++end;
+ return (end - index)*sizeof(HeapItem);
+ }
+};
+
+inline HeapItem *Chunk::realBase()
+{
+ return reinterpret_cast<HeapItem *>(this);
+}
+
+inline HeapItem *Chunk::first()
+{
+ return reinterpret_cast<HeapItem *>(data);
+}
+
+Q_STATIC_ASSERT(sizeof(Chunk) == Chunk::ChunkSize);
+Q_STATIC_ASSERT((1 << Chunk::ChunkShift) == Chunk::ChunkSize);
+Q_STATIC_ASSERT(1 << Chunk::SlotSizeShift == Chunk::SlotSize);
+Q_STATIC_ASSERT(sizeof(HeapItem) == Chunk::SlotSize);
+Q_STATIC_ASSERT(QT_POINTER_SIZE*8 == Chunk::Bits);
+Q_STATIC_ASSERT((1 << Chunk::BitShift) == Chunk::Bits);
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index 826a074701..8f9e4b7f83 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -14,6 +14,8 @@ solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
# Ensure this gcc optimization is switched off for mips platforms to avoid trouble with JIT.
gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks
+DEFINES += QT_NO_FOREACH
+
exists("qqml_enable_gcov") {
QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors
LIBS_PRIVATE += -lgcov
diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp
index 39d609454f..b1c320afd4 100644
--- a/src/qml/qml/qqmlabstractbinding.cpp
+++ b/src/qml/qml/qqmlabstractbinding.cpp
@@ -191,7 +191,7 @@ void QQmlAbstractBinding::removeFromObject()
void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop)
{
- qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
+ qmlWarning(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
}
QString QQmlAbstractBinding::expression() const
diff --git a/src/qml/qml/qqmlabstracturlinterceptor.h b/src/qml/qml/qqmlabstracturlinterceptor.h
index dfb8a46027..665b37fb3a 100644
--- a/src/qml/qml/qqmlabstracturlinterceptor.h
+++ b/src/qml/qml/qqmlabstracturlinterceptor.h
@@ -47,7 +47,6 @@ QT_BEGIN_NAMESPACE
class Q_QML_EXPORT QQmlAbstractUrlInterceptor
{
- Q_FLAGS(InterceptionPoint)
public:
enum DataType { //Matches QQmlDataBlob::Type
QmlFile = 0,
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index 8a97b7eba7..2a96d96302 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -190,9 +190,14 @@ void QQmlApplicationEnginePrivate::_q_finishLoad(QObject *o)
/*!
\fn QQmlApplicationEngine::objectCreated(QObject *object, const QUrl &url)
- This signal is emitted when an object finishes loading. If loading was successful, \a object contains a pointer to the loaded object.
- Otherwise the pointer is NULL. The \a url loaded is also provided, note that if a QString file path was initially passed to the
- QQmlApplicationEngine, this url will be the equivalent of QUrl::fromLocalFile(filePath).
+ This signal is emitted when an object finishes loading. If loading was
+ successful, \a object contains a pointer to the loaded object, otherwise
+ the pointer is NULL.
+
+ The \a url to the component the \a object came from is also provided.
+
+ \note If the path to the component was provided as a QString containing a
+ relative path, the \a url will contain a fully resolved path to the file.
*/
/*!
@@ -226,7 +231,7 @@ QQmlApplicationEngine::QQmlApplicationEngine(const QUrl &url, QObject *parent)
This is provided as a convenience, and is the same as using the empty constructor and calling load afterwards.
*/
QQmlApplicationEngine::QQmlApplicationEngine(const QString &filePath, QObject *parent)
- : QQmlApplicationEngine(QUrl::fromLocalFile(filePath), parent)
+ : QQmlApplicationEngine(QUrl::fromUserInput(filePath, QLatin1String("."), QUrl::AssumeLocalFile), parent)
{
}
@@ -265,7 +270,7 @@ void QQmlApplicationEngine::load(const QUrl &url)
void QQmlApplicationEngine::load(const QString &filePath)
{
Q_D(QQmlApplicationEngine);
- d->startLoad(QUrl::fromLocalFile(filePath));
+ d->startLoad(QUrl::fromUserInput(filePath, QLatin1String("."), QUrl::AssumeLocalFile));
}
/*!
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 254d5e1907..19ece44beb 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -91,7 +91,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
function += QQmlPropertyCache::signalParameterStringForJS(v4, signal.parameterNames(), &error);
if (!error.isEmpty()) {
- qmlInfo(scopeObject()) << error;
+ qmlWarning(scopeObject()) << error;
return;
}
} else
@@ -129,7 +129,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
QString error;
QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, &error);
if (!error.isEmpty()) {
- qmlInfo(scopeObject()) << error;
+ qmlWarning(scopeObject()) << error;
return;
}
runtimeFunction->updateInternalClass(engine, signalParameters);
@@ -199,7 +199,10 @@ void QQmlBoundSignalExpression::evaluate(void **a)
// for several cases (such as QVariant type and QObject-derived types)
//args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
if (type == qMetaTypeId<QJSValue>()) {
- callData->args[ii] = *QJSValuePrivate::getValue(reinterpret_cast<QJSValue *>(a[ii + 1]));
+ if (QV4::Value *v4Value = QJSValuePrivate::valueForData(reinterpret_cast<QJSValue *>(a[ii + 1]), &callData->args[ii]))
+ callData->args[ii] = *v4Value;
+ else
+ callData->args[ii] = QV4::Encode::undefined();
} else if (type == QMetaType::QVariant) {
callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
} else if (type == QMetaType::Int) {
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 6ebcd142fb..a04f47e6a4 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -47,8 +47,6 @@
#include "qqml.h"
#include "qqmlengine.h"
#include "qqmlbinding_p.h"
-#include <private/qqmldebugconnector_p.h>
-#include <private/qqmldebugserviceinterfaces_p.h>
#include "qqmlincubator.h"
#include "qqmlincubator_p.h"
#include <private/qqmljavascriptexpression_p.h>
@@ -876,15 +874,6 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
depthIncreased = false;
}
- if (rv) {
- if (QQmlEngineDebugService *service =
- QQmlDebugConnector::service<QQmlEngineDebugService>()) {
- if (!context->isInternal)
- context->asQQmlContextPrivate()->instances.append(rv);
- service->objectCreated(engine, rv);
- }
- }
-
return rv;
}
@@ -1074,11 +1063,11 @@ struct QmlIncubatorObject : public QV4::Object
V4_OBJECT2(QmlIncubatorObject, Object)
V4_NEEDS_DESTROY
- static QV4::ReturnedValue method_get_statusChanged(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_set_statusChanged(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_status(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_object(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_forceCompletion(QV4::CallContext *ctx);
+ static void method_get_statusChanged(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_set_statusChanged(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_status(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_object(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_forceCompletion(const BuiltinFunction *, Scope &scope, CallData *callData);
static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e);
@@ -1244,7 +1233,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
if (args->length() >= 2) {
QV4::ScopedValue v(scope, (*args)[1]);
if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) {
- qmlInfo(this) << tr("createObject: value is not an object");
+ qmlWarning(this) << tr("createObject: value is not an object");
args->setReturnValue(QV4::Encode::null());
return;
}
@@ -1361,7 +1350,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
QV4::ScopedValue v(scope, (*args)[1]);
if (v->isNull()) {
} else if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) {
- qmlInfo(this) << tr("createObject: value is not an object");
+ qmlWarning(this) << tr("createObject: value is not an object");
args->setReturnValue(QV4::Encode::null());
return;
} else {
@@ -1426,58 +1415,53 @@ QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4)
incubationProto.set(v4, proto);
}
-QV4::ReturnedValue QV4::QmlIncubatorObject::method_get_object(QV4::CallContext *ctx)
+void QV4::QmlIncubatorObject::method_get_object(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->thisObject().as<QmlIncubatorObject>());
+ QV4::Scoped<QmlIncubatorObject> o(scope, callData->thisObject.as<QmlIncubatorObject>());
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return QV4::QObjectWrapper::wrap(ctx->d()->engine, o->d()->incubator->object());
+ scope.result = QV4::QObjectWrapper::wrap(scope.engine, o->d()->incubator->object());
}
-QV4::ReturnedValue QV4::QmlIncubatorObject::method_forceCompletion(QV4::CallContext *ctx)
+void QV4::QmlIncubatorObject::method_forceCompletion(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->thisObject().as<QmlIncubatorObject>());
+ QV4::Scoped<QmlIncubatorObject> o(scope, callData->thisObject.as<QmlIncubatorObject>());
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
o->d()->incubator->forceCompletion();
- return QV4::Encode::undefined();
+ RETURN_UNDEFINED();
}
-QV4::ReturnedValue QV4::QmlIncubatorObject::method_get_status(QV4::CallContext *ctx)
+void QV4::QmlIncubatorObject::method_get_status(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->thisObject().as<QmlIncubatorObject>());
+ QV4::Scoped<QmlIncubatorObject> o(scope, callData->thisObject.as<QmlIncubatorObject>());
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return QV4::Encode(o->d()->incubator->status());
+ scope.result = QV4::Encode(o->d()->incubator->status());
}
-QV4::ReturnedValue QV4::QmlIncubatorObject::method_get_statusChanged(QV4::CallContext *ctx)
+void QV4::QmlIncubatorObject::method_get_statusChanged(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->thisObject().as<QmlIncubatorObject>());
+ QV4::Scoped<QmlIncubatorObject> o(scope, callData->thisObject.as<QmlIncubatorObject>());
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return o->d()->statusChanged.asReturnedValue();
+ scope.result = o->d()->statusChanged;
}
-QV4::ReturnedValue QV4::QmlIncubatorObject::method_set_statusChanged(QV4::CallContext *ctx)
+void QV4::QmlIncubatorObject::method_set_statusChanged(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->thisObject().as<QmlIncubatorObject>());
- if (!o || ctx->argc() < 1)
- return ctx->engine()->throwTypeError();
+ QV4::Scoped<QmlIncubatorObject> o(scope, callData->thisObject.as<QmlIncubatorObject>());
+ if (!o || callData->argc < 1)
+ THROW_TYPE_ERROR();
+ o->d()->statusChanged = callData->args[0];
- o->d()->statusChanged = ctx->args()[0];
- return QV4::Encode::undefined();
+ RETURN_UNDEFINED();
}
QQmlComponentExtension::~QQmlComponentExtension()
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 85c91a592a..0b0bbef795 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -83,7 +83,7 @@ QT_BEGIN_NAMESPACE
by \a data, which is a block of data previously returned by a call
to compile().
- Errors should be reported using qmlInfo(object).
+ Errors should be reported using qmlWarning(object).
The \a object will be an instance of the TypeClass specified by QML_REGISTER_CUSTOM_TYPE.
*/
diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp
index 7552e1e82b..d5d2c9a28d 100644
--- a/src/qml/qml/qqmldelayedcallqueue.cpp
+++ b/src/qml/qml/qqmldelayedcallqueue.cpp
@@ -105,17 +105,15 @@ void QQmlDelayedCallQueue::init(QV4::ExecutionEngine* engine)
m_tickedMethod = metaObject.method(methodIndex);
}
-QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(QV4::CallContext *ctx)
+void QQmlDelayedCallQueue::addUniquelyAndExecuteLater(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- const QV4::CallData *callData = ctx->d()->callData;
-
if (callData->argc == 0)
- V4THROW_ERROR("Qt.callLater: no arguments given");
+ THROW_GENERIC_ERROR("Qt.callLater: no arguments given");
const QV4::FunctionObject *func = callData->args[0].as<QV4::FunctionObject>();
if (!func)
- V4THROW_ERROR("Qt.callLater: first argument not a function or signal");
+ THROW_GENERIC_ERROR("Qt.callLater: first argument not a function or signal");
QPair<QObject *, int> functionData = QV4::QObjectMethod::extractQtMethod(func);
@@ -171,7 +169,7 @@ QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(QV4::CallCon
m_tickedMethod.invoke(this, Qt::QueuedConnection);
m_callbackOutstanding = true;
}
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
void QQmlDelayedCallQueue::storeAnyArguments(DelayedFunctionCall &dfc, const QV4::CallData *callData, int offset, QV4::ExecutionEngine *engine)
diff --git a/src/qml/qml/qqmldelayedcallqueue_p.h b/src/qml/qml/qqmldelayedcallqueue_p.h
index ef899170a2..cffde4f0c0 100644
--- a/src/qml/qml/qqmldelayedcallqueue_p.h
+++ b/src/qml/qml/qqmldelayedcallqueue_p.h
@@ -70,7 +70,7 @@ public:
void init(QV4::ExecutionEngine *);
- QV4::ReturnedValue addUniquelyAndExecuteLater(QV4::CallContext *ctx);
+ void addUniquelyAndExecuteLater(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
public Q_SLOTS:
void ticked();
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index fde7cc4cef..4cca8a4d58 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -188,6 +188,15 @@ bool QQmlDirParser::parse(const QString &source)
_plugins.append(entry);
+ } else if (sections[0] == QLatin1String("classname")) {
+ if (sectionCount < 2) {
+ reportError(lineNumber, 0,
+ QStringLiteral("classname directive requires an argument, but %1 were provided").arg(sectionCount - 1));
+
+ continue;
+ }
+
+ // Ignore these. qmlimportscanner uses them.
} else if (sections[0] == QLatin1String("internal")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index c2915c840b..e1fa97b52f 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -436,7 +436,6 @@ The following functions are also on the Qt object.
\list
\li \c "android" - Android
- \li \c "blackberry" - BlackBerry OS
\li \c "ios" - iOS
\li \c "tvos" - tvOS
\li \c "linux" - Linux
@@ -444,7 +443,6 @@ The following functions are also on the Qt object.
\li \c "unix" - Other Unix-based OS
\li \c "windows" - Windows
\li \c "winrt" - WinRT / UWP
- \li \c "winphone" - Windows Phone
\endlist
\endtable
*/
@@ -1914,9 +1912,29 @@ void QQmlEnginePrivate::sendExit(int retCode)
static void dumpwarning(const QQmlError &error)
{
- QMessageLogger(error.url().toString().toLatin1().constData(),
- error.line(), 0).warning().nospace()
- << qPrintable(error.toString());
+ switch (error.messageType()) {
+ case QtDebugMsg:
+ QMessageLogger(error.url().toString().toLatin1().constData(),
+ error.line(), 0).debug().nospace()
+ << qPrintable(error.toString());
+ break;
+ case QtInfoMsg:
+ QMessageLogger(error.url().toString().toLatin1().constData(),
+ error.line(), 0).info().nospace()
+ << qPrintable(error.toString());
+ break;
+ case QtWarningMsg:
+ case QtFatalMsg: // fatal does not support streaming, and furthermore, is actually fatal. Probably not desirable for QML.
+ QMessageLogger(error.url().toString().toLatin1().constData(),
+ error.line(), 0).warning().nospace()
+ << qPrintable(error.toString());
+ break;
+ case QtCriticalMsg:
+ QMessageLogger(error.url().toString().toLatin1().constData(),
+ error.line(), 0).critical().nospace()
+ << qPrintable(error.toString());
+ break;
+ }
}
static void dumpwarning(const QList<QQmlError> &errors)
@@ -2129,8 +2147,7 @@ bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList
Returns the directory where SQL and other offline
storage is placed.
- QQuickWebView and the SQL databases created with openDatabase()
- are stored here.
+ The SQL databases created with openDatabase() are stored here.
The default is QML/OfflineStorage in the platform-standard
user application data directory.
diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp
index 0a6c7b4960..7a1e02eec6 100644
--- a/src/qml/qml/qqmlerror.cpp
+++ b/src/qml/qml/qqmlerror.cpp
@@ -85,11 +85,12 @@ public:
QString description;
quint16 line;
quint16 column;
+ QtMsgType messageType;
QObject *object;
};
QQmlErrorPrivate::QQmlErrorPrivate()
-: line(0), column(0), object()
+: line(0), column(0), messageType(QtMsgType::QtWarningMsg), object()
{
}
@@ -119,12 +120,14 @@ QQmlError &QQmlError::operator=(const QQmlError &other)
delete d;
d = 0;
} else {
- if (!d) d = new QQmlErrorPrivate;
+ if (!d)
+ d = new QQmlErrorPrivate;
d->url = other.d->url;
d->description = other.d->description;
d->line = other.d->line;
d->column = other.d->column;
d->object = other.d->object;
+ d->messageType = other.d->messageType;
}
return *this;
}
@@ -150,8 +153,9 @@ bool QQmlError::isValid() const
*/
QUrl QQmlError::url() const
{
- if (d) return d->url;
- else return QUrl();
+ if (d)
+ return d->url;
+ return QUrl();
}
/*!
@@ -159,7 +163,8 @@ QUrl QQmlError::url() const
*/
void QQmlError::setUrl(const QUrl &url)
{
- if (!d) d = new QQmlErrorPrivate;
+ if (!d)
+ d = new QQmlErrorPrivate;
d->url = url;
}
@@ -168,8 +173,9 @@ void QQmlError::setUrl(const QUrl &url)
*/
QString QQmlError::description() const
{
- if (d) return d->description;
- else return QString();
+ if (d)
+ return d->description;
+ return QString();
}
/*!
@@ -177,7 +183,8 @@ QString QQmlError::description() const
*/
void QQmlError::setDescription(const QString &description)
{
- if (!d) d = new QQmlErrorPrivate;
+ if (!d)
+ d = new QQmlErrorPrivate;
d->description = description;
}
@@ -186,8 +193,9 @@ void QQmlError::setDescription(const QString &description)
*/
int QQmlError::line() const
{
- if (d) return qmlSourceCoordinate(d->line);
- else return -1;
+ if (d)
+ return qmlSourceCoordinate(d->line);
+ return -1;
}
/*!
@@ -195,7 +203,8 @@ int QQmlError::line() const
*/
void QQmlError::setLine(int line)
{
- if (!d) d = new QQmlErrorPrivate;
+ if (!d)
+ d = new QQmlErrorPrivate;
d->line = qmlSourceCoordinate(line);
}
@@ -204,8 +213,9 @@ void QQmlError::setLine(int line)
*/
int QQmlError::column() const
{
- if (d) return qmlSourceCoordinate(d->column);
- else return -1;
+ if (d)
+ return qmlSourceCoordinate(d->column);
+ return -1;
}
/*!
@@ -213,7 +223,8 @@ int QQmlError::column() const
*/
void QQmlError::setColumn(int column)
{
- if (!d) d = new QQmlErrorPrivate;
+ if (!d)
+ d = new QQmlErrorPrivate;
d->column = qmlSourceCoordinate(column);
}
@@ -225,8 +236,9 @@ void QQmlError::setColumn(int column)
*/
QObject *QQmlError::object() const
{
- if (d) return d->object;
- else return 0;
+ if (d)
+ return d->object;
+ return 0;
}
/*!
@@ -234,11 +246,37 @@ QObject *QQmlError::object() const
*/
void QQmlError::setObject(QObject *object)
{
- if (!d) d = new QQmlErrorPrivate;
+ if (!d)
+ d = new QQmlErrorPrivate;
d->object = object;
}
/*!
+ \since 5.9
+
+ Returns the message type.
+ */
+QtMsgType QQmlError::messageType() const
+{
+ if (d)
+ return d->messageType;
+ return QtMsgType::QtWarningMsg;
+}
+
+/*!
+ \since 5.9
+
+ Sets the \a messageType for this message. The message type determines which
+ QDebug handlers are responsible for recieving the message.
+ */
+void QQmlError::setMessageType(QtMsgType messageType)
+{
+ if (!d)
+ d = new QQmlErrorPrivate;
+ d->messageType = messageType;
+}
+
+/*!
Returns the error as a human readable string.
*/
QString QQmlError::toString() const
diff --git a/src/qml/qml/qqmlerror.h b/src/qml/qml/qqmlerror.h
index e4c42223cf..ef529e3828 100644
--- a/src/qml/qml/qqmlerror.h
+++ b/src/qml/qml/qqmlerror.h
@@ -47,6 +47,7 @@
QT_BEGIN_NAMESPACE
+// ### Qt 6: should this be called QQmlMessage, since it can have a message type?
class QDebug;
class QQmlErrorPrivate;
class Q_QML_EXPORT QQmlError
@@ -69,6 +70,8 @@ public:
void setColumn(int);
QObject *object() const;
void setObject(QObject *);
+ QtMsgType messageType() const;
+ void setMessageType(QtMsgType messageType);
QString toString() const;
private:
diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp
index ca19691e93..097fa71200 100644
--- a/src/qml/qml/qqmlextensionplugin.cpp
+++ b/src/qml/qml/qqmlextensionplugin.cpp
@@ -117,4 +117,14 @@ void QQmlExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
Q_UNUSED(uri);
}
+/*!
+ \class QQmlExtensionInterface
+ \internal
+ \inmodule QtQml
+
+ \class QQmlTypesExtensionInterface
+ \internal
+ \inmodule QtQml
+*/
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 8712b638c5..bd41659f27 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -130,42 +130,74 @@ bool isPathAbsolute(const QString &path)
#endif
}
-// If the type does not already exist as a file import, add the type and return the new type
-QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeName,
+/*
+ \internal
+
+ Fetches the QQmlType instance registered for \a urlString, creating a
+ registration for it if it is not already registered, using the associated
+ \a typeName, \a isCompositeSingleton, \a majorVersion and \a minorVersion
+ details.
+
+ Errors (if there are any) are placed into \a errors, if it is nonzero. Note
+ that errors are treated as fatal if \a errors is not set.
+*/
+QQmlType *fetchOrCreateTypeForUrl(const QString &urlString, const QHashedStringRef& typeName,
bool isCompositeSingleton, QList<QQmlError> *errors,
int majorVersion=-1, int minorVersion=-1)
{
- QUrl url(urlString);
+ QUrl url(urlString); // ### unfortunate (costly) conversion
QQmlType *ret = QQmlMetaType::qmlType(url);
- if (!ret) { //QQmlType not yet existing for composite or composite singleton type
- int dot = typeName.indexOf(QLatin1Char('.'));
- QHashedStringRef unqualifiedtype = dot < 0 ? typeName : QHashedStringRef(typeName.constData() + dot + 1, typeName.length() - dot - 1);
-
- //XXX: The constData of the string ref is pointing somewhere unsafe in qmlregister, so we need to create a temporary copy
- QByteArray buf(unqualifiedtype.toString().toUtf8());
-
- if (isCompositeSingleton) {
- QQmlPrivate::RegisterCompositeSingletonType reg = {
- url,
- "", //Empty URI indicates loaded via file imports
- majorVersion,
- minorVersion,
- buf.constData()
- };
- ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeSingletonRegistration, &reg));
- } else {
- QQmlPrivate::RegisterCompositeType reg = {
- url,
- "", //Empty URI indicates loaded via file imports
- majorVersion,
- minorVersion,
- buf.constData()
- };
- ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &reg));
- }
+ if (ret)
+ return ret;
+
+ int dot = typeName.indexOf(QLatin1Char('.'));
+ QHashedStringRef unqualifiedtype = dot < 0 ? typeName : QHashedStringRef(typeName.constData() + dot + 1, typeName.length() - dot - 1);
+
+ // We need a pointer, but we were passed a string. Take a copy so we
+ // can guarentee it will live long enough to reach qmlregister.
+ QByteArray buf(unqualifiedtype.toString().toUtf8());
+
+ // Register the type. Note that the URI parameters here are empty; for
+ // file type imports, we do not place them in a URI as we don't
+ // necessarily have a good and unique one (picture a library import,
+ // which may be found in multiple plugin locations on disk), but there
+ // are other reasons for this too.
+ //
+ // By not putting them in a URI, we prevent the types from being
+ // registered on a QQmlTypeModule; this is important, as once types are
+ // placed on there, they cannot be easily removed, meaning if the
+ // developer subsequently loads a different import (meaning different
+ // types) with the same URI (using, say, a different plugin path), it is
+ // very undesirable that we continue to associate the types from the
+ // "old" URI with that new module.
+ //
+ // Not having URIs also means that the types cannot be found by name
+ // etc, the only way to look them up is through QQmlImports -- for
+ // better or worse.
+ if (isCompositeSingleton) {
+ QQmlPrivate::RegisterCompositeSingletonType reg = {
+ url,
+ "", // uri
+ majorVersion,
+ minorVersion,
+ buf.constData()
+ };
+ ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeSingletonRegistration, &reg));
+ } else {
+ QQmlPrivate::RegisterCompositeType reg = {
+ url,
+ "", // uri
+ majorVersion,
+ minorVersion,
+ buf.constData()
+ };
+ ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &reg));
}
- if (!ret) {//Usually when a type name is "found" but invalid
- //qDebug() << ret << urlString << QQmlMetaType::qmlType(url);
+
+ // This means that the type couldn't be found by URL, but could not be
+ // registered either, meaning we most likely were passed some kind of bad
+ // data.
+ if (!ret) {
if (!errors) // Cannot list errors properly, just quit
qFatal("%s", QQmlMetaType::typeRegistrationFailures().join('\n').toLatin1().constData());
QQmlError error;
@@ -204,20 +236,49 @@ void qmlClearEnginePlugins()
typedef QPair<QStaticPlugin, QJsonArray> StaticPluginPair;
#endif
+/*!
+ \internal
+
+ A QQmlImportNamespace is a way of seperating imports into a local namespace.
+
+ Within a QML document, there is at least one namespace (the
+ "unqualified set") where imports without a qualifier are placed, i.e:
+
+ import QtQuick 2.6
+
+ will have a single namespace (the unqualified set) containing a single import
+ for QtQuick 2.6. However, there may be others if an import statement gives
+ a qualifier, i.e the following will result in an additional new
+ QQmlImportNamespace in the qualified set:
+
+ import MyFoo 1.0 as Foo
+*/
class QQmlImportNamespace
{
public:
QQmlImportNamespace() : nextNamespace(0) {}
~QQmlImportNamespace() { qDeleteAll(imports); }
+ /*!
+ \internal
+
+ A QQmlImportNamespace::Import represents an actual instance of an import
+ within a namespace.
+
+ \note The uri here may not necessarily be unique (e.g. for file imports).
+
+ \note Version numbers may be -1 for file imports: this means that no
+ version was specified as part of the import. Type resolution will be
+ responsible for attempting to find the "best" possible version.
+ */
struct Import {
- QString uri;
- QString url;
- int majversion;
- int minversion;
- bool isLibrary;
- QQmlDirComponents qmlDirComponents;
- QQmlDirScripts qmlDirScripts;
+ QString uri; // e.g. QtQuick
+ QString url; // the base path of the import
+ int majversion; // the major version imported
+ int minversion; // the minor version imported
+ bool isLibrary; // true means that this is not a file import
+ QQmlDirComponents qmlDirComponents; // a copy of the components listed in the qmldir
+ QQmlDirScripts qmlDirScripts; // a copy of the scripts in the qmldir
bool setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoader::QmldirContent *qmldir,
QQmlImportNamespace *nameSpace, QList<QQmlError> *errors);
@@ -273,9 +334,12 @@ public:
QString base;
int ref;
+ // storage of data related to imports without a namespace
mutable QQmlImportNamespace unqualifiedset;
QQmlImportNamespace *findQualifiedNamespace(const QHashedStringRef &) const;
+
+ // storage of data related to imports with a namespace
mutable QFieldList<QQmlImportNamespace, &QQmlImportNamespace::nextNamespace> qualifiedSets;
QQmlTypeLoader *typeLoader;
@@ -683,15 +747,17 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
if ((candidate == end) ||
(c.majorVersion > candidate->majorVersion) ||
((c.majorVersion == candidate->majorVersion) && (c.minorVersion > candidate->minorVersion))) {
- componentUrl = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName);
- if (c.internal && base) {
- if (resolveLocalUrl(*base, c.fileName) != componentUrl)
- continue; // failed attempt to access an internal type
- }
- if (base && (*base == componentUrl)) {
- if (typeRecursionDetected)
- *typeRecursionDetected = true;
- continue; // no recursion
+ if (base) {
+ componentUrl = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName);
+ if (c.internal) {
+ if (resolveLocalUrl(*base, c.fileName) != componentUrl)
+ continue; // failed attempt to access an internal type
+ }
+ if (*base == componentUrl) {
+ if (typeRecursionDetected)
+ *typeRecursionDetected = true;
+ continue; // no recursion
+ }
}
// This is our best candidate so far
@@ -702,9 +768,11 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
}
if (candidate != end) {
+ if (!base) // ensure we have a componentUrl
+ componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName);
int major = vmajor ? *vmajor : -1;
int minor = vminor ? *vminor : -1;
- QQmlType *returnType = getTypeForUrl(componentUrl, type, isCompositeSingleton, 0,
+ QQmlType *returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton, 0,
major, minor);
if (type_return)
*type_return = returnType;
@@ -732,7 +800,7 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
if (typeRecursionDetected)
*typeRecursionDetected = true;
} else {
- QQmlType *returnType = getTypeForUrl(qmlUrl, type, false, 0);
+ QQmlType *returnType = fetchOrCreateTypeForUrl(qmlUrl, type, false, 0);
if (type_return)
*type_return = returnType;
return returnType != 0;
@@ -777,7 +845,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor,
return true;
if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) {
// qualified, and only 1 url
- *type_return = getTypeForUrl(resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")), type, false, errors);
+ *type_return = fetchOrCreateTypeForUrl(resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")), type, false, errors);
return (*type_return != 0);
}
}
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index 963638ca34..54d0b240f5 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -380,6 +380,23 @@ finishIncubate:
}
}
+void QQmlIncubatorPrivate::cancel(QObject *object, QQmlContext *context)
+{
+ if (!context)
+ context = qmlContext(object);
+ if (!context)
+ return;
+
+ QQmlContextData *data = QQmlContextData::get(context);
+ QQmlIncubatorPrivate *p = (QQmlIncubatorPrivate *)data->activeVMEData;
+ if (!p)
+ return;
+
+ p->vmeGuard.unguard(object);
+ if (!p->creator.isNull())
+ p->creator->cancel(object);
+}
+
/*!
Incubate objects for \a msecs, or until there are no more objects to incubate.
*/
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index ecf3b6d2ca..758e0a29f6 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -40,6 +40,8 @@
#ifndef QQMLINCUBATOR_P_H
#define QQMLINCUBATOR_P_H
+#include "qqmlincubator.h"
+
#include <private/qintrusivelist_p.h>
#include <private/qqmlvme_p.h>
#include <private/qrecursionwatcher_p.h>
@@ -100,6 +102,9 @@ public:
void forceCompletion(QQmlInstantiationInterrupt &i);
void incubate(QQmlInstantiationInterrupt &i);
+
+ // used by Qt Quick Controls 2
+ Q_QML_PRIVATE_EXPORT static void cancel(QObject *object, QQmlContext *context = 0);
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp
index 5b6e02d5b1..dae15e2eca 100644
--- a/src/qml/qml/qqmlinfo.cpp
+++ b/src/qml/qml/qqmlinfo.cpp
@@ -50,13 +50,45 @@
QT_BEGIN_NAMESPACE
/*!
+ \fn QQmlInfo QtQml::qmlDebug(const QObject *object)
+ \relates QQmlEngine
+ \since 5.9
+
+ Prints debug messages that include the file and line number for the
+ specified QML \a object.
+
+ When QML types produce logging messages, it improves traceability
+ if they include the QML file and line number on which the
+ particular instance was instantiated.
+
+ To include the file and line number, an object must be passed. If
+ the file and line number is not available for that instance
+ (either it was not instantiated by the QML engine or location
+ information is disabled), "unknown location" will be used instead.
+
+ For example,
+
+ \code
+ qmlDebug(object) << "Internal state: 42";
+ \endcode
+
+ prints
+
+ \code
+ QML MyCustomType (unknown location): Internal state: 42
+ \endcode
+
+ \sa QtQml::qmlInfo, QtQml::qmlWarning
+*/
+
+/*!
\fn QQmlInfo QtQml::qmlInfo(const QObject *object)
\relates QQmlEngine
- Prints warning messages that include the file and line number for the
+ Prints informational messages that include the file and line number for the
specified QML \a object.
- When QML types display warning messages, it improves traceability
+ When QML types produce logging messages, it improves traceability
if they include the QML file and line number on which the
particular instance was instantiated.
@@ -76,14 +108,58 @@ QT_BEGIN_NAMESPACE
\code
QML MyCustomType (unknown location): component property is a write-once property
\endcode
+
+ \note In versions prior to Qt 5.9, qmlInfo reported messages using a warning
+ QtMsgType. For Qt 5.9 and above, qmlInfo uses an info QtMsgType. To send
+ warnings, use qmlWarning.
+
+ \sa QtQml::qmlDebug, QtQml::qmlWarning
+*/
+
+
+/*!
+ \fn QQmlInfo QtQml::qmlWarning(const QObject *object)
+ \relates QQmlEngine
+ \since 5.9
+
+ Prints warning messages that include the file and line number for the
+ specified QML \a object.
+
+ When QML types produce logging messages, it improves traceability
+ if they include the QML file and line number on which the
+ particular instance was instantiated.
+
+ To include the file and line number, an object must be passed. If
+ the file and line number is not available for that instance
+ (either it was not instantiated by the QML engine or location
+ information is disabled), "unknown location" will be used instead.
+
+ For example,
+
+ \code
+ qmlInfo(object) << tr("property cannot be set to 0");
+ \endcode
+
+ prints
+
+ \code
+ QML MyCustomType (unknown location): property cannot be set to 0
+ \endcode
+
+ \sa QtQml::qmlDebug, QtQml::qmlInfo
*/
class QQmlInfoPrivate
{
public:
- QQmlInfoPrivate() : ref (1), object(0) {}
+ QQmlInfoPrivate(QtMsgType type)
+ : ref (1)
+ , msgType(type)
+ , object(nullptr)
+ {}
int ref;
+ QtMsgType msgType;
const QObject *object;
QString buffer;
QList<QQmlError> errors;
@@ -110,6 +186,7 @@ QQmlInfo::~QQmlInfo()
if (!d->buffer.isEmpty()) {
QQmlError error;
+ error.setMessageType(d->msgType);
QObject *object = const_cast<QObject *>(d->object);
@@ -139,28 +216,32 @@ QQmlInfo::~QQmlInfo()
namespace QtQml {
-QQmlInfo qmlInfo(const QObject *me)
-{
- QQmlInfoPrivate *d = new QQmlInfoPrivate;
- d->object = me;
- return QQmlInfo(d);
-}
+#define MESSAGE_FUNCS(FuncName, MessageLevel) \
+ QQmlInfo FuncName(const QObject *me) \
+ { \
+ QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
+ d->object = me; \
+ return QQmlInfo(d); \
+ } \
+ QQmlInfo FuncName(const QObject *me, const QQmlError &error) \
+ { \
+ QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
+ d->object = me; \
+ d->errors << error; \
+ return QQmlInfo(d); \
+ } \
+ QQmlInfo FuncName(const QObject *me, const QList<QQmlError> &errors) \
+ { \
+ QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \
+ d->object = me; \
+ d->errors = errors; \
+ return QQmlInfo(d); \
+ }
-QQmlInfo qmlInfo(const QObject *me, const QQmlError &error)
-{
- QQmlInfoPrivate *d = new QQmlInfoPrivate;
- d->object = me;
- d->errors << error;
- return QQmlInfo(d);
-}
+MESSAGE_FUNCS(qmlDebug, QtMsgType::QtDebugMsg)
+MESSAGE_FUNCS(qmlInfo, QtMsgType::QtInfoMsg)
+MESSAGE_FUNCS(qmlWarning, QtMsgType::QtWarningMsg)
-QQmlInfo qmlInfo(const QObject *me, const QList<QQmlError> &errors)
-{
- QQmlInfoPrivate *d = new QQmlInfoPrivate;
- d->object = me;
- d->errors = errors;
- return QQmlInfo(d);
-}
} // namespace QtQml
diff --git a/src/qml/qml/qqmlinfo.h b/src/qml/qml/qqmlinfo.h
index ab0281a688..673125632e 100644
--- a/src/qml/qml/qqmlinfo.h
+++ b/src/qml/qml/qqmlinfo.h
@@ -48,11 +48,19 @@ QT_BEGIN_NAMESPACE
class QQmlInfo;
+// declared in namespace to avoid symbol conflicts with QtDeclarative
namespace QtQml {
- // declared in namespace to avoid symbol conflicts with QtDeclarative
+ Q_QML_EXPORT QQmlInfo qmlDebug(const QObject *me);
+ Q_QML_EXPORT QQmlInfo qmlDebug(const QObject *me, const QQmlError &error);
+ Q_QML_EXPORT QQmlInfo qmlDebug(const QObject *me, const QList<QQmlError> &errors);
+
Q_QML_EXPORT QQmlInfo qmlInfo(const QObject *me);
Q_QML_EXPORT QQmlInfo qmlInfo(const QObject *me, const QQmlError &error);
Q_QML_EXPORT QQmlInfo qmlInfo(const QObject *me, const QList<QQmlError> &errors);
+
+ Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me);
+ Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me, const QQmlError &error);
+ Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me, const QList<QQmlError> &errors);
}
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wheader-hygiene")
@@ -93,9 +101,15 @@ public:
#endif
private:
+ friend Q_QML_EXPORT QQmlInfo QtQml::qmlDebug(const QObject *me);
+ friend Q_QML_EXPORT QQmlInfo QtQml::qmlDebug(const QObject *me, const QQmlError &error);
+ friend Q_QML_EXPORT QQmlInfo QtQml::qmlDebug(const QObject *me, const QList<QQmlError> &errors);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlInfo(const QObject *me);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlInfo(const QObject *me, const QQmlError &error);
friend Q_QML_EXPORT QQmlInfo QtQml::qmlInfo(const QObject *me, const QList<QQmlError> &errors);
+ friend Q_QML_EXPORT QQmlInfo QtQml::qmlWarning(const QObject *me);
+ friend Q_QML_EXPORT QQmlInfo QtQml::qmlWarning(const QObject *me, const QQmlError &error);
+ friend Q_QML_EXPORT QQmlInfo QtQml::qmlWarning(const QObject *me, const QList<QQmlError> &errors);
QQmlInfo(QQmlInfoPrivate *);
QQmlInfoPrivate *d;
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp
index a719956483..edd93ef03d 100644
--- a/src/qml/qml/qqmllist.cpp
+++ b/src/qml/qml/qqmllist.cpp
@@ -335,7 +335,7 @@ int QQmlListReference::count() const
\since 5.0
\inmodule QtQml
\brief The QQmlListProperty class allows applications to expose list-like
-properties to QML.
+properties of QObject-derived classes to QML.
QML has many list properties, where more than one object value can be assigned.
The use of a list property from QML looks like this:
@@ -369,7 +369,8 @@ QML list properties are type-safe - in this case \c {Fruit} is a QObject type th
The \l {Qt Quick 1} version of this class is named QDeclarativeListProperty.
-\note QQmlListProperty can only be used for lists of QObject-derived object pointers.
+\sa {Extending QML - Object and List Property Types Example}
+
*/
/*!
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 3876e774c3..712da78807 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -56,10 +56,17 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QQmlLocaleData);
+#define THROW_ERROR(string) \
+ do { \
+ scope.result = scope.engine->throwError(QString::fromUtf8(string)); \
+ return; \
+ } while (false)
+
+
#define GET_LOCALE_DATA_RESOURCE(OBJECT) \
QV4::Scoped<QQmlLocaleData> r(scope, OBJECT.as<QQmlLocaleData>()); \
if (!r) \
- V4THROW_ERROR("Not a valid Locale object")
+ THROW_ERROR("Not a valid Locale object")
static bool isLocaleObject(const QV4::Value &val)
{
@@ -80,215 +87,219 @@ void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine)
engine->dateCtor()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated);
}
-QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ctx)
+void QQmlDateExtension::method_toLocaleString(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- if (ctx->argc() > 2)
- return QV4::DatePrototype::method_toLocaleString(ctx);
-
- QV4::Scope scope(ctx);
+ if (callData->argc > 2) {
+ QV4::DatePrototype::method_toLocaleString(b, scope, callData);
+ return;
+ }
- QV4::DateObject *date = ctx->thisObject().as<DateObject>();
- if (!date)
- return QV4::DatePrototype::method_toLocaleString(ctx);
+ QV4::DateObject *date = callData->thisObject.as<DateObject>();
+ if (!date) {
+ QV4::DatePrototype::method_toLocaleString(b, scope, callData);
+ return;
+ }
QDateTime dt = date->toQDateTime();
- if (ctx->argc() == 0) {
+ if (callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->d()->engine->newString(locale.toString(dt))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(locale.toString(dt)));
}
- if (!isLocaleObject(ctx->args()[0]))
- return QV4::DatePrototype::method_toLocaleString(ctx); // Use the default Date toLocaleString()
+ if (!isLocaleObject(callData->args[0])) {
+ QV4::DatePrototype::method_toLocaleString(b, scope, callData); // Use the default Date toLocaleString()
+ return;
+ }
- GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
+ GET_LOCALE_DATA_RESOURCE(callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QString formattedDt;
- if (ctx->argc() == 2) {
- if (String *s = ctx->args()[1].stringValue()) {
+ if (callData->argc == 2) {
+ if (String *s = callData->args[1].stringValue()) {
QString format = s->toQString();
formattedDt = r->d()->locale->toString(dt, format);
- } else if (ctx->args()[1].isNumber()) {
- quint32 intFormat = ctx->args()[1].toNumber();
+ } else if (callData->args[1].isNumber()) {
+ quint32 intFormat = callData->args[1].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
formattedDt = r->d()->locale->toString(dt, format);
} else {
- V4THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
+ THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
}
} else {
formattedDt = r->d()->locale->toString(dt, enumFormat);
}
- return ctx->d()->engine->newString(formattedDt)->asReturnedValue();
+ scope.result = scope.engine->newString(formattedDt);
}
-QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext *ctx)
+void QQmlDateExtension::method_toLocaleTimeString(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- if (ctx->argc() > 2)
- return QV4::DatePrototype::method_toLocaleTimeString(ctx);
-
- QV4::Scope scope(ctx);
+ if (callData->argc > 2) {
+ QV4::DatePrototype::method_toLocaleTimeString(b, scope, callData);
+ return;
+ }
- QV4::DateObject *date = ctx->thisObject().as<DateObject>();
- if (!date)
- return QV4::DatePrototype::method_toLocaleTimeString(ctx);
+ QV4::DateObject *date = callData->thisObject.as<DateObject>();
+ if (!date) {
+ QV4::DatePrototype::method_toLocaleTimeString(b, scope, callData);
+ return;
+ }
QDateTime dt = date->toQDateTime();
QTime time = dt.time();
- if (ctx->argc() == 0) {
+ if (callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->d()->engine->newString(locale.toString(time))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(locale.toString(time)));
}
- if (!isLocaleObject(ctx->args()[0]))
- return QV4::DatePrototype::method_toLocaleTimeString(ctx); // Use the default Date toLocaleTimeString()
+ if (!isLocaleObject(callData->args[0]))
+ return QV4::DatePrototype::method_toLocaleTimeString(b, scope, callData); // Use the default Date toLocaleTimeString()
- GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
+ GET_LOCALE_DATA_RESOURCE(callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QString formattedTime;
- if (ctx->argc() == 2) {
- if (String *s = ctx->args()[1].stringValue()) {
+ if (callData->argc == 2) {
+ if (String *s = callData->args[1].stringValue()) {
QString format = s->toQString();
formattedTime = r->d()->locale->toString(time, format);
- } else if (ctx->args()[1].isNumber()) {
- quint32 intFormat = ctx->args()[1].toNumber();
+ } else if (callData->args[1].isNumber()) {
+ quint32 intFormat = callData->args[1].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
formattedTime = r->d()->locale->toString(time, format);
} else {
- V4THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format");
+ THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format");
}
} else {
formattedTime = r->d()->locale->toString(time, enumFormat);
}
- return ctx->d()->engine->newString(formattedTime)->asReturnedValue();
+ scope.result = scope.engine->newString(formattedTime);
}
-QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext *ctx)
+void QQmlDateExtension::method_toLocaleDateString(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- if (ctx->argc() > 2)
- return QV4::DatePrototype::method_toLocaleDateString(ctx);
-
- QV4::Scope scope(ctx);
+ if (callData->argc > 2) {
+ QV4::DatePrototype::method_toLocaleDateString(b, scope, callData);
+ return;
+ }
- QV4::DateObject *dateObj = ctx->thisObject().as<DateObject>();
- if (!dateObj)
- return QV4::DatePrototype::method_toLocaleDateString(ctx);
+ QV4::DateObject *dateObj = callData->thisObject.as<DateObject>();
+ if (!dateObj) {
+ QV4::DatePrototype::method_toLocaleDateString(b, scope, callData);
+ return;
+ }
QDateTime dt = dateObj->toQDateTime();
QDate date = dt.date();
- if (ctx->argc() == 0) {
+ if (callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->d()->engine->newString(locale.toString(date))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(locale.toString(date)));
}
- if (!isLocaleObject(ctx->args()[0]))
- return QV4::DatePrototype::method_toLocaleDateString(ctx); // Use the default Date toLocaleDateString()
+ if (!isLocaleObject(callData->args[0]))
+ return QV4::DatePrototype::method_toLocaleDateString(b, scope, callData); // Use the default Date toLocaleDateString()
- GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
+ GET_LOCALE_DATA_RESOURCE(callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QString formattedDate;
- if (ctx->argc() == 2) {
- if (String *s = ctx->args()[1].stringValue()) {
+ if (callData->argc == 2) {
+ if (String *s = callData->args[1].stringValue()) {
QString format = s->toQString();
formattedDate = r->d()->locale->toString(date, format);
- } else if (ctx->args()[1].isNumber()) {
- quint32 intFormat = ctx->args()[1].toNumber();
+ } else if (callData->args[1].isNumber()) {
+ quint32 intFormat = callData->args[1].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
formattedDate = r->d()->locale->toString(date, format);
} else {
- V4THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format");
+ THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format");
}
} else {
formattedDate = r->d()->locale->toString(date, enumFormat);
}
- return ctx->d()->engine->newString(formattedDate)->asReturnedValue();
+ scope.result = scope.engine->newString(formattedDate);
}
-QV4::ReturnedValue QQmlDateExtension::method_fromLocaleString(QV4::CallContext *ctx)
+void QQmlDateExtension::method_fromLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::ExecutionEngine * const engine = ctx->d()->engine;
- if (ctx->argc() == 1) {
- if (String *s = ctx->args()[0].stringValue()) {
+ QV4::ExecutionEngine * const engine = scope.engine;
+ if (callData->argc == 1) {
+ if (String *s = callData->args[0].stringValue()) {
QLocale locale;
QString dateString = s->toQString();
QDateTime dt = locale.toDateTime(dateString);
- return QV4::Encode(engine->newDateObject(dt));
+ RETURN_RESULT(engine->newDateObject(dt));
}
}
- QV4::Scope scope(ctx);
-
- if (ctx->argc() < 1 || ctx->argc() > 3 || !isLocaleObject(ctx->args()[0]))
- V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments");
+ if (callData->argc < 1 || callData->argc > 3 || !isLocaleObject(callData->args[0]))
+ THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments");
- GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
+ GET_LOCALE_DATA_RESOURCE(callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QDateTime dt;
- QString dateString = ctx->args()[1].toQStringNoThrow();
- if (ctx->argc() == 3) {
- if (String *s = ctx->args()[2].stringValue()) {
+ QString dateString = callData->args[1].toQStringNoThrow();
+ if (callData->argc == 3) {
+ if (String *s = callData->args[2].stringValue()) {
QString format = s->toQString();
dt = r->d()->locale->toDateTime(dateString, format);
- } else if (ctx->args()[2].isNumber()) {
- quint32 intFormat = ctx->args()[2].toNumber();
+ } else if (callData->args[2].isNumber()) {
+ quint32 intFormat = callData->args[2].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
dt = r->d()->locale->toDateTime(dateString, format);
} else {
- V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
+ THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
}
} else {
dt = r->d()->locale->toDateTime(dateString, enumFormat);
}
- return QV4::Encode(engine->newDateObject(dt));
+ scope.result = engine->newDateObject(dt);
}
-QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::CallContext *ctx)
+void QQmlDateExtension::method_fromLocaleTimeString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::ExecutionEngine * const engine = ctx->d()->engine;
+ QV4::ExecutionEngine * const engine = scope.engine;
- if (ctx->argc() == 1) {
- if (String *s = ctx->args()[0].stringValue()) {
+ if (callData->argc == 1) {
+ if (String *s = callData->args[0].stringValue()) {
QLocale locale;
QString timeString = s->toQString();
QTime time = locale.toTime(timeString);
QDateTime dt = QDateTime::currentDateTime();
dt.setTime(time);
- return QV4::Encode(engine->newDateObject(dt));
+ RETURN_RESULT(engine->newDateObject(dt));
}
}
- if (ctx->argc() < 1 || ctx->argc() > 3 || !isLocaleObject(ctx->args()[0]))
- V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments");
-
- QV4::Scope scope(ctx);
+ if (callData->argc < 1 || callData->argc > 3 || !isLocaleObject(callData->args[0]))
+ THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments");
- GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
+ GET_LOCALE_DATA_RESOURCE(callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QTime tm;
- QString dateString = ctx->args()[1].toQStringNoThrow();
- if (ctx->argc() == 3) {
- if (String *s = ctx->args()[2].stringValue()) {
+ QString dateString = callData->args[1].toQStringNoThrow();
+ if (callData->argc == 3) {
+ if (String *s = callData->args[2].stringValue()) {
QString format = s->toQString();
tm = r->d()->locale->toTime(dateString, format);
- } else if (ctx->args()[2].isNumber()) {
- quint32 intFormat = ctx->args()[2].toNumber();
+ } else if (callData->args[2].isNumber()) {
+ quint32 intFormat = callData->args[2].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
tm = r->d()->locale->toTime(dateString, format);
} else {
- V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
+ THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
}
} else {
tm = r->d()->locale->toTime(dateString, enumFormat);
@@ -300,58 +311,56 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::CallConte
dt.setTime(tm);
}
- return QV4::Encode(engine->newDateObject(dt));
+ RETURN_RESULT(engine->newDateObject(dt));
}
-QV4::ReturnedValue QQmlDateExtension::method_fromLocaleDateString(QV4::CallContext *ctx)
+void QQmlDateExtension::method_fromLocaleDateString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::ExecutionEngine * const engine = ctx->d()->engine;
+ QV4::ExecutionEngine * const engine = scope.engine;
- if (ctx->argc() == 1) {
- if (String *s = ctx->args()[0].stringValue()) {
+ if (callData->argc == 1) {
+ if (String *s = callData->args[0].stringValue()) {
QLocale locale;
QString dateString = s->toQString();
QDate date = locale.toDate(dateString);
- return QV4::Encode(engine->newDateObject(QDateTime(date)));
+ RETURN_RESULT(engine->newDateObject(QDateTime(date)));
}
}
- if (ctx->argc() < 1 || ctx->argc() > 3 || !isLocaleObject(ctx->args()[0]))
- V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments");
+ if (callData->argc < 1 || callData->argc > 3 || !isLocaleObject(callData->args[0]))
+ THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments");
- QV4::Scope scope(ctx);
-
- GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
+ GET_LOCALE_DATA_RESOURCE(callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QDate dt;
- QString dateString = ctx->args()[1].toQStringNoThrow();
- if (ctx->argc() == 3) {
- if (String *s = ctx->args()[2].stringValue()) {
+ QString dateString = callData->args[1].toQStringNoThrow();
+ if (callData->argc == 3) {
+ if (String *s = callData->args[2].stringValue()) {
QString format = s->toQString();
dt = r->d()->locale->toDate(dateString, format);
- } else if (ctx->args()[2].isNumber()) {
- quint32 intFormat = ctx->args()[2].toNumber();
+ } else if (callData->args[2].isNumber()) {
+ quint32 intFormat = callData->args[2].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
dt = r->d()->locale->toDate(dateString, format);
} else {
- V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
+ THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
}
} else {
dt = r->d()->locale->toDate(dateString, enumFormat);
}
- return QV4::Encode(engine->newDateObject(QDateTime(dt)));
+ RETURN_RESULT(engine->newDateObject(QDateTime(dt)));
}
-QV4::ReturnedValue QQmlDateExtension::method_timeZoneUpdated(QV4::CallContext *ctx)
+void QQmlDateExtension::method_timeZoneUpdated(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 0)
- V4THROW_ERROR("Locale: Date.timeZoneUpdated(): Invalid arguments");
+ if (callData->argc != 0)
+ THROW_ERROR("Locale: Date.timeZoneUpdated(): Invalid arguments");
QV4::DatePrototype::timezoneUpdated();
- return QV4::Encode::undefined();
+ RETURN_UNDEFINED();
}
//-----------------
@@ -364,148 +373,143 @@ void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine)
engine->numberCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
}
-QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext *ctx)
+void QQmlNumberExtension::method_toLocaleString(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- if (ctx->argc() > 3)
- V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
+ if (callData->argc > 3)
+ THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
- double number = ctx->thisObject().toNumber();
+ double number = callData->thisObject.toNumber();
- if (ctx->argc() == 0) {
+ if (callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->d()->engine->newString(locale.toString(number))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(locale.toString(number)));
}
- if (!isLocaleObject(ctx->args()[0]))
- return QV4::NumberPrototype::method_toLocaleString(ctx); // Use the default Number toLocaleString()
-
- QV4::Scope scope(ctx);
+ if (!isLocaleObject(callData->args[0])) {
+ QV4::NumberPrototype::method_toLocaleString(b, scope, callData); // Use the default Number toLocaleString()
+ return;
+ }
- GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
+ GET_LOCALE_DATA_RESOURCE(callData->args[0]);
quint16 format = 'f';
- if (ctx->argc() > 1) {
- if (!ctx->args()[1].isString())
- V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
- QString fs = ctx->args()[1].toQString();
+ if (callData->argc > 1) {
+ if (!callData->args[1].isString())
+ THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
+ QString fs = callData->args[1].toQString();
if (fs.length())
format = fs.at(0).unicode();
}
int prec = 2;
- if (ctx->argc() > 2) {
- if (!ctx->args()[2].isNumber())
- V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
- prec = ctx->args()[2].toInt32();
+ if (callData->argc > 2) {
+ if (!callData->args[2].isNumber())
+ THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
+ prec = callData->args[2].toInt32();
}
- return ctx->d()->engine->newString(r->d()->locale->toString(number, (char)format, prec))->asReturnedValue();
+ scope.result = scope.engine->newString(r->d()->locale->toString(number, (char)format, prec));
}
-QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::CallContext *ctx)
+void QQmlNumberExtension::method_toLocaleCurrencyString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() > 2)
- V4THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
+ if (callData->argc > 2)
+ THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
- double number = ctx->thisObject().toNumber();
+ double number = callData->thisObject.toNumber();
- if (ctx->argc() == 0) {
+ if (callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->d()->engine->newString(locale.toString(number))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(locale.toString(number)));
}
- if (!isLocaleObject(ctx->args()[0]))
- V4THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
-
- QV4::Scope scope(ctx);
+ if (!isLocaleObject(callData->args[0]))
+ THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
- GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
+ GET_LOCALE_DATA_RESOURCE(callData->args[0]);
QString symbol;
- if (ctx->argc() > 1) {
- if (!ctx->args()[1].isString())
- V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
- symbol = ctx->args()[1].toQStringNoThrow();
+ if (callData->argc > 1) {
+ if (!callData->args[1].isString())
+ THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
+ symbol = callData->args[1].toQStringNoThrow();
}
- return ctx->d()->engine->newString(r->d()->locale->toCurrencyString(number, symbol))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(r->d()->locale->toCurrencyString(number, symbol)));
}
-QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext *ctx)
+void QQmlNumberExtension::method_fromLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 1 || ctx->argc() > 2)
- V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
+ if (callData->argc < 1 || callData->argc > 2)
+ THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
int numberIdx = 0;
QLocale locale;
- QV4::Scope scope(ctx);
-
- if (ctx->argc() == 2) {
- if (!isLocaleObject(ctx->args()[0]))
- V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
+ if (callData->argc == 2) {
+ if (!isLocaleObject(callData->args[0]))
+ THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
- GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
+ GET_LOCALE_DATA_RESOURCE(callData->args[0]);
locale = *r->d()->locale;
numberIdx = 1;
}
- QString ns = ctx->args()[numberIdx].toQString();
+ QString ns = callData->args[numberIdx].toQString();
if (!ns.length())
- return QV4::Encode(Q_QNAN);
+ RETURN_RESULT(QV4::Encode(Q_QNAN));
bool ok = false;
double val = locale.toDouble(ns, &ok);
if (!ok)
- V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format")
+ THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format");
- return QV4::Encode(val);
+ scope.result = QV4::Encode(val);
}
//--------------
// Locale object
-QV4::ReturnedValue QQmlLocaleData::method_get_firstDayOfWeek(QV4::CallContext *ctx)
+void QQmlLocaleData::method_get_firstDayOfWeek(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QLocale *locale = getThisLocale(ctx);
+ QLocale *locale = getThisLocale(scope, callData);
if (!locale)
- return QV4::Encode::undefined();
+ return;
int fdow = int(locale->firstDayOfWeek());
if (fdow == 7)
fdow = 0; // Qt::Sunday = 7, but Sunday is 0 in JS Date
- return QV4::Encode(fdow);
+ scope.result = QV4::Encode(fdow);
}
-QV4::ReturnedValue QQmlLocaleData::method_get_measurementSystem(QV4::CallContext *ctx)
+void QQmlLocaleData::method_get_measurementSystem(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QLocale *locale = getThisLocale(ctx);
+ QLocale *locale = getThisLocale(scope, callData);
if (!locale)
- return QV4::Encode::undefined();
- return QV4::Encode(locale->measurementSystem());
+ return;
+ scope.result = QV4::Encode(locale->measurementSystem());
}
-QV4::ReturnedValue QQmlLocaleData::method_get_textDirection(QV4::CallContext *ctx)
+void QQmlLocaleData::method_get_textDirection(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QLocale *locale = getThisLocale(ctx);
+ QLocale *locale = getThisLocale(scope, callData);
if (!locale)
- return QV4::Encode::undefined();
+ return;
- return QV4::Encode(locale->textDirection());
+ scope.result = QV4::Encode(locale->textDirection());
}
-QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::CallContext *ctx)
+void QQmlLocaleData::method_get_weekDays(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QLocale *locale = getThisLocale(ctx);
+ QLocale *locale = getThisLocale(scope, callData);
if (!locale)
- return QV4::Encode::undefined();
+ return;
QList<Qt::DayOfWeek> days = locale->weekdays();
- QV4::ScopedArrayObject result(scope, ctx->d()->engine->newArrayObject());
+ QV4::ScopedArrayObject result(scope, scope.engine->newArrayObject());
result->arrayReserve(days.size());
for (int i = 0; i < days.size(); ++i) {
int day = days.at(i);
@@ -515,59 +519,58 @@ QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::CallContext *ctx)
}
result->setArrayLengthUnchecked(days.size());
- return result.asReturnedValue();
+ scope.result = result.asReturnedValue();
}
-QV4::ReturnedValue QQmlLocaleData::method_get_uiLanguages(QV4::CallContext *ctx)
+void QQmlLocaleData::method_get_uiLanguages(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::Scope scope(ctx);
- QLocale *locale = getThisLocale(ctx);
+ QLocale *locale = getThisLocale(scope, callData);
if (!locale)
- return QV4::Encode::undefined();
+ return;
QStringList langs = locale->uiLanguages();
- QV4::ScopedArrayObject result(scope, ctx->d()->engine->newArrayObject());
+ QV4::ScopedArrayObject result(scope, scope.engine->newArrayObject());
result->arrayReserve(langs.size());
QV4::ScopedValue v(scope);
for (int i = 0; i < langs.size(); ++i)
- result->arrayPut(i, (v = ctx->d()->engine->newString(langs.at(i))));
+ result->arrayPut(i, (v = scope.engine->newString(langs.at(i))));
result->setArrayLengthUnchecked(langs.size());
- return result.asReturnedValue();
+ scope.result = result.asReturnedValue();
}
-QV4::ReturnedValue QQmlLocaleData::method_currencySymbol(QV4::CallContext *ctx)
+void QQmlLocaleData::method_currencySymbol(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QLocale *locale = getThisLocale(ctx);
+ QLocale *locale = getThisLocale(scope, callData);
if (!locale)
- return QV4::Encode::undefined();
+ return;
- if (ctx->argc() > 1)
- V4THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
+ if (callData->argc > 1)
+ THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
- if (ctx->argc() == 1) {
- quint32 intFormat = ctx->args()[0].toNumber();
+ if (callData->argc == 1) {
+ quint32 intFormat = callData->args[0].toNumber();
format = QLocale::CurrencySymbolFormat(intFormat);
}
- return ctx->d()->engine->newString(locale->currencySymbol(format))->asReturnedValue();
+ scope.result = scope.engine->newString(locale->currencySymbol(format));
}
#define LOCALE_FORMAT(FUNC) \
-QV4::ReturnedValue QQmlLocaleData::method_ ##FUNC (QV4::CallContext *ctx) { \
- QLocale *locale = getThisLocale(ctx); \
+void QQmlLocaleData::method_ ##FUNC (const BuiltinFunction *, Scope &scope, CallData *callData) { \
+ QLocale *locale = getThisLocale(scope, callData); \
if (!locale) \
- return QV4::Encode::undefined(); \
- if (ctx->argc() > 1) \
- V4THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \
+ return; \
+ if (callData->argc > 1) \
+ THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \
QLocale::FormatType format = QLocale::LongFormat;\
- if (ctx->argc() == 1) { \
- quint32 intFormat = ctx->args()[0].toUInt32(); \
+ if (callData->argc == 1) { \
+ quint32 intFormat = callData->args[0].toUInt32(); \
format = QLocale::FormatType(intFormat); \
} \
- return ctx->engine()->newString(locale-> FUNC (format))->asReturnedValue(); \
+ scope.result = scope.engine->newString(locale-> FUNC (format)); \
}
LOCALE_FORMAT(dateTimeFormat)
@@ -576,57 +579,57 @@ LOCALE_FORMAT(dateFormat)
// +1 added to idx because JS is 0-based, whereas QLocale months begin at 1.
#define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \
-QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::CallContext *ctx) {\
- QLocale *locale = getThisLocale(ctx); \
+void QQmlLocaleData::method_ ## VARIABLE (const BuiltinFunction *, Scope &scope, CallData *callData) {\
+ QLocale *locale = getThisLocale(scope, callData); \
if (!locale) \
- return QV4::Encode::undefined(); \
- if (ctx->argc() < 1 || ctx->argc() > 2) \
- V4THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
+ return; \
+ if (callData->argc < 1 || callData->argc > 2) \
+ THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
QLocale::FormatType enumFormat = QLocale::LongFormat; \
- int idx = ctx->args()[0].toInt32() + 1; \
+ int idx = callData->args[0].toInt32() + 1; \
if (idx < 1 || idx > 12) \
- V4THROW_ERROR("Locale: Invalid month"); \
+ THROW_ERROR("Locale: Invalid month"); \
QString name; \
- if (ctx->argc() == 2) { \
- if (ctx->args()[1].isNumber()) { \
- quint32 intFormat = ctx->args()[1].toUInt32(); \
+ if (callData->argc == 2) { \
+ if (callData->args[1].isNumber()) { \
+ quint32 intFormat = callData->args[1].toUInt32(); \
QLocale::FormatType format = QLocale::FormatType(intFormat); \
name = locale-> VARIABLE(idx, format); \
} else { \
- V4THROW_ERROR("Locale: Invalid datetime format"); \
+ THROW_ERROR("Locale: Invalid datetime format"); \
} \
} else { \
name = locale-> VARIABLE(idx, enumFormat); \
} \
- return ctx->engine()->newString(name)->asReturnedValue(); \
+ scope.result = scope.engine->newString(name); \
}
// 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date
#define LOCALE_FORMATTED_DAYNAME(VARIABLE) \
-QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::CallContext *ctx) {\
- QLocale *locale = getThisLocale(ctx); \
+void QQmlLocaleData::method_ ## VARIABLE (const BuiltinFunction *, Scope &scope, CallData *callData) {\
+ QLocale *locale = getThisLocale(scope, callData); \
if (!locale) \
- return QV4::Encode::undefined(); \
- if (ctx->argc() < 1 || ctx->argc() > 2) \
- V4THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
+ return; \
+ if (callData->argc < 1 || callData->argc > 2) \
+ THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
QLocale::FormatType enumFormat = QLocale::LongFormat; \
- int idx = ctx->args()[0].toInt32(); \
+ int idx = callData->args[0].toInt32(); \
if (idx < 0 || idx > 7) \
- V4THROW_ERROR("Locale: Invalid day"); \
+ THROW_ERROR("Locale: Invalid day"); \
if (idx == 0) idx = 7; \
QString name; \
- if (ctx->argc() == 2) { \
- if (ctx->args()[1].isNumber()) { \
- quint32 intFormat = ctx->args()[1].toUInt32(); \
+ if (callData->argc == 2) { \
+ if (callData->args[1].isNumber()) { \
+ quint32 intFormat = callData->args[1].toUInt32(); \
QLocale::FormatType format = QLocale::FormatType(intFormat); \
name = locale-> VARIABLE(idx, format); \
} else { \
- V4THROW_ERROR("Locale: Invalid datetime format"); \
+ THROW_ERROR("Locale: Invalid datetime format"); \
} \
} else { \
name = locale-> VARIABLE(idx, enumFormat); \
} \
- return ctx->engine()->newString(name)->asReturnedValue(); \
+ scope.result = scope.engine->newString(name); \
}
LOCALE_FORMATTED_MONTHNAME(monthName)
@@ -634,12 +637,12 @@ LOCALE_FORMATTED_MONTHNAME(standaloneMonthName)
LOCALE_FORMATTED_DAYNAME(dayName)
LOCALE_FORMATTED_DAYNAME(standaloneDayName)
-#define LOCALE_STRING_PROPERTY(VARIABLE) QV4::ReturnedValue QQmlLocaleData::method_get_ ## VARIABLE (QV4::CallContext* ctx) \
+#define LOCALE_STRING_PROPERTY(VARIABLE) void QQmlLocaleData::method_get_ ## VARIABLE (const BuiltinFunction *, Scope &scope, CallData *callData) \
{ \
- QLocale *locale = getThisLocale(ctx); \
+ QLocale *locale = getThisLocale(scope, callData); \
if (!locale) \
- return QV4::Encode::undefined(); \
- return ctx->engine()->newString(locale-> VARIABLE())->asReturnedValue();\
+ return; \
+ scope.result = scope.engine->newString(locale-> VARIABLE());\
}
LOCALE_STRING_PROPERTY(name)
@@ -830,18 +833,22 @@ void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
engine->stringPrototype()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
}
-QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx)
+void QQmlLocale::method_localeCompare(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].as<StringObject>()))
- return QV4::StringPrototype::method_localeCompare(ctx);
+ if (callData->argc != 1 || (!callData->args[0].isString() && !callData->args[0].as<StringObject>())) {
+ QV4::StringPrototype::method_localeCompare(b, scope, callData);
+ return;
+ }
- if (!ctx->thisObject().isString() && !ctx->thisObject().as<StringObject>())
- return QV4::StringPrototype::method_localeCompare(ctx);
+ if (!callData->thisObject.isString() && !callData->thisObject.as<StringObject>()) {
+ QV4::StringPrototype::method_localeCompare(b, scope, callData);
+ return;
+ }
- QString thisString = ctx->thisObject().toQStringNoThrow();
- QString thatString = ctx->args()[0].toQStringNoThrow();
+ QString thisString = callData->thisObject.toQStringNoThrow();
+ QString thatString = callData->args[0].toQStringNoThrow();
- return QV4::Encode(QString::localeAwareCompare(thisString, thatString));
+ scope.result = QV4::Encode(QString::localeAwareCompare(thisString, thatString));
}
/*!
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index 275f58db7d..1a2ffc72b0 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -67,13 +67,13 @@ public:
static void registerExtension(QV4::ExecutionEngine *engine);
private:
- static QV4::ReturnedValue method_toLocaleString(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_toLocaleTimeString(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_toLocaleDateString(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_fromLocaleString(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_fromLocaleTimeString(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_fromLocaleDateString(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_timeZoneUpdated(QV4::CallContext *ctx);
+ static void method_toLocaleString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_toLocaleTimeString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_toLocaleDateString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_fromLocaleString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_fromLocaleTimeString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_fromLocaleDateString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_timeZoneUpdated(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
};
@@ -83,9 +83,9 @@ public:
static void registerExtension(QV4::ExecutionEngine *engine);
private:
- static QV4::ReturnedValue method_toLocaleString(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_fromLocaleString(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_toLocaleCurrencyString(QV4::CallContext *ctx);
+ static void method_toLocaleString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_fromLocaleString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_toLocaleCurrencyString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
};
@@ -135,7 +135,7 @@ public:
private:
QQmlLocale();
- static QV4::ReturnedValue method_localeCompare(QV4::CallContext *ctx);
+ static void method_localeCompare(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
};
namespace QV4 {
@@ -158,43 +158,43 @@ struct QQmlLocaleData : public QV4::Object
V4_OBJECT2(QQmlLocaleData, Object)
V4_NEEDS_DESTROY
- static QLocale *getThisLocale(QV4::CallContext *ctx) {
- QV4::Object *o = ctx->thisObject().as<Object>();
+ static QLocale *getThisLocale(QV4::Scope &scope, QV4::CallData *callData) {
+ QV4::Object *o = callData->thisObject.as<Object>();
QQmlLocaleData *thisObject = o ? o->as<QQmlLocaleData>() : 0;
if (!thisObject) {
- ctx->engine()->throwTypeError();
+ scope.engine->throwTypeError();
return 0;
}
return thisObject->d()->locale;
}
- static QV4::ReturnedValue method_currencySymbol(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_dateTimeFormat(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_timeFormat(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_dateFormat(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_monthName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_standaloneMonthName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_dayName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_standaloneDayName(QV4::CallContext *ctx);
-
- static QV4::ReturnedValue method_get_firstDayOfWeek(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_measurementSystem(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_textDirection(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_weekDays(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_uiLanguages(QV4::CallContext *ctx);
-
- static QV4::ReturnedValue method_get_name(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_nativeLanguageName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_nativeCountryName(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_decimalPoint(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_groupSeparator(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_percent(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_zeroDigit(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_negativeSign(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_positiveSign(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_exponential(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_amText(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_pmText(QV4::CallContext *ctx);
+ static void method_currencySymbol(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_dateTimeFormat(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_timeFormat(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_dateFormat(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_monthName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_standaloneMonthName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_dayName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_standaloneDayName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+
+ static void method_get_firstDayOfWeek(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_measurementSystem(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_textDirection(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_weekDays(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_uiLanguages(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+
+ static void method_get_name(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_nativeLanguageName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_nativeCountryName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_decimalPoint(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_groupSeparator(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_percent(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_zeroDigit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_negativeSign(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_positiveSign(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_exponential(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_amText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_pmText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
};
}
diff --git a/src/qml/qml/qqmlloggingcategory.cpp b/src/qml/qml/qqmlloggingcategory.cpp
index 70e59db07b..764b874131 100644
--- a/src/qml/qml/qqmlloggingcategory.cpp
+++ b/src/qml/qml/qqmlloggingcategory.cpp
@@ -112,13 +112,13 @@ void QQmlLoggingCategory::componentComplete()
{
m_initialized = true;
if (m_name.isNull())
- qmlInfo(this) << QLatin1String("Declaring the name of the LoggingCategory is mandatory and cannot be changed later !");
+ qmlWarning(this) << QLatin1String("Declaring the name of the LoggingCategory is mandatory and cannot be changed later !");
}
void QQmlLoggingCategory::setName(const QString &name)
{
if (m_initialized) {
- qmlInfo(this) << QLatin1String("The name of a LoggingCategory cannot be changed after the Item is created");
+ qmlWarning(this) << QLatin1String("The name of a LoggingCategory cannot be changed after the Item is created");
return;
}
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 520c44f4da..bd6b9a1599 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -79,7 +79,7 @@ struct QQmlMetaTypeData
Files urlToNonFileImportType; // For non-file imported composite and composite
// singleton types. This way we can locate any
// of them by url, even if it was registered as
- // a module via qmlRegisterCompositeType.
+ // a module via QQmlPrivate::RegisterCompositeType
typedef QHash<const QMetaObject *, QQmlType *> MetaObjects;
MetaObjects metaObjectToType;
typedef QHash<int, QQmlMetaType::StringConverter> StringConverters;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 2e2a3fb303..85fbd86dc4 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -53,6 +53,8 @@
#include <private/qqmlscriptstring_p.h>
#include <private/qqmlpropertyvalueinterceptor_p.h>
#include <private/qqmlvaluetypeproxybinding_p.h>
+#include <private/qqmldebugconnector_p.h>
+#include <private/qqmldebugserviceinterfaces_p.h>
QT_USE_NAMESPACE
@@ -168,7 +170,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
context = new QQmlContextData;
context->isInternal = true;
- context->imports = compilationUnit->importCache;
+ context->imports = compilationUnit->typeNameCache;
context->initFromTypeCompilationUnit(compilationUnit, subComponentIndex);
context->setParent(parentContext);
@@ -216,6 +218,17 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
phase = ObjectsCreated;
+ if (instance) {
+ if (QQmlEngineDebugService *service
+ = QQmlDebugConnector::service<QQmlEngineDebugService>()) {
+ if (!parentContext->isInternal)
+ parentContext->asQQmlContextPrivate()->instances.append(instance);
+ service->objectCreated(engine, instance);
+ } else if (!parentContext->isInternal && QQmlDebugConnector::service<QV4DebugService>()) {
+ parentContext->asQQmlContextPrivate()->instances.append(instance);
+ }
+ }
+
return instance;
}
@@ -1137,7 +1150,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
customParser->engine = QQmlEnginePrivate::get(engine);
- customParser->imports = compilationUnit->importCache;
+ customParser->imports = compilationUnit->typeNameCache;
QList<const QV4::CompiledData::Binding *> bindings;
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
@@ -1257,6 +1270,21 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
return sharedState->rootContext;
}
+void QQmlObjectCreator::cancel(QObject *object)
+{
+ int last = sharedState->allCreatedObjects.count() - 1;
+ int i = last;
+ while (i >= 0) {
+ if (sharedState->allCreatedObjects.at(i) == object) {
+ if (i < last)
+ qSwap(sharedState->allCreatedObjects[i], sharedState->allCreatedObjects[last]);
+ sharedState->allCreatedObjects.pop();
+ break;
+ }
+ --i;
+ }
+}
+
void QQmlObjectCreator::clear()
{
if (phase == Done || phase == Finalizing || phase == Startup)
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index caee7b9d1d..982324be3c 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -90,6 +90,7 @@ public:
QObject *create(int subComponentIndex = -1, QObject *parent = 0, QQmlInstantiationInterrupt *interrupt = 0);
bool populateDeferredProperties(QObject *instance);
QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt);
+ void cancel(QObject *object);
void clear();
QQmlComponentAttached **componentAttachment() const { return &sharedState->componentAttached; }
diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp
index a47a0ab4a4..64ca208f1b 100644
--- a/src/qml/qml/qqmlplatform.cpp
+++ b/src/qml/qml/qqmlplatform.cpp
@@ -59,16 +59,12 @@ QString QQmlPlatform::os()
{
#if defined(Q_OS_ANDROID)
return QStringLiteral("android");
-#elif defined(Q_OS_BLACKBERRY)
- return QStringLiteral("blackberry");
#elif defined(Q_OS_IOS)
return QStringLiteral("ios");
#elif defined(Q_OS_TVOS)
return QStringLiteral("tvos");
#elif defined(Q_OS_MAC)
return QStringLiteral("osx");
-#elif defined(Q_OS_WINPHONE)
- return QStringLiteral("winphone");
#elif defined(Q_OS_WINRT)
return QStringLiteral("winrt");
#elif defined(Q_OS_WIN)
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 76ac15e2f1..13ad02f7cb 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2127,11 +2127,11 @@ bool QQmlTypeData::tryLoadFromDiskCache()
return true;
}
-void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &importCache,
+void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
{
Q_ASSERT(m_compiledData);
- m_compiledData->importCache = importCache;
+ m_compiledData->typeNameCache = typeNameCache;
m_compiledData->resolvedTypes = resolvedTypeCache;
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
@@ -2217,10 +2217,10 @@ void QQmlTypeData::done()
}
}
- QQmlRefPointer<QQmlTypeNameCache> importCache;
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache;
{
- QQmlCompileError error = buildTypeResolutionCaches(&importCache, &resolvedTypeCache);
+ QQmlCompileError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache);
if (error.isSet()) {
setError(error);
return;
@@ -2240,9 +2240,9 @@ void QQmlTypeData::done()
if (!m_document.isNull()) {
// Compile component
- compile(importCache, resolvedTypeCache);
+ compile(typeNameCache, resolvedTypeCache);
} else {
- createTypeAndPropertyCaches(importCache, resolvedTypeCache);
+ createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache);
}
if (isError())
@@ -2303,7 +2303,7 @@ void QQmlTypeData::done()
qualifier = qualifier.mid(lastDotIndex+1);
}
- m_compiledData->importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
+ m_compiledData->typeNameCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
QQmlScriptData *scriptData = script.script->scriptData();
scriptData->addref();
m_compiledData->dependentScripts << scriptData;
@@ -2428,7 +2428,7 @@ void QQmlTypeData::continueLoadFromIR()
QList<QQmlError> errors;
- foreach (const QV4::CompiledData::Import *import, m_document->imports) {
+ for (const QV4::CompiledData::Import *import : qAsConst(m_document->imports)) {
if (!addImport(import, &errors)) {
Q_ASSERT(errors.size());
QQmlError error(errors.takeFirst());
@@ -2489,12 +2489,12 @@ QString QQmlTypeData::stringAt(int index) const
return m_document->jsGenerator.stringTable.stringForIndex(index);
}
-void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
+void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
{
Q_ASSERT(m_compiledData.isNull());
QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine());
- QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), importCache, resolvedTypeCache);
+ QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), typeNameCache, resolvedTypeCache);
m_compiledData = compiler.compile();
if (!m_compiledData) {
setError(compiler.compilationErrors());
@@ -2575,50 +2575,11 @@ void QQmlTypeData::resolveTypes()
int majorVersion = -1;
int minorVersion = -1;
- QQmlImportNamespace *typeNamespace = 0;
- QList<QQmlError> errors;
const QString name = stringAt(unresolvedRef.key());
- bool typeFound = m_importCache.resolveType(name, &ref.type,
- &majorVersion, &minorVersion, &typeNamespace, &errors);
- if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
- // Lazy loading of implicit import
- if (loadImplicitImport()) {
- // Try again to find the type
- errors.clear();
- typeFound = m_importCache.resolveType(name, &ref.type,
- &majorVersion, &minorVersion, &typeNamespace, &errors);
- } else {
- return; //loadImplicitImport() hit an error, and called setError already
- }
- }
-
- if ((!typeFound || typeNamespace) && reportErrors) {
- // Known to not be a type:
- // - known to be a namespace (Namespace {})
- // - type with unknown namespace (UnknownNamespace.SomeType {})
- QQmlError error;
- if (typeNamespace) {
- error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(name));
- } else {
- if (errors.size()) {
- error = errors.takeFirst();
- } else {
- // this should not be possible!
- // Description should come from error provided by addImport() function.
- error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
- }
- error.setUrl(m_importCache.baseUrl());
- error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(name).arg(error.description()));
- }
- error.setLine(unresolvedRef->location.line);
- error.setColumn(unresolvedRef->location.column);
-
- errors.prepend(error);
- setError(errors);
+ if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line, unresolvedRef->location.column, reportErrors) && reportErrors)
return;
- }
if (ref.type && ref.type->isComposite()) {
ref.typeData = typeLoader()->getType(ref.type->sourceUrl());
@@ -2637,20 +2598,20 @@ void QQmlTypeData::resolveTypes()
}
QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
- QQmlRefPointer<QQmlTypeNameCache> *importCache,
+ QQmlRefPointer<QQmlTypeNameCache> *typeNameCache,
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
) const
{
- importCache->adopt(new QQmlTypeNameCache);
+ typeNameCache->adopt(new QQmlTypeNameCache);
for (const QString &ns: m_namespaces)
- (*importCache)->add(ns);
+ (*typeNameCache)->add(ns);
// Add any Composite Singletons that were used to the import cache
for (const QQmlTypeData::TypeReference &singleton: m_compositeSingletons)
- (*importCache)->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
+ (*typeNameCache)->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
- m_importCache.populateCache(*importCache);
+ m_importCache.populateCache(*typeNameCache);
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
@@ -2687,7 +2648,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
return noError;
}
-bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref)
+bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref, int lineNumber, int columnNumber, bool reportErrors)
{
QQmlImportNamespace *typeNamespace = 0;
QList<QQmlError> errors;
@@ -2706,7 +2667,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &
}
}
- if (!typeFound || typeNamespace) {
+ if ((!typeFound || typeNamespace) && reportErrors) {
// Known to not be a type:
// - known to be a namespace (Namespace {})
// - type with unknown namespace (UnknownNamespace.SomeType {})
@@ -2725,6 +2686,11 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &
error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(typeName).arg(error.description()));
}
+ if (lineNumber != -1)
+ error.setLine(lineNumber);
+ if (columnNumber != -1)
+ error.setColumn(columnNumber);
+
errors.prepend(error);
setError(errors);
return false;
@@ -2744,7 +2710,7 @@ void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData:
}
QQmlScriptData::QQmlScriptData()
- : importCache(0)
+ : typeNameCache(0)
, m_loaded(false)
, m_program(0)
{
@@ -2801,8 +2767,8 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
// For backward compatibility, if there are no imports, we need to use the
// imports from the parent context. See QTBUG-17518.
- if (!importCache->isEmpty()) {
- ctxt->imports = importCache;
+ if (!typeNameCache->isEmpty()) {
+ ctxt->imports = typeNameCache;
} else if (effectiveCtxt) {
ctxt->imports = effectiveCtxt->imports;
ctxt->importedScripts = effectiveCtxt->importedScripts;
@@ -2857,9 +2823,9 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
void QQmlScriptData::clear()
{
- if (importCache) {
- importCache->release();
- importCache = 0;
+ if (typeNameCache) {
+ typeNameCache->release();
+ typeNameCache = 0;
}
for (int ii = 0; ii < scripts.count(); ++ii)
@@ -2980,7 +2946,7 @@ void QQmlScriptBlob::done()
}
}
- m_scriptData->importCache = new QQmlTypeNameCache();
+ m_scriptData->typeNameCache = new QQmlTypeNameCache();
QSet<QString> ns;
@@ -2992,13 +2958,13 @@ void QQmlScriptBlob::done()
if (!script.nameSpace.isNull()) {
if (!ns.contains(script.nameSpace)) {
ns.insert(script.nameSpace);
- m_scriptData->importCache->add(script.nameSpace);
+ m_scriptData->typeNameCache->add(script.nameSpace);
}
}
- m_scriptData->importCache->add(script.qualifier, scriptIndex, script.nameSpace);
+ m_scriptData->typeNameCache->add(script.qualifier, scriptIndex, script.nameSpace);
}
- m_importCache.populateCache(m_scriptData->importCache);
+ m_importCache.populateCache(m_scriptData->typeNameCache);
}
QString QQmlScriptBlob::stringAt(int index) const
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index b1d6451974..14141db180 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -449,14 +449,14 @@ private:
void continueLoadFromIR();
void resolveTypes();
QQmlCompileError buildTypeResolutionCaches(
- QQmlRefPointer<QQmlTypeNameCache> *importCache,
+ QQmlRefPointer<QQmlTypeNameCache> *typeNameCache,
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
) const;
- void compile(const QQmlRefPointer<QQmlTypeNameCache> &importCache,
+ void compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
- void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &importCache,
+ void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
- bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref);
+ bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref, int lineNumber = -1, int columnNumber = -1, bool reportErrors = true);
void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
@@ -504,7 +504,7 @@ public:
QUrl url;
QString urlString;
- QQmlTypeNameCache *importCache;
+ QQmlTypeNameCache *typeNameCache;
QList<QQmlScriptBlob *> scripts;
QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 6ce52bb9e5..44b612e7d2 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -312,18 +312,18 @@ bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const
return true;
}
-ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
+void QQmlValueTypeWrapper::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Object *o = ctx->thisObject().as<Object>();
+ Object *o = callData->thisObject.as<Object>();
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
QQmlValueTypeWrapper *w = o->as<QQmlValueTypeWrapper>();
if (!w)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (QQmlValueTypeReference *ref = w->as<QQmlValueTypeReference>())
if (!ref->readReferenceValue())
- return Encode::undefined();
+ RETURN_UNDEFINED();
QString result;
// Prepare a buffer to pass to QMetaType::convert()
@@ -346,7 +346,7 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
}
result += QLatin1Char(')');
}
- return Encode(ctx->engine()->newString(result));
+ scope.result = scope.engine->newString(result);
}
ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index fec54df770..87f9116056 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -111,7 +111,7 @@ public:
static PropertyAttributes query(const Managed *, String *name);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
- static QV4::ReturnedValue method_toString(CallContext *ctx);
+ static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData);
static void initProto(ExecutionEngine *v4);
};
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 72d4ab7e8f..c60f4edc80 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -120,6 +120,18 @@ void QQmlVMEGuard::guard(QQmlObjectCreator *creator)
m_contexts[0] = creator->parentContextData();
}
+void QQmlVMEGuard::unguard(QObject *object)
+{
+ for (int ii = 0; ii < m_objectCount; ++ii) {
+ if (m_objects[ii] == object) {
+ if (ii < m_objectCount - 1)
+ ::memmove((void *) m_objects[ii], (void *) m_objects[ii + 1], sizeof(QPointer<QObject> *));
+ delete m_objects[--m_objectCount];
+ break;
+ }
+ }
+}
+
void QQmlVMEGuard::clear()
{
delete [] m_objects;
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index 99d63380ad..9585b5b6df 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -131,6 +131,7 @@ public:
~QQmlVMEGuard();
void guard(QQmlObjectCreator *);
+ void unguard(QObject *);
void clear();
bool isOK() const;
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 545daa96f8..490a4e19ab 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -325,9 +325,12 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
if (compiledObject->nProperties || compiledObject->nFunctions) {
Q_ASSERT(cache && cache->engine);
QV4::ExecutionEngine *v4 = cache->engine;
- QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, compiledObject->nProperties + compiledObject->nFunctions);
- propertyAndMethodStorage.set(v4, data);
- std::fill(data->data, data->data + data->size, QV4::Encode::undefined());
+ uint size = compiledObject->nProperties + compiledObject->nFunctions;
+ if (size) {
+ QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, size);
+ propertyAndMethodStorage.set(v4, data);
+ std::fill(data->data, data->data + data->size, QV4::Encode::undefined());
+ }
// Need JS wrapper to ensure properties/methods are marked.
ensureQObjectWrapper();
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 22c3c49c58..d0d9f080da 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -71,10 +71,12 @@ using namespace QV4;
#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network)
-#define V4THROW_REFERENCE(string) { \
- ScopedObject error(scope, ctx->engine()->newReferenceErrorObject(QStringLiteral(string))); \
- return ctx->engine()->throwError(error); \
- }
+#define V4THROW_REFERENCE(string) \
+ do { \
+ ScopedObject error(scope, scope.engine->newReferenceErrorObject(QStringLiteral(string))); \
+ scope.result = scope.engine->throwError(error); \
+ return; \
+ } while (false)
QT_BEGIN_NAMESPACE
@@ -274,25 +276,25 @@ public:
static void initClass(ExecutionEngine *engine);
// JS API
- static ReturnedValue method_get_nodeName(CallContext *ctx);
- static ReturnedValue method_get_nodeValue(CallContext *ctx);
- static ReturnedValue method_get_nodeType(CallContext *ctx);
- static ReturnedValue method_get_namespaceUri(CallContext *ctx);
-
- static ReturnedValue method_get_parentNode(CallContext *ctx);
- static ReturnedValue method_get_childNodes(CallContext *ctx);
- static ReturnedValue method_get_firstChild(CallContext *ctx);
- static ReturnedValue method_get_lastChild(CallContext *ctx);
- static ReturnedValue method_get_previousSibling(CallContext *ctx);
- static ReturnedValue method_get_nextSibling(CallContext *ctx);
- static ReturnedValue method_get_attributes(CallContext *ctx);
-
- //static ReturnedValue ownerDocument(CallContext *ctx);
- //static ReturnedValue namespaceURI(CallContext *ctx);
- //static ReturnedValue prefix(CallContext *ctx);
- //static ReturnedValue localName(CallContext *ctx);
- //static ReturnedValue baseURI(CallContext *ctx);
- //static ReturnedValue textContent(CallContext *ctx);
+ static void method_get_nodeName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_nodeValue(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_nodeType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_namespaceUri(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+
+ static void method_get_parentNode(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_childNodes(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_firstChild(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_lastChild(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_previousSibling(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_nextSibling(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_attributes(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+
+ //static void ownerDocument(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ //static void namespaceURI(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ //static void prefix(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ //static void localName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ //static void baseURI(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ //static void textContent(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
static ReturnedValue getProto(ExecutionEngine *v4);
@@ -353,12 +355,12 @@ class Attr : public Node
{
public:
// JS API
- static ReturnedValue method_name(CallContext *ctx);
-// static ReturnedValue specified(CallContext *);
- static ReturnedValue method_value(CallContext *ctx);
- static ReturnedValue method_ownerElement(CallContext *ctx);
-// static ReturnedValue schemaTypeInfo(CallContext *);
-// static ReturnedValue isId(CallContext *c);
+ static void method_name(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+// static void specified(CallContext *);
+ static void method_value(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_ownerElement(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+// static void schemaTypeInfo(CallContext *);
+// static void isId(CallContext *c);
// C++ API
static ReturnedValue prototype(ExecutionEngine *);
@@ -368,7 +370,7 @@ class CharacterData : public Node
{
public:
// JS API
- static ReturnedValue method_length(CallContext *ctx);
+ static void method_length(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
// C++ API
static ReturnedValue prototype(ExecutionEngine *v4);
@@ -378,8 +380,8 @@ class Text : public CharacterData
{
public:
// JS API
- static ReturnedValue method_isElementContentWhitespace(CallContext *ctx);
- static ReturnedValue method_wholeText(CallContext *ctx);
+ static void method_isElementContentWhitespace(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_wholeText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
// C++ API
static ReturnedValue prototype(ExecutionEngine *);
@@ -396,10 +398,10 @@ class Document : public Node
{
public:
// JS API
- static ReturnedValue method_xmlVersion(CallContext *ctx);
- static ReturnedValue method_xmlEncoding(CallContext *ctx);
- static ReturnedValue method_xmlStandalone(CallContext *ctx);
- static ReturnedValue method_documentElement(CallContext *ctx);
+ static void method_xmlVersion(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_xmlEncoding(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_xmlStandalone(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_documentElement(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
// C++ API
static ReturnedValue prototype(ExecutionEngine *);
@@ -418,12 +420,11 @@ void NodeImpl::release()
document->release();
}
-ReturnedValue NodePrototype::method_get_nodeName(CallContext *ctx)
+void NodePrototype::method_get_nodeName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
QString name;
switch (r->d()->d->type) {
@@ -440,15 +441,14 @@ ReturnedValue NodePrototype::method_get_nodeName(CallContext *ctx)
name = r->d()->d->name;
break;
}
- return Encode(ctx->d()->engine->newString(name));
+ scope.result = Encode(scope.engine->newString(name));
}
-ReturnedValue NodePrototype::method_get_nodeValue(CallContext *ctx)
+void NodePrototype::method_get_nodeValue(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (r->d()->d->type == NodeImpl::Document ||
r->d()->d->type == NodeImpl::DocumentFragment ||
@@ -457,135 +457,128 @@ ReturnedValue NodePrototype::method_get_nodeValue(CallContext *ctx)
r->d()->d->type == NodeImpl::Entity ||
r->d()->d->type == NodeImpl::EntityReference ||
r->d()->d->type == NodeImpl::Notation)
- return Encode::null();
+ RETURN_RESULT(Encode::null());
- return Encode(ctx->d()->engine->newString(r->d()->d->data));
+ scope.result = Encode(scope.engine->newString(r->d()->d->data));
}
-ReturnedValue NodePrototype::method_get_nodeType(CallContext *ctx)
+void NodePrototype::method_get_nodeType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(r->d()->d->type);
+ scope.result = Encode(r->d()->d->type);
}
-ReturnedValue NodePrototype::method_get_namespaceUri(CallContext *ctx)
+void NodePrototype::method_get_namespaceUri(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return Encode(ctx->d()->engine->newString(r->d()->d->namespaceUri));
+ scope.result = Encode(scope.engine->newString(r->d()->d->namespaceUri));
}
-ReturnedValue NodePrototype::method_get_parentNode(CallContext *ctx)
+void NodePrototype::method_get_parentNode(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (r->d()->d->parent)
- return Node::create(scope.engine, r->d()->d->parent);
+ scope.result = Node::create(scope.engine, r->d()->d->parent);
else
- return Encode::null();
+ scope.result = Encode::null();
}
-ReturnedValue NodePrototype::method_get_childNodes(CallContext *ctx)
+void NodePrototype::method_get_childNodes(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
- return NodeList::create(scope.engine, r->d()->d);
+ scope.result = NodeList::create(scope.engine, r->d()->d);
}
-ReturnedValue NodePrototype::method_get_firstChild(CallContext *ctx)
+void NodePrototype::method_get_firstChild(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (r->d()->d->children.isEmpty())
- return Encode::null();
+ scope.result = Encode::null();
else
- return Node::create(scope.engine, r->d()->d->children.constFirst());
+ scope.result = Node::create(scope.engine, r->d()->d->children.constFirst());
}
-ReturnedValue NodePrototype::method_get_lastChild(CallContext *ctx)
+void NodePrototype::method_get_lastChild(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (r->d()->d->children.isEmpty())
- return Encode::null();
+ scope.result = Encode::null();
else
- return Node::create(scope.engine, r->d()->d->children.constLast());
+ scope.result = Node::create(scope.engine, r->d()->d->children.constLast());
}
-ReturnedValue NodePrototype::method_get_previousSibling(CallContext *ctx)
+void NodePrototype::method_get_previousSibling(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (!r->d()->d->parent)
- return Encode::null();
+ RETURN_RESULT(Encode::null());
for (int ii = 0; ii < r->d()->d->parent->children.count(); ++ii) {
if (r->d()->d->parent->children.at(ii) == r->d()->d) {
if (ii == 0)
- return Encode::null();
+ scope.result = Encode::null();
else
- return Node::create(scope.engine, r->d()->d->parent->children.at(ii - 1));
+ scope.result = Node::create(scope.engine, r->d()->d->parent->children.at(ii - 1));
+ return;
}
}
- return Encode::null();
+ scope.result = Encode::null();
}
-ReturnedValue NodePrototype::method_get_nextSibling(CallContext *ctx)
+void NodePrototype::method_get_nextSibling(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (!r->d()->d->parent)
- return Encode::null();
+ RETURN_RESULT(Encode::null());
for (int ii = 0; ii < r->d()->d->parent->children.count(); ++ii) {
if (r->d()->d->parent->children.at(ii) == r->d()->d) {
if ((ii + 1) == r->d()->d->parent->children.count())
- return Encode::null();
+ scope.result = Encode::null();
else
- return Node::create(scope.engine, r->d()->d->parent->children.at(ii + 1));
+ scope.result = Node::create(scope.engine, r->d()->d->parent->children.at(ii + 1));
+ return;
}
}
- return Encode::null();
+ scope.result = Encode::null();
}
-ReturnedValue NodePrototype::method_get_attributes(CallContext *ctx)
+void NodePrototype::method_get_attributes(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (r->d()->d->type != NodeImpl::Element)
- return Encode::null();
+ scope.result = Encode::null();
else
- return NamedNodeMap::create(scope.engine, r->d()->d, r->d()->d->attributes);
+ scope.result = NamedNodeMap::create(scope.engine, r->d()->d, r->d()->d->attributes);
}
ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
@@ -666,44 +659,40 @@ ReturnedValue Attr::prototype(ExecutionEngine *engine)
return d->attrPrototype.value();
}
-ReturnedValue Attr::method_name(CallContext *ctx)
+void Attr::method_name(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- return QV4::Encode(scope.engine->newString(r->d()->d->name));
+ scope.result = scope.engine->newString(r->d()->d->name);
}
-ReturnedValue Attr::method_value(CallContext *ctx)
+void Attr::method_value(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- return QV4::Encode(scope.engine->newString(r->d()->d->data));
+ scope.result = scope.engine->newString(r->d()->d->data);
}
-ReturnedValue Attr::method_ownerElement(CallContext *ctx)
+void Attr::method_ownerElement(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- return Node::create(scope.engine, r->d()->d->parent);
+ scope.result = Node::create(scope.engine, r->d()->d->parent);
}
-ReturnedValue CharacterData::method_length(CallContext *ctx)
+void CharacterData::method_length(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- return Encode(r->d()->d->data.length());
+ scope.result = Encode(r->d()->d->data.length());
}
ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
@@ -722,23 +711,22 @@ ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
return d->characterDataPrototype.value();
}
-ReturnedValue Text::method_isElementContentWhitespace(CallContext *ctx)
+void Text::method_isElementContentWhitespace(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
- if (!r) return Encode::undefined();
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
+ if (!r)
+ RETURN_UNDEFINED();
- return Encode(QStringRef(&r->d()->d->data).trimmed().isEmpty());
+ scope.result = Encode(QStringRef(&r->d()->d->data).trimmed().isEmpty());
}
-ReturnedValue Text::method_wholeText(CallContext *ctx)
+void Text::method_wholeText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- return QV4::Encode(scope.engine->newString(r->d()->d->data));
+ scope.result = scope.engine->newString(r->d()->d->data);
}
ReturnedValue Text::prototype(ExecutionEngine *v4)
@@ -964,44 +952,40 @@ ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data)
return (v4->memoryManager->allocObject<NodeList>(data))->asReturnedValue();
}
-ReturnedValue Document::method_documentElement(CallContext *ctx)
+void Document::method_documentElement(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r || r->d()->d->type != NodeImpl::Document)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- return Node::create(scope.engine, static_cast<DocumentImpl *>(r->d()->d)->root);
+ scope.result = Node::create(scope.engine, static_cast<DocumentImpl *>(r->d()->d)->root);
}
-ReturnedValue Document::method_xmlStandalone(CallContext *ctx)
+void Document::method_xmlStandalone(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r || r->d()->d->type != NodeImpl::Document)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- return Encode(static_cast<DocumentImpl *>(r->d()->d)->isStandalone);
+ scope.result = Encode(static_cast<DocumentImpl *>(r->d()->d)->isStandalone);
}
-ReturnedValue Document::method_xmlVersion(CallContext *ctx)
+void Document::method_xmlVersion(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r || r->d()->d->type != NodeImpl::Document)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- return QV4::Encode(scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->version));
+ scope.result = scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->version);
}
-ReturnedValue Document::method_xmlEncoding(CallContext *ctx)
+void Document::method_xmlEncoding(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<Node> r(scope, ctx->thisObject().as<Node>());
+ Scoped<Node> r(scope, callData->thisObject.as<Node>());
if (!r || r->d()->d->type != NodeImpl::Document)
- return Encode::undefined();
+ RETURN_UNDEFINED();
- return QV4::Encode(scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->encoding));
+ scope.result = scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->encoding);
}
class QQmlXMLHttpRequest : public QObject
@@ -1657,21 +1641,21 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
void setupProto();
- static ReturnedValue method_open(CallContext *ctx);
- static ReturnedValue method_setRequestHeader(CallContext *ctx);
- static ReturnedValue method_send(CallContext *ctx);
- static ReturnedValue method_abort(CallContext *ctx);
- static ReturnedValue method_getResponseHeader(CallContext *ctx);
- static ReturnedValue method_getAllResponseHeaders(CallContext *ctx);
-
- static ReturnedValue method_get_readyState(CallContext *ctx);
- static ReturnedValue method_get_status(CallContext *ctx);
- static ReturnedValue method_get_statusText(CallContext *ctx);
- static ReturnedValue method_get_responseText(CallContext *ctx);
- static ReturnedValue method_get_responseXML(CallContext *ctx);
- static ReturnedValue method_get_response(CallContext *ctx);
- static ReturnedValue method_get_responseType(CallContext *ctx);
- static ReturnedValue method_set_responseType(CallContext *ctx);
+ static void method_open(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_setRequestHeader(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_send(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_abort(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_getResponseHeader(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_getAllResponseHeaders(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+
+ static void method_get_readyState(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_status(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_statusText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_responseText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_responseXML(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_response(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_responseType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_responseType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
};
}
@@ -1733,19 +1717,18 @@ void QQmlXMLHttpRequestCtor::setupProto()
// XMLHttpRequest methods
-ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_open(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- if (ctx->argc() < 2 || ctx->argc() > 5)
- V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
+ if (callData->argc < 2 || callData->argc > 5)
+ THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
// Argument 0 - Method
- QString method = ctx->args()[0].toQStringNoThrow().toUpper();
+ QString method = callData->args[0].toQStringNoThrow().toUpper();
if (method != QLatin1String("GET") &&
method != QLatin1String("PUT") &&
method != QLatin1String("HEAD") &&
@@ -1754,26 +1737,26 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
method != QLatin1String("OPTIONS") &&
method != QLatin1String("PROPFIND") &&
method != QLatin1String("PATCH"))
- V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
+ THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
- QUrl url = QUrl(ctx->args()[1].toQStringNoThrow());
+ QUrl url = QUrl(callData->args[1].toQStringNoThrow());
if (url.isRelative())
url = scope.engine->callingQmlContext()->resolvedUrl(url);
bool async = true;
// Argument 2 - async (optional)
- if (ctx->argc() > 2) {
- async = ctx->args()[2].booleanValue();
+ if (callData->argc > 2) {
+ async = callData->args[2].booleanValue();
}
// Argument 3/4 - user/pass (optional)
QString username, password;
- if (ctx->argc() > 3)
- username = ctx->args()[3].toQStringNoThrow();
- if (ctx->argc() > 4)
- password = ctx->args()[4].toQStringNoThrow();
+ if (callData->argc > 3)
+ username = callData->args[3].toQStringNoThrow();
+ if (callData->argc > 4)
+ password = callData->args[4].toQStringNoThrow();
// Clear the fragment (if any)
url.setFragment(QString());
@@ -1782,25 +1765,24 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
if (!username.isNull()) url.setUserName(username);
if (!password.isNull()) url.setPassword(password);
- return r->open(w, scope.engine->callingQmlContext(), method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad);
+ scope.result = r->open(w, scope.engine->callingQmlContext(), method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad);
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_setRequestHeader(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- if (ctx->argc() != 2)
- V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
+ if (callData->argc != 2)
+ THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
if (r->readyState() != QQmlXMLHttpRequest::Opened || r->sendFlag())
- V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
+ THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
- QString name = ctx->args()[0].toQStringNoThrow();
- QString value = ctx->args()[1].toQStringNoThrow();
+ QString name = callData->args[0].toQStringNoThrow();
+ QString value = callData->args[1].toQStringNoThrow();
// ### Check that name and value are well formed
@@ -1825,148 +1807,139 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx)
nameUpper == QLatin1String("VIA") ||
nameUpper.startsWith(QLatin1String("PROXY-")) ||
nameUpper.startsWith(QLatin1String("SEC-")))
- return Encode::undefined();
+ RETURN_UNDEFINED();
r->addHeader(name, value);
- return Encode::undefined();
+ RETURN_UNDEFINED();
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_send(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_send(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
if (r->readyState() != QQmlXMLHttpRequest::Opened ||
r->sendFlag())
- V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
+ THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
QByteArray data;
- if (ctx->argc() > 0)
- data = ctx->args()[0].toQStringNoThrow().toUtf8();
+ if (callData->argc > 0)
+ data = callData->args[0].toQStringNoThrow().toUtf8();
- return r->send(w, scope.engine->callingQmlContext(), data);
+ scope.result = r->send(w, scope.engine->callingQmlContext(), data);
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_abort(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- return r->abort(w, scope.engine->callingQmlContext());
+ scope.result = r->abort(w, scope.engine->callingQmlContext());
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_getResponseHeader(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- if (ctx->argc() != 1)
- V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
+ if (callData->argc != 1)
+ THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
if (r->readyState() != QQmlXMLHttpRequest::Loading &&
r->readyState() != QQmlXMLHttpRequest::Done &&
r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
- V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
+ THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
- return QV4::Encode(scope.engine->newString(r->header(ctx->args()[0].toQStringNoThrow())));
+ scope.result = scope.engine->newString(r->header(callData->args[0].toQStringNoThrow()));
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- if (ctx->argc() != 0)
- V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
+ if (callData->argc != 0)
+ THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
if (r->readyState() != QQmlXMLHttpRequest::Loading &&
r->readyState() != QQmlXMLHttpRequest::Done &&
r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
- V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
+ THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
- return QV4::Encode(scope.engine->newString(r->headers()));
+ scope.result = scope.engine->newString(r->headers());
}
// XMLHttpRequest properties
-ReturnedValue QQmlXMLHttpRequestCtor::method_get_readyState(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_get_readyState(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- return Encode(r->readyState());
+ scope.result = Encode(r->readyState());
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_get_status(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_get_status(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
r->readyState() == QQmlXMLHttpRequest::Opened)
- V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
+ THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
if (r->errorFlag())
- return Encode(0);
+ scope.result = Encode(0);
else
- return Encode(r->replyStatus());
+ scope.result = Encode(r->replyStatus());
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_get_statusText(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_get_statusText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
r->readyState() == QQmlXMLHttpRequest::Opened)
- V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
+ THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
if (r->errorFlag())
- return QV4::Encode(scope.engine->newString(QString()));
+ scope.result = scope.engine->newString(QString());
else
- return QV4::Encode(scope.engine->newString(r->replyStatusText()));
+ scope.result = scope.engine->newString(r->replyStatusText());
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseText(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_get_responseText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
if (r->readyState() != QQmlXMLHttpRequest::Loading &&
r->readyState() != QQmlXMLHttpRequest::Done)
- return QV4::Encode(scope.engine->newString(QString()));
+ scope.result = scope.engine->newString(QString());
else
- return QV4::Encode(scope.engine->newString(r->responseBody()));
+ scope.result = scope.engine->newString(r->responseBody());
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_get_responseXML(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
@@ -1974,66 +1947,63 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx)
if (!r->receivedXml() ||
(r->readyState() != QQmlXMLHttpRequest::Loading &&
r->readyState() != QQmlXMLHttpRequest::Done)) {
- return Encode::null();
+ scope.result = Encode::null();
} else {
if (r->responseType().isEmpty())
r->setResponseType(QLatin1String("document"));
- return r->xmlResponseBody(scope.engine);
+ scope.result = r->xmlResponseBody(scope.engine);
}
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_get_response(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
if (r->readyState() != QQmlXMLHttpRequest::Loading &&
r->readyState() != QQmlXMLHttpRequest::Done)
- return QV4::Encode(scope.engine->newString(QString()));
+ RETURN_RESULT(scope.engine->newString(QString()));
const QString& responseType = r->responseType();
if (responseType.compare(QLatin1String("text"), Qt::CaseInsensitive) == 0 || responseType.isEmpty()) {
- return QV4::Encode(scope.engine->newString(r->responseBody()));
+ RETURN_RESULT(scope.engine->newString(r->responseBody()));
} else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) {
- return QV4::Encode(scope.engine->newArrayBuffer(r->rawResponseBody()));
+ RETURN_RESULT(scope.engine->newArrayBuffer(r->rawResponseBody()));
} else if (responseType.compare(QLatin1String("json"), Qt::CaseInsensitive) == 0) {
- return r->jsonResponseBody(scope.engine);
+ RETURN_RESULT(r->jsonResponseBody(scope.engine));
} else if (responseType.compare(QLatin1String("document"), Qt::CaseInsensitive) == 0) {
- return r->xmlResponseBody(scope.engine);
+ RETURN_RESULT(r->xmlResponseBody(scope.engine));
} else {
- return QV4::Encode(scope.engine->newString(QString()));
+ RETURN_RESULT(scope.engine->newString(QString()));
}
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseType(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_get_responseType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- return QV4::Encode(scope.engine->newString(r->responseType()));
+ scope.result = scope.engine->newString(r->responseType());
}
-ReturnedValue QQmlXMLHttpRequestCtor::method_set_responseType(CallContext *ctx)
+void QQmlXMLHttpRequestCtor::method_set_responseType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->thisObject().as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- if (ctx->argc() < 1)
- V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
+ if (callData->argc < 1)
+ THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
// Argument 0 - response type
- r->setResponseType(ctx->args()[0].toQStringNoThrow());
+ r->setResponseType(callData->args[0].toQStringNoThrow());
- return Encode::undefined();
+ scope.result = Encode::undefined();
}
void qt_rem_qmlxmlhttprequest(ExecutionEngine * /* engine */, void *d)
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 19dc100f40..d359a0f62f 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -85,6 +85,12 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QtObject);
+#define THROW_TYPE_ERROR_WITH_MESSAGE(msg) \
+ do { \
+ scope.result = scope.engine->throwTypeError(QString::fromUtf8(msg)); \
+ return; \
+ } while (false)
+
struct StaticQtMetaObject : public QObject
{
static const QMetaObject *get()
@@ -223,12 +229,12 @@ void QtObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint
\qmlmethod bool Qt::isQtObject(object)
Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
*/
-ReturnedValue QtObject::method_isQtObject(QV4::CallContext *ctx)
+void QtObject::method_isQtObject(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() == 0)
- return QV4::Encode(false);
+ if (callData->argc == 0)
+ RETURN_RESULT(QV4::Encode(false));
- return QV4::Encode(ctx->args()[0].as<QV4::QObjectWrapper>() != 0);
+ scope.result = QV4::Encode(callData->args[0].as<QV4::QObjectWrapper>() != 0);
}
/*!
@@ -237,16 +243,16 @@ ReturnedValue QtObject::method_isQtObject(QV4::CallContext *ctx)
Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
All components should be in the range 0-1 inclusive.
*/
-ReturnedValue QtObject::method_rgba(QV4::CallContext *ctx)
+void QtObject::method_rgba(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- int argCount = ctx->argc();
+ int argCount = callData->argc;
if (argCount < 3 || argCount > 4)
- V4THROW_ERROR("Qt.rgba(): Invalid arguments");
+ THROW_GENERIC_ERROR("Qt.rgba(): Invalid arguments");
- double r = ctx->args()[0].toNumber();
- double g = ctx->args()[1].toNumber();
- double b = ctx->args()[2].toNumber();
- double a = (argCount == 4) ? ctx->args()[3].toNumber() : 1;
+ double r = callData->args[0].toNumber();
+ double g = callData->args[1].toNumber();
+ double b = callData->args[2].toNumber();
+ double a = (argCount == 4) ? callData->args[3].toNumber() : 1;
if (r < 0.0) r=0.0;
if (r > 1.0) r=1.0;
@@ -257,7 +263,7 @@ ReturnedValue QtObject::method_rgba(QV4::CallContext *ctx)
if (a < 0.0) a=0.0;
if (a > 1.0) a=1.0;
- return ctx->engine()->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a));
+ scope.result = scope.engine->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a));
}
/*!
@@ -266,16 +272,16 @@ ReturnedValue QtObject::method_rgba(QV4::CallContext *ctx)
Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
All components should be in the range 0-1 inclusive.
*/
-ReturnedValue QtObject::method_hsla(QV4::CallContext *ctx)
+void QtObject::method_hsla(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- int argCount = ctx->argc();
+ int argCount = callData->argc;
if (argCount < 3 || argCount > 4)
- V4THROW_ERROR("Qt.hsla(): Invalid arguments");
+ THROW_GENERIC_ERROR("Qt.hsla(): Invalid arguments");
- double h = ctx->args()[0].toNumber();
- double s = ctx->args()[1].toNumber();
- double l = ctx->args()[2].toNumber();
- double a = (argCount == 4) ? ctx->args()[3].toNumber() : 1;
+ double h = callData->args[0].toNumber();
+ double s = callData->args[1].toNumber();
+ double l = callData->args[2].toNumber();
+ double a = (argCount == 4) ? callData->args[3].toNumber() : 1;
if (h < 0.0) h=0.0;
if (h > 1.0) h=1.0;
@@ -286,7 +292,7 @@ ReturnedValue QtObject::method_hsla(QV4::CallContext *ctx)
if (a < 0.0) a=0.0;
if (a > 1.0) a=1.0;
- return ctx->engine()->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a));
+ scope.result = scope.engine->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a));
}
/*!
@@ -297,23 +303,23 @@ All components should be in the range 0-1 inclusive.
\since 5.5
*/
-ReturnedValue QtObject::method_hsva(QV4::CallContext *ctx)
+void QtObject::method_hsva(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- int argCount = ctx->argc();
+ int argCount = callData->argc;
if (argCount < 3 || argCount > 4)
- V4THROW_ERROR("Qt.hsva(): Invalid arguments");
+ THROW_GENERIC_ERROR("Qt.hsva(): Invalid arguments");
- double h = ctx->args()[0].toNumber();
- double s = ctx->args()[1].toNumber();
- double v = ctx->args()[2].toNumber();
- double a = (argCount == 4) ? ctx->args()[3].toNumber() : 1;
+ double h = callData->args[0].toNumber();
+ double s = callData->args[1].toNumber();
+ double v = callData->args[2].toNumber();
+ double a = (argCount == 4) ? callData->args[3].toNumber() : 1;
h = qBound(0.0, h, 1.0);
s = qBound(0.0, s, 1.0);
v = qBound(0.0, v, 1.0);
a = qBound(0.0, a, 1.0);
- return ctx->engine()->fromVariant(QQml_colorProvider()->fromHsvF(h, s, v, a));
+ scope.result = scope.engine->fromVariant(QQml_colorProvider()->fromHsvF(h, s, v, a));
}
/*!
@@ -324,35 +330,35 @@ may be either color values or string values. If a string value is supplied it
must be convertible to a color, as described for the \l{colorbasictypedocs}{color}
basic type.
*/
-ReturnedValue QtObject::method_colorEqual(QV4::CallContext *ctx)
+void QtObject::method_colorEqual(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 2)
- V4THROW_ERROR("Qt.colorEqual(): Invalid arguments");
+ if (callData->argc != 2)
+ THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments");
bool ok = false;
- QVariant lhs = ctx->d()->engine->toVariant(ctx->args()[0], -1);
+ QVariant lhs = scope.engine->toVariant(callData->args[0], -1);
if (lhs.userType() == QVariant::String) {
lhs = QQmlStringConverters::colorFromString(lhs.toString(), &ok);
if (!ok) {
- V4THROW_ERROR("Qt.colorEqual(): Invalid color name");
+ THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid color name");
}
} else if (lhs.userType() != QVariant::Color) {
- V4THROW_ERROR("Qt.colorEqual(): Invalid arguments");
+ THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments");
}
- QVariant rhs = ctx->engine()->toVariant(ctx->args()[1], -1);
+ QVariant rhs = scope.engine->toVariant(callData->args[1], -1);
if (rhs.userType() == QVariant::String) {
rhs = QQmlStringConverters::colorFromString(rhs.toString(), &ok);
if (!ok) {
- V4THROW_ERROR("Qt.colorEqual(): Invalid color name");
+ THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid color name");
}
} else if (rhs.userType() != QVariant::Color) {
- V4THROW_ERROR("Qt.colorEqual(): Invalid arguments");
+ THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments");
}
bool equal = (lhs == rhs);
- return QV4::Encode(equal);
+ scope.result = QV4::Encode(equal);
}
/*!
@@ -362,47 +368,47 @@ Returns a \c rect with the top-left corner at \c x, \c y and the specified \c wi
The returned object has \c x, \c y, \c width and \c height attributes with the given values.
*/
-ReturnedValue QtObject::method_rect(QV4::CallContext *ctx)
+void QtObject::method_rect(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 4)
- V4THROW_ERROR("Qt.rect(): Invalid arguments");
+ if (callData->argc != 4)
+ THROW_GENERIC_ERROR("Qt.rect(): Invalid arguments");
- double x = ctx->args()[0].toNumber();
- double y = ctx->args()[1].toNumber();
- double w = ctx->args()[2].toNumber();
- double h = ctx->args()[3].toNumber();
+ double x = callData->args[0].toNumber();
+ double y = callData->args[1].toNumber();
+ double w = callData->args[2].toNumber();
+ double h = callData->args[3].toNumber();
- return ctx->engine()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
+ scope.result = scope.engine->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
}
/*!
\qmlmethod point Qt::point(int x, int y)
Returns a Point with the specified \c x and \c y coordinates.
*/
-ReturnedValue QtObject::method_point(QV4::CallContext *ctx)
+void QtObject::method_point(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 2)
- V4THROW_ERROR("Qt.point(): Invalid arguments");
+ if (callData->argc != 2)
+ THROW_GENERIC_ERROR("Qt.point(): Invalid arguments");
- double x = ctx->args()[0].toNumber();
- double y = ctx->args()[1].toNumber();
+ double x = callData->args[0].toNumber();
+ double y = callData->args[1].toNumber();
- return ctx->engine()->fromVariant(QVariant::fromValue(QPointF(x, y)));
+ scope.result = scope.engine->fromVariant(QVariant::fromValue(QPointF(x, y)));
}
/*!
\qmlmethod Qt::size(int width, int height)
Returns a Size with the specified \c width and \c height.
*/
-ReturnedValue QtObject::method_size(QV4::CallContext *ctx)
+void QtObject::method_size(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 2)
- V4THROW_ERROR("Qt.size(): Invalid arguments");
+ if (callData->argc != 2)
+ THROW_GENERIC_ERROR("Qt.size(): Invalid arguments");
- double w = ctx->args()[0].toNumber();
- double h = ctx->args()[1].toNumber();
+ double w = callData->args[0].toNumber();
+ double h = callData->args[1].toNumber();
- return ctx->engine()->fromVariant(QVariant::fromValue(QSizeF(w, h)));
+ scope.result = scope.engine->fromVariant(QVariant::fromValue(QSizeF(w, h)));
}
/*!
@@ -413,17 +419,17 @@ key-value pairs where valid keys are the \l{fontbasictypedocs}{font} type's
subproperty names, and the values are valid values for each subproperty.
Invalid keys will be ignored.
*/
-ReturnedValue QtObject::method_font(QV4::CallContext *ctx)
+void QtObject::method_font(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1 || !ctx->args()[0].isObject())
- V4THROW_ERROR("Qt.font(): Invalid arguments");
+ if (callData->argc != 1 || !callData->args[0].isObject())
+ THROW_GENERIC_ERROR("Qt.font(): Invalid arguments");
- QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ QV4::ExecutionEngine *v4 = scope.engine;
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(ctx->args()[0]), v4, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(callData->args[0]), v4, &ok);
if (!ok)
- V4THROW_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified");
- return ctx->engine()->fromVariant(v);
+ THROW_GENERIC_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified");
+ scope.result = scope.engine->fromVariant(v);
}
@@ -432,73 +438,73 @@ ReturnedValue QtObject::method_font(QV4::CallContext *ctx)
\qmlmethod Qt::vector2d(real x, real y)
Returns a Vector2D with the specified \c x and \c y.
*/
-ReturnedValue QtObject::method_vector2d(QV4::CallContext *ctx)
+void QtObject::method_vector2d(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 2)
- V4THROW_ERROR("Qt.vector2d(): Invalid arguments");
+ if (callData->argc != 2)
+ THROW_GENERIC_ERROR("Qt.vector2d(): Invalid arguments");
float xy[3]; // qvector2d uses float internally
- xy[0] = ctx->args()[0].toNumber();
- xy[1] = ctx->args()[1].toNumber();
+ xy[0] = callData->args[0].toNumber();
+ xy[1] = callData->args[1].toNumber();
const void *params[] = { xy };
- return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params));
+ scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params));
}
/*!
\qmlmethod Qt::vector3d(real x, real y, real z)
Returns a Vector3D with the specified \c x, \c y and \c z.
*/
-ReturnedValue QtObject::method_vector3d(QV4::CallContext *ctx)
+void QtObject::method_vector3d(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 3)
- V4THROW_ERROR("Qt.vector3d(): Invalid arguments");
+ if (callData->argc != 3)
+ THROW_GENERIC_ERROR("Qt.vector3d(): Invalid arguments");
float xyz[3]; // qvector3d uses float internally
- xyz[0] = ctx->args()[0].toNumber();
- xyz[1] = ctx->args()[1].toNumber();
- xyz[2] = ctx->args()[2].toNumber();
+ xyz[0] = callData->args[0].toNumber();
+ xyz[1] = callData->args[1].toNumber();
+ xyz[2] = callData->args[2].toNumber();
const void *params[] = { xyz };
- return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params));
+ scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params));
}
/*!
\qmlmethod Qt::vector4d(real x, real y, real z, real w)
Returns a Vector4D with the specified \c x, \c y, \c z and \c w.
*/
-ReturnedValue QtObject::method_vector4d(QV4::CallContext *ctx)
+void QtObject::method_vector4d(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 4)
- V4THROW_ERROR("Qt.vector4d(): Invalid arguments");
+ if (callData->argc != 4)
+ THROW_GENERIC_ERROR("Qt.vector4d(): Invalid arguments");
float xyzw[4]; // qvector4d uses float internally
- xyzw[0] = ctx->args()[0].toNumber();
- xyzw[1] = ctx->args()[1].toNumber();
- xyzw[2] = ctx->args()[2].toNumber();
- xyzw[3] = ctx->args()[3].toNumber();
+ xyzw[0] = callData->args[0].toNumber();
+ xyzw[1] = callData->args[1].toNumber();
+ xyzw[2] = callData->args[2].toNumber();
+ xyzw[3] = callData->args[3].toNumber();
const void *params[] = { xyzw };
- return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params));
+ scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params));
}
/*!
\qmlmethod Qt::quaternion(real scalar, real x, real y, real z)
Returns a Quaternion with the specified \c scalar, \c x, \c y, and \c z.
*/
-ReturnedValue QtObject::method_quaternion(QV4::CallContext *ctx)
+void QtObject::method_quaternion(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 4)
- V4THROW_ERROR("Qt.quaternion(): Invalid arguments");
+ if (callData->argc != 4)
+ THROW_GENERIC_ERROR("Qt.quaternion(): Invalid arguments");
qreal sxyz[4]; // qquaternion uses qreal internally
- sxyz[0] = ctx->args()[0].toNumber();
- sxyz[1] = ctx->args()[1].toNumber();
- sxyz[2] = ctx->args()[2].toNumber();
- sxyz[3] = ctx->args()[3].toNumber();
+ sxyz[0] = callData->args[0].toNumber();
+ sxyz[1] = callData->args[1].toNumber();
+ sxyz[2] = callData->args[2].toNumber();
+ sxyz[3] = callData->args[3].toNumber();
const void *params[] = { sxyz };
- return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params));
+ scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params));
}
/*!
@@ -510,44 +516,47 @@ matrix values.
Finally, the function may be called with no arguments and the resulting
matrix will be the identity matrix.
*/
-ReturnedValue QtObject::method_matrix4x4(QV4::CallContext *ctx)
+void QtObject::method_matrix4x4(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ QV4::ExecutionEngine *v4 = scope.engine;
- if (ctx->argc() == 0)
- return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, Q_NULLPTR));
+ if (callData->argc == 0) {
+ scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, Q_NULLPTR));
+ return;
+ }
- if (ctx->argc() == 1 && ctx->args()[0].isObject()) {
+ if (callData->argc == 1 && callData->args[0].isObject()) {
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(ctx->args()[0]), v4, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(callData->args[0]), v4, &ok);
if (!ok)
- V4THROW_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array");
- return ctx->engine()->fromVariant(v);
+ THROW_GENERIC_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array");
+ scope.result = scope.engine->fromVariant(v);
+ return;
}
- if (ctx->argc() != 16)
- V4THROW_ERROR("Qt.matrix4x4(): Invalid arguments");
+ if (callData->argc != 16)
+ THROW_GENERIC_ERROR("Qt.matrix4x4(): Invalid arguments");
qreal vals[16]; // qmatrix4x4 uses qreal internally
- vals[0] = ctx->args()[0].toNumber();
- vals[1] = ctx->args()[1].toNumber();
- vals[2] = ctx->args()[2].toNumber();
- vals[3] = ctx->args()[3].toNumber();
- vals[4] = ctx->args()[4].toNumber();
- vals[5] = ctx->args()[5].toNumber();
- vals[6] = ctx->args()[6].toNumber();
- vals[7] = ctx->args()[7].toNumber();
- vals[8] = ctx->args()[8].toNumber();
- vals[9] = ctx->args()[9].toNumber();
- vals[10] = ctx->args()[10].toNumber();
- vals[11] = ctx->args()[11].toNumber();
- vals[12] = ctx->args()[12].toNumber();
- vals[13] = ctx->args()[13].toNumber();
- vals[14] = ctx->args()[14].toNumber();
- vals[15] = ctx->args()[15].toNumber();
+ vals[0] = callData->args[0].toNumber();
+ vals[1] = callData->args[1].toNumber();
+ vals[2] = callData->args[2].toNumber();
+ vals[3] = callData->args[3].toNumber();
+ vals[4] = callData->args[4].toNumber();
+ vals[5] = callData->args[5].toNumber();
+ vals[6] = callData->args[6].toNumber();
+ vals[7] = callData->args[7].toNumber();
+ vals[8] = callData->args[8].toNumber();
+ vals[9] = callData->args[9].toNumber();
+ vals[10] = callData->args[10].toNumber();
+ vals[11] = callData->args[11].toNumber();
+ vals[12] = callData->args[12].toNumber();
+ vals[13] = callData->args[13].toNumber();
+ vals[14] = callData->args[14].toNumber();
+ vals[15] = callData->args[15].toNumber();
const void *params[] = { vals };
- return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params));
+ scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params));
}
/*!
@@ -564,27 +573,29 @@ by factor and converts the color back to RGB.
If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
*/
-ReturnedValue QtObject::method_lighter(QV4::CallContext *ctx)
+void QtObject::method_lighter(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1 && ctx->argc() != 2)
- V4THROW_ERROR("Qt.lighter(): Invalid arguments");
+ if (callData->argc != 1 && callData->argc != 2)
+ THROW_GENERIC_ERROR("Qt.lighter(): Invalid arguments");
- QVariant v = ctx->engine()->toVariant(ctx->args()[0], -1);
+ QVariant v = scope.engine->toVariant(callData->args[0], -1);
if (v.userType() == QVariant::String) {
bool ok = false;
v = QQmlStringConverters::colorFromString(v.toString(), &ok);
if (!ok) {
- return QV4::Encode::null();
+ scope.result = QV4::Encode::null();
+ return;
}
} else if (v.userType() != QVariant::Color) {
- return QV4::Encode::null();
+ scope.result = QV4::Encode::null();
+ return;
}
qreal factor = 1.5;
- if (ctx->argc() == 2)
- factor = ctx->args()[1].toNumber();
+ if (callData->argc == 2)
+ factor = callData->args[1].toNumber();
- return ctx->engine()->fromVariant(QQml_colorProvider()->lighter(v, factor));
+ scope.result = scope.engine->fromVariant(QQml_colorProvider()->lighter(v, factor));
}
/*!
@@ -602,27 +613,29 @@ by factor and converts the color back to RGB.
If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
*/
-ReturnedValue QtObject::method_darker(QV4::CallContext *ctx)
+void QtObject::method_darker(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1 && ctx->argc() != 2)
- V4THROW_ERROR("Qt.darker(): Invalid arguments");
+ if (callData->argc != 1 && callData->argc != 2)
+ THROW_GENERIC_ERROR("Qt.darker(): Invalid arguments");
- QVariant v = ctx->engine()->toVariant(ctx->args()[0], -1);
+ QVariant v = scope.engine->toVariant(callData->args[0], -1);
if (v.userType() == QVariant::String) {
bool ok = false;
v = QQmlStringConverters::colorFromString(v.toString(), &ok);
if (!ok) {
- return QV4::Encode::null();
+ scope.result = QV4::Encode::null();
+ return;
}
} else if (v.userType() != QVariant::Color) {
- return QV4::Encode::null();
+ scope.result = QV4::Encode::null();
+ return;
}
qreal factor = 2.0;
- if (ctx->argc() == 2)
- factor = ctx->args()[1].toNumber();
+ if (callData->argc == 2)
+ factor = callData->args[1].toNumber();
- return ctx->engine()->fromVariant(QQml_colorProvider()->darker(v, factor));
+ scope.result = scope.engine->fromVariant(QQml_colorProvider()->darker(v, factor));
}
/*!
@@ -649,36 +662,40 @@ ReturnedValue QtObject::method_darker(QV4::CallContext *ctx)
Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
*/
-ReturnedValue QtObject::method_tint(QV4::CallContext *ctx)
+void QtObject::method_tint(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 2)
- V4THROW_ERROR("Qt.tint(): Invalid arguments");
+ if (callData->argc != 2)
+ THROW_GENERIC_ERROR("Qt.tint(): Invalid arguments");
// base color
- QVariant v1 = ctx->engine()->toVariant(ctx->args()[0], -1);
+ QVariant v1 = scope.engine->toVariant(callData->args[0], -1);
if (v1.userType() == QVariant::String) {
bool ok = false;
v1 = QQmlStringConverters::colorFromString(v1.toString(), &ok);
if (!ok) {
- return QV4::Encode::null();
+ scope.result = QV4::Encode::null();
+ return;
}
} else if (v1.userType() != QVariant::Color) {
- return QV4::Encode::null();
+ scope.result = QV4::Encode::null();
+ return;
}
// tint color
- QVariant v2 = ctx->engine()->toVariant(ctx->args()[1], -1);
+ QVariant v2 = scope.engine->toVariant(callData->args[1], -1);
if (v2.userType() == QVariant::String) {
bool ok = false;
v2 = QQmlStringConverters::colorFromString(v2.toString(), &ok);
if (!ok) {
- return QV4::Encode::null();
+ scope.result = QV4::Encode::null();
+ return;
}
} else if (v2.userType() != QVariant::Color) {
- return QV4::Encode::null();
+ scope.result = QV4::Encode::null();
+ return;
}
- return ctx->engine()->fromVariant(QQml_colorProvider()->tint(v1, v2));
+ scope.result = scope.engine->fromVariant(QQml_colorProvider()->tint(v1, v2));
}
/*!
@@ -697,32 +714,31 @@ If \a format is not specified, \a date is formatted using
\sa Locale
*/
-ReturnedValue QtObject::method_formatDate(QV4::CallContext *ctx)
+void QtObject::method_formatDate(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 1 || ctx->argc() > 2)
- V4THROW_ERROR("Qt.formatDate(): Invalid arguments");
- QV4::Scope scope(ctx);
+ if (callData->argc < 1 || callData->argc > 2)
+ THROW_GENERIC_ERROR("Qt.formatDate(): Invalid arguments");
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- QDate date = ctx->engine()->toVariant(ctx->args()[0], -1).toDateTime().date();
+ QDate date = scope.engine->toVariant(callData->args[0], -1).toDateTime().date();
QString formattedDate;
- if (ctx->argc() == 2) {
- QV4::ScopedString s(scope, ctx->args()[1]);
+ if (callData->argc == 2) {
+ QV4::ScopedString s(scope, callData->args[1]);
if (s) {
QString format = s->toQString();
formattedDate = date.toString(format);
- } else if (ctx->args()[1].isNumber()) {
- quint32 intFormat = ctx->args()[1].asDouble();
+ } else if (callData->args[1].isNumber()) {
+ quint32 intFormat = callData->args[1].asDouble();
Qt::DateFormat format = Qt::DateFormat(intFormat);
formattedDate = date.toString(format);
} else {
- V4THROW_ERROR("Qt.formatDate(): Invalid date format");
+ THROW_GENERIC_ERROR("Qt.formatDate(): Invalid date format");
}
} else {
formattedDate = date.toString(enumFormat);
}
- return ctx->d()->engine->newString(formattedDate)->asReturnedValue();
+ scope.result = scope.engine->newString(formattedDate);
}
/*!
@@ -740,38 +756,37 @@ If \a format is not specified, \a time is formatted using
\sa Locale
*/
-ReturnedValue QtObject::method_formatTime(QV4::CallContext *ctx)
+void QtObject::method_formatTime(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 1 || ctx->argc() > 2)
- V4THROW_ERROR("Qt.formatTime(): Invalid arguments");
- QV4::Scope scope(ctx);
+ if (callData->argc < 1 || callData->argc > 2)
+ THROW_GENERIC_ERROR("Qt.formatTime(): Invalid arguments");
- QVariant argVariant = ctx->engine()->toVariant(ctx->args()[0], -1);
+ QVariant argVariant = scope.engine->toVariant(callData->args[0], -1);
QTime time;
- if (ctx->args()[0].as<DateObject>() || (argVariant.type() == QVariant::String))
+ if (callData->args[0].as<DateObject>() || (argVariant.type() == QVariant::String))
time = argVariant.toDateTime().time();
else // if (argVariant.type() == QVariant::Time), or invalid.
time = argVariant.toTime();
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
QString formattedTime;
- if (ctx->argc() == 2) {
- QV4::ScopedString s(scope, ctx->args()[1]);
+ if (callData->argc == 2) {
+ QV4::ScopedString s(scope, callData->args[1]);
if (s) {
QString format = s->toQString();
formattedTime = time.toString(format);
- } else if (ctx->args()[1].isNumber()) {
- quint32 intFormat = ctx->args()[1].asDouble();
+ } else if (callData->args[1].isNumber()) {
+ quint32 intFormat = callData->args[1].asDouble();
Qt::DateFormat format = Qt::DateFormat(intFormat);
formattedTime = time.toString(format);
} else {
- V4THROW_ERROR("Qt.formatTime(): Invalid time format");
+ THROW_GENERIC_ERROR("Qt.formatTime(): Invalid time format");
}
} else {
formattedTime = time.toString(enumFormat);
}
- return ctx->d()->engine->newString(formattedTime)->asReturnedValue();
+ scope.result = scope.engine->newString(formattedTime);
}
/*!
@@ -864,32 +879,31 @@ with the \a format values below to produce the following results:
\sa Locale
*/
-ReturnedValue QtObject::method_formatDateTime(QV4::CallContext *ctx)
+void QtObject::method_formatDateTime(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 1 || ctx->argc() > 2)
- V4THROW_ERROR("Qt.formatDateTime(): Invalid arguments");
- QV4::Scope scope(ctx);
+ if (callData->argc < 1 || callData->argc > 2)
+ THROW_GENERIC_ERROR("Qt.formatDateTime(): Invalid arguments");
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- QDateTime dt = ctx->engine()->toVariant(ctx->args()[0], -1).toDateTime();
+ QDateTime dt = scope.engine->toVariant(callData->args[0], -1).toDateTime();
QString formattedDt;
- if (ctx->argc() == 2) {
- QV4::ScopedString s(scope, ctx->args()[1]);
+ if (callData->argc == 2) {
+ QV4::ScopedString s(scope, callData->args[1]);
if (s) {
QString format = s->toQString();
formattedDt = dt.toString(format);
- } else if (ctx->args()[1].isNumber()) {
- quint32 intFormat = ctx->args()[1].asDouble();
+ } else if (callData->args[1].isNumber()) {
+ quint32 intFormat = callData->args[1].asDouble();
Qt::DateFormat format = Qt::DateFormat(intFormat);
formattedDt = dt.toString(format);
} else {
- V4THROW_ERROR("Qt.formatDateTime(): Invalid datetime format");
+ THROW_GENERIC_ERROR("Qt.formatDateTime(): Invalid datetime format");
}
} else {
formattedDt = dt.toString(enumFormat);
}
- return ctx->d()->engine->newString(formattedDt)->asReturnedValue();
+ scope.result = scope.engine->newString(formattedDt);
}
/*!
@@ -903,90 +917,94 @@ ReturnedValue QtObject::method_formatDateTime(QV4::CallContext *ctx)
still fail to launch or fail to open the requested URL. This result will not be reported back
to the application.
*/
-ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx)
+void QtObject::method_openUrlExternally(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1)
- return QV4::Encode(false);
+ if (callData->argc != 1) {
+ scope.result = QV4::Encode(false);
+ return;
+ }
- QUrl url(Value::fromReturnedValue(method_resolvedUrl(ctx)).toQStringNoThrow());
- return ctx->engine()->fromVariant(QQml_guiProvider()->openUrlExternally(url));
+ method_resolvedUrl(b, scope, callData);
+ QUrl url(scope.result.toQStringNoThrow());
+ scope.result = scope.engine->fromVariant(QQml_guiProvider()->openUrlExternally(url));
}
/*!
\qmlmethod url Qt::resolvedUrl(url url)
Returns \a url resolved relative to the URL of the caller.
*/
-ReturnedValue QtObject::method_resolvedUrl(QV4::CallContext *ctx)
+void QtObject::method_resolvedUrl(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- ExecutionEngine *v4 = ctx->engine();
+ ExecutionEngine *v4 = scope.engine;
- QUrl url = v4->toVariant(ctx->args()[0], -1).toUrl();
+ QUrl url = v4->toVariant(callData->args[0], -1).toUrl();
QQmlEngine *e = v4->qmlEngine();
QQmlEnginePrivate *p = 0;
if (e) p = QQmlEnginePrivate::get(e);
if (p) {
QQmlContextData *ctxt = v4->callingQmlContext();
if (ctxt)
- return v4->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue();
+ scope.result = v4->newString(ctxt->resolvedUrl(url).toString());
else
- return v4->newString(url.toString())->asReturnedValue();
+ scope.result = v4->newString(url.toString());
+ return;
}
- return v4->newString(e->baseUrl().resolved(url).toString())->asReturnedValue();
+ scope.result = v4->newString(e->baseUrl().resolved(url).toString());
}
/*!
\qmlmethod list<string> Qt::fontFamilies()
Returns a list of the font families available to the application.
*/
-ReturnedValue QtObject::method_fontFamilies(CallContext *ctx)
+void QtObject::method_fontFamilies(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 0)
- V4THROW_ERROR("Qt.fontFamilies(): Invalid arguments");
+ if (callData->argc != 0)
+ THROW_GENERIC_ERROR("Qt.fontFamilies(): Invalid arguments");
- return ctx->engine()->fromVariant(QVariant(QQml_guiProvider()->fontFamilies()));
+ scope.result = scope.engine->fromVariant(QVariant(QQml_guiProvider()->fontFamilies()));
}
/*!
\qmlmethod string Qt::md5(data)
Returns a hex string of the md5 hash of \c data.
*/
-ReturnedValue QtObject::method_md5(CallContext *ctx)
+void QtObject::method_md5(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1)
- V4THROW_ERROR("Qt.md5(): Invalid arguments");
+ if (callData->argc != 1)
+ THROW_GENERIC_ERROR("Qt.md5(): Invalid arguments");
- QByteArray data = ctx->args()[0].toQStringNoThrow().toUtf8();
+ QByteArray data = callData->args[0].toQStringNoThrow().toUtf8();
QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
- return ctx->d()->engine->newString(QLatin1String(result.toHex()))->asReturnedValue();
+ scope.result = scope.engine->newString(QLatin1String(result.toHex()));
}
/*!
\qmlmethod string Qt::btoa(data)
Binary to ASCII - this function returns a base64 encoding of \c data.
*/
-ReturnedValue QtObject::method_btoa(CallContext *ctx)
+void QtObject::method_btoa(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1)
- V4THROW_ERROR("Qt.btoa(): Invalid arguments");
+ if (callData->argc != 1)
+ THROW_GENERIC_ERROR("Qt.btoa(): Invalid arguments");
- QByteArray data = ctx->args()[0].toQStringNoThrow().toUtf8();
+ QByteArray data = callData->args[0].toQStringNoThrow().toUtf8();
- return ctx->d()->engine->newString(QLatin1String(data.toBase64()))->asReturnedValue();
+ scope.result = scope.engine->newString(QLatin1String(data.toBase64()));
}
/*!
\qmlmethod string Qt::atob(data)
ASCII to binary - this function decodes the base64 encoded \a data string and returns it.
*/
-ReturnedValue QtObject::method_atob(CallContext *ctx)
+void QtObject::method_atob(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1)
- V4THROW_ERROR("Qt.atob(): Invalid arguments");
+ if (callData->argc != 1)
+ THROW_GENERIC_ERROR("Qt.atob(): Invalid arguments");
- QByteArray data = ctx->args()[0].toQStringNoThrow().toLatin1();
+ QByteArray data = callData->args[0].toQStringNoThrow().toLatin1();
- return ctx->d()->engine->newString(QString::fromUtf8(QByteArray::fromBase64(data)))->asReturnedValue();
+ scope.result = scope.engine->newString(QString::fromUtf8(QByteArray::fromBase64(data)));
}
/*!
@@ -998,10 +1016,10 @@ QQmlEngine::quit() signal to the QCoreApplication::quit() slot.
\sa exit()
*/
-ReturnedValue QtObject::method_quit(CallContext *ctx)
+void QtObject::method_quit(const BuiltinFunction *, Scope &scope, CallData *)
{
- QQmlEnginePrivate::get(ctx->engine()->qmlEngine())->sendQuit();
- return QV4::Encode::undefined();
+ QQmlEnginePrivate::get(scope.engine->qmlEngine())->sendQuit();
+ scope.result = Encode::undefined();
}
/*!
@@ -1015,15 +1033,15 @@ ReturnedValue QtObject::method_quit(CallContext *ctx)
\sa quit()
*/
-ReturnedValue QtObject::method_exit(CallContext *ctx)
+void QtObject::method_exit(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1)
- V4THROW_ERROR("Qt.exit(): Invalid arguments");
+ if (callData->argc != 1)
+ THROW_GENERIC_ERROR("Qt.exit(): Invalid arguments");
- int retCode = ctx->args()[0].toNumber();
+ int retCode = callData->args[0].toNumber();
- QQmlEnginePrivate::get(ctx->engine()->qmlEngine())->sendExit(retCode);
- return QV4::Encode::undefined();
+ QQmlEnginePrivate::get(scope.engine->qmlEngine())->sendExit(retCode);
+ scope.result = QV4::Encode::undefined();
}
/*!
@@ -1050,11 +1068,10 @@ If this is the case, consider using \l{QtQml::Qt::createComponent()}{Qt.createCo
See \l {Dynamic QML Object Creation from JavaScript} for more information on using this function.
*/
-ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
+void QtObject::method_createQmlObject(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- Scope scope(ctx);
- if (ctx->argc() < 2 || ctx->argc() > 3)
- V4THROW_ERROR("Qt.createQmlObject(): Invalid arguments");
+ if (callData->argc < 2 || callData->argc > 3)
+ THROW_GENERIC_ERROR("Qt.createQmlObject(): Invalid arguments");
struct Error {
static ReturnedValue create(QV4::ExecutionEngine *v4, const QList<QQmlError> &errors) {
@@ -1085,7 +1102,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
}
};
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QV8Engine *v8engine = scope.engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
QQmlContextData *context = scope.engine->callingQmlContext();
@@ -1097,13 +1114,13 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
effectiveContext = context->asQQmlContext();
Q_ASSERT(effectiveContext);
- QString qml = ctx->args()[0].toQStringNoThrow();
+ QString qml = callData->args[0].toQStringNoThrow();
if (qml.isEmpty())
- return QV4::Encode::null();
+ RETURN_RESULT(Encode::null());
QUrl url;
- if (ctx->argc() > 2)
- url = QUrl(ctx->args()[2].toQStringNoThrow());
+ if (callData->argc > 2)
+ url = QUrl(callData->args[2].toQStringNoThrow());
else
url = QUrl(QLatin1String("inline"));
@@ -1111,11 +1128,11 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
url = context->resolvedUrl(url);
QObject *parentArg = 0;
- QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, ctx->args()[1]);
+ QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, callData->args[1]);
if (!!qobjectWrapper)
parentArg = qobjectWrapper->object();
if (!parentArg)
- V4THROW_ERROR("Qt.createQmlObject(): Missing parent object");
+ THROW_GENERIC_ERROR("Qt.createQmlObject(): Missing parent object");
QQmlTypeData *typeData = QQmlEnginePrivate::get(engine)->typeLoader.getType(
qml.toUtf8(), url, QQmlTypeLoader::Synchronous);
@@ -1126,12 +1143,12 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
componentPrivate->progress = 1.0;
if (component.isError()) {
- ScopedValue v(scope, Error::create(ctx->d()->engine, component.errors()));
- return ctx->engine()->throwError(v);
+ ScopedValue v(scope, Error::create(scope.engine, component.errors()));
+ RETURN_RESULT(scope.engine->throwError(v));
}
if (!component.isReady())
- V4THROW_ERROR("Qt.createQmlObject(): Component is not ready");
+ THROW_GENERIC_ERROR("Qt.createQmlObject(): Component is not ready");
QObject *obj = component.beginCreate(effectiveContext);
if (obj) {
@@ -1150,13 +1167,14 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
component.completeCreate();
if (component.isError()) {
- ScopedValue v(scope, Error::create(ctx->d()->engine, component.errors()));
- return ctx->engine()->throwError(v);
+ ScopedValue v(scope, Error::create(scope.engine, component.errors()));
+ scope.result = scope.engine->throwError(v);
+ return;
}
Q_ASSERT(obj);
- return QV4::QObjectWrapper::wrap(ctx->d()->engine, obj);
+ scope.result = QV4::QObjectWrapper::wrap(scope.engine, obj);
}
/*!
@@ -1203,14 +1221,12 @@ See \l {Dynamic QML Object Creation from JavaScript} for more information on usi
To create a QML object from an arbitrary string of QML (instead of a file),
use \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}.
*/
-ReturnedValue QtObject::method_createComponent(CallContext *ctx)
+void QtObject::method_createComponent(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 1 || ctx->argc() > 3)
- return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
+ if (callData->argc < 1 || callData->argc > 3)
+ THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments");
- Scope scope(ctx);
-
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QV8Engine *v8engine = scope.engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
QQmlContextData *context = scope.engine->callingQmlContext();
@@ -1219,41 +1235,41 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
if (context->isPragmaLibraryContext)
effectiveContext = 0;
- QString arg = ctx->args()[0].toQStringNoThrow();
+ QString arg = callData->args[0].toQStringNoThrow();
if (arg.isEmpty())
- return QV4::Encode::null();
+ RETURN_RESULT(QV4::Encode::null());
QQmlComponent::CompilationMode compileMode = QQmlComponent::PreferSynchronous;
QObject *parentArg = 0;
int consumedCount = 1;
- if (ctx->argc() > 1) {
- ScopedValue lastArg(scope, ctx->args()[ctx->argc()-1]);
+ if (callData->argc > 1) {
+ ScopedValue lastArg(scope, callData->args[callData->argc-1]);
// The second argument could be the mode enum
- if (ctx->args()[1].isInteger()) {
- int mode = ctx->args()[1].integerValue();
+ if (callData->args[1].isInteger()) {
+ int mode = callData->args[1].integerValue();
if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous))
- return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
+ THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments");
compileMode = QQmlComponent::CompilationMode(mode);
consumedCount += 1;
} else {
// The second argument could be the parent only if there are exactly two args
- if ((ctx->argc() != 2) || !(lastArg->isObject() || lastArg->isNull()))
- return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
+ if ((callData->argc != 2) || !(lastArg->isObject() || lastArg->isNull()))
+ THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments");
}
- if (consumedCount < ctx->argc()) {
+ if (consumedCount < callData->argc) {
if (lastArg->isObject()) {
Scoped<QObjectWrapper> qobjectWrapper(scope, lastArg);
if (qobjectWrapper)
parentArg = qobjectWrapper->object();
if (!parentArg)
- return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object"));
+ THROW_GENERIC_ERROR("Qt.createComponent(): Invalid parent object");
} else if (lastArg->isNull()) {
parentArg = 0;
} else {
- return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object"));
+ THROW_GENERIC_ERROR("Qt.createComponent(): Invalid parent object");
}
}
}
@@ -1264,7 +1280,7 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
QQmlData::get(c, true)->explicitIndestructibleSet = false;
QQmlData::get(c)->indestructible = false;
- return QV4::QObjectWrapper::wrap(ctx->d()->engine, c);
+ scope.result = QV4::QObjectWrapper::wrap(scope.engine, c);
}
/*!
@@ -1287,18 +1303,18 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
\sa Locale
*/
-ReturnedValue QtObject::method_locale(CallContext *ctx)
+void QtObject::method_locale(const BuiltinFunction *, Scope &scope, CallData *callData)
{
QString code;
- if (ctx->argc() > 1)
- V4THROW_ERROR("locale() requires 0 or 1 argument");
- if (ctx->argc() == 1 && !ctx->args()[0].isString())
- V4THROW_TYPE("locale(): argument (locale code) must be a string");
+ if (callData->argc > 1)
+ THROW_GENERIC_ERROR("locale() requires 0 or 1 argument");
+ if (callData->argc == 1 && !callData->args[0].isString())
+ THROW_TYPE_ERROR_WITH_MESSAGE("locale(): argument (locale code) must be a string");
- if (ctx->argc() == 1)
- code = ctx->args()[0].toQStringNoThrow();
+ if (callData->argc == 1)
+ code = callData->args[0].toQStringNoThrow();
- return QQmlLocale::locale(ctx->engine(), code);
+ scope.result = QQmlLocale::locale(scope.engine, code);
}
void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *originalFunction)
@@ -1360,62 +1376,62 @@ DEFINE_OBJECT_VTABLE(QQmlBindingFunction);
\since 5.0
*/
-ReturnedValue QtObject::method_binding(CallContext *ctx)
+void QtObject::method_binding(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1)
- V4THROW_ERROR("binding() requires 1 argument");
- const QV4::FunctionObject *f = ctx->args()[0].as<FunctionObject>();
+ if (callData->argc != 1)
+ THROW_GENERIC_ERROR("binding() requires 1 argument");
+ const QV4::FunctionObject *f = callData->args[0].as<FunctionObject>();
if (!f)
- V4THROW_TYPE("binding(): argument (binding expression) must be a function");
+ THROW_TYPE_ERROR_WITH_MESSAGE("binding(): argument (binding expression) must be a function");
- return (ctx->d()->engine->memoryManager->allocObject<QQmlBindingFunction>(f))->asReturnedValue();
+ scope.result = scope.engine->memoryManager->allocObject<QQmlBindingFunction>(f);
}
-ReturnedValue QtObject::method_get_platform(CallContext *ctx)
+void QtObject::method_get_platform(const BuiltinFunction *, Scope &scope, CallData *callData)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->thisObject().as<Object>();
+ Object *o = callData->thisObject.as<Object>();
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
QtObject *qt = o->as<QtObject>();
if (!qt)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (!qt->d()->platform)
// Only allocate a platform object once
- qt->d()->platform = new QQmlPlatform(ctx->d()->engine->jsEngine());
+ qt->d()->platform = new QQmlPlatform(scope.engine->jsEngine());
- return QV4::QObjectWrapper::wrap(ctx->d()->engine, qt->d()->platform);
+ scope.result = QV4::QObjectWrapper::wrap(scope.engine, qt->d()->platform);
}
-ReturnedValue QtObject::method_get_application(CallContext *ctx)
+void QtObject::method_get_application(const BuiltinFunction *, Scope &scope, CallData *callData)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->thisObject().as<Object>();
+ Object *o = callData->thisObject.as<Object>();
if (!o)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
QtObject *qt = o->as<QtObject>();
if (!qt)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (!qt->d()->application)
// Only allocate an application object once
- qt->d()->application = QQml_guiProvider()->application(ctx->d()->engine->jsEngine());
+ qt->d()->application = QQml_guiProvider()->application(scope.engine->jsEngine());
- return QV4::QObjectWrapper::wrap(ctx->d()->engine, qt->d()->application);
+ scope.result = QV4::QObjectWrapper::wrap(scope.engine, qt->d()->application);
}
-ReturnedValue QtObject::method_get_inputMethod(CallContext *ctx)
+void QtObject::method_get_inputMethod(const BuiltinFunction *, Scope &scope, CallData *)
{
QObject *o = QQml_guiProvider()->inputMethod();
- return QV4::QObjectWrapper::wrap(ctx->d()->engine, o);
+ scope.result = QV4::QObjectWrapper::wrap(scope.engine, o);
}
-ReturnedValue QtObject::method_get_styleHints(CallContext *ctx)
+void QtObject::method_get_styleHints(const BuiltinFunction *, Scope &scope, CallData *)
{
QObject *o = QQml_guiProvider()->styleHints();
- return QV4::QObjectWrapper::wrap(ctx->d()->engine, o);
+ scope.result = QV4::QObjectWrapper::wrap(scope.engine, o);
}
@@ -1475,35 +1491,35 @@ static QString jsStack(QV4::ExecutionEngine *engine) {
return stack;
}
-static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *ctx,
- bool printStack = false)
+static void writeToConsole(const BuiltinFunction *, Scope &scope, CallData *callData,
+ ConsoleLogTypes logType, bool printStack = false)
{
QLoggingCategory *loggingCategory = 0;
QString result;
- QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ QV4::ExecutionEngine *v4 = scope.engine;
int start = 0;
- if (ctx->argc() > 0) {
- if (const QObjectWrapper* wrapper = ctx->args()[0].as<QObjectWrapper>()) {
+ if (callData->argc > 0) {
+ if (const QObjectWrapper* wrapper = callData->args[0].as<QObjectWrapper>()) {
if (QQmlLoggingCategory* category = qobject_cast<QQmlLoggingCategory*>(wrapper->object())) {
if (category->category())
loggingCategory = category->category();
else
- V4THROW_ERROR("A QmlLoggingCatgory was provided without a valid name");
+ THROW_GENERIC_ERROR("A QmlLoggingCatgory was provided without a valid name");
start = 1;
}
}
}
- for (int i = start; i < ctx->argc(); ++i) {
+ for (int i = start; i < callData->argc; ++i) {
if (i != start)
result.append(QLatin1Char(' '));
- if (ctx->args()[i].as<ArrayObject>())
- result += QLatin1Char('[') + ctx->args()[i].toQStringNoThrow() + QLatin1Char(']');
+ if (callData->args[i].as<ArrayObject>())
+ result += QLatin1Char('[') + callData->args[i].toQStringNoThrow() + QLatin1Char(']');
else
- result.append(ctx->args()[i].toQStringNoThrow());
+ result.append(callData->args[i].toQStringNoThrow());
}
if (printStack)
@@ -1540,32 +1556,32 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c
break;
}
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
DEFINE_OBJECT_VTABLE(ConsoleObject);
-QV4::ReturnedValue ConsoleObject::method_error(CallContext *ctx)
+void ConsoleObject::method_error(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- return writeToConsole(Error, ctx);
+ writeToConsole(b, scope, callData, Error);
}
-QV4::ReturnedValue ConsoleObject::method_log(CallContext *ctx)
+void ConsoleObject::method_log(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
//console.log
//console.debug
//print
- return writeToConsole(Log, ctx);
+ writeToConsole(b, scope, callData, Log);
}
-QV4::ReturnedValue ConsoleObject::method_info(CallContext *ctx)
+void ConsoleObject::method_info(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- return writeToConsole(Info, ctx);
+ writeToConsole(b, scope, callData, Info);
}
-QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
+void ConsoleObject::method_profile(const BuiltinFunction *, Scope &scope, CallData *)
{
- QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ QV4::ExecutionEngine *v4 = scope.engine;
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
@@ -1579,12 +1595,12 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
logger.debug("Profiling started.");
}
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
-QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
+void ConsoleObject::method_profileEnd(const BuiltinFunction *, Scope &scope, CallData *)
{
- QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ QV4::ExecutionEngine *v4 = scope.engine;
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
@@ -1599,46 +1615,46 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
logger.debug("Profiling ended.");
}
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
-QV4::ReturnedValue ConsoleObject::method_time(CallContext *ctx)
+void ConsoleObject::method_time(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1)
- V4THROW_ERROR("console.time(): Invalid arguments");
+ if (callData->argc != 1)
+ THROW_GENERIC_ERROR("console.time(): Invalid arguments");
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QV8Engine *v8engine = scope.engine->v8Engine;
- QString name = ctx->args()[0].toQStringNoThrow();
+ QString name = callData->args[0].toQStringNoThrow();
v8engine->startTimer(name);
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
-QV4::ReturnedValue ConsoleObject::method_timeEnd(CallContext *ctx)
+void ConsoleObject::method_timeEnd(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1)
- V4THROW_ERROR("console.timeEnd(): Invalid arguments");
+ if (callData->argc != 1)
+ THROW_GENERIC_ERROR("console.timeEnd(): Invalid arguments");
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QV8Engine *v8engine = scope.engine->v8Engine;
- QString name = ctx->args()[0].toQStringNoThrow();
+ QString name = callData->args[0].toQStringNoThrow();
bool wasRunning;
qint64 elapsed = v8engine->stopTimer(name, &wasRunning);
if (wasRunning) {
qDebug("%s: %llims", qPrintable(name), elapsed);
}
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
-QV4::ReturnedValue ConsoleObject::method_count(CallContext *ctx)
+void ConsoleObject::method_count(const BuiltinFunction *, Scope &scope, CallData *callData)
{
// first argument: name to print. Ignore any additional arguments
QString name;
- if (ctx->argc() > 0)
- name = ctx->args()[0].toQStringNoThrow();
+ if (callData->argc > 0)
+ name = callData->args[0].toQStringNoThrow();
- QV4::ExecutionEngine *v4 = ctx->d()->engine;
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QV4::ExecutionEngine *v4 = scope.engine;
+ QV8Engine *v8engine = scope.engine->v8Engine;
QV4::StackFrame frame = v4->currentStackFrame();
@@ -1651,15 +1667,15 @@ QV4::ReturnedValue ConsoleObject::method_count(CallContext *ctx)
qPrintable(frame.function))
.debug("%s", qPrintable(message));
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
-QV4::ReturnedValue ConsoleObject::method_trace(CallContext *ctx)
+void ConsoleObject::method_trace(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 0)
- V4THROW_ERROR("console.trace(): Invalid arguments");
+ if (callData->argc != 0)
+ THROW_GENERIC_ERROR("console.trace(): Invalid arguments");
- QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ QV4::ExecutionEngine *v4 = scope.engine;
QString stack = jsStack(v4);
@@ -1668,28 +1684,28 @@ QV4::ReturnedValue ConsoleObject::method_trace(CallContext *ctx)
frame.function.toUtf8().constData())
.debug("%s", qPrintable(stack));
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
-QV4::ReturnedValue ConsoleObject::method_warn(CallContext *ctx)
+void ConsoleObject::method_warn(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- return writeToConsole(Warn, ctx);
+ return writeToConsole(b, scope, callData, Warn);
}
-QV4::ReturnedValue ConsoleObject::method_assert(CallContext *ctx)
+void ConsoleObject::method_assert(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() == 0)
- V4THROW_ERROR("console.assert(): Missing argument");
+ if (callData->argc == 0)
+ THROW_GENERIC_ERROR("console.assert(): Missing argument");
- QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ QV4::ExecutionEngine *v4 = scope.engine;
- if (!ctx->args()[0].toBoolean()) {
+ if (!callData->args[0].toBoolean()) {
QString message;
- for (int i = 1; i < ctx->argc(); ++i) {
+ for (int i = 1; i < callData->argc; ++i) {
if (i != 1)
message.append(QLatin1Char(' '));
- message.append(ctx->args()[i].toQStringNoThrow());
+ message.append(callData->args[i].toQStringNoThrow());
}
QString stack = jsStack(v4);
@@ -1700,17 +1716,17 @@ QV4::ReturnedValue ConsoleObject::method_assert(CallContext *ctx)
.critical("%s\n%s",qPrintable(message), qPrintable(stack));
}
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
-QV4::ReturnedValue ConsoleObject::method_exception(CallContext *ctx)
+void ConsoleObject::method_exception(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- if (ctx->argc() == 0)
- V4THROW_ERROR("console.exception(): Missing argument");
+ if (callData->argc == 0)
+ THROW_GENERIC_ERROR("console.exception(): Missing argument");
- writeToConsole(Error, ctx, true);
+ writeToConsole(b, scope, callData, Error, true);
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
@@ -1766,38 +1782,38 @@ void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions ext
\sa {Internationalization and Localization with Qt Quick}
*/
-ReturnedValue GlobalExtensions::method_qsTranslate(CallContext *ctx)
-{
- if (ctx->argc() < 2)
- V4THROW_ERROR("qsTranslate() requires at least two arguments");
- if (!ctx->args()[0].isString())
- V4THROW_ERROR("qsTranslate(): first argument (context) must be a string");
- if (!ctx->args()[1].isString())
- V4THROW_ERROR("qsTranslate(): second argument (sourceText) must be a string");
- if ((ctx->argc() > 2) && !ctx->args()[2].isString())
- V4THROW_ERROR("qsTranslate(): third argument (disambiguation) must be a string");
-
- QString context = ctx->args()[0].toQStringNoThrow();
- QString text = ctx->args()[1].toQStringNoThrow();
+void GlobalExtensions::method_qsTranslate(const BuiltinFunction *, Scope &scope, CallData *callData)
+{
+ if (callData->argc < 2)
+ THROW_GENERIC_ERROR("qsTranslate() requires at least two arguments");
+ if (!callData->args[0].isString())
+ THROW_GENERIC_ERROR("qsTranslate(): first argument (context) must be a string");
+ if (!callData->args[1].isString())
+ THROW_GENERIC_ERROR("qsTranslate(): second argument (sourceText) must be a string");
+ if ((callData->argc > 2) && !callData->args[2].isString())
+ THROW_GENERIC_ERROR("qsTranslate(): third argument (disambiguation) must be a string");
+
+ QString context = callData->args[0].toQStringNoThrow();
+ QString text = callData->args[1].toQStringNoThrow();
QString comment;
- if (ctx->argc() > 2) comment = ctx->args()[2].toQStringNoThrow();
+ if (callData->argc > 2) comment = callData->args[2].toQStringNoThrow();
int i = 3;
- if (ctx->argc() > i && ctx->args()[i].isString()) {
+ if (callData->argc > i && callData->args[i].isString()) {
qWarning("qsTranslate(): specifying the encoding as fourth argument is deprecated");
++i;
}
int n = -1;
- if (ctx->argc() > i)
- n = ctx->args()[i].toInt32();
+ if (callData->argc > i)
+ n = callData->args[i].toInt32();
QString result = QCoreApplication::translate(context.toUtf8().constData(),
text.toUtf8().constData(),
comment.toUtf8().constData(),
n);
- return ctx->d()->engine->newString(result)->asReturnedValue();
+ scope.result = scope.engine->newString(result);
}
/*!
@@ -1822,11 +1838,12 @@ ReturnedValue GlobalExtensions::method_qsTranslate(CallContext *ctx)
\sa {Internationalization and Localization with Qt Quick}
*/
-ReturnedValue GlobalExtensions::method_qsTranslateNoOp(CallContext *ctx)
+void GlobalExtensions::method_qsTranslateNoOp(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 2)
- return QV4::Encode::undefined();
- return ctx->args()[1].asReturnedValue();
+ if (callData->argc < 2)
+ scope.result = QV4::Encode::undefined();
+ else
+ scope.result = callData->args[1];
}
/*!
@@ -1846,18 +1863,17 @@ ReturnedValue GlobalExtensions::method_qsTranslateNoOp(CallContext *ctx)
\sa {Internationalization and Localization with Qt Quick}
*/
-ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
-{
- if (ctx->argc() < 1)
- V4THROW_ERROR("qsTr() requires at least one argument");
- if (!ctx->args()[0].isString())
- V4THROW_ERROR("qsTr(): first argument (sourceText) must be a string");
- if ((ctx->argc() > 1) && !ctx->args()[1].isString())
- V4THROW_ERROR("qsTr(): second argument (disambiguation) must be a string");
- if ((ctx->argc() > 2) && !ctx->args()[2].isNumber())
- V4THROW_ERROR("qsTr(): third argument (n) must be a number");
-
- Scope scope(ctx);
+void GlobalExtensions::method_qsTr(const BuiltinFunction *, Scope &scope, CallData *callData)
+{
+ if (callData->argc < 1)
+ THROW_GENERIC_ERROR("qsTr() requires at least one argument");
+ if (!callData->args[0].isString())
+ THROW_GENERIC_ERROR("qsTr(): first argument (sourceText) must be a string");
+ if ((callData->argc > 1) && !callData->args[1].isString())
+ THROW_GENERIC_ERROR("qsTr(): second argument (disambiguation) must be a string");
+ if ((callData->argc > 2) && !callData->args[2].isNumber())
+ THROW_GENERIC_ERROR("qsTr(): third argument (n) must be a number");
+
QString context;
if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) {
QString path = ctxt->urlString();
@@ -1866,7 +1882,7 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
int length = lastDot - (lastSlash + 1);
context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
} else {
- ExecutionContext *parentCtx = scope.engine->parentContext(ctx);
+ ExecutionContext *parentCtx = scope.engine->currentContext;
// The first non-empty source URL in the call stack determines the translation context.
while (!!parentCtx && context.isEmpty()) {
if (QV4::CompiledData::CompilationUnit *unit = parentCtx->d()->compilationUnit) {
@@ -1885,18 +1901,18 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
}
}
- QString text = ctx->args()[0].toQStringNoThrow();
+ QString text = callData->args[0].toQStringNoThrow();
QString comment;
- if (ctx->argc() > 1)
- comment = ctx->args()[1].toQStringNoThrow();
+ if (callData->argc > 1)
+ comment = callData->args[1].toQStringNoThrow();
int n = -1;
- if (ctx->argc() > 2)
- n = ctx->args()[2].toInt32();
+ if (callData->argc > 2)
+ n = callData->args[2].toInt32();
QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(),
comment.toUtf8().constData(), n);
- return ctx->d()->engine->newString(result)->asReturnedValue();
+ scope.result = scope.engine->newString(result);
}
/*!
@@ -1921,11 +1937,12 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
\sa {Internationalization and Localization with Qt Quick}
*/
-ReturnedValue GlobalExtensions::method_qsTrNoOp(CallContext *ctx)
+void GlobalExtensions::method_qsTrNoOp(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 1)
- return QV4::Encode::undefined();
- return ctx->args()[0].asReturnedValue();
+ if (callData->argc < 1)
+ scope.result = QV4::Encode::undefined();
+ else
+ scope.result = callData->args[0];
}
/*!
@@ -1958,20 +1975,20 @@ ReturnedValue GlobalExtensions::method_qsTrNoOp(CallContext *ctx)
\sa QT_TRID_NOOP(), {Internationalization and Localization with Qt Quick}
*/
-ReturnedValue GlobalExtensions::method_qsTrId(CallContext *ctx)
+void GlobalExtensions::method_qsTrId(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 1)
- V4THROW_ERROR("qsTrId() requires at least one argument");
- if (!ctx->args()[0].isString())
- V4THROW_TYPE("qsTrId(): first argument (id) must be a string");
- if (ctx->argc() > 1 && !ctx->args()[1].isNumber())
- V4THROW_TYPE("qsTrId(): second argument (n) must be a number");
+ if (callData->argc < 1)
+ THROW_GENERIC_ERROR("qsTrId() requires at least one argument");
+ if (!callData->args[0].isString())
+ THROW_TYPE_ERROR_WITH_MESSAGE("qsTrId(): first argument (id) must be a string");
+ if (callData->argc > 1 && !callData->args[1].isNumber())
+ THROW_TYPE_ERROR_WITH_MESSAGE("qsTrId(): second argument (n) must be a number");
int n = -1;
- if (ctx->argc() > 1)
- n = ctx->args()[1].toInt32();
+ if (callData->argc > 1)
+ n = callData->args[1].toInt32();
- return ctx->d()->engine->newString(qtTrId(ctx->args()[0].toQStringNoThrow().toUtf8().constData(), n))->asReturnedValue();
+ scope.result = scope.engine->newString(qtTrId(callData->args[0].toQStringNoThrow().toUtf8().constData(), n));
}
/*!
@@ -1990,41 +2007,41 @@ ReturnedValue GlobalExtensions::method_qsTrId(CallContext *ctx)
\sa qsTrId(), {Internationalization and Localization with Qt Quick}
*/
-ReturnedValue GlobalExtensions::method_qsTrIdNoOp(CallContext *ctx)
+void GlobalExtensions::method_qsTrIdNoOp(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() < 1)
- return QV4::Encode::undefined();
- return ctx->args()[0].asReturnedValue();
+ if (callData->argc < 1)
+ scope.result = QV4::Encode::undefined();
+ else
+ scope.result = callData->args[0];
}
#endif // translation
-QV4::ReturnedValue GlobalExtensions::method_gc(CallContext *ctx)
+void GlobalExtensions::method_gc(const BuiltinFunction *, Scope &scope, CallData *)
{
- ctx->d()->engine->memoryManager->runGC();
+ scope.engine->memoryManager->runGC();
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
-ReturnedValue GlobalExtensions::method_string_arg(CallContext *ctx)
+void GlobalExtensions::method_string_arg(const BuiltinFunction *, Scope &scope, CallData *callData)
{
- if (ctx->argc() != 1)
- V4THROW_ERROR("String.arg(): Invalid arguments");
+ if (callData->argc != 1)
+ THROW_GENERIC_ERROR("String.arg(): Invalid arguments");
- QString value = ctx->thisObject().toQString();
+ QString value = callData->thisObject.toQString();
- QV4::Scope scope(ctx);
- QV4::ScopedValue arg(scope, ctx->args()[0]);
+ QV4::ScopedValue arg(scope, callData->args[0]);
if (arg->isInteger())
- return ctx->d()->engine->newString(value.arg(arg->integerValue()))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(value.arg(arg->integerValue())));
else if (arg->isDouble())
- return ctx->d()->engine->newString(value.arg(arg->doubleValue()))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(value.arg(arg->doubleValue())));
else if (arg->isBoolean())
- return ctx->d()->engine->newString(value.arg(arg->booleanValue()))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(value.arg(arg->booleanValue())));
- return ctx->d()->engine->newString(value.arg(arg->toQString()))->asReturnedValue();
+ RETURN_RESULT(scope.engine->newString(value.arg(arg->toQString())));
}
/*!
@@ -2047,10 +2064,10 @@ be passed on to the function invoked. Note that if redundant calls
are eliminated, then only the last set of arguments will be passed to the
function.
*/
-ReturnedValue QtObject::method_callLater(CallContext *ctx)
+void QtObject::method_callLater(const BuiltinFunction *b, Scope &scope, CallData *callData)
{
- QV8Engine *v8engine = ctx->engine()->v8Engine;
- return v8engine->delayedCallQueue()->addUniquelyAndExecuteLater(ctx);
+ QV8Engine *v8engine = scope.engine->v8Engine;
+ v8engine->delayedCallQueue()->addUniquelyAndExecuteLater(b, scope, callData);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index fe43532647..21613b7c10 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -93,45 +93,45 @@ struct QtObject : Object
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
- static ReturnedValue method_isQtObject(CallContext *ctx);
- static ReturnedValue method_rgba(CallContext *ctx);
- static ReturnedValue method_hsla(CallContext *ctx);
- static ReturnedValue method_hsva(CallContext *ctx);
- static ReturnedValue method_colorEqual(CallContext *ctx);
- static ReturnedValue method_font(CallContext *ctx);
- static ReturnedValue method_rect(CallContext *ctx);
- static ReturnedValue method_point(CallContext *ctx);
- static ReturnedValue method_size(CallContext *ctx);
- static ReturnedValue method_vector2d(CallContext *ctx);
- static ReturnedValue method_vector3d(CallContext *ctx);
- static ReturnedValue method_vector4d(CallContext *ctx);
- static ReturnedValue method_quaternion(CallContext *ctx);
- static ReturnedValue method_matrix4x4(CallContext *ctx);
- static ReturnedValue method_lighter(CallContext *ctx);
- static ReturnedValue method_darker(CallContext *ctx);
- static ReturnedValue method_tint(CallContext *ctx);
- static ReturnedValue method_formatDate(CallContext *ctx);
- static ReturnedValue method_formatTime(CallContext *ctx);
- static ReturnedValue method_formatDateTime(CallContext *ctx);
- static ReturnedValue method_openUrlExternally(CallContext *ctx);
- static ReturnedValue method_fontFamilies(CallContext *ctx);
- static ReturnedValue method_md5(CallContext *ctx);
- static ReturnedValue method_btoa(CallContext *ctx);
- static ReturnedValue method_atob(CallContext *ctx);
- static ReturnedValue method_quit(CallContext *ctx);
- static ReturnedValue method_exit(CallContext *ctx);
- static ReturnedValue method_resolvedUrl(CallContext *ctx);
- static ReturnedValue method_createQmlObject(CallContext *ctx);
- static ReturnedValue method_createComponent(CallContext *ctx);
- static ReturnedValue method_locale(CallContext *ctx);
- static ReturnedValue method_binding(CallContext *ctx);
-
- static ReturnedValue method_get_platform(CallContext *ctx);
- static ReturnedValue method_get_application(CallContext *ctx);
- static ReturnedValue method_get_inputMethod(CallContext *ctx);
- static ReturnedValue method_get_styleHints(CallContext *ctx);
-
- static ReturnedValue method_callLater(CallContext *ctx);
+ static void method_isQtObject(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_rgba(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_hsla(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_hsva(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_colorEqual(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_font(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_rect(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_point(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_size(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_vector2d(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_vector3d(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_vector4d(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_quaternion(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_matrix4x4(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_lighter(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_darker(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_tint(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_formatDate(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_formatTime(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_formatDateTime(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_openUrlExternally(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_fontFamilies(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_md5(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_btoa(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_atob(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_quit(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_exit(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_resolvedUrl(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_createQmlObject(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_createComponent(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_locale(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_binding(const BuiltinFunction *, Scope &scope, CallData *callData);
+
+ static void method_get_platform(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_application(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_inputMethod(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_get_styleHints(const BuiltinFunction *, Scope &scope, CallData *callData);
+
+ static void method_callLater(const BuiltinFunction *, Scope &scope, CallData *callData);
private:
void addAll();
@@ -142,18 +142,18 @@ struct ConsoleObject : Object
{
V4_OBJECT2(ConsoleObject, Object)
- static ReturnedValue method_error(CallContext *ctx);
- static ReturnedValue method_log(CallContext *ctx);
- static ReturnedValue method_info(CallContext *ctx);
- static ReturnedValue method_profile(CallContext *ctx);
- static ReturnedValue method_profileEnd(CallContext *ctx);
- static ReturnedValue method_time(CallContext *ctx);
- static ReturnedValue method_timeEnd(CallContext *ctx);
- static ReturnedValue method_count(CallContext *ctx);
- static ReturnedValue method_trace(CallContext *ctx);
- static ReturnedValue method_warn(CallContext *ctx);
- static ReturnedValue method_assert(CallContext *ctx);
- static ReturnedValue method_exception(CallContext *ctx);
+ static void method_error(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_log(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_info(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_profile(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_profileEnd(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_time(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_timeEnd(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_count(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_trace(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_warn(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_assert(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_exception(const BuiltinFunction *, Scope &scope, CallData *callData);
};
@@ -161,17 +161,17 @@ struct Q_QML_PRIVATE_EXPORT GlobalExtensions {
static void init(Object *globalObject, QJSEngine::Extensions extensions);
#if QT_CONFIG(translation)
- static ReturnedValue method_qsTranslate(CallContext *ctx);
- static ReturnedValue method_qsTranslateNoOp(CallContext *ctx);
- static ReturnedValue method_qsTr(CallContext *ctx);
- static ReturnedValue method_qsTrNoOp(CallContext *ctx);
- static ReturnedValue method_qsTrId(CallContext *ctx);
- static ReturnedValue method_qsTrIdNoOp(CallContext *ctx);
+ static void method_qsTranslate(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_qsTranslateNoOp(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_qsTr(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_qsTrNoOp(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_qsTrId(const BuiltinFunction *, Scope &scope, CallData *callData);
+ static void method_qsTrIdNoOp(const BuiltinFunction *, Scope &scope, CallData *callData);
#endif
- static ReturnedValue method_gc(CallContext *ctx);
+ static void method_gc(const BuiltinFunction *, Scope &scope, CallData *callData);
// on String:prototype
- static ReturnedValue method_string_arg(CallContext *ctx);
+ static void method_string_arg(const BuiltinFunction *, Scope &scope, CallData *callData);
};
diff --git a/src/qml/qml/v8/qv4domerrors_p.h b/src/qml/qml/v8/qv4domerrors_p.h
index faa9dd8bc7..a9bdbe01ae 100644
--- a/src/qml/qml/v8/qv4domerrors_p.h
+++ b/src/qml/qml/v8/qv4domerrors_p.h
@@ -74,11 +74,12 @@ QT_BEGIN_NAMESPACE
#define DOMEXCEPTION_VALIDATION_ERR 16
#define DOMEXCEPTION_TYPE_MISMATCH_ERR 17
-#define V4THROW_DOM(error, string) { \
+#define THROW_DOM(error, string) { \
QV4::ScopedValue v(scope, scope.engine->newString(QStringLiteral(string))); \
QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(error))); \
- return ctx->engine()->throwError(ex); \
+ scope.result = scope.engine->throwError(ex); \
+ return; \
}
namespace QV4 {
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index a545fe57ca..2ded9c13c8 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -82,12 +82,12 @@ void QQmlBindPrivate::validate(QObject *binding) const
return;
if (!prop.isValid()) {
- qmlInfo(binding) << "Property '" << propName << "' does not exist on " << QQmlMetaType::prettyTypeName(obj) << ".";
+ qmlWarning(binding) << "Property '" << propName << "' does not exist on " << QQmlMetaType::prettyTypeName(obj) << ".";
return;
}
if (!prop.isWritable()) {
- qmlInfo(binding) << "Property '" << propName << "' on " << QQmlMetaType::prettyTypeName(obj) << " is read-only.";
+ qmlWarning(binding) << "Property '" << propName << "' on " << QQmlMetaType::prettyTypeName(obj) << " is read-only.";
return;
}
}
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 2aed4d9972..870aeaa6e2 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -168,7 +168,7 @@ void QQmlConnections::setTarget(QObject *obj)
if (d->targetSet && d->target == obj)
return;
d->targetSet = true; // even if setting to 0, it is *set*
- foreach (QQmlBoundSignal *s, d->boundsignals) {
+ for (QQmlBoundSignal *s : qAsConst(d->boundsignals)) {
// It is possible that target is being changed due to one of our signal
// handlers -> use deleteLater().
if (s->isNotifying())
@@ -278,7 +278,7 @@ void QQmlConnections::connectSignals()
QQmlContextData *ctxtdata = ddata ? ddata->outerContext : 0;
const QV4::CompiledData::Unit *qmlUnit = d->compilationUnit->data;
- foreach (const QV4::CompiledData::Binding *binding, d->bindings) {
+ for (const QV4::CompiledData::Binding *binding : qAsConst(d->bindings)) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script);
QString propName = qmlUnit->stringAt(binding->propertyNameIndex);
@@ -295,7 +295,7 @@ void QQmlConnections::connectSignals()
d->boundsignals += signal;
} else {
if (!d->ignoreUnknownSignals)
- qmlInfo(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName);
+ qmlWarning(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName);
}
}
}
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index be10b270ae..a5878dcffd 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -264,7 +264,7 @@ QQmlDelegateModel::~QQmlDelegateModel()
{
Q_D(QQmlDelegateModel);
- foreach (QQmlDelegateModelItem *cacheItem, d->m_cache) {
+ for (QQmlDelegateModelItem *cacheItem : qAsConst(d->m_cache)) {
if (cacheItem->object) {
delete cacheItem->object;
@@ -310,7 +310,7 @@ void QQmlDelegateModel::componentComplete()
--d->m_groupCount;
--i;
} else if (name.at(0).isUpper()) {
- qmlInfo(d->m_groups[i]) << QQmlDelegateModelGroup::tr("Group names must start with a lower case letter");
+ qmlWarning(d->m_groups[i]) << QQmlDelegateModelGroup::tr("Group names must start with a lower case letter");
d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
--d->m_groupCount;
--i;
@@ -404,7 +404,7 @@ void QQmlDelegateModel::setDelegate(QQmlComponent *delegate)
{
Q_D(QQmlDelegateModel);
if (d->m_transaction) {
- qmlInfo(this) << tr("The delegate of a DelegateModel cannot be changed within onUpdated.");
+ qmlWarning(this) << tr("The delegate of a DelegateModel cannot be changed within onUpdated.");
return;
}
bool wasValid = d->m_delegate != 0;
@@ -610,7 +610,7 @@ void QQmlDelegateModelPrivate::group_append(
if (d->m_complete)
return;
if (d->m_groupCount == Compositor::MaximumGroupCount) {
- qmlInfo(d->q_func()) << QQmlDelegateModel::tr("The maximum number of supported DelegateModelGroups is 8");
+ qmlWarning(d->q_func()) << QQmlDelegateModel::tr("The maximum number of supported DelegateModelGroups is 8");
return;
}
d->m_groups[d->m_groupCount] = group;
@@ -719,7 +719,7 @@ void QQmlDelegateModel::setFilterGroup(const QString &group)
Q_D(QQmlDelegateModel);
if (d->m_transaction) {
- qmlInfo(this) << tr("The group of a DelegateModel cannot be changed within onChanged");
+ qmlWarning(this) << tr("The group of a DelegateModel cannot be changed within onChanged");
return;
}
@@ -764,7 +764,8 @@ void QQmlDelegateModelPrivate::updateFilterGroup()
emit q->countChanged();
if (m_parts) {
- foreach (QQmlPartsModel *model, m_parts->models)
+ auto partsCopy = m_parts->models; // deliberate; this may alter m_parts
+ for (QQmlPartsModel *model : qAsConst(partsCopy))
model->updateFilterGroup(m_compositorGroup, changeSet);
}
}
@@ -889,7 +890,7 @@ void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incuba
emitCreatedItem(incubationTask, cacheItem->object);
cacheItem->releaseObject();
} else if (status == QQmlIncubator::Error) {
- qmlInfo(q, m_delegate->errors()) << "Error creating delegate";
+ qmlWarning(q, m_delegate->errors()) << "Error creating delegate";
}
if (!cacheItem->isObjectReferenced()) {
@@ -1472,7 +1473,8 @@ void QQmlDelegateModelPrivate::emitChanges()
for (int i = 1; i < m_groupCount; ++i)
QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset);
- foreach (QQmlDelegateModelItem *cacheItem, m_cache) {
+ auto cacheCopy = m_cache; // deliberate; emitChanges may alter m_cache
+ for (QQmlDelegateModelItem *cacheItem : qAsConst(cacheCopy)) {
if (cacheItem->attached)
cacheItem->attached->emitChanges();
}
@@ -1793,24 +1795,26 @@ int QQmlDelegateModelItemMetaType::parseGroups(const QV4::Value &groups) const
return groupFlags;
}
-QV4::ReturnedValue QQmlDelegateModelItem::get_model(QV4::CallContext *ctx)
+void QQmlDelegateModelItem::get_model(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->thisObject().as<QQmlDelegateModelItemObject>());
- if (!o)
- return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, callData->thisObject.as<QQmlDelegateModelItemObject>());
+ if (!o) {
+ scope.result = scope.engine->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return;
+ }
if (!o->d()->item->metaType->model)
- return QV4::Encode::undefined();
+ RETURN_UNDEFINED();
- return o->d()->item->get();
+ scope.result = o->d()->item->get();
}
-QV4::ReturnedValue QQmlDelegateModelItem::get_groups(QV4::CallContext *ctx)
+void QQmlDelegateModelItem::get_groups(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->thisObject().as<QQmlDelegateModelItemObject>());
- if (!o)
- return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, callData->thisObject.as<QQmlDelegateModelItemObject>());
+ if (!o) {
+ scope.result = scope.engine->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return;
+ }
QStringList groups;
for (int i = 1; i < o->d()->item->metaType->groupCount; ++i) {
@@ -1818,27 +1822,29 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_groups(QV4::CallContext *ctx)
groups.append(o->d()->item->metaType->groupNames.at(i - 1));
}
- return scope.engine->fromVariant(groups);
+ scope.result = scope.engine->fromVariant(groups);
}
-QV4::ReturnedValue QQmlDelegateModelItem::set_groups(QV4::CallContext *ctx)
+void QQmlDelegateModelItem::set_groups(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->thisObject().as<QQmlDelegateModelItemObject>());
- if (!o)
- return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- if (!ctx->argc())
- return ctx->engine()->throwTypeError();
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, callData->thisObject.as<QQmlDelegateModelItemObject>());
+ if (!o) {
+ scope.result = scope.engine->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return;
+ }
+
+ if (!callData->argc)
+ THROW_TYPE_ERROR();
if (!o->d()->item->metaType->model)
- return QV4::Encode::undefined();
+ RETURN_UNDEFINED();
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(o->d()->item->metaType->model);
- const int groupFlags = model->m_cacheMetaType->parseGroups(ctx->args()[0]);
+ const int groupFlags = model->m_cacheMetaType->parseGroups(callData->args[0]);
const int cacheIndex = model->m_cache.indexOf(o->d()->item);
Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
model->setGroups(it, 1, Compositor::Cache, groupFlags);
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
QV4::ReturnedValue QQmlDelegateModelItem::get_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &)
@@ -2459,7 +2465,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
if (!model->m_context || !model->m_context->isValid()) {
return QQmlV4Handle(QV4::Encode::undefined());
} else if (index < 0 || index >= model->m_compositor.count(d->group)) {
- qmlInfo(this) << tr("get: index out of range");
+ qmlWarning(this) << tr("get: index out of range");
return QQmlV4Handle(QV4::Encode::undefined());
}
@@ -2552,7 +2558,7 @@ void QQmlDelegateModelGroup::insert(QQmlV4Function *args)
QV4::ScopedValue v(scope, (*args)[i]);
if (d->parseIndex(v, &index, &group)) {
if (index < 0 || index > model->m_compositor.count(group)) {
- qmlInfo(this) << tr("insert: index out of range");
+ qmlWarning(this) << tr("insert: index out of range");
return;
}
if (++i == args->length())
@@ -2637,7 +2643,7 @@ void QQmlDelegateModelGroup::create(QQmlV4Function *args)
}
}
if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("create: index out of range");
+ qmlWarning(this) << tr("create: index out of range");
return;
}
@@ -2690,22 +2696,22 @@ void QQmlDelegateModelGroup::resolve(QQmlV4Function *args)
QV4::ScopedValue v(scope, (*args)[0]);
if (d->parseIndex(v, &from, &fromGroup)) {
if (from < 0 || from >= model->m_compositor.count(fromGroup)) {
- qmlInfo(this) << tr("resolve: from index out of range");
+ qmlWarning(this) << tr("resolve: from index out of range");
return;
}
} else {
- qmlInfo(this) << tr("resolve: from index invalid");
+ qmlWarning(this) << tr("resolve: from index invalid");
return;
}
v = (*args)[1];
if (d->parseIndex(v, &to, &toGroup)) {
if (to < 0 || to >= model->m_compositor.count(toGroup)) {
- qmlInfo(this) << tr("resolve: to index out of range");
+ qmlWarning(this) << tr("resolve: to index out of range");
return;
}
} else {
- qmlInfo(this) << tr("resolve: to index invalid");
+ qmlWarning(this) << tr("resolve: to index invalid");
return;
}
@@ -2713,11 +2719,11 @@ void QQmlDelegateModelGroup::resolve(QQmlV4Function *args)
Compositor::iterator toIt = model->m_compositor.find(toGroup, to);
if (!fromIt->isUnresolved()) {
- qmlInfo(this) << tr("resolve: from is not an unresolved item");
+ qmlWarning(this) << tr("resolve: from is not an unresolved item");
return;
}
if (!toIt->list) {
- qmlInfo(this) << tr("resolve: to is not a model item");
+ qmlWarning(this) << tr("resolve: to is not a model item");
return;
}
@@ -2787,7 +2793,7 @@ void QQmlDelegateModelGroup::remove(QQmlV4Function *args)
QV4::Scope scope(args->v4engine());
QV4::ScopedValue v(scope, (*args)[0]);
if (!d->parseIndex(v, &index, &group)) {
- qmlInfo(this) << tr("remove: invalid index");
+ qmlWarning(this) << tr("remove: invalid index");
return;
}
@@ -2799,11 +2805,11 @@ void QQmlDelegateModelGroup::remove(QQmlV4Function *args)
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("remove: index out of range");
+ qmlWarning(this) << tr("remove: index out of range");
} else if (count != 0) {
Compositor::iterator it = model->m_compositor.find(group, index);
if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlInfo(this) << tr("remove: invalid count");
+ qmlWarning(this) << tr("remove: invalid count");
} else {
model->removeGroups(it, count, d->group, 1 << d->group);
}
@@ -2858,11 +2864,11 @@ void QQmlDelegateModelGroup::addGroups(QQmlV4Function *args)
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("addGroups: index out of range");
+ qmlWarning(this) << tr("addGroups: index out of range");
} else if (count != 0) {
Compositor::iterator it = model->m_compositor.find(group, index);
if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlInfo(this) << tr("addGroups: invalid count");
+ qmlWarning(this) << tr("addGroups: invalid count");
} else {
model->addGroups(it, count, d->group, groups);
}
@@ -2888,11 +2894,11 @@ void QQmlDelegateModelGroup::removeGroups(QQmlV4Function *args)
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("removeGroups: index out of range");
+ qmlWarning(this) << tr("removeGroups: index out of range");
} else if (count != 0) {
Compositor::iterator it = model->m_compositor.find(group, index);
if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlInfo(this) << tr("removeGroups: invalid count");
+ qmlWarning(this) << tr("removeGroups: invalid count");
} else {
model->removeGroups(it, count, d->group, groups);
}
@@ -2918,11 +2924,11 @@ void QQmlDelegateModelGroup::setGroups(QQmlV4Function *args)
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlInfo(this) << tr("setGroups: index out of range");
+ qmlWarning(this) << tr("setGroups: index out of range");
} else if (count != 0) {
Compositor::iterator it = model->m_compositor.find(group, index);
if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlInfo(this) << tr("setGroups: invalid count");
+ qmlWarning(this) << tr("setGroups: invalid count");
} else {
model->setGroups(it, count, d->group, groups);
}
@@ -2957,13 +2963,13 @@ void QQmlDelegateModelGroup::move(QQmlV4Function *args)
QV4::Scope scope(args->v4engine());
QV4::ScopedValue v(scope, (*args)[0]);
if (!d->parseIndex(v, &from, &fromGroup)) {
- qmlInfo(this) << tr("move: invalid from index");
+ qmlWarning(this) << tr("move: invalid from index");
return;
}
v = (*args)[1];
if (!d->parseIndex(v, &to, &toGroup)) {
- qmlInfo(this) << tr("move: invalid to index");
+ qmlWarning(this) << tr("move: invalid to index");
return;
}
@@ -2976,11 +2982,11 @@ void QQmlDelegateModelGroup::move(QQmlV4Function *args)
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
if (count < 0) {
- qmlInfo(this) << tr("move: invalid count");
+ qmlWarning(this) << tr("move: invalid count");
} else if (from < 0 || from + count > model->m_compositor.count(fromGroup)) {
- qmlInfo(this) << tr("move: from index out of range");
+ qmlWarning(this) << tr("move: from index out of range");
} else if (!model->m_compositor.verifyMoveTo(fromGroup, from, toGroup, to, count, d->group)) {
- qmlInfo(this) << tr("move: to index out of range");
+ qmlWarning(this) << tr("move: to index out of range");
} else if (count > 0) {
QVector<Compositor::Remove> removes;
QVector<Compositor::Insert> inserts;
@@ -3038,7 +3044,7 @@ QString QQmlPartsModel::filterGroup() const
void QQmlPartsModel::setFilterGroup(const QString &group)
{
if (QQmlDelegateModelPrivate::get(m_model)->m_transaction) {
- qmlInfo(this) << tr("The group of a DelegateModel cannot be changed within onChanged");
+ qmlWarning(this) << tr("The group of a DelegateModel cannot be changed within onChanged");
return;
}
@@ -3151,7 +3157,7 @@ QObject *QQmlPartsModel::object(int index, bool asynchronous)
model->release(object);
if (!model->m_delegateValidated) {
if (object)
- qmlInfo(model->m_delegate) << tr("Delegate component must be Package type.");
+ qmlWarning(model->m_delegate) << tr("Delegate component must be Package type.");
model->m_delegateValidated = true;
}
@@ -3232,28 +3238,25 @@ struct QQmlDelegateModelGroupChange : QV4::Object
return e->memoryManager->allocObject<QQmlDelegateModelGroupChange>();
}
- static QV4::ReturnedValue method_get_index(QV4::CallContext *ctx) {
- QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->thisObject().as<QQmlDelegateModelGroupChange>());
+ static void method_get_index(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) {
+ QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, callData->thisObject.as<QQmlDelegateModelGroupChange>());
if (!that)
- return ctx->engine()->throwTypeError();
- return QV4::Encode(that->d()->change.index);
+ THROW_TYPE_ERROR();
+ scope.result = QV4::Encode(that->d()->change.index);
}
- static QV4::ReturnedValue method_get_count(QV4::CallContext *ctx) {
- QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->thisObject().as<QQmlDelegateModelGroupChange>());
+ static void method_get_count(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) {
+ QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, callData->thisObject.as<QQmlDelegateModelGroupChange>());
if (!that)
- return ctx->engine()->throwTypeError();
- return QV4::Encode(that->d()->change.count);
+ THROW_TYPE_ERROR();
+ scope.result = QV4::Encode(that->d()->change.count);
}
- static QV4::ReturnedValue method_get_moveId(QV4::CallContext *ctx) {
- QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->thisObject().as<QQmlDelegateModelGroupChange>());
+ static void method_get_moveId(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) {
+ QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, callData->thisObject.as<QQmlDelegateModelGroupChange>());
if (!that)
- return ctx->engine()->throwTypeError();
+ THROW_TYPE_ERROR();
if (that->d()->change.moveId < 0)
- return QV4::Encode::undefined();
- return QV4::Encode(that->d()->change.moveId);
+ RETURN_UNDEFINED();
+ scope.result = QV4::Encode(that->d()->change.moveId);
}
};
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 4c2841b8ba..cb4a1f79ba 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -131,9 +131,9 @@ public:
virtual void setValue(const QString &role, const QVariant &value) { Q_UNUSED(role); Q_UNUSED(value); }
virtual bool resolveIndex(const QQmlAdaptorModel &, int) { return false; }
- static QV4::ReturnedValue get_model(QV4::CallContext *ctx);
- static QV4::ReturnedValue get_groups(QV4::CallContext *ctx);
- static QV4::ReturnedValue set_groups(QV4::CallContext *ctx);
+ static void get_model(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void get_groups(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void set_groups(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
static QV4::ReturnedValue get_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &);
static QV4::ReturnedValue set_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg);
static QV4::ReturnedValue get_index(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg);
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 1a2e4c7f6f..cc4ccbaeb1 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -99,7 +99,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::Da
if (node) {
const Role &r = *node->value;
if (type != r.type)
- qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
+ qmlWarning(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
return r;
}
@@ -112,7 +112,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::Data
if (node) {
const Role &r = *node->value;
if (type != r.type)
- qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
+ qmlWarning(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
return r;
}
@@ -226,7 +226,7 @@ const ListLayout::Role *ListLayout::getRoleOrCreate(const QString &key, const QV
}
if (type == Role::Invalid) {
- qmlInfo(0) << "Can't create role for unsupported data type";
+ qmlWarning(0) << "Can't create role for unsupported data type";
return 0;
}
@@ -1201,7 +1201,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d
}
roleIndex = setListProperty(role, subModel);
} else {
- qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
+ qmlWarning(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
}
} else if (d.isBoolean()) {
roleIndex = setBoolProperty(role, d.booleanValue());
@@ -1267,10 +1267,12 @@ void ModelNodeMetaObject::updateValues()
{
const int roleCount = m_model->m_listModel->roleCount();
if (!m_initialized) {
- int *changedRoles = reinterpret_cast<int *>(alloca(roleCount * sizeof(int)));
- for (int i = 0; i < roleCount; ++i)
- changedRoles[i] = i;
- emitDirectNotifies(changedRoles, roleCount);
+ if (roleCount) {
+ int *changedRoles = reinterpret_cast<int *>(alloca(roleCount * sizeof(int)));
+ for (int i = 0; i < roleCount; ++i)
+ changedRoles[i] = i;
+ emitDirectNotifies(changedRoles, roleCount);
+ }
return;
}
for (int i=0 ; i < roleCount ; ++i) {
@@ -1984,18 +1986,18 @@ void QQmlListModel::setDynamicRoles(bool enableDynamicRoles)
if (m_mainThread && m_agent == 0) {
if (enableDynamicRoles) {
if (m_layout->roleCount())
- qmlInfo(this) << tr("unable to enable dynamic roles as this model is not empty!");
+ qmlWarning(this) << tr("unable to enable dynamic roles as this model is not empty!");
else
m_dynamicRoles = true;
} else {
if (m_roles.count()) {
- qmlInfo(this) << tr("unable to enable static roles as this model is not empty!");
+ qmlWarning(this) << tr("unable to enable static roles as this model is not empty!");
} else {
m_dynamicRoles = false;
}
}
} else {
- qmlInfo(this) << tr("dynamic role setting must be made from the main thread, before any worker scripts are created");
+ qmlWarning(this) << tr("dynamic role setting must be made from the main thread, before any worker scripts are created");
}
}
@@ -2048,7 +2050,7 @@ void QQmlListModel::remove(QQmlV4Function *args)
int removeCount = (argLength == 2 ? QV4::ScopedValue(scope, (*args)[1])->toInt32() : 1);
if (index < 0 || index+removeCount > count() || removeCount <= 0) {
- qmlInfo(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+removeCount).arg(count());
+ qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+removeCount).arg(count());
return;
}
@@ -2064,7 +2066,7 @@ void QQmlListModel::remove(QQmlV4Function *args)
emitItemsRemoved(index, removeCount);
} else {
- qmlInfo(this) << tr("remove: incorrect number of arguments");
+ qmlWarning(this) << tr("remove: incorrect number of arguments");
}
}
@@ -2092,7 +2094,7 @@ void QQmlListModel::insert(QQmlV4Function *args)
int index = arg0->toInt32();
if (index < 0 || index > count()) {
- qmlInfo(this) << tr("insert: index %1 out of range").arg(index);
+ qmlWarning(this) << tr("insert: index %1 out of range").arg(index);
return;
}
@@ -2124,10 +2126,10 @@ void QQmlListModel::insert(QQmlV4Function *args)
emitItemsInserted(index, 1);
} else {
- qmlInfo(this) << tr("insert: value is not an object");
+ qmlWarning(this) << tr("insert: value is not an object");
}
} else {
- qmlInfo(this) << tr("insert: value is not an object");
+ qmlWarning(this) << tr("insert: value is not an object");
}
}
@@ -2150,7 +2152,7 @@ void QQmlListModel::move(int from, int to, int n)
if (n==0 || from==to)
return;
if (!canMove(from, to, n)) {
- qmlInfo(this) << tr("move: out of range");
+ qmlWarning(this) << tr("move: out of range");
return;
}
@@ -2239,10 +2241,10 @@ void QQmlListModel::append(QQmlV4Function *args)
emitItemsInserted(index, 1);
} else {
- qmlInfo(this) << tr("append: value is not an object");
+ qmlWarning(this) << tr("append: value is not an object");
}
} else {
- qmlInfo(this) << tr("append: value is not an object");
+ qmlWarning(this) << tr("append: value is not an object");
}
}
@@ -2321,11 +2323,11 @@ void QQmlListModel::set(int index, const QQmlV4Handle &handle)
QV4::ScopedObject object(scope, handle);
if (!object) {
- qmlInfo(this) << tr("set: value is not an object");
+ qmlWarning(this) << tr("set: value is not an object");
return;
}
if (index > count() || index < 0) {
- qmlInfo(this) << tr("set: index %1 out of range").arg(index);
+ qmlWarning(this) << tr("set: index %1 out of range").arg(index);
return;
}
@@ -2371,7 +2373,7 @@ void QQmlListModel::set(int index, const QQmlV4Handle &handle)
void QQmlListModel::setProperty(int index, const QString& property, const QVariant& value)
{
if (count() == 0 || index >= count() || index < 0) {
- qmlInfo(this) << tr("set: index %1 out of range").arg(index);
+ qmlWarning(this) << tr("set: index %1 out of range").arg(index);
return;
}
@@ -2401,7 +2403,7 @@ void QQmlListModel::sync()
// This is just a dummy method to make it look like sync() exists in
// ListModel (and not just QQmlListModelWorkerAgent) and to let
// us document sync().
- qmlInfo(this) << "List sync() can only be called from a WorkerScript";
+ qmlWarning(this) << "List sync() can only be called from a WorkerScript";
}
bool QQmlListModelParser::verifyProperty(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding)
@@ -2543,7 +2545,7 @@ void QQmlListModelParser::applyBindings(QObject *obj, QV4::CompiledData::Compila
}
if (setRoles == false)
- qmlInfo(obj) << "All ListElement declarations are empty, no roles can be created unless dynamicRoles is set.";
+ qmlWarning(obj) << "All ListElement declarations are empty, no roles can be created unless dynamicRoles is set.";
}
bool QQmlListModelParser::definesEmptyList(const QString &s)
diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp
index 695043b592..21205f4490 100644
--- a/src/qml/types/qqmlobjectmodel.cpp
+++ b/src/qml/types/qqmlobjectmodel.cpp
@@ -373,7 +373,7 @@ void QQmlObjectModel::insert(int index, QObject *object)
{
Q_D(QQmlObjectModel);
if (index < 0 || index > count()) {
- qmlInfo(this) << tr("insert: index %1 out of range").arg(index);
+ qmlWarning(this) << tr("insert: index %1 out of range").arg(index);
return;
}
d->insert(index, object);
@@ -400,7 +400,7 @@ void QQmlObjectModel::move(int from, int to, int n)
if (n <= 0 || from == to)
return;
if (from < 0 || to < 0 || from + n > count() || to + n > count()) {
- qmlInfo(this) << tr("move: out of range");
+ qmlWarning(this) << tr("move: out of range");
return;
}
d->move(from, to, n);
@@ -418,7 +418,7 @@ void QQmlObjectModel::remove(int index, int n)
{
Q_D(QQmlObjectModel);
if (index < 0 || n <= 0 || index + n > count()) {
- qmlInfo(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count());
+ qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count());
return;
}
d->remove(index, n);
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 5f716da17a..f35e17c34d 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -185,7 +185,7 @@ public:
int m_nextId;
- static QV4::ReturnedValue method_sendMessage(QV4::CallContext *ctx);
+ static void method_sendMessage(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
signals:
void stopThread();
@@ -292,14 +292,13 @@ QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *eng
{
}
-QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::CallContext *ctx)
+void QQuickWorkerScriptEnginePrivate::method_sendMessage(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
{
- WorkerEngine *engine = (WorkerEngine*)ctx->engine()->v8Engine;
+ WorkerEngine *engine = (WorkerEngine*)scope.engine->v8Engine;
- int id = ctx->argc() > 1 ? ctx->args()[1].toInt32() : 0;
+ int id = callData->argc > 1 ? callData->args[1].toInt32() : 0;
- QV4::Scope scope(ctx);
- QV4::ScopedValue v(scope, ctx->argument(2));
+ QV4::ScopedValue v(scope, callData->argument(2));
QByteArray data = QV4::Serialize::serialize(v, scope.engine);
QMutexLocker locker(&engine->p->m_lock);
@@ -307,7 +306,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::Call
if (script && script->owner)
QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data));
- return QV4::Encode::undefined();
+ scope.result = QV4::Encode::undefined();
}
QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script)