3#include <QCoreApplication>
5#include <private/qv4promiseobject_p.h>
6#include <private/qv4symbol_p.h>
28bool isPromise(
const Value &
object)
33bool isCallable(
const Value &
object)
38void insertIdLengthTag(
Scope& scope, Heap::FunctionObject* function)
46 e->hasException =
false;
104 const int type =
event->type();
121 ScopedValue promise(scope, capability->d()->promise);
123 if (ro->d()->type == Heap::PromiseReaction::Function) {
135 reaction->call(promise,
result, 1);
138 if (ro->d()->type == Heap::PromiseReaction::Identity) {
144 reaction->call(promise, resolution, 1);
151class FunctionBuilder {
153 static Heap::FunctionObject *makeResolveFunction(
ExecutionEngine*
e, QV4::Heap::PromiseObject *promise) {
157 insertIdLengthTag(scope, resolveWrapper->d());
158 resolveWrapper->d()->promise.set(
e, promise);
160 return resolveWrapper->d();
163 static Heap::FunctionObject *makeRejectFunction(
ExecutionEngine*
e, QV4::Heap::PromiseObject *promise) {
167 insertIdLengthTag(scope, rejectWrapper->d());
168 rejectWrapper->d()->promise.set(
e, promise);
170 return rejectWrapper->d();
173 static Heap::FunctionObject *makeResolveElementFunction(
ExecutionEngine*
e,
uint index, Heap::PromiseExecutionState *executionState)
178 resolveElementWrapper->d()->index =
index;
179 resolveElementWrapper->d()->alreadyResolved =
false;
180 resolveElementWrapper->d()->state.set(
e, executionState);
182 insertIdLengthTag(scope, resolveElementWrapper->d());
184 return resolveElementWrapper->d();
198 jsCallData.
args[0] = resolve;
199 jsCallData.
args[1] = reject;
206 reject->
call(rejectCallData);
210void Heap::PromiseObject::setState(PromiseObject::State
state)
215bool Heap::PromiseObject::isSettled()
const
217 return (
state != Pending);
220bool Heap::PromiseObject::isPending()
const
222 return (
state == Pending);
225bool Heap::PromiseObject::isFulfilled()
const
227 return (
state == Fulfilled);
230bool Heap::PromiseObject::isRejected()
const
232 return (
state == Rejected);
239 if (
a->arrayData()) {
241 const uint sz = ad->length();
243 for (
uint i = 0;
i < sz;
i++) {
245 r->d()->triggerWithValue(scope.engine,
value);
254 if (
a->arrayData()) {
256 const uint sz = ad->d()->length();
258 for (
uint i = 0;
i < sz;
i++) {
260 r->d()->triggerWithValue(scope.engine,
value);
265Heap::PromiseReaction *Heap::PromiseReaction::createFulfillReaction(
ExecutionEngine*
e,
270 fulfillReaction->d()->capability.set(
e, capability->d());
274 if (!scopedFullfillReaction) {
275 fulfillReaction->d()->type = PromiseReaction::Identity;
277 fulfillReaction->d()->type = PromiseReaction::Function;
278 fulfillReaction->d()->handler.set(
e, scopedFullfillReaction);
281 fulfillReaction->d()->type = PromiseReaction::Identity;
284 return fulfillReaction->d();
287Heap::PromiseReaction *Heap::PromiseReaction::createRejectReaction(
ExecutionEngine*
e,
292 rejectReaction->d()->capability.set(
e, capability->d());
296 if (!scopedRejectReaction) {
297 rejectReaction->d()->type = PromiseReaction::Thrower;
299 rejectReaction->d()->type = PromiseReaction::Function;
300 rejectReaction->d()->handler.set(
e, scopedRejectReaction);
303 rejectReaction->d()->type = PromiseReaction::Thrower;
306 return rejectReaction->d();
312 auto handler =
e->getPromiseReactionHandler();
314 handler->addReaction(
e, reaction,
value);
324 Heap::Object::init();
328 fulfillReactions.set(
e,
a);
333 rejectReactions.set(
e,
a);
337void Heap::CapabilitiesExecutorWrapper::init()
339 Heap::FunctionObject::init();
342void Heap::CapabilitiesExecutorWrapper::destroy()
344 Heap::FunctionObject::destroy();
347void Heap::PromiseExecutionState::init()
350 remainingElementCount = 0;
353void Heap::ResolveElementWrapper::init()
356 alreadyResolved =
false;
358 Heap::FunctionObject::init();
361void Heap::ResolveWrapper::init()
363 alreadyResolved =
false;
364 Heap::FunctionObject::init();
367void Heap::RejectWrapper::init()
369 alreadyResolved =
false;
370 Heap::FunctionObject::init();
398 a->d()->state = Heap::PromiseObject::Pending;
408 jsCallData.
args[0] = resolve;
409 jsCallData.
args[1] = reject;
412 executor->call(jsCallData);
417 callData.args[0] = exception;
418 reject->call(callData);
422 a->setProtoFromNewTarget(newTarget);
433 if (!thisObject || !thisObject->
isObject())
444 if (isPromise(
x) &&
x->isObject()) {
447 ScopedObject constructor(scope,
x->objectValue()->get(
e->id_constructor()));
448 if (so->d() == constructor->d())
449 return x->asReturnedValue();
456 if (!newPromise || !isCallable(capability->d()->resolve) || !isCallable(capability->d()->reject))
462 resolve->call(undefined,
x, 1);
473 if (!thisObject || !thisObject->
isObject())
487 if (!newPromise || !isCallable(capability->d()->resolve) || !isCallable(capability->d()->reject))
493 reject->call(undefined,
r, 1);
504 if (!thisObject || !thisObject->
isObject())
513 if (!newPromise || !isCallable(capability->d()->resolve) || !isCallable(capability->d()->reject)) {
515 return e->exceptionValue->asReturnedValue();
520 capability->d()->promise.set(
e, newPromise);
529 error =
e->exceptionValue;
534 reject->call(newPromise,
error, 1);
539 executionState->d()->remainingElementCount = 1;
540 executionState->d()->capability.set(
e, capability);
543 executionState->d()->values.set(
e,
results);
557 nextObject = *nextValue;
559 nextObject =
e->newBooleanObject(nextValue->
toBoolean());
561 nextObject =
e->newNumberObject(nextValue->
toInteger());
564 nextObject =
e->newStringObject(scopedString);
573 completion =
e->exceptionValue->asReturnedValue();
580 reject->call(newPromise, completion, 1);
588 completion =
e->exceptionValue->asReturnedValue();
591 reject->call(newPromise, completion, 1);
595 executionState->d()->remainingElementCount++;
603 completion =
e->exceptionValue->asReturnedValue();
610 reject->call(newPromise, completion, 1);
617 jsCallData.
args[0] = resolveElement;
618 jsCallData.
args[1] = reject;
621 then->call(jsCallData);
623 ScopedValue completion(scope,
e->exceptionValue->asReturnedValue());
629 reject->call(newPromise, completion, 1);
637 executionState->d()->remainingElementCount--;
638 if (executionState->d()->remainingElementCount == 0) {
659 if (!thisObject || !thisObject->
isObject())
668 if (!newPromise || !isCallable(capability->d()->resolve) || !isCallable(capability->d()->reject))
670 capability->d()->promise.set(scope.
engine, newPromise);
676 if (!iteratorObject) {
678 reject->call(newPromise,
error, 1);
691 completion =
e->exceptionValue->asReturnedValue();
694 reject->call(newPromise, completion, 1);
703 nextObject = *nextValue;
719 completion =
e->exceptionValue->asReturnedValue();
726 reject->call(newPromise, completion, 1);
734 completion =
e->exceptionValue->asReturnedValue();
737 reject->call(newPromise, completion, 1);
747 completion =
e->exceptionValue->asReturnedValue();
754 reject->call(newPromise, completion, 1);
761 jsCallData.
args[0] = resolveOriginalPromise;
762 jsCallData.
args[1] = reject;
765 then->call(jsCallData);
767 ScopedValue completion(scope,
e->exceptionValue->asReturnedValue());
773 reject->call(newPromise, completion, 1);
795 defineDefaultProperty(
engine->id_constructor(), (
o = ctor));
798 defineReadonlyConfigurableProperty(
engine->symbol_toStringTag(),
val);
816 onFulfilled = argv[0];
823 onRejected = argv[1];
835 ScopedObject nextPromise(scope,
e->newPromiseObject(constructor, capability));
836 capability->d()->promise.set(scope.
engine, nextPromise);
841 ScopedValue resolution(scope, promise->d()->resolution);
842 if (promise->d()->isPending()) {
847 a->push_back(newValue);
854 a->push_back(newValue);
856 }
else if (promise->d()->isFulfilled()) {
859 }
else if (promise->d()->isRejected()) {
880 }
else if (thisObject->
isString()) {
891 onRejected = argv[0];
896 jsCallData.
args[1] = onRejected;
904 return then->call(jsCallData);
913 Heap::PromiseCapability *capabilities = self->d()->capabilities;
915 if (!capabilities->resolve.isUndefined() || !capabilities->reject.isUndefined())
918 if (argc >= 1 && !argv[0].isUndefined())
919 capabilities->resolve.set(scope.
engine, argv[0]);
921 if (argc >= 2 && !argv[1].isUndefined())
922 capabilities->reject.set(scope.
engine, argv[1]);
934 if (self->d()->alreadyResolved)
945 self->d()->alreadyResolved =
true;
950 so->d()->remainingElementCount--;
951 if (so->d()->remainingElementCount == 0) {
953 ScopedValue promise(scope, capability->d()->promise);
955 resolve->call(promise,
values, 1);
972 if (self->d()->alreadyResolved || !promise->d()->isPending())
976 self->d()->alreadyResolved =
true;
980 resolution = argv[0];
988 promise->d()->setState(Heap::PromiseObject::Fulfilled);
989 promise->d()->resolution.set(scope.
engine, resolution);
990 promise->d()->triggerFullfillReactions(scope.
engine);
993 auto resolutionObject = resolution->
as<
Object>();
1002 promise->d()->setState(Heap::PromiseObject::Rejected);
1003 promise->d()->resolution.set(scope.
engine, thenValue);
1004 promise->d()->triggerRejectReactions(scope.
engine);
1008 promise->d()->setState(Heap::PromiseObject::Fulfilled);
1009 promise->d()->resolution.set(scope.
engine, resolution);
1010 promise->d()->triggerFullfillReactions(scope.
engine);
1029 if (self->d()->alreadyResolved || !promise->d()->isPending())
1039 if (!isPromise(
value)) {
1040 self->d()->alreadyResolved =
true;
1041 promise->d()->setState(Heap::PromiseObject::Rejected);
1042 promise->d()->resolution.set(scope.
engine,
value);
1044 promise->d()->triggerRejectReactions(scope.
engine);
1052 jsCallData.
args[0] = *
f;
1056 then->call(jsCallData);
1064#include "moc_qv4promiseobject_p.cpp"
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
static int registerEventType(int hint=-1) noexcept
ObjectType::Data * allocate(Args &&... args)
ReactionHandler(QObject *parent=nullptr)
void addResolveThenable(ExecutionEngine *e, const PromiseObject *promise, const Object *thenable, const FunctionObject *then)
void customEvent(QEvent *event) override
This event handler can be reimplemented in a subclass to receive custom events.
~ReactionHandler() override
void addReaction(ExecutionEngine *e, const Value *reaction, const Value *value)
void executeResolveThenable(ResolveThenableEvent *event)
void executeReaction(ReactionEvent *event)
Combined button and popup list for selecting options.
const int PROMISE_REACTION_EVENT
const int PROMISE_RESOLVE_THENABLE_EVENT
\qmltype Particle \inqmlmodule QtQuick.Particles
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLenum GLsizei GLsizei GLint * values
[15]
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
#define QStringLiteral(str)
#define THROW_TYPE_ERROR()
#define THROW_GENERIC_ERROR(str)
#define DEFINE_OBJECT_VTABLE(classname)
static constexpr ReturnedValue undefined()
MemoryManager * memoryManager
Heap::PromiseObject * newPromiseObject()
String * id_length() const
Heap::Object * newNumberObject(double value)
Heap::String * newIdentifier(const QString &text)
Heap::Object * newBooleanObject(bool b)
Promise::ReactionHandler * getPromiseReactionHandler()
Heap::Object * newStringObject(const String *string)
ReturnedValue catchException(StackTrace *trace=nullptr)
ReturnedValue call(const JSCallData &data) const
void init(QV4::ExecutionContext *scope)
void defineDefaultProperty(StringOrSymbol *name, const Value &value, PropertyAttributes attributes=Attr_Data|Attr_NotEnumerable)
void defineReadonlyConfigurableProperty(const QString &name, const Value &value)
void defineReadonlyProperty(const QString &name, const Value &value)
ReturnedValue get(StringOrSymbol *name, bool *hasProperty=nullptr, const Value *receiver=nullptr) const
static ReturnedValue method_all(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_race(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_reject(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_resolve(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_catch(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_then(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
void init(ExecutionEngine *engine, Object *ctor)
QV4::PersistentValue resolution
ReactionEvent(ExecutionEngine *e, const Value *reaction_, const Value *resolution_)
QV4::PersistentValue reaction
QV4::PersistentValue thenable
QV4::PersistentValue promise
QV4::PersistentValue then
ResolveThenableEvent(ExecutionEngine *e, const PromiseObject *promise_, const Object *thenable_, const FunctionObject *then_)
static ReturnedValue call(ExecutionEngine *, const Value &, int)
static ReturnedValue call(ExecutionEngine *, const Value &, const Value &)
static ReturnedValue call(ExecutionEngine *, const Value &, Value *)
bool hasException() const
QML_NEARLY_ALWAYS_INLINE void setPointer(const Managed *p)
QML_NEARLY_ALWAYS_INLINE ReturnedValue asReturnedValue() const
static constexpr VTable::CallAsConstructor virtualCallAsConstructor
static constexpr VTable::Call virtualCall
static constexpr Value fromInt32(int i)
Heap::String * toString(ExecutionEngine *e) const
static constexpr Value undefinedValue()
static Value fromHeapObject(HeapBasePtr m)
static constexpr Value fromReturnedValue(ReturnedValue val)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent