1 /****************************************************************************
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
32 ****************************************************************************/
34 #include "qv4object_p.h"
35 #include "qv4jsir_p.h"
36 #include "qv4isel_p.h"
37 #include "qv4objectproto_p.h"
38 #include "qv4stringobject_p.h"
39 #include "qv4function_p.h"
40 #include <private/qv4mm_p.h>
42 #include "qv4arrayobject_p.h"
43 #include "qv4scopedvalue_p.h"
45 #include <private/qqmljsengine_p.h>
46 #include <private/qqmljslexer_p.h>
47 #include <private/qqmljsparser_p.h>
48 #include <private/qqmljsast_p.h>
49 #include <private/qqmlcontextwrapper_p.h>
50 #include <private/qqmlengine_p.h>
51 #include <qv4codegen_p.h>
52 #include "private/qlocale_tools_p.h"
53 #include "private/qqmlbuiltinfunctions_p.h"
55 #include <QtCore/QDebug>
57 #include "qv4alloca_p.h"
58 #include "qv4profiling_p.h"
63 DEFINE_OBJECT_VTABLE(FunctionObject);
65 Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
66 : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
70 Scope s(scope->engine());
71 ScopedFunctionObject f(s, this);
72 f->init(name, createProto);
75 Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto)
76 : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
80 Scope s(scope->engine());
81 ScopedString name(s, function->name());
82 ScopedFunctionObject f(s, this);
83 f->init(name, createProto);
86 Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto)
87 : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
91 Scope s(scope->engine());
92 ScopedFunctionObject f(s, this);
93 ScopedString n(s, s.engine->newString(name));
94 f->init(n, createProto);
97 Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
98 : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
100 , function(Q_NULLPTR)
102 Scope s(scope->engine);
103 ScopedFunctionObject f(s, this);
104 ScopedString n(s, s.engine->newString(name));
105 f->init(n, createProto);
108 Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name)
109 : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
111 , function(Q_NULLPTR)
114 ScopedFunctionObject f(s, this);
115 ScopedString n(s, name);
119 Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name)
120 : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
122 , function(Q_NULLPTR)
124 Scope s(scope->engine);
125 ScopedFunctionObject f(s, this);
126 ScopedString n(s, name);
130 Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype)
131 : Heap::Object(ic, prototype)
132 , scope(ic->engine->rootContext()->d())
133 , function(Q_NULLPTR)
135 Scope scope(ic->engine);
136 ScopedObject o(scope, this);
137 o->ensureMemberIndex(ic->engine, Index_Prototype);
138 memberData->data[Index_Prototype] = Encode::undefined();
142 Heap::FunctionObject::~FunctionObject()
145 function->compilationUnit->release();
148 void FunctionObject::init(String *n, bool createProto)
150 Scope s(internalClass()->engine);
151 ScopedValue protectThis(s, this);
153 ensureMemberIndex(s.engine, Heap::FunctionObject::Index_Prototype);
155 ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype()));
156 proto->ensureMemberIndex(s.engine, Heap::FunctionObject::Index_ProtoConstructor);
157 proto->memberData()->data[Heap::FunctionObject::Index_ProtoConstructor] = this->asReturnedValue();
158 memberData()->data[Heap::FunctionObject::Index_Prototype] = proto.asReturnedValue();
160 memberData()->data[Heap::FunctionObject::Index_Prototype] = Encode::undefined();
164 defineReadonlyProperty(s.engine->id_name(), v);
167 ReturnedValue FunctionObject::name() const
169 return get(scope()->engine->id_name());
173 ReturnedValue FunctionObject::newInstance()
175 Scope scope(internalClass()->engine);
176 ScopedCallData callData(scope);
177 return construct(callData);
180 ReturnedValue FunctionObject::construct(const Managed *that, CallData *)
182 return static_cast<const FunctionObject *>(that)->engine()->throwTypeError();
185 ReturnedValue FunctionObject::call(const Managed *, CallData *)
187 return Encode::undefined();
190 void FunctionObject::markObjects(Heap::Base *that, ExecutionEngine *e)
192 Heap::FunctionObject *o = static_cast<Heap::FunctionObject *>(that);
196 Object::markObjects(that, e);
199 Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function, bool createProto)
201 if (function->needsActivation() ||
202 function->compiledFunction->flags & CompiledData::Function::HasCatchOrWith ||
203 function->compiledFunction->nFormals > QV4::Global::ReservedArgumentCount ||
204 function->isNamedExpression())
205 return scope->d()->engine->memoryManager->alloc<ScriptFunction>(scope, function);
206 return scope->d()->engine->memoryManager->alloc<SimpleScriptFunction>(scope, function, createProto);
209 bool FunctionObject::isBinding() const
211 return d()->vtable() == QQmlBindingFunction::staticVTable();
214 bool FunctionObject::isBoundFunction() const
216 return d()->vtable() == BoundFunction::staticVTable();
219 QQmlSourceLocation FunctionObject::sourceLocation() const
222 Q_ASSERT(as<const QV4::QQmlBindingFunction>());
223 return static_cast<QV4::Heap::QQmlBindingFunction *>(d())->bindingLocation;
225 QV4::Function *function = d()->function;
228 return QQmlSourceLocation(function->sourceFile(), function->compiledFunction->location.line, function->compiledFunction->location.column);
231 DEFINE_OBJECT_VTABLE(FunctionCtor);
233 Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope)
234 : Heap::FunctionObject(scope, QStringLiteral("Function"))
239 ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
241 Scope scope(static_cast<const Object *>(that)->engine());
242 Scoped<FunctionCtor> f(scope, static_cast<const FunctionCtor *>(that));
243 ScopedContext ctx(scope, scope.engine->currentContext());
246 if (callData->argc > 0) {
247 for (int i = 0; i < callData->argc - 1; ++i) {
249 arguments += QLatin1String(", ");
250 arguments += callData->args[i].toQString();
252 body = callData->args[callData->argc - 1].toQString();
254 if (ctx->d()->engine->hasException)
255 return Encode::undefined();
257 QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}");
259 QQmlJS::Engine ee, *engine = ⅇ
260 QQmlJS::Lexer lexer(engine);
261 lexer.setCode(function, 1, false);
262 QQmlJS::Parser parser(engine);
264 const bool parsed = parser.parseExpression();
267 return scope.engine->throwSyntaxError(QLatin1String("Parse error"));
269 using namespace QQmlJS::AST;
270 FunctionExpression *fe = QQmlJS::AST::cast<FunctionExpression *>(parser.rootNode());
272 return scope.engine->throwSyntaxError(QLatin1String("Parse error"));
274 IR::Module module(scope.engine->debugger != 0);
276 QQmlJS::RuntimeCodegen cg(scope.engine, f->strictMode());
277 cg.generateFromFunctionExpression(QString(), function, fe, &module);
279 Compiler::JSUnitGenerator jsGenerator(&module);
280 QScopedPointer<EvalInstructionSelection> isel(scope.engine->iselFactory->create(QQmlEnginePrivate::get(scope.engine), scope.engine->executableAllocator, &module, &jsGenerator));
281 QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = isel->compile();
282 Function *vmf = compilationUnit->linkToEngine(scope.engine);
284 ScopedContext global(scope, scope.engine->rootContext());
285 return FunctionObject::createScriptFunction(global, vmf)->asReturnedValue();
288 // 15.3.1: This is equivalent to new Function(...)
289 ReturnedValue FunctionCtor::call(const Managed *that, CallData *callData)
291 return construct(that, callData);
294 DEFINE_OBJECT_VTABLE(FunctionPrototype);
296 Heap::FunctionPrototype::FunctionPrototype(InternalClass *ic, QV4::Object *prototype)
297 : Heap::FunctionObject(ic, prototype)
301 void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
304 ScopedObject o(scope);
306 ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
307 ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
309 defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(0));
310 defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
311 defineDefaultProperty(engine->id_toString(), method_toString, 0);
312 defineDefaultProperty(QStringLiteral("apply"), method_apply, 2);
313 defineDefaultProperty(QStringLiteral("call"), method_call, 1);
314 defineDefaultProperty(QStringLiteral("bind"), method_bind, 1);
318 ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
320 FunctionObject *fun = ctx->thisObject().as<FunctionObject>();
322 return ctx->engine()->throwTypeError();
324 return ctx->d()->engine->newString(QStringLiteral("function() { [code] }"))->asReturnedValue();
327 ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
330 ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
332 return ctx->engine()->throwTypeError();
334 ScopedValue arg(scope, ctx->argument(1));
336 ScopedObject arr(scope, arg);
341 if (!arg->isNullOrUndefined())
342 return ctx->engine()->throwTypeError();
344 len = arr->getLength();
347 ScopedCallData callData(scope, len);
350 if (arr->arrayType() != Heap::ArrayData::Simple || arr->protoHasArray()) {
351 for (quint32 i = 0; i < len; ++i)
352 callData->args[i] = arr->getIndexed(i);
354 uint alen = arr->arrayData() ? arr->arrayData()->len : 0;
357 for (uint i = 0; i < alen; ++i)
358 callData->args[i] = static_cast<Heap::SimpleArrayData *>(arr->arrayData())->data(i);
359 for (quint32 i = alen; i < len; ++i)
360 callData->args[i] = Primitive::undefinedValue();
364 callData->thisObject = ctx->argument(0);
365 return o->call(callData);
368 ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
372 ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
374 return ctx->engine()->throwTypeError();
376 ScopedCallData callData(scope, ctx->argc() ? ctx->argc() - 1 : 0);
378 for (int i = 1; i < ctx->argc(); ++i)
379 callData->args[i - 1] = ctx->args()[i];
381 callData->thisObject = ctx->argument(0);
382 return o->call(callData);
385 ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
388 ScopedFunctionObject target(scope, ctx->thisObject());
390 return ctx->engine()->throwTypeError();
392 ScopedValue boundThis(scope, ctx->argument(0));
393 Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0);
394 if (ctx->argc() > 1) {
395 boundArgs = MemberData::reallocate(scope.engine, 0, ctx->argc() - 1);
396 boundArgs->d()->size = ctx->argc() - 1;
397 memcpy(boundArgs->data(), ctx->args() + 1, (ctx->argc() - 1)*sizeof(Value));
400 ScopedContext global(scope, scope.engine->rootContext());
401 return BoundFunction::create(global, target, boundThis, boundArgs)->asReturnedValue();
404 DEFINE_OBJECT_VTABLE(ScriptFunction);
406 Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *function)
407 : Heap::SimpleScriptFunction(scope, function, true)
411 ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData)
413 ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
414 if (v4->hasException)
415 return Encode::undefined();
416 CHECK_STACK_LIMITS(v4);
419 Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
421 InternalClass *ic = scope.engine->emptyClass;
422 ScopedObject proto(scope, f->protoForConstructor());
423 ScopedObject obj(scope, v4->newObject(ic, proto));
425 ScopedContext context(scope, v4->currentContext());
426 callData->thisObject = obj.asReturnedValue();
427 Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
429 ExecutionContextSaver ctxSaver(scope, context);
430 ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
432 if (f->function()->compiledFunction->hasQmlDependencies())
433 QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
435 if (v4->hasException)
436 return Encode::undefined();
438 if (result->isObject())
439 return result->asReturnedValue();
440 return obj.asReturnedValue();
443 ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
445 ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
446 if (v4->hasException)
447 return Encode::undefined();
448 CHECK_STACK_LIMITS(v4);
451 Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
452 ScopedContext context(scope, v4->currentContext());
454 Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
456 ExecutionContextSaver ctxSaver(scope, context);
457 ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
459 if (f->function()->compiledFunction->hasQmlDependencies())
460 QmlContextWrapper::registerQmlDependencies(scope.engine, f->function()->compiledFunction);
462 return result->asReturnedValue();
465 DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
467 Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto)
468 : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype())
470 this->scope = scope->d();
472 this->function = function;
473 function->compilationUnit->addref();
475 Q_ASSERT(function->code);
478 ScopedFunctionObject f(s, this);
481 ScopedString name(s, function->name());
482 f->init(name, createProto);
483 f->defineReadonlyProperty(scope->d()->engine->id_length(), Primitive::fromInt32(f->formalParameterCount()));
485 f->ensureMemberIndex(s.engine, Index_Length);
486 memberData->data[Index_Name] = function->name();
487 memberData->data[Index_Length] = Primitive::fromInt32(f->formalParameterCount());
490 if (scope->d()->strictMode) {
491 ScopedProperty pd(s);
492 pd->value = s.engine->thrower();
493 pd->set = s.engine->thrower();
494 f->insertMember(scope->d()->engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
495 f->insertMember(scope->d()->engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
499 ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *callData)
501 ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
502 if (v4->hasException)
503 return Encode::undefined();
504 CHECK_STACK_LIMITS(v4);
507 Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
509 InternalClass *ic = scope.engine->emptyClass;
510 ScopedObject proto(scope, f->protoForConstructor());
511 callData->thisObject = v4->newObject(ic, proto);
513 ExecutionContextSaver ctxSaver(scope, v4->currentContext());
515 CallContext::Data ctx(v4);
517 ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
519 ctx.setVtable(CallContext::staticVTable());
520 ctx.strictMode = f->strictMode();
521 ctx.callData = callData;
522 ctx.function = f->d();
523 ctx.compilationUnit = f->function()->compilationUnit;
524 ctx.lookups = ctx.compilationUnit->runtimeLookups;
525 ctx.outer = f->scope();
526 ctx.locals = scope.alloc(f->varCount());
527 for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
528 callData->args[i] = Encode::undefined();
529 Q_ASSERT(v4->currentContext() == &ctx);
531 ScopedObject result(scope, Q_V4_PROFILE(v4, f->function()));
533 if (f->function()->compiledFunction->hasQmlDependencies())
534 QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
537 return callData->thisObject.asReturnedValue();
538 return result.asReturnedValue();
541 ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData)
543 ExecutionEngine *v4 = static_cast<const SimpleScriptFunction *>(that)->internalClass()->engine;
544 if (v4->hasException)
545 return Encode::undefined();
546 CHECK_STACK_LIMITS(v4);
549 Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
551 ExecutionContextSaver ctxSaver(scope, v4->currentContext());
553 CallContext::Data ctx(v4);
555 ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
557 ctx.setVtable(CallContext::staticVTable());
558 ctx.strictMode = f->strictMode();
559 ctx.callData = callData;
560 ctx.function = f->d();
561 ctx.compilationUnit = f->function()->compilationUnit;
562 ctx.lookups = ctx.compilationUnit->runtimeLookups;
563 ctx.outer = f->scope();
564 ctx.locals = scope.alloc(f->varCount());
565 for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
566 callData->args[i] = Encode::undefined();
567 Q_ASSERT(v4->currentContext() == &ctx);
569 ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
571 if (f->function()->compiledFunction->hasQmlDependencies())
572 QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
574 return result->asReturnedValue();
577 Heap::Object *SimpleScriptFunction::protoForConstructor()
579 Scope scope(engine());
580 ScopedObject p(scope, protoProperty());
583 return scope.engine->objectPrototype()->d();
588 DEFINE_OBJECT_VTABLE(BuiltinFunction);
590 Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *))
591 : Heap::FunctionObject(scope, name)
596 ReturnedValue BuiltinFunction::construct(const Managed *f, CallData *)
598 return static_cast<const BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
601 ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData)
603 const BuiltinFunction *f = static_cast<const BuiltinFunction *>(that);
604 ExecutionEngine *v4 = f->internalClass()->engine;
605 if (v4->hasException)
606 return Encode::undefined();
607 CHECK_STACK_LIMITS(v4);
610 ExecutionContextSaver ctxSaver(scope, v4->currentContext());
612 CallContext::Data ctx(v4);
614 ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
616 ctx.setVtable(CallContext::staticVTable());
617 ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
618 ctx.callData = callData;
619 Q_ASSERT(v4->currentContext() == &ctx);
620 Scoped<CallContext> sctx(scope, &ctx);
622 return f->d()->code(sctx);
625 ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callData)
627 const IndexedBuiltinFunction *f = static_cast<const IndexedBuiltinFunction *>(that);
628 ExecutionEngine *v4 = f->internalClass()->engine;
629 if (v4->hasException)
630 return Encode::undefined();
631 CHECK_STACK_LIMITS(v4);
634 ExecutionContextSaver ctxSaver(scope, v4->currentContext());
636 CallContext::Data ctx(v4);
638 ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
640 ctx.setVtable(CallContext::staticVTable());
641 ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
642 ctx.callData = callData;
643 Q_ASSERT(v4->currentContext() == &ctx);
644 Scoped<CallContext> sctx(scope, &ctx);
646 return f->d()->code(sctx, f->d()->index);
649 DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
651 DEFINE_OBJECT_VTABLE(BoundFunction);
653 Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target,
654 const Value &boundThis, QV4::MemberData *boundArgs)
655 : Heap::FunctionObject(scope, QStringLiteral("__bound function__"))
656 , target(target->d())
657 , boundArgs(boundArgs ? boundArgs->d() : 0)
659 this->boundThis = boundThis;
662 ScopedObject f(s, this);
664 ScopedValue l(s, target->get(s.engine->id_length()));
665 int len = l->toUInt32();
667 len -= boundArgs->size();
670 f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(len));
672 ScopedProperty pd(s);
673 pd->value = s.engine->thrower();
674 pd->set = s.engine->thrower();
675 f->insertMember(s.engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
676 f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
679 ReturnedValue BoundFunction::call(const Managed *that, CallData *dd)
681 const BoundFunction *f = static_cast<const BoundFunction *>(that);
682 Scope scope(f->engine());
683 if (scope.hasException())
684 return Encode::undefined();
686 Scoped<MemberData> boundArgs(scope, f->boundArgs());
687 ScopedCallData callData(scope, (boundArgs ? boundArgs->size() : 0) + dd->argc);
688 callData->thisObject = f->boundThis();
689 Value *argp = callData->args;
691 memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
692 argp += boundArgs->size();
694 memcpy(argp, dd->args, dd->argc*sizeof(Value));
695 ScopedFunctionObject t(scope, f->target());
696 return t->call(callData);
699 ReturnedValue BoundFunction::construct(const Managed *that, CallData *dd)
701 const BoundFunction *f = static_cast<const BoundFunction *>(that);
702 Scope scope(f->engine());
703 if (scope.hasException())
704 return Encode::undefined();
706 Scoped<MemberData> boundArgs(scope, f->boundArgs());
707 ScopedCallData callData(scope, (boundArgs ? boundArgs->size() : 0) + dd->argc);
708 Value *argp = callData->args;
710 memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
711 argp += boundArgs->size();
713 memcpy(argp, dd->args, dd->argc*sizeof(Value));
714 ScopedFunctionObject t(scope, f->target());
715 return t->construct(callData);
718 void BoundFunction::markObjects(Heap::Base *that, ExecutionEngine *e)
720 BoundFunction::Data *o = static_cast<BoundFunction::Data *>(that);
722 o->boundThis.mark(e);
724 o->boundArgs->mark(e);
725 FunctionObject::markObjects(that, e);