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)
104 const int type =
event->type();
118 Scoped<QV4::PromiseCapability> capability(scope, ro->d()->capability);
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();
199 jsCallData.args[1] = reject;
200 jsCallData.thisObject =
event->thenable.as<
QV4::Object>();
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()) {
240 Scoped<QV4::ArrayData> ad(scope,
a->arrayData());
241 const uint sz = ad->length();
243 for (
uint i = 0;
i < sz;
i++) {
244 Scoped<QV4::PromiseReaction>
r(scope, ad->get(
i));
245 r->d()->triggerWithValue(scope.engine,
value);
254 if (
a->arrayData()) {
255 Scoped<QV4::ArrayData> ad(scope,
a->arrayData());
256 const uint sz = ad->d()->length();
258 for (
uint i = 0;
i < sz;
i++) {
259 Scoped<QV4::PromiseReaction>
r(scope, ad->d()->get(
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();
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;
409 jsCallData.args[1] = reject;
412 executor->call(jsCallData);
417 callData.args[0] = exception;
418 reject->call(callData);
422 a->setProtoFromNewTarget(newTarget);
424 return a->asReturnedValue();
433 if (!thisObject || !thisObject->
isObject())
444 if (isPromise(
x) &&
x->isObject()) {
448 if (so->d() == constructor->d())
449 return x->asReturnedValue();
456 if (!newPromise || !isCallable(capability->d()->resolve) || !isCallable(capability->d()->reject))
464 return newPromise.asReturnedValue();
473 if (!thisObject || !thisObject->
isObject())
487 if (!newPromise || !isCallable(capability->d()->resolve) || !isCallable(capability->d()->reject))
493 reject->call(undefined,
r, 1);
495 return newPromise.asReturnedValue();
504 if (!thisObject || !thisObject->
isObject())
513 if (!newPromise || !isCallable(capability->d()->resolve) || !isCallable(capability->d()->reject)) {
520 capability->d()->promise.set(e, newPromise);
534 reject->call(newPromise,
error, 1);
535 return newPromise.asReturnedValue();
539 executionState->d()->remainingElementCount = 1;
540 executionState->d()->capability.set(e, capability);
543 executionState->d()->values.set(e,
results);
552 if (doneValue->toBoolean())
556 if (nextValue->isObject()) {
557 nextObject = *nextValue;
558 }
else if (nextValue->isBoolean()) {
560 }
else if (nextValue->isInteger() || nextValue->isDouble()) {
562 }
else if (nextValue->isString()) {
577 if (!doneValue->toBoolean())
580 reject->call(newPromise, completion, 1);
581 return newPromise.asReturnedValue();
586 ScopedValue completion(scope, doneValue->toBoolean()
593 reject->call(newPromise, completion, 1);
594 return newPromise.asReturnedValue();
597 executionState->d()->remainingElementCount++;
609 if (!doneValue->toBoolean())
612 reject->call(newPromise, completion, 1);
613 return newPromise.asReturnedValue();
619 jsCallData.args[0] = resolveElement;
620 jsCallData.args[1] = reject;
621 jsCallData.thisObject = nextPromise;
623 then->call(jsCallData);
628 if (!doneValue->toBoolean())
631 reject->call(newPromise, completion, 1);
632 return newPromise.asReturnedValue();
639 executionState->d()->remainingElementCount--;
640 if (executionState->d()->remainingElementCount == 0) {
653 return newPromise.asReturnedValue();
661 if (!thisObject || !thisObject->
isObject())
670 if (!newPromise || !isCallable(capability->d()->resolve) || !isCallable(capability->d()->reject))
672 capability->d()->promise.set(scope.
engine, newPromise);
678 if (!iteratorObject) {
680 reject->call(newPromise,
error, 1);
681 return newPromise.asReturnedValue();
691 ScopedValue completion(scope, doneValue->toBoolean()
698 reject->call(newPromise, completion, 1);
699 return newPromise.asReturnedValue();
702 if (doneValue->toBoolean())
706 if (nextValue->isObject()) {
707 nextObject = *nextValue;
708 }
else if (nextValue->isBoolean()) {
710 }
else if (nextValue->isInteger() || nextValue->isDouble()) {
712 }
else if (nextValue->isString()) {
727 if (!doneValue->toBoolean())
730 reject->call(newPromise, completion, 1);
731 return newPromise.asReturnedValue();
736 ScopedValue completion(scope, doneValue->toBoolean()
743 reject->call(newPromise, completion, 1);
744 return newPromise.asReturnedValue();
757 if (!doneValue->toBoolean())
760 reject->call(newPromise, completion, 1);
761 return newPromise.asReturnedValue();
767 jsCallData.args[0] = resolveOriginalPromise;
768 jsCallData.args[1] = reject;
769 jsCallData.thisObject = nextPromise;
771 then->call(jsCallData);
776 if (!doneValue->toBoolean())
779 reject->call(newPromise, completion, 1);
780 return newPromise.asReturnedValue();
784 return newPromise.asReturnedValue();
793 ctor->defineReadonlyProperty(
engine->id_prototype(), (
o =
this));
799 ctor->addSymbolSpecies();
801 defineDefaultProperty(
engine->id_constructor(), (
o = ctor));
804 defineReadonlyConfigurableProperty(
engine->symbol_toStringTag(), val);
816 Scoped<QV4::PromiseObject> promise(scope, thisObject);
822 onFulfilled = argv[0];
829 onRejected = argv[1];
842 capability->d()->promise.set(scope.
engine, nextPromise);
844 Scoped<PromiseReaction> fulfillReaction(scope, Heap::PromiseReaction::createFulfillReaction(scope.
engine, capability, onFulfilled));
845 Scoped<PromiseReaction> rejectReaction(scope, Heap::PromiseReaction::createRejectReaction(scope.
engine, capability, onRejected));
847 ScopedValue resolution(scope, promise->d()->resolution);
848 if (promise->d()->isPending()) {
853 a->push_back(newValue);
860 a->push_back(newValue);
862 }
else if (promise->d()->isFulfilled()) {
865 }
else if (promise->d()->isRejected()) {
873 return nextPromise->asReturnedValue();
879 Scoped<Object> promise(scope);
881 promise.setPointer(thisObject->
as<
Object>());
886 }
else if (thisObject->
isString()) {
897 onRejected = argv[0];
902 jsCallData.args[1] = onRejected;
903 jsCallData.thisObject = promise;
910 return then->call(jsCallData);
919 Heap::PromiseCapability *capabilities = self->d()->capabilities;
921 if (!capabilities->resolve.isUndefined() || !capabilities->reject.isUndefined())
924 if (argc >= 1 && !argv[0].isUndefined())
925 capabilities->resolve.set(scope.
engine, argv[0]);
927 if (argc >= 2 && !argv[1].isUndefined())
928 capabilities->reject.set(scope.
engine, argv[1]);
940 if (self->d()->alreadyResolved)
950 Scoped<PromiseExecutionState> so(scope, self->d()->state);
951 self->d()->alreadyResolved =
true;
956 so->d()->remainingElementCount--;
957 if (so->d()->remainingElementCount == 0) {
958 Scoped<PromiseCapability> capability(scope, so->d()->capability);
959 ScopedValue promise(scope, capability->d()->promise);
976 Scoped<PromiseObject> promise(scope, self->d()->promise);
978 if (self->d()->alreadyResolved || !promise->d()->isPending())
982 self->d()->alreadyResolved =
true;
986 resolution = argv[0];
994 promise->d()->setState(Heap::PromiseObject::Fulfilled);
995 promise->d()->resolution.set(scope.
engine, resolution);
996 promise->d()->triggerFullfillReactions(scope.
engine);
999 auto resolutionObject = resolution->
as<
Object>();
1008 promise->d()->setState(Heap::PromiseObject::Rejected);
1009 promise->d()->resolution.set(scope.
engine, thenValue);
1010 promise->d()->triggerRejectReactions(scope.
engine);
1014 promise->d()->setState(Heap::PromiseObject::Fulfilled);
1015 promise->d()->resolution.set(scope.
engine, resolution);
1016 promise->d()->triggerFullfillReactions(scope.
engine);
1034 Scoped<PromiseObject> promise(scope, self->d()->promise);
1035 if (self->d()->alreadyResolved || !promise->d()->isPending())
1045 if (!isPromise(
value)) {
1046 self->d()->alreadyResolved =
true;
1047 promise->d()->setState(Heap::PromiseObject::Rejected);
1048 promise->d()->resolution.set(scope.
engine,
value);
1050 promise->d()->triggerRejectReactions(scope.
engine);
1058 jsCallData.args[0] = *
f;
1060 jsCallData.thisObject =
value;
1062 then->call(jsCallData);
1070#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
Scoped< FunctionObject > ScopedFunctionObject
Scoped< String > ScopedString
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]
static const QQmlJSScope * resolve(const QQmlJSScope *current, const QStringList &names)
#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
String * id_constructor() const
Heap::Object * newNumberObject(double value)
Heap::String * newIdentifier(const QString &text)
Heap::Object * newBooleanObject(bool b)
Promise::ReactionHandler * getPromiseReactionHandler()
Heap::ArrayObject * newArrayObject(int count=0)
Heap::Object * newTypeErrorObject(const QString &message)
Heap::Object * newStringObject(const String *string)
ReturnedValue catchException(StackTrace *trace=nullptr)
ReturnedValue call(const Value *thisObject, const Value *argv, int argc) const
void init(ExecutionEngine *engine)
bool set(StringOrSymbol *name, const Value &v, ThrowOnFailure shouldThrow)
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 &)
static ReturnedValue call(ExecutionEngine *, const Value &, Value *)
bool hasException() const
constexpr 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)