diff options
Diffstat (limited to 'src/qml/jsruntime/qv4functionobject.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 397 |
1 files changed, 217 insertions, 180 deletions
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 6fb7946023..e9f91fbc06 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -1,50 +1,11 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qv4object_p.h" -#include "qv4objectproto_p.h" -#include "qv4stringobject_p.h" #include "qv4function_p.h" #include "qv4symbol_p.h" #include <private/qv4mm_p.h> -#include "qv4arrayobject_p.h" #include "qv4scopedvalue_p.h" #include "qv4argumentsobject_p.h" @@ -63,86 +24,63 @@ #include <QtCore/QDebug> #include <algorithm> -#include "qv4profiling_p.h" using namespace QV4; DEFINE_OBJECT_VTABLE(FunctionObject); -void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, VTable::Call call) +void Heap::FunctionObject::init(QV4::ExecutionEngine *engine, QV4::String *name) { - jsCall = call; - jsConstruct = nullptr; - - Object::init(); - this->scope.set(scope->engine(), scope->d()); - Scope s(scope->engine()); - ScopedFunctionObject f(s, this); - if (name) - f->setName(name); -} - -void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name) -{ - ExecutionEngine *e = scope->engine(); - - jsCall = vtable()->call; - jsConstruct = vtable()->callAsConstructor; - Object::init(); - this->scope.set(scope->engine(), scope->d()); - Scope s(e); + Scope s(engine); ScopedFunctionObject f(s, this); if (name) f->setName(name); } - - -void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function, QV4::String *n) +void Heap::FunctionObject::init(QV4::ExecutionEngine *engine, const QString &name) { - jsCall = vtable()->call; - jsConstruct = vtable()->callAsConstructor; - - Object::init(); - setFunction(function); - this->scope.set(scope->engine(), scope->d()); - Scope s(scope->engine()); - ScopedString name(s, n ? n->d() : function->name()); - ScopedFunctionObject f(s, this); - if (name) - f->setName(name); + Scope valueScope(engine); + ScopedString s(valueScope, engine->newString(name)); + init(engine, s); } -void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const QString &name) +void Heap::FunctionObject::init() { - Scope valueScope(scope); - ScopedString s(valueScope, valueScope.engine->newString(name)); - init(scope, s); + init(internalClass->engine, static_cast<QV4::String *>(nullptr)); } -void Heap::FunctionObject::init() +void Heap::JavaScriptFunctionObject::init( + QV4::ExecutionContext *scope, Function *function, QV4::String *n) { - jsCall = vtable()->call; - jsConstruct = vtable()->callAsConstructor; - - Object::init(); - this->scope.set(internalClass->engine, internalClass->engine->rootContext()->d()); + Q_ASSERT(n || function); + Scope s(scope->engine()); + ScopedString name(s, n ? n->d() : function->name()); + FunctionObject::init(s.engine, name); + this->scope.set(s.engine, scope->d()); + setFunction(function); } -void Heap::FunctionObject::setFunction(Function *f) +void Heap::JavaScriptFunctionObject::setFunction(Function *f) { if (f) { function = f; function->executableCompilationUnit()->addref(); } } -void Heap::FunctionObject::destroy() +void Heap::JavaScriptFunctionObject::destroy() { if (function) function->executableCompilationUnit()->release(); - Object::destroy(); + FunctionObject::destroy(); +} + +void Heap::DynamicFunctionObject::init( + QV4::ExecutionEngine *engine, QV4::String *name, VTable::Call call) +{ + FunctionObject::init(engine, name); + jsCall = call; } void FunctionObject::createDefaultPrototypeProperty(uint protoConstructorSlot) @@ -158,12 +96,27 @@ void FunctionObject::createDefaultPrototypeProperty(uint protoConstructorSlot) ReturnedValue FunctionObject::name() const { - return get(scope()->internalClass->engine->id_name()); + return get(engine()->id_name()); } -ReturnedValue FunctionObject::virtualCall(const FunctionObject *, const Value *, const Value *, int) +ReturnedValue FunctionObject::failCall() const { - return Encode::undefined(); + return engine()->throwTypeError(QStringLiteral("Function can only be called with |new|.")); +} + +ReturnedValue FunctionObject::failCallAsConstructor() const +{ + return engine()->throwTypeError(QStringLiteral("Function is not a constructor.")); +} + +void FunctionObject::virtualConvertAndCall( + const FunctionObject *f, QObject *thisObject, + void **argv, const QMetaType *types, int argc) +{ + QV4::convertAndCall(f->engine(), thisObject, argv, types, argc, + [f](const Value *thisObject, const Value *argv, int argc) { + return f->call(thisObject, argv, argc); + }); } Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function) @@ -173,15 +126,20 @@ Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *sco return scope->engine()->memoryManager->allocate<ScriptFunction>(scope, function); } -Heap::FunctionObject *FunctionObject::createConstructorFunction(ExecutionContext *scope, Function *function, Object *homeObject, bool isDerivedConstructor) +Heap::FunctionObject *FunctionObject::createConstructorFunction( + ExecutionContext *scope, Function *function, Object *homeObject, bool isDerivedConstructor) { + QV4::ExecutionEngine *engine = scope->engine(); if (!function) { - Heap::DefaultClassConstructorFunction *c = scope->engine()->memoryManager->allocate<DefaultClassConstructorFunction>(scope); + Heap::DefaultClassConstructorFunction *c + = engine->memoryManager->allocate<DefaultClassConstructorFunction>(scope); c->isDerivedConstructor = isDerivedConstructor; return c; } - Heap::ConstructorFunction *c = scope->engine()->memoryManager->allocate<ConstructorFunction>(scope, function); - c->homeObject.set(scope->engine(), homeObject->d()); + + Heap::ConstructorFunction *c + = engine->memoryManager->allocate<ConstructorFunction>(scope, function); + c->homeObject.set(engine, homeObject->d()); c->isDerivedConstructor = isDerivedConstructor; return c; } @@ -198,9 +156,10 @@ Heap::FunctionObject *FunctionObject::createBuiltinFunction(ExecutionEngine *eng Scope scope(engine); ScopedString name(scope, nameOrSymbol); if (!name) - name = engine->newString(QChar::fromLatin1('[') + nameOrSymbol->toQString().midRef(1) + QChar::fromLatin1(']')); + name = engine->newString(QChar::fromLatin1('[') + QStringView{nameOrSymbol->toQString()}.mid(1) + QChar::fromLatin1(']')); - ScopedFunctionObject function(scope, engine->memoryManager->allocate<FunctionObject>(engine->rootContext(), name, code)); + ScopedFunctionObject function( + scope, engine->memoryManager->allocate<DynamicFunctionObject>(engine, name, code)); function->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(argumentCount)); return function->d(); } @@ -216,16 +175,29 @@ ReturnedValue FunctionObject::getHomeObject() const return Encode::undefined(); } -QQmlSourceLocation FunctionObject::sourceLocation() const +DEFINE_OBJECT_VTABLE(JavaScriptFunctionObject); + +QQmlSourceLocation JavaScriptFunctionObject::sourceLocation() const { return d()->function->sourceLocation(); } +DEFINE_OBJECT_VTABLE(DynamicFunctionObject); + +ReturnedValue DynamicFunctionObject::virtualCall( + const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) { + Heap::DynamicFunctionObject *d = static_cast<const DynamicFunctionObject *>(f)->d(); + if (d->jsCall) + return d->jsCall(f, thisObject, argv, argc); + return d->internalClass->engine->throwTypeError( + QStringLiteral("Function can only be called with |new|.")); +} + DEFINE_OBJECT_VTABLE(FunctionCtor); -void Heap::FunctionCtor::init(QV4::ExecutionContext *scope) +void Heap::FunctionCtor::init(QV4::ExecutionEngine *engine) { - Heap::FunctionObject::init(scope, QStringLiteral("Function")); + Heap::FunctionObject::init(engine, QStringLiteral("Function")); } // 15.3.2 @@ -273,7 +245,7 @@ QQmlRefPointer<ExecutableCompilationUnit> FunctionCtor::parse(ExecutionEngine *e if (engine->hasException) return nullptr; - return ExecutableCompilationUnit::create(cg.generateCompilationUnit()); + return engine->insertCompilationUnit(cg.generateCompilationUnit()); } ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) @@ -285,7 +257,7 @@ ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, co if (engine->hasException) return Encode::undefined(); - Function *vmf = compilationUnit->linkToEngine(engine); + Function *vmf = compilationUnit->rootFunction(); ExecutionContext *global = engine->scriptContext(); ReturnedValue o = Encode(FunctionObject::createScriptFunction(global, vmf)); @@ -328,6 +300,12 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(engine->symbol_hasInstance(), method_hasInstance, 1, Attr_ReadOnly); } +ReturnedValue FunctionPrototype::virtualCall( + const FunctionObject *, const Value *, const Value *, int) +{ + return Encode::undefined(); +} + ReturnedValue FunctionPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int) { ExecutionEngine *v4 = b->engine(); @@ -358,47 +336,49 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons return v4->throwTypeError(); thisObject = argc ? argv : nullptr; if (argc < 2 || argv[1].isNullOrUndefined()) - return f->call(thisObject, argv, 0); + return checkedResult(v4, f->call(thisObject, argv, 0)); Object *arr = argv[1].objectValue(); if (!arr) return v4->throwTypeError(); - uint len = arr->getLength(); - Scope scope(v4); + const int len = v4->safeForAllocLength(arr->getLength()); + CHECK_EXCEPTION(); + Value *arguments = scope.alloc<Scope::Uninitialized>(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->argc()); + int l = qMin(len, a->d()->context->argc()); memcpy(arguments, a->d()->context->args(), l*sizeof(Value)); - for (quint32 i = l; i < len; ++i) + for (int i = l; i < len; ++i) arguments[i] = Value::undefinedValue(); } else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) { auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData()); - uint alen = sad ? sad->values.size : 0; + int alen = sad ? sad->values.size : 0; if (alen > len) alen = len; - for (uint i = 0; i < alen; ++i) + for (int i = 0; i < alen; ++i) arguments[i] = sad->data(i); - for (quint32 i = alen; i < len; ++i) + for (int i = alen; i < len; ++i) arguments[i] = Value::undefinedValue(); } else { // need to init the arguments array, as the get() calls below can have side effects memset(arguments, 0, len*sizeof(Value)); - for (quint32 i = 0; i < len; ++i) + for (int i = 0; i < len; ++i) arguments[i] = arr->get(i); } } - return f->call(thisObject, arguments, len); + return checkedResult(v4, f->call(thisObject, arguments, len)); } ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { + QV4::ExecutionEngine *v4 = b->engine(); if (!thisObject->isFunctionObject()) - return b->engine()->throwTypeError(); + return v4->throwTypeError(); const FunctionObject *f = static_cast<const FunctionObject *>(thisObject); @@ -407,7 +387,7 @@ ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const ++argv; --argc; } - return f->call(thisObject, argv, argc); + return checkedResult(v4, f->call(thisObject, argv, argc)); } ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) @@ -442,10 +422,13 @@ ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Valu boundArgs->set(scope.engine, i, argv[i + 1]); } - ScopedContext ctx(scope, target->scope()); - Heap::BoundFunction *bound = BoundFunction::create(ctx, target, boundThis, boundArgs); - bound->setFunction(target->function()); - return bound->asReturnedValue(); + if (target->isConstructor()) { + return scope.engine->memoryManager->allocate<BoundConstructor>(target, boundThis, boundArgs) + ->asReturnedValue(); + } + + return scope.engine->memoryManager->allocate<BoundFunction>(target, boundThis, boundArgs) + ->asReturnedValue(); } ReturnedValue FunctionPrototype::method_hasInstance(const FunctionObject *, const Value *thisObject, const Value *argv, int argc) @@ -480,18 +463,18 @@ ReturnedValue ScriptFunction::virtualCallAsConstructor(const FunctionObject *fo, } ScopedValue thisObject(scope, v4->memoryManager->allocObject<Object>(ic)); - CppStackFrame frame; - frame.init(v4, f->function(), argv, argc); + JSTypesStackFrame frame; + frame.init(f->function(), argv, argc); frame.setupJSFrame(v4->jsStackTop, *f, f->scope(), thisObject, newTarget ? *newTarget : Value::undefinedValue()); - frame.push(); + frame.push(v4); v4->jsStackTop += frame.requiredJSStackFrameSize(); ReturnedValue result = Moth::VME::exec(&frame, v4); - frame.pop(); + frame.pop(v4); if (Q_UNLIKELY(v4->hasException)) return Encode::undefined(); @@ -502,49 +485,87 @@ ReturnedValue ScriptFunction::virtualCallAsConstructor(const FunctionObject *fo, DEFINE_OBJECT_VTABLE(ArrowFunction); -ReturnedValue ArrowFunction::virtualCall(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc) +void ArrowFunction::virtualCallWithMetaTypes(const FunctionObject *fo, QObject *thisObject, + void **a, const QMetaType *types, int argc) +{ + const ArrowFunction *self = static_cast<const ArrowFunction *>(fo); + Function *function = self->function(); + if (function->kind != Function::AotCompiled) { + QV4::convertAndCall(fo->engine(), thisObject, a, types, argc, + [fo](const Value *thisObject, const Value *argv, int argc) { + return ArrowFunction::virtualCall(fo, thisObject, argv, argc); + }); + return; + } + + QV4::Scope scope(fo->engine()); + QV4::Scoped<ExecutionContext> context(scope, self->scope()); + MetaTypesStackFrame frame; + frame.init(function, thisObject, context, a, types, argc); + frame.push(scope.engine); + Moth::VME::exec(&frame, scope.engine); + frame.pop(scope.engine); +} + +static ReturnedValue qfoDoCall( + const QV4::JavaScriptFunctionObject *fo, const QV4::Value *thisObject, + const QV4::Value *argv, int argc) { ExecutionEngine *engine = fo->engine(); - CppStackFrame frame; - frame.init(engine, fo->function(), argv, argc, true); + JSTypesStackFrame frame; + frame.init(fo->function(), argv, argc, true); frame.setupJSFrame(engine->jsStackTop, *fo, fo->scope(), - thisObject ? *thisObject : Value::undefinedValue(), - Value::undefinedValue()); + thisObject ? *thisObject : Value::undefinedValue()); - frame.push(); + frame.push(engine); engine->jsStackTop += frame.requiredJSStackFrameSize(); ReturnedValue result; do { - frame.pendingTailCall = false; + frame.setPendingTailCall(false); result = Moth::VME::exec(&frame, engine); - frame.isTailCalling = true; - } while (frame.pendingTailCall); + frame.setTailCalling(true); + } while (frame.pendingTailCall()); - frame.pop(); + frame.pop(engine); return result; } +ReturnedValue ArrowFunction::virtualCall(const QV4::FunctionObject *fo, const Value *thisObject, + const QV4::Value *argv, int argc) +{ + const ArrowFunction *self = static_cast<const ArrowFunction *>(fo); + Function *function = self->function(); + switch (function->kind) { + case Function::AotCompiled: + return QV4::convertAndCall( + fo->engine(), &function->aotCompiledFunction, thisObject, argv, argc, + [fo](QObject *thisObject, void **a, const QMetaType *types, int argc) { + ArrowFunction::virtualCallWithMetaTypes(fo, thisObject, a, types, argc); + }); + case Function::JsTyped: + return QV4::coerceAndCall( + fo->engine(), &function->jsTypedFunction, function->compiledFunction, argv, argc, + [self, thisObject](const Value *argv, int argc) { + return qfoDoCall(self, thisObject, argv, argc); + }); + default: + break; + } + + return qfoDoCall(self, thisObject, argv, argc); +} + void Heap::ArrowFunction::init(QV4::ExecutionContext *scope, Function *function, QV4::String *n) { - FunctionObject::init(); - this->scope.set(scope->engine(), scope->d()); - - setFunction(function); Q_ASSERT(function); + JavaScriptFunctionObject::init(scope, function, n); Scope s(scope); - ScopedFunctionObject f(s, this); - - ScopedString name(s, n ? n->d() : function->name()); - if (name) - f->setName(name); - Q_ASSERT(internalClass && internalClass->verifyIndex(s.engine->id_length()->propertyKey(), Index_Length)); setProperty(s.engine, Index_Length, Value::fromInt32(int(function->compiledFunction->length))); - canBeTailCalled = true; } void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function) @@ -557,6 +578,13 @@ void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_ProtoConstructor); } +void Heap::DefaultClassConstructorFunction::init(QV4::ExecutionContext *scope) +{ + Scope s(scope->engine()); + FunctionObject::init(s.engine, nullptr); + this->scope.set(s.engine, scope->d()); +} + Heap::InternalClass *ScriptFunction::classForConstructor() const { Scope scope(engine()); @@ -583,19 +611,19 @@ ReturnedValue ConstructorFunction::virtualCallAsConstructor(const FunctionObject ExecutionEngine *v4 = f->engine(); - CppStackFrame frame; - frame.init(v4, f->function(), argv, argc); - frame.setupJSFrame(v4->jsStackTop, *f, f->scope(), + JSTypesStackFrame frame; + frame.init(c->function(), argv, argc); + frame.setupJSFrame(v4->jsStackTop, *f, c->scope(), Value::emptyValue(), newTarget ? *newTarget : Value::undefinedValue()); - frame.push(); + frame.push(v4); v4->jsStackTop += frame.requiredJSStackFrameSize(); ReturnedValue result = Moth::VME::exec(&frame, v4); ReturnedValue thisObject = frame.jsFrame->thisObject.asReturnedValue(); - frame.pop(); + frame.pop(v4); if (Q_UNLIKELY(v4->hasException)) return Encode::undefined(); @@ -637,20 +665,20 @@ ReturnedValue DefaultClassConstructorFunction::virtualCallAsConstructor(const Fu ScopedFunctionObject super(scope, f->getPrototypeOf()); Q_ASSERT(super->isFunctionObject()); - CppStackFrame frame; - frame.init(v4, nullptr, argv, argc); - frame.setupJSFrame(v4->jsStackTop, *f, f->scope(), + JSTypesStackFrame frame; + frame.init(nullptr, argv, argc); + frame.setupJSFrame(v4->jsStackTop, *f, c->scope(), Value::undefinedValue(), newTarget ? *newTarget : Value::undefinedValue(), argc, argc); - frame.push(); + frame.push(v4); v4->jsStackTop += frame.requiredJSStackFrameSize(argc); // Do a super call ReturnedValue result = super->callAsConstructor(argv, argc, newTarget); ReturnedValue thisObject = frame.jsFrame->thisObject.asReturnedValue(); - frame.pop(); + frame.pop(v4); if (Q_UNLIKELY(v4->hasException)) return Encode::undefined(); @@ -676,57 +704,66 @@ DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); DEFINE_OBJECT_VTABLE(BoundFunction); -void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, - const Value &boundThis, QV4::MemberData *boundArgs) +void Heap::BoundFunction::init( + QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs) { - Scope s(scope); - Heap::FunctionObject::init(scope, QStringLiteral("__bound function__")); + ExecutionEngine *engine = target->engine(); + Scope s(engine); + ScopedString name(s, engine->newString(QStringLiteral("__bound function__"))); + if (auto *js = target->as<QV4::JavaScriptFunctionObject>()) { + ScopedContext ctx(s, js->scope()); + JavaScriptFunctionObject::init(ctx, js->function(), name); + } else { + Q_ASSERT(name); + JavaScriptFunctionObject::init(engine->rootContext(), nullptr, name); + } + this->target.set(s.engine, target->d()); this->boundArgs.set(s.engine, boundArgs ? boundArgs->d() : nullptr); - this->boundThis.set(scope->engine(), boundThis); - - if (!target->isConstructor()) - jsConstruct = nullptr; + this->boundThis.set(s.engine, boundThis); ScopedObject f(s, this); - ScopedValue l(s, target->get(s.engine->id_length())); + ScopedValue l(s, target->get(engine->id_length())); int len = l->toUInt32(); if (boundArgs) len -= boundArgs->size(); if (len < 0) len = 0; - f->defineReadonlyConfigurableProperty(s.engine->id_length(), Value::fromInt32(len)); + f->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(len)); ScopedProperty pd(s); - pd->value = s.engine->thrower(); - pd->set = s.engine->thrower(); - f->insertMember(s.engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); - f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); + pd->value = engine->thrower(); + pd->set = engine->thrower(); + f->insertMember(engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); + f->insertMember(engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); } ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *, const Value *argv, int argc) { - const BoundFunction *f = static_cast<const BoundFunction *>(fo); - Scope scope(f->engine()); - - if (scope.hasException()) + QV4::ExecutionEngine *v4 = fo->engine(); + if (v4->hasException) return Encode::undefined(); + const BoundFunction *f = static_cast<const BoundFunction *>(fo); + Scope scope(v4); Scoped<MemberData> boundArgs(scope, f->boundArgs()); ScopedFunctionObject target(scope, f->target()); - JSCallData jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc); - *jsCallData->thisObject = f->boundThis(); - Value *argp = jsCallData->args; + JSCallArguments jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc); + *jsCallData.thisObject = f->boundThis(); + Value *argp = jsCallData.args; if (boundArgs) { memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value)); argp += boundArgs->size(); } memcpy(argp, argv, argc*sizeof(Value)); - return target->call(jsCallData); + return checkedResult(v4, target->call(jsCallData)); } -ReturnedValue BoundFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *) +DEFINE_OBJECT_VTABLE(BoundConstructor); + +ReturnedValue BoundConstructor::virtualCallAsConstructor( + const FunctionObject *fo, const Value *argv, int argc, const Value *) { const BoundFunction *f = static_cast<const BoundFunction *>(fo); Scope scope(f->engine()); @@ -736,8 +773,8 @@ ReturnedValue BoundFunction::virtualCallAsConstructor(const FunctionObject *fo, Scoped<MemberData> boundArgs(scope, f->boundArgs()); ScopedFunctionObject target(scope, f->target()); - JSCallData jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc); - Value *argp = jsCallData->args; + JSCallArguments jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc); + Value *argp = jsCallData.args; if (boundArgs) { memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value)); argp += boundArgs->size(); |