Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qv4functionobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qv4object_p.h"
5#include "qv4function_p.h"
6#include "qv4symbol_p.h"
7#include <private/qv4mm_p.h>
8
9#include "qv4scopedvalue_p.h"
11
12#include <private/qqmljsengine_p.h>
13#include <private/qqmljslexer_p.h>
14#include <private/qqmljsparser_p.h>
15#include <private/qqmljsast_p.h>
16#include <private/qqmljavascriptexpression_p.h>
17#include <private/qqmlengine_p.h>
18#include <qv4runtimecodegen_p.h>
19#include "private/qlocale_tools_p.h"
20#include "private/qqmlbuiltinfunctions_p.h"
21#include <private/qv4jscall_p.h>
22#include <private/qv4vme_moth_p.h>
23#include <private/qv4alloca_p.h>
24
25#include <QtCore/QDebug>
26#include <algorithm>
27
28using namespace QV4;
29
30
32
33void Heap::FunctionObject::init(QV4::ExecutionEngine *engine, QV4::String *name)
34{
35 Object::init();
36 Scope s(engine);
38 if (name)
39 f->setName(name);
40}
41
42void Heap::FunctionObject::init(QV4::ExecutionEngine *engine, const QString &name)
43{
44 Scope valueScope(engine);
45 ScopedString s(valueScope, engine->newString(name));
46 init(engine, s);
47}
48
49void Heap::FunctionObject::init()
50{
51 init(internalClass->engine, static_cast<QV4::String *>(nullptr));
52}
53
54void Heap::JavaScriptFunctionObject::init(
55 QV4::ExecutionContext *scope, Function *function, QV4::String *n)
56{
57 Q_ASSERT(n || function);
58 Scope s(scope->engine());
59 ScopedString name(s, n ? n->d() : function->name());
60 FunctionObject::init(s.engine, name);
61 this->scope.set(s.engine, scope->d());
62 setFunction(function);
63}
64
65void Heap::JavaScriptFunctionObject::setFunction(Function *f)
66{
67 if (f) {
68 function = f;
69 function->executableCompilationUnit()->addref();
70 }
71}
72void Heap::JavaScriptFunctionObject::destroy()
73{
74 if (function)
75 function->executableCompilationUnit()->release();
76 FunctionObject::destroy();
77}
78
79void Heap::DynamicFunctionObject::init(
81{
82 FunctionObject::init(engine, name);
83 jsCall = call;
84}
85
87{
88 Scope s(this);
89
90 Q_ASSERT(s.engine->internalClasses(EngineBase::Class_ObjectProto)->verifyIndex(s.engine->id_constructor()->propertyKey(), protoConstructorSlot));
91
92 ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses(EngineBase::Class_ObjectProto)));
93 proto->setProperty(protoConstructorSlot, d());
94 defineDefaultProperty(s.engine->id_prototype(), proto, Attr_NotEnumerable|Attr_NotConfigurable);
95}
96
98{
99 return get(engine()->id_name());
100}
101
103{
104 return engine()->throwTypeError(QStringLiteral("Function can only be called with |new|."));
105}
106
108{
109 return engine()->throwTypeError(QStringLiteral("Function is not a constructor."));
110}
111
113 const FunctionObject *f, QObject *thisObject,
114 void **argv, const QMetaType *types, int argc)
115{
116 QV4::convertAndCall(f->engine(), thisObject, argv, types, argc,
117 [f](const Value *thisObject, const Value *argv, int argc) {
118 return f->call(thisObject, argv, argc);
119 });
120}
121
122Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function)
123{
124 if (function->isArrowFunction())
125 return scope->engine()->memoryManager->allocate<ArrowFunction>(scope, function);
126 return scope->engine()->memoryManager->allocate<ScriptFunction>(scope, function);
127}
128
130 ExecutionContext *scope, Function *function, Object *homeObject, bool isDerivedConstructor)
131{
133 if (!function) {
134 Heap::DefaultClassConstructorFunction *c
136 c->isDerivedConstructor = isDerivedConstructor;
137 return c;
138 }
139
140 Heap::ConstructorFunction *c
142 c->homeObject.set(engine, homeObject->d());
143 c->isDerivedConstructor = isDerivedConstructor;
144 return c;
145}
146
147Heap::FunctionObject *FunctionObject::createMemberFunction(ExecutionContext *scope, Function *function, Object *homeObject, QV4::String *name)
148{
149 Heap::MemberFunction *m = scope->engine()->memoryManager->allocate<MemberFunction>(scope, function, name);
150 m->homeObject.set(scope->engine(), homeObject->d());
151 return m;
152}
153
154Heap::FunctionObject *FunctionObject::createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount)
155{
156 Scope scope(engine);
157 ScopedString name(scope, nameOrSymbol);
158 if (!name)
159 name = engine->newString(QChar::fromLatin1('[') + QStringView{nameOrSymbol->toQString()}.mid(1) + QChar::fromLatin1(']'));
160
163 function->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(argumentCount));
164 return function->d();
165}
166
168{
169 const MemberFunction *m = as<MemberFunction>();
170 if (m)
171 return m->d()->homeObject->asReturnedValue();
172 const ConstructorFunction *c = as<ConstructorFunction>();
173 if (c)
174 return c->d()->homeObject->asReturnedValue();
175 return Encode::undefined();
176}
177
179
181{
182 return d()->function->sourceLocation();
183}
184
186
188 const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) {
189 Heap::DynamicFunctionObject *d = static_cast<const DynamicFunctionObject *>(f)->d();
190 if (d->jsCall)
191 return d->jsCall(f, thisObject, argv, argc);
193 QStringLiteral("Function can only be called with |new|."));
194}
195
197
199{
200 Heap::FunctionObject::init(engine, QStringLiteral("Function"));
201}
202
203// 15.3.2
204QQmlRefPointer<ExecutableCompilationUnit> FunctionCtor::parse(ExecutionEngine *engine, const Value *argv, int argc, Type t)
205{
207 QString body;
208 if (argc > 0) {
209 for (int i = 0, ei = argc - 1; i < ei; ++i) {
210 if (i)
211 arguments += QLatin1String(", ");
212 arguments += argv[i].toQString();
213 }
214 body = argv[argc - 1].toQString();
215 }
216 if (engine->hasException)
217 return nullptr;
218
219 QString function = (t == Type_Function ? QLatin1String("function anonymous(") : QLatin1String("function* anonymous(")) + arguments + QLatin1String("\n){") + body + QLatin1String("\n}");
220
222 QQmlJS::Lexer lexer(&ee);
223 lexer.setCode(function, 1, false);
224 QQmlJS::Parser parser(&ee);
225
226 const bool parsed = parser.parseExpression();
227
228 if (!parsed) {
229 engine->throwSyntaxError(QLatin1String("Parse error"));
230 return nullptr;
231 }
232
233 QQmlJS::AST::FunctionExpression *fe = QQmlJS::AST::cast<QQmlJS::AST::FunctionExpression *>(parser.rootNode());
234 if (!fe) {
235 engine->throwSyntaxError(QLatin1String("Parse error"));
236 return nullptr;
237 }
238
239 Compiler::Module module(engine->debugger() != nullptr);
240
241 Compiler::JSUnitGenerator jsGenerator(&module);
242 RuntimeCodegen cg(engine, &jsGenerator, false);
243 cg.generateFromFunctionExpression(QString(), function, fe, &module);
244
245 if (engine->hasException)
246 return nullptr;
247
249}
250
251ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
252{
253 ExecutionEngine *engine = f->engine();
254
255 QQmlRefPointer<ExecutableCompilationUnit> compilationUnit
256 = parse(engine, argv, argc, Type_Function);
257 if (engine->hasException)
258 return Encode::undefined();
259
260 Function *vmf = compilationUnit->rootFunction();
263
264 if (!newTarget)
265 return o;
266 Scope scope(engine);
267 ScopedObject obj(scope, o);
268 obj->setProtoFromNewTarget(newTarget);
269 return obj->asReturnedValue();
270}
271
272// 15.3.1: This is equivalent to new Function(...)
273ReturnedValue FunctionCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
274{
275 return virtualCallAsConstructor(f, argv, argc, f);
276}
277
279
281{
282 Heap::FunctionObject::init();
283}
284
286{
287 Scope scope(engine);
288 ScopedObject o(scope);
289
290 ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(1));
291 ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
292
295 defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
296 defineDefaultProperty(engine->id_toString(), method_toString, 0);
297 defineDefaultProperty(QStringLiteral("apply"), method_apply, 2);
298 defineDefaultProperty(QStringLiteral("call"), method_call, 1);
299 defineDefaultProperty(QStringLiteral("bind"), method_bind, 1);
301}
302
304 const FunctionObject *, const Value *, const Value *, int)
305{
306 return Encode::undefined();
307}
308
310{
311 ExecutionEngine *v4 = b->engine();
312 const FunctionObject *fun = thisObject->as<FunctionObject>();
313 if (!fun)
314 return v4->throwTypeError();
315
316 const Scope scope(fun->engine());
317 const ScopedString scopedFunctionName(scope, fun->name());
318 const QString functionName(scopedFunctionName ? scopedFunctionName->toQString() : QString());
319 QString functionAsString = QStringLiteral("function");
320
321 // If fun->name() is empty, then there is no function name
322 // to append because the function is anonymous.
323 if (!functionName.isEmpty())
324 functionAsString.append(QLatin1Char(' ') + functionName);
325
326 functionAsString.append(QStringLiteral("() { [native code] }"));
327
328 return Encode(v4->newString(functionAsString));
329}
330
331ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
332{
333 ExecutionEngine *v4 = b->engine();
334 const FunctionObject *f = thisObject->as<FunctionObject>();
335 if (!f)
336 return v4->throwTypeError();
337 thisObject = argc ? argv : nullptr;
338 if (argc < 2 || argv[1].isNullOrUndefined())
339 return checkedResult(v4, f->call(thisObject, argv, 0));
340
341 Object *arr = argv[1].objectValue();
342 if (!arr)
343 return v4->throwTypeError();
344
345 Scope scope(v4);
346 const int len = v4->safeForAllocLength(arr->getLength());
348
350 if (len) {
351 if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast<ArgumentsObject>()->fullyCreated()) {
353 int l = qMin(len, a->d()->context->argc());
354 memcpy(arguments, a->d()->context->args(), l*sizeof(Value));
355 for (int i = l; i < len; ++i)
357 } else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) {
358 auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData());
359 int alen = sad ? sad->values.size : 0;
360 if (alen > len)
361 alen = len;
362 for (int i = 0; i < alen; ++i)
363 arguments[i] = sad->data(i);
364 for (int i = alen; i < len; ++i)
366 } else {
367 // need to init the arguments array, as the get() calls below can have side effects
368 memset(arguments, 0, len*sizeof(Value));
369 for (int i = 0; i < len; ++i)
370 arguments[i] = arr->get(i);
371 }
372 }
373
374 return checkedResult(v4, f->call(thisObject, arguments, len));
375}
376
377ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
378{
379 QV4::ExecutionEngine *v4 = b->engine();
380 if (!thisObject->isFunctionObject())
381 return v4->throwTypeError();
382
383 const FunctionObject *f = static_cast<const FunctionObject *>(thisObject);
384
385 thisObject = argc ? argv : nullptr;
386 if (argc) {
387 ++argv;
388 --argc;
389 }
390 return checkedResult(v4, f->call(thisObject, argv, argc));
391}
392
393ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
394{
395 QV4::Scope scope(b);
396 ScopedFunctionObject target(scope, thisObject);
397 if (!target || target->isBinding())
398 return scope.engine->throwTypeError();
399
400 ScopedValue boundThis(scope, argc ? argv[0] : Value::undefinedValue());
401 Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)nullptr);
402
403 int nArgs = (argc - 1 >= 0) ? argc - 1 : 0;
404 if (target->isBoundFunction()) {
405 BoundFunction *bound = static_cast<BoundFunction *>(target.getPointer());
406 Scoped<MemberData> oldArgs(scope, bound->boundArgs());
407 boundThis = bound->boundThis();
408 int oldSize = !oldArgs ? 0 : oldArgs->size();
409 if (oldSize + nArgs) {
410 boundArgs = MemberData::allocate(scope.engine, oldSize + nArgs);
411 boundArgs->d()->values.size = oldSize + nArgs;
412 for (uint i = 0; i < static_cast<uint>(oldSize); ++i)
413 boundArgs->set(scope.engine, i, oldArgs->data()[i]);
414 for (uint i = 0; i < static_cast<uint>(nArgs); ++i)
415 boundArgs->set(scope.engine, oldSize + i, argv[i + 1]);
416 }
417 target = bound->target();
418 } else if (nArgs) {
419 boundArgs = MemberData::allocate(scope.engine, nArgs);
420 boundArgs->d()->values.size = nArgs;
421 for (uint i = 0, ei = static_cast<uint>(nArgs); i < ei; ++i)
422 boundArgs->set(scope.engine, i, argv[i + 1]);
423 }
424
425 if (target->isConstructor()) {
426 return scope.engine->memoryManager->allocate<BoundConstructor>(target, boundThis, boundArgs)
427 ->asReturnedValue();
428 }
429
430 return scope.engine->memoryManager->allocate<BoundFunction>(target, boundThis, boundArgs)
431 ->asReturnedValue();
432}
433
434ReturnedValue FunctionPrototype::method_hasInstance(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
435{
436 if (!argc)
437 return Encode(false);
438 const Object *o = thisObject->as<Object>();
439 if (!o)
440 return Encode(false);
441
442 return Object::virtualInstanceOf(o, argv[0]);
443}
444
446
447ReturnedValue ScriptFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *newTarget)
448{
449 ExecutionEngine *v4 = fo->engine();
450 const ScriptFunction *f = static_cast<const ScriptFunction *>(fo);
451 Q_ASSERT(newTarget->isFunctionObject());
452 const FunctionObject *nt = static_cast<const FunctionObject *>(newTarget);
453
454 Scope scope(v4);
455 Scoped<InternalClass> ic(scope);
456 if (nt->d() == f->d()) {
457 ic = f->classForConstructor();
458 } else {
459 ScopedObject o(scope, nt->protoProperty());
461 if (o)
462 ic = ic->changePrototype(o->d());
463 }
464 ScopedValue thisObject(scope, v4->memoryManager->allocObject<Object>(ic));
465
467 frame.init(f->function(), argv, argc);
468 frame.setupJSFrame(v4->jsStackTop, *f, f->scope(),
469 thisObject,
470 newTarget ? *newTarget : Value::undefinedValue());
471
472 frame.push(v4);
473 v4->jsStackTop += frame.requiredJSStackFrameSize();
474
476
477 frame.pop(v4);
478
479 if (Q_UNLIKELY(v4->hasException))
480 return Encode::undefined();
481 else if (!Value::fromReturnedValue(result).isObject())
482 return thisObject->asReturnedValue();
483 return result;
484}
485
487
489 void **a, const QMetaType *types, int argc)
490{
491 const ArrowFunction *self = static_cast<const ArrowFunction *>(fo);
492 Function *function = self->function();
493 if (function->kind != Function::AotCompiled) {
494 QV4::convertAndCall(fo->engine(), thisObject, a, types, argc,
495 [fo](const Value *thisObject, const Value *argv, int argc) {
496 return ArrowFunction::virtualCall(fo, thisObject, argv, argc);
497 });
498 return;
499 }
500
501 QV4::Scope scope(fo->engine());
504 frame.init(function, thisObject, context, a, types, argc);
505 frame.push(scope.engine);
506 Moth::VME::exec(&frame, scope.engine);
507 frame.pop(scope.engine);
508}
509
511 const QV4::JavaScriptFunctionObject *fo, const QV4::Value *thisObject,
512 const QV4::Value *argv, int argc)
513{
514 ExecutionEngine *engine = fo->engine();
516 frame.init(fo->function(), argv, argc, true);
517 frame.setupJSFrame(engine->jsStackTop, *fo, fo->scope(),
518 thisObject ? *thisObject : Value::undefinedValue());
519
520 frame.push(engine);
521 engine->jsStackTop += frame.requiredJSStackFrameSize();
522
524
525 do {
526 frame.setPendingTailCall(false);
528 frame.setTailCalling(true);
529 } while (frame.pendingTailCall());
530
531 frame.pop(engine);
532
533 return result;
534}
535
537 const QV4::Value *argv, int argc)
538{
539 const ArrowFunction *self = static_cast<const ArrowFunction *>(fo);
540 Function *function = self->function();
541 switch (function->kind) {
543 return QV4::convertAndCall(
544 fo->engine(), &function->aotCompiledFunction, thisObject, argv, argc,
545 [fo](QObject *thisObject, void **a, const QMetaType *types, int argc) {
546 ArrowFunction::virtualCallWithMetaTypes(fo, thisObject, a, types, argc);
547 });
549 return QV4::coerceAndCall(
550 fo->engine(), &function->jsTypedFunction, function->compiledFunction, argv, argc,
551 [self, thisObject](const Value *argv, int argc) {
552 return qfoDoCall(self, thisObject, argv, argc);
553 });
554 default:
555 break;
556 }
557
558 return qfoDoCall(self, thisObject, argv, argc);
559}
560
562{
563 Q_ASSERT(function);
564 JavaScriptFunctionObject::init(scope, function, n);
565
566 Scope s(scope);
567 Q_ASSERT(internalClass && internalClass->verifyIndex(s.engine->id_length()->propertyKey(), Index_Length));
568 setProperty(s.engine, Index_Length, Value::fromInt32(int(function->compiledFunction->length)));
569}
570
571void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function)
572{
573 ArrowFunction::init(scope, function);
574 Q_ASSERT(!function->isArrowFunction());
575
576 Scope s(scope);
577 ScopedFunctionObject f(s, this);
578 f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_ProtoConstructor);
579}
580
581void Heap::DefaultClassConstructorFunction::init(QV4::ExecutionContext *scope)
582{
583 Scope s(scope->engine());
584 FunctionObject::init(s.engine, nullptr);
585 this->scope.set(s.engine, scope->d());
586}
587
589{
590 Scope scope(engine());
591 ScopedValue o(scope, protoProperty());
592 if (d()->cachedClassForConstructor && d()->cachedClassForConstructor->prototype == o->heapObject())
593 return d()->cachedClassForConstructor;
594
595 Scoped<InternalClass> ic(scope, engine()->internalClasses(EngineBase::Class_Object));
596 ScopedObject p(scope, o);
597 if (p)
598 ic = ic->changePrototype(p->d());
599 d()->cachedClassForConstructor.set(scope.engine, ic->d());
600
601 return ic->d();
602}
603
605
607{
608 const ConstructorFunction *c = static_cast<const ConstructorFunction *>(f);
609 if (!c->d()->isDerivedConstructor)
610 return ScriptFunction::virtualCallAsConstructor(f, argv, argc, newTarget);
611
612 ExecutionEngine *v4 = f->engine();
613
615 frame.init(c->function(), argv, argc);
616 frame.setupJSFrame(v4->jsStackTop, *f, c->scope(),
618 newTarget ? *newTarget : Value::undefinedValue());
619
620 frame.push(v4);
621 v4->jsStackTop += frame.requiredJSStackFrameSize();
622
624 ReturnedValue thisObject = frame.jsFrame->thisObject.asReturnedValue();
625
626 frame.pop(v4);
627
628 if (Q_UNLIKELY(v4->hasException))
629 return Encode::undefined();
630 else if (Value::fromReturnedValue(result).isObject())
631 return result;
632 else if (!Value::fromReturnedValue(result).isUndefined())
633 return v4->throwTypeError();
634 else if (Value::fromReturnedValue(thisObject).isEmpty()) {
635 Scope scope(v4);
636 ScopedString s(scope, v4->newString(QStringLiteral("this")));
637 return v4->throwReferenceError(s);
638 }
639 return thisObject;
640}
641
643{
644 return f->engine()->throwTypeError(QStringLiteral("Cannot call a class constructor without |new|"));
645}
646
648
650
652{
654 ExecutionEngine *v4 = f->engine();
655
656 Scope scope(v4);
657
658 if (!c->d()->isDerivedConstructor) {
659 ScopedObject proto(scope, static_cast<const Object *>(newTarget)->get(scope.engine->id_prototype()));
660 ScopedObject c(scope, scope.engine->newObject());
661 c->setPrototypeUnchecked(proto);
662 return c->asReturnedValue();
663 }
664
665 ScopedFunctionObject super(scope, f->getPrototypeOf());
666 Q_ASSERT(super->isFunctionObject());
667
669 frame.init(nullptr, argv, argc);
670 frame.setupJSFrame(v4->jsStackTop, *f, c->scope(),
672 newTarget ? *newTarget : Value::undefinedValue(), argc, argc);
673
674 frame.push(v4);
675 v4->jsStackTop += frame.requiredJSStackFrameSize(argc);
676
677 // Do a super call
678 ReturnedValue result = super->callAsConstructor(argv, argc, newTarget);
679 ReturnedValue thisObject = frame.jsFrame->thisObject.asReturnedValue();
680
681 frame.pop(v4);
682
683 if (Q_UNLIKELY(v4->hasException))
684 return Encode::undefined();
685 else if (Value::fromReturnedValue(result).isObject())
686 return result;
687 else if (!Value::fromReturnedValue(result).isUndefined())
688 return v4->throwTypeError();
689 else if (Value::fromReturnedValue(thisObject).isEmpty()) {
690 Scope scope(v4);
691 ScopedString s(scope, v4->newString(QStringLiteral("this")));
692 return v4->throwReferenceError(s);
693 }
694
695 return thisObject;
696}
697
699{
700 return f->engine()->throwTypeError(QStringLiteral("Cannot call a class constructor without |new|"));
701}
702
704
706
707void Heap::BoundFunction::init(
708 QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs)
709{
710 ExecutionEngine *engine = target->engine();
711 Scope s(engine);
712 ScopedString name(s, engine->newString(QStringLiteral("__bound function__")));
713 if (auto *js = target->as<QV4::JavaScriptFunctionObject>()) {
714 ScopedContext ctx(s, js->scope());
715 JavaScriptFunctionObject::init(ctx, js->function(), name);
716 } else {
717 Q_ASSERT(name);
718 JavaScriptFunctionObject::init(engine->rootContext(), nullptr, name);
719 }
720
721 this->target.set(s.engine, target->d());
722 this->boundArgs.set(s.engine, boundArgs ? boundArgs->d() : nullptr);
723 this->boundThis.set(s.engine, boundThis);
724
725 ScopedObject f(s, this);
726
727 ScopedValue l(s, target->get(engine->id_length()));
728 int len = l->toUInt32();
729 if (boundArgs)
730 len -= boundArgs->size();
731 if (len < 0)
732 len = 0;
733 f->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(len));
734
735 ScopedProperty pd(s);
736 pd->value = engine->thrower();
737 pd->set = engine->thrower();
738 f->insertMember(engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
739 f->insertMember(engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
740}
741
742ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *, const Value *argv, int argc)
743{
744 QV4::ExecutionEngine *v4 = fo->engine();
745 if (v4->hasException)
746 return Encode::undefined();
747
748 const BoundFunction *f = static_cast<const BoundFunction *>(fo);
749 Scope scope(v4);
750 Scoped<MemberData> boundArgs(scope, f->boundArgs());
751 ScopedFunctionObject target(scope, f->target());
752 JSCallArguments jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc);
753 *jsCallData.thisObject = f->boundThis();
754 Value *argp = jsCallData.args;
755 if (boundArgs) {
756 memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
757 argp += boundArgs->size();
758 }
759 memcpy(argp, argv, argc*sizeof(Value));
760 return checkedResult(v4, target->call(jsCallData));
761}
762
764
766 const FunctionObject *fo, const Value *argv, int argc, const Value *)
767{
768 const BoundFunction *f = static_cast<const BoundFunction *>(fo);
769 Scope scope(f->engine());
770
771 if (scope.hasException())
772 return Encode::undefined();
773
774 Scoped<MemberData> boundArgs(scope, f->boundArgs());
776 JSCallArguments jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc);
777 Value *argp = jsCallData.args;
778 if (boundArgs) {
779 memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
780 argp += boundArgs->size();
781 }
782 memcpy(argp, argv, argc*sizeof(Value));
783 return target->callAsConstructor(jsCallData);
784}
pointer data()
Definition qlist.h:431
\inmodule QtCore
Definition qmetatype.h:341
\inmodule QtCore
Definition qobject.h:103
void setCode(const QString &code, int lineno, bool qmlMode=true, CodeContinuation codeContinuation=CodeContinuation::Reset)
\inmodule QtCore
Definition qstringview.h:78
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QQmlRefPointer< QV4::CompiledData::CompilationUnit > generateCompilationUnit(bool generateUnitData=true)
ObjectType::Data * allocate(Args &&... args)
Definition qv4mm_p.h:298
ObjectType::Data * allocObject(Heap::InternalClass *ic, Args &&... args)
Definition qv4mm_p.h:282
static void exec(MetaTypesStackFrame *frame, ExecutionEngine *engine)
void generateFromFunctionExpression(const QString &fileName, const QString &sourceCode, QQmlJS::AST::FunctionExpression *ast, Compiler::Module *module)
EGLContext ctx
type name READ getFunction WRITE setFunction
[0]
QList< QVariant > arguments
Scoped< FunctionObject > ScopedFunctionObject
ReturnedValue convertAndCall(ExecutionEngine *engine, const Function::AOTCompiledFunction *aotFunction, const Value *thisObject, const Value *argv, int argc, Callable call)
quint64 ReturnedValue
ReturnedValue checkedResult(QV4::ExecutionEngine *v4, ReturnedValue result)
Scoped< String > ScopedString
ReturnedValue coerceAndCall(ExecutionEngine *engine, const Function::JSTypedFunction *typedFunction, const CompiledData::Function *compiledFunction, const Value *argv, int argc, Callable call)
@ Attr_NotConfigurable
@ Attr_NotEnumerable
@ Attr_ReadOnly
@ Attr_Accessor
Scoped< ExecutionContext > ScopedContext
static void * context
#define Q_UNLIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
static QDBusError::ErrorType get(const char *name)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
GLboolean GLboolean GLboolean b
const GLfloat * m
GLboolean GLboolean GLboolean GLboolean a
[7]
GLsizei GLenum GLenum * types
GLfloat GLfloat f
GLenum target
GLuint name
GLfloat n
GLhandleARB obj
[2]
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLsizei len
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
unsigned int uint
Definition qtypes.h:34
static ReturnedValue qfoDoCall(const QV4::JavaScriptFunctionObject *fo, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
#define CHECK_EXCEPTION()
#define DEFINE_OBJECT_VTABLE(classname)
QObject::connect nullptr
QFrame frame
[0]
QJSValue fun
[0]
args<< 1<< 2;QJSValue threeAgain=fun.call(args);QString fileName="helloworld.qs";QFile scriptFile(fileName);if(!scriptFile.open(QIODevice::ReadOnly)) QTextStream stream(&scriptFile);QString contents=stream.readAll();scriptFile.close();myEngine.evaluate(contents, fileName);myEngine.globalObject().setProperty("myNumber", 123);...QJSValue myNumberPlusOne=myEngine.evaluate("myNumber + 1");QJSValue result=myEngine.evaluate(...);if(result.isError()) qDebug()<< "Uncaught exception at line"<< result.property("lineNumber").toInt()<< ":"<< result.toString();QPushButton *button=new QPushButton;QJSValue scriptButton=myEngine.newQObject(button);myEngine.globalObject().setProperty("button", scriptButton);myEngine.evaluate("button.checkable = true");qDebug()<< scriptButton.property("checkable").toBool();scriptButton.property("show").call();QJSEngine engine;QObject *myQObject=new QObject();myQObject- setProperty)("dynamicProperty", 3)
QJSValue global
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
static bool isNonStrictArgumentsObject(Managed *m)
Heap::FunctionObject * target() const
Heap::MemberData * boundArgs() const
static constexpr ReturnedValue undefined()
Heap::InternalClass * internalClasses(InternalClassType icType)
MemoryManager * memoryManager
QQmlRefPointer< ExecutableCompilationUnit > insertCompilationUnit(QQmlRefPointer< QV4::CompiledData::CompilationUnit > &&unit)
QV4::Debugging::Debugger * debugger() const
String * id_length() const
ReturnedValue throwReferenceError(const Value &value)
String * id_toString() const
String * id_prototype() const
Heap::Object * newObject()
String * id_name() const
int safeForAllocLength(qint64 len64)
Heap::String * newString(char16_t c)
ExecutionContext * scriptContext() const
String * id_empty() const
Symbol * symbol_hasInstance() const
ReturnedValue throwSyntaxError(const QString &message)
ReturnedValue throwTypeError()
static QQmlRefPointer< ExecutableCompilationUnit > parse(ExecutionEngine *engine, const Value *argv, int argc, Type t=Type_Function)
static Heap::FunctionObject * createMemberFunction(ExecutionContext *scope, Function *function, Object *homeObject, String *name)
static Heap::FunctionObject * createScriptFunction(ExecutionContext *scope, Function *function)
ReturnedValue getHomeObject() const
ReturnedValue failCall() const
static Heap::FunctionObject * createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount)
ReturnedValue protoProperty() const
ReturnedValue name() const
static Heap::FunctionObject * createConstructorFunction(ExecutionContext *scope, Function *function, Object *homeObject, bool isDerivedConstructor)
ReturnedValue failCallAsConstructor() const
void createDefaultPrototypeProperty(uint protoConstructorSlot)
static ReturnedValue method_bind(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_call(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_hasInstance(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_apply(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
void init(QV4::ExecutionContext *scope, Function *function, QV4::String *name=nullptr)
void init(QV4::ExecutionEngine *engine)
QQmlSourceLocation sourceLocation() const
V4_NEEDS_DESTROY Heap::ExecutionContext * scope() const
Heap::InternalClass * internalClass() const
ExecutionEngine * engine() const
static Heap::MemberData * allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old=nullptr)
void set(EngineBase *e, uint index, Value v)
uint size() const
void defineDefaultProperty(StringOrSymbol *name, const Value &value, PropertyAttributes attributes=Attr_Data|Attr_NotEnumerable)
bool set(StringOrSymbol *name, const Value &v, ThrowOnFailure shouldThrow)
void setProperty(const InternalClassEntry &entry, const Property *p)
Definition qv4object.cpp:91
void defineReadonlyConfigurableProperty(const QString &name, const Value &value)
ReturnedValue get(StringOrSymbol *name, bool *hasProperty=nullptr, const Value *receiver=nullptr) const
Value * alloc(qint64 nValues) const =delete
ExecutionEngine * engine
Heap::InternalClass * classForConstructor() const
constexpr ReturnedValue asReturnedValue() const
bool isNullOrUndefined() const
static constexpr VTable::CallAsConstructor virtualCallAsConstructor
static constexpr VTable::Call virtualCall
static constexpr VTable::CallWithMetaTypes virtualCallWithMetaTypes
static constexpr VTable::InstanceOf virtualInstanceOf
static constexpr VTable::CallWithMetaTypes virtualConvertAndCall
ReturnedValue(* Call)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
Definition qv4vtable_p.h:52
static constexpr Value fromInt32(int i)
Definition qv4value_p.h:187
bool isFunctionObject() const
Definition qv4value_p.h:309
static constexpr Value undefinedValue()
Definition qv4value_p.h:191
QML_NEARLY_ALWAYS_INLINE Object * objectValue() const
Definition qv4value_p.h:70
static constexpr Value fromReturnedValue(ReturnedValue val)
Definition qv4value_p.h:165
const T * as() const
Definition qv4value_p.h:132
QString toQString() const
Definition qv4value.cpp:158
static constexpr Value emptyValue()
Definition qv4value_p.h:179
Definition moc.h:23