blob: 8bbac581ded69c615b9e223c5c4b3e76b7a4b3c6 [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
namespace Js
{
struct JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper
{
Field(bool) alreadyResolved;
};
class JavascriptPromiseResolveOrRejectFunction : public RuntimeFunction
{
protected:
DEFINE_VTABLE_CTOR(JavascriptPromiseResolveOrRejectFunction, RuntimeFunction);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseResolveOrRejectFunction);
public:
JavascriptPromiseResolveOrRejectFunction(DynamicType* type);
JavascriptPromiseResolveOrRejectFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromise* promise, bool isReject, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyResolvedRecord);
inline static bool Is(Var var);
inline static JavascriptPromiseResolveOrRejectFunction* FromVar(Var var);
JavascriptPromise* GetPromise();
bool IsRejectFunction();
bool IsAlreadyResolved();
void SetAlreadyResolved(bool is);
private:
Field(JavascriptPromise*) promise;
Field(bool) isReject;
Field(JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper*) alreadyResolvedWrapper;
#if ENABLE_TTD
public:
virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
#endif
};
class JavascriptPromiseAsyncSpawnExecutorFunction : public RuntimeFunction
{
protected:
DEFINE_VTABLE_CTOR(JavascriptPromiseAsyncSpawnExecutorFunction, RuntimeFunction);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseAsyncSpawnExecutorFunction);
public:
JavascriptPromiseAsyncSpawnExecutorFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptGenerator* generator, Var target);
inline static bool Is(Var var);
inline static JavascriptPromiseAsyncSpawnExecutorFunction* FromVar(Var var);
JavascriptGenerator* GetGenerator();
Var GetTarget();
private:
Field(JavascriptGenerator*) generator;
Field(Var) target; // this
#if ENABLE_TTD
public:
virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
#endif
};
class JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction : public RuntimeFunction
{
protected:
DEFINE_VTABLE_CTOR(JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction, RuntimeFunction);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction);
public:
JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptGenerator* generator, Var argument, Var resolve = nullptr, Var reject = nullptr, bool isReject = false);
inline static bool Is(Var var);
inline static JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* FromVar(Var var);
JavascriptGenerator* GetGenerator();
Var GetReject();
Var GetResolve();
bool GetIsReject();
Var GetArgument();
private:
Field(JavascriptGenerator*) generator;
Field(Var) reject;
Field(Var) resolve;
Field(bool) isReject;
Field(Var) argument;
#if ENABLE_TTD
public:
virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
#endif
};
class JavascriptPromiseCapabilitiesExecutorFunction : public RuntimeFunction
{
protected:
DEFINE_VTABLE_CTOR(JavascriptPromiseCapabilitiesExecutorFunction, RuntimeFunction);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseCapabilitiesExecutorFunction);
public:
JavascriptPromiseCapabilitiesExecutorFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromiseCapability* capability);
inline static bool Is(Var var);
inline static JavascriptPromiseCapabilitiesExecutorFunction* FromVar(Var var);
JavascriptPromiseCapability* GetCapability();
private:
Field(JavascriptPromiseCapability*) capability;
#if ENABLE_TTD
public:
virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
#endif
};
class JavascriptPromiseResolveThenableTaskFunction : public RuntimeFunction
{
protected:
DEFINE_VTABLE_CTOR(JavascriptPromiseResolveThenableTaskFunction, RuntimeFunction);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseResolveThenableTaskFunction);
public:
JavascriptPromiseResolveThenableTaskFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromise* promise, RecyclableObject* thenable, RecyclableObject* thenFunction)
: RuntimeFunction(type, functionInfo), promise(promise), thenable(thenable), thenFunction(thenFunction)
{ }
inline static bool Is(Var var)
{
if (JavascriptFunction::Is(var))
{
JavascriptFunction* obj = JavascriptFunction::FromVar(var);
return VirtualTableInfo<JavascriptPromiseResolveThenableTaskFunction>::HasVirtualTable(obj)
|| VirtualTableInfo<CrossSiteObject<JavascriptPromiseResolveThenableTaskFunction>>::HasVirtualTable(obj);
}
return false;
}
inline static JavascriptPromiseResolveThenableTaskFunction* FromVar(Var var)
{
Assert(JavascriptPromiseResolveThenableTaskFunction::Is(var));
return static_cast<JavascriptPromiseResolveThenableTaskFunction*>(var);
}
JavascriptPromise* GetPromise();
RecyclableObject* GetThenable();
RecyclableObject* GetThenFunction();
private:
Field(JavascriptPromise*) promise;
Field(RecyclableObject*) thenable;
Field(RecyclableObject*) thenFunction;
#if ENABLE_TTD
public:
virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
#endif
};
class JavascriptPromiseReactionTaskFunction : public RuntimeFunction
{
protected:
DEFINE_VTABLE_CTOR(JavascriptPromiseReactionTaskFunction, RuntimeFunction);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseReactionTaskFunction);
public:
JavascriptPromiseReactionTaskFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromiseReaction* reaction, Var argument)
: RuntimeFunction(type, functionInfo), reaction(reaction), argument(argument)
{ }
inline static bool Is(Var var)
{
if (JavascriptFunction::Is(var))
{
JavascriptFunction* obj = JavascriptFunction::FromVar(var);
return VirtualTableInfo<JavascriptPromiseReactionTaskFunction>::HasVirtualTable(obj)
|| VirtualTableInfo<CrossSiteObject<JavascriptPromiseReactionTaskFunction>>::HasVirtualTable(obj);
}
return false;
}
inline static JavascriptPromiseReactionTaskFunction* FromVar(Var var)
{
Assert(JavascriptPromiseReactionTaskFunction::Is(var));
return static_cast<JavascriptPromiseReactionTaskFunction*>(var);
}
JavascriptPromiseReaction* GetReaction();
Var GetArgument();
private:
Field(JavascriptPromiseReaction*) reaction;
Field(Var) argument;
#if ENABLE_TTD
public:
virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
#endif
};
struct JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper
{
Field(uint32) remainingElements;
};
class JavascriptPromiseAllResolveElementFunction : public RuntimeFunction
{
protected:
DEFINE_VTABLE_CTOR(JavascriptPromiseAllResolveElementFunction, RuntimeFunction);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseAllResolveElementFunction);
public:
JavascriptPromiseAllResolveElementFunction(DynamicType* type);
JavascriptPromiseAllResolveElementFunction(DynamicType* type, FunctionInfo* functionInfo, uint32 index, JavascriptArray* values, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper);
inline static bool Is(Var var);
inline static JavascriptPromiseAllResolveElementFunction* FromVar(Var var);
JavascriptPromiseCapability* GetCapabilities();
uint32 GetIndex();
uint32 GetRemainingElements();
JavascriptArray* GetValues();
bool IsAlreadyCalled() const;
void SetAlreadyCalled(const bool is);
uint32 DecrementRemainingElements();
private:
Field(JavascriptPromiseCapability*) capabilities;
Field(uint32) index;
Field(JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper*) remainingElementsWrapper;
Field(JavascriptArray*) values;
Field(bool) alreadyCalled;
#if ENABLE_TTD
public:
virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
#endif
};
class JavascriptPromiseCapability : FinalizableObject
{
private:
JavascriptPromiseCapability(Var promise, Var resolve, Var reject)
: promise(promise), resolve(resolve), reject(reject)
{ }
public:
static JavascriptPromiseCapability* New(Var promise, Var resolve, Var reject, ScriptContext* scriptContext);
Var GetResolve();
Var GetReject();
Var GetPromise();
void SetPromise(Var);
void SetResolve(Var resolve);
void SetReject(Var reject);
public:
// Finalizable support
virtual void Finalize(bool isShutdown)
{
}
virtual void Dispose(bool isShutdown)
{
}
virtual void Mark(Recycler *recycler) override
{
AssertMsg(false, "Mark called on object that isnt TrackableObject");
}
private:
Field(Var) promise;
Field(Var) resolve;
Field(Var) reject;
#if ENABLE_TTD
public:
//Do any additional marking that is needed for a TT snapshotable object
void MarkVisitPtrs(TTD::SnapshotExtractor* extractor);
//Do the extraction
void ExtractSnapPromiseCapabilityInto(TTD::NSSnapValues::SnapPromiseCapabilityInfo* snapPromiseCapability, JsUtil::List<TTD_PTR_ID, HeapAllocator>& depOnList, TTD::SlabAllocator& alloc);
#endif
};
typedef JsUtil::List<Js::JavascriptPromiseCapability*> JavascriptPromiseCapabilityList;
class JavascriptPromiseReaction : FinalizableObject
{
private:
JavascriptPromiseReaction(JavascriptPromiseCapability* capabilities, RecyclableObject* handler)
: capabilities(capabilities), handler(handler)
{ }
public:
static JavascriptPromiseReaction* New(JavascriptPromiseCapability* capabilities, RecyclableObject* handler, ScriptContext* scriptContext);
JavascriptPromiseCapability* GetCapabilities();
RecyclableObject* GetHandler();
public:
// Finalizable support
virtual void Finalize(bool isShutdown)
{
}
virtual void Dispose(bool isShutdown)
{
}
virtual void Mark(Recycler *recycler) override
{
AssertMsg(false, "Mark called on object that isnt TrackableObject");
}
private:
Field(JavascriptPromiseCapability*) capabilities;
Field(RecyclableObject*) handler;
#if ENABLE_TTD
public:
//Do any additional marking that is needed for a TT snapshotable object
void MarkVisitPtrs(TTD::SnapshotExtractor* extractor);
//Do the extraction
void ExtractSnapPromiseReactionInto(TTD::NSSnapValues::SnapPromiseReactionInfo* snapPromiseReaction, JsUtil::List<TTD_PTR_ID, HeapAllocator>& depOnList, TTD::SlabAllocator& alloc);
#endif
};
typedef JsUtil::List<Js::JavascriptPromiseReaction*> JavascriptPromiseReactionList;
class JavascriptPromise : public DynamicObject
{
private:
DEFINE_VTABLE_CTOR(JavascriptPromise, DynamicObject);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromise);
public:
class EntryInfo
{
public:
static FunctionInfo NewInstance;
static FunctionInfo All;
static FunctionInfo Catch;
static FunctionInfo Race;
static FunctionInfo Reject;
static FunctionInfo Resolve;
static FunctionInfo Then;
static FunctionInfo Identity;
static FunctionInfo Thrower;
static FunctionInfo ResolveOrRejectFunction;
static FunctionInfo CapabilitiesExecutorFunction;
static FunctionInfo AllResolveElementFunction;
static FunctionInfo GetterSymbolSpecies;
};
JavascriptPromise(DynamicType * type);
static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryAll(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryCatch(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryRace(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryReject(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryResolve(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryThen(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryCapabilitiesExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryResolveOrRejectFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryReactionTaskFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryResolveThenableTaskFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryIdentityFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryThrowerFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryAllResolveElementFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryJavascriptPromiseAsyncSpawnExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryJavascriptPromiseAsyncSpawnStepNextExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryJavascriptPromiseAsyncSpawnStepThrowExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryJavascriptPromiseAsyncSpawnCallStepExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
static bool Is(Var aValue);
static JavascriptPromise* FromVar(Js::Var aValue);
static Var CreateRejectedPromise(Var resolution, ScriptContext* scriptContext, Var promiseConstructor = nullptr);
static Var CreateResolvedPromise(Var resolution, ScriptContext* scriptContext, Var promiseConstructor = nullptr);
static Var CreatePassThroughPromise(JavascriptPromise* sourcePromise, ScriptContext* scriptContext);
static Var CreateThenPromise(JavascriptPromise* sourcePromise, RecyclableObject* fulfillmentHandler, RecyclableObject* rejectionHandler, ScriptContext* scriptContext);
virtual BOOL GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
JavascriptPromiseReactionList* GetResolveReactions();
JavascriptPromiseReactionList* GetRejectReactions();
static JavascriptPromiseCapability* NewPromiseCapability(Var constructor, ScriptContext* scriptContext);
static JavascriptPromiseCapability* CreatePromiseCapabilityRecord(RecyclableObject* constructor, ScriptContext* scriptContext);
static Var TriggerPromiseReactions(JavascriptPromiseReactionList* reactions, Var resolution, ScriptContext* scriptContext);
static void EnqueuePromiseReactionTask(JavascriptPromiseReaction* reaction, Var resolution, ScriptContext* scriptContext);
static void InitializePromise(JavascriptPromise* promise, JavascriptPromiseResolveOrRejectFunction** resolve, JavascriptPromiseResolveOrRejectFunction** reject, ScriptContext* scriptContext);
static Var TryCallResolveOrRejectHandler(Var handler, Var value, ScriptContext* scriptContext);
static Var TryRejectWithExceptionObject(JavascriptExceptionObject* exceptionObject, Var handler, ScriptContext* scriptContext);
static JavascriptPromise* CreateEnginePromise(ScriptContext *scriptContext);
Var Resolve(Var resolution, ScriptContext* scriptContext);
Var Reject(Var resolution, ScriptContext* scriptContext);
enum PromiseStatus
{
PromiseStatusCode_Undefined,
PromiseStatusCode_Unresolved,
PromiseStatusCode_HasResolution,
PromiseStatusCode_HasRejection
};
PromiseStatus GetStatus() const { return status; }
Var GetResult() const { return result; }
protected:
Var ResolveHelper(Var resolution, bool isRejecting, ScriptContext* scriptContext);
protected:
Field(PromiseStatus) status;
Field(Var) result;
Field(JavascriptPromiseReactionList*) resolveReactions;
Field(JavascriptPromiseReactionList*) rejectReactions;
private :
static void AsyncSpawnStep(JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* nextFunction, JavascriptGenerator* gen, Var resolve, Var reject);
#if ENABLE_TTD
public:
virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
static JavascriptPromise* InitializePromise_TTD(ScriptContext* scriptContext, uint32 status, Var result, JsUtil::List<Js::JavascriptPromiseReaction*, HeapAllocator>& resolveReactions, JsUtil::List<Js::JavascriptPromiseReaction*, HeapAllocator>& rejectReactions);
#endif
};
}