JavascriptPromise.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. namespace Js
  7. {
  8. struct JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper
  9. {
  10. bool alreadyResolved;
  11. };
  12. class JavascriptPromiseResolveOrRejectFunction : public RuntimeFunction
  13. {
  14. protected:
  15. DEFINE_VTABLE_CTOR(JavascriptPromiseResolveOrRejectFunction, RuntimeFunction);
  16. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseResolveOrRejectFunction);
  17. public:
  18. JavascriptPromiseResolveOrRejectFunction(DynamicType* type);
  19. JavascriptPromiseResolveOrRejectFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromise* promise, bool isReject, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyResolvedRecord);
  20. inline static bool Is(Var var);
  21. inline static JavascriptPromiseResolveOrRejectFunction* FromVar(Var var);
  22. JavascriptPromise* GetPromise();
  23. bool IsRejectFunction();
  24. bool IsAlreadyResolved();
  25. void SetAlreadyResolved(bool is);
  26. private:
  27. JavascriptPromise* promise;
  28. bool isReject;
  29. JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyResolvedWrapper;
  30. };
  31. class JavascriptPromiseAsyncSpawnExecutorFunction : public RuntimeFunction
  32. {
  33. protected:
  34. DEFINE_VTABLE_CTOR(JavascriptPromiseAsyncSpawnExecutorFunction, RuntimeFunction);
  35. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseAsyncSpawnExecutorFunction);
  36. public:
  37. JavascriptPromiseAsyncSpawnExecutorFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptGenerator* generatorFunction, Var target);
  38. inline static bool Is(Var var);
  39. inline static JavascriptPromiseAsyncSpawnExecutorFunction* FromVar(Var var);
  40. JavascriptGenerator* GetGeneratorFunction();
  41. Var GetTarget();
  42. private:
  43. JavascriptGenerator* generatorFunction;
  44. Var target; // this
  45. };
  46. class JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction : public RuntimeFunction
  47. {
  48. protected:
  49. DEFINE_VTABLE_CTOR(JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction, RuntimeFunction);
  50. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction);
  51. public:
  52. JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptGenerator* generator, Var argument, JavascriptFunction* resolve = NULL, JavascriptFunction* reject = NULL, bool isReject = false);
  53. inline static bool Is(Var var);
  54. inline static JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* FromVar(Var var);
  55. JavascriptGenerator* GetGenerator();
  56. JavascriptFunction* GetReject();
  57. JavascriptFunction* GetResolve();
  58. bool GetIsReject();
  59. Var GetArgument();
  60. private:
  61. JavascriptGenerator* generator;
  62. JavascriptFunction* reject;
  63. JavascriptFunction* resolve;
  64. bool isReject;
  65. Var argument;
  66. };
  67. class JavascriptPromiseCapabilitiesExecutorFunction : public RuntimeFunction
  68. {
  69. protected:
  70. DEFINE_VTABLE_CTOR(JavascriptPromiseCapabilitiesExecutorFunction, RuntimeFunction);
  71. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseCapabilitiesExecutorFunction);
  72. public:
  73. JavascriptPromiseCapabilitiesExecutorFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromiseCapability* capability);
  74. inline static bool Is(Var var);
  75. inline static JavascriptPromiseCapabilitiesExecutorFunction* FromVar(Var var);
  76. JavascriptPromiseCapability* GetCapability();
  77. private:
  78. JavascriptPromiseCapability* capability;
  79. };
  80. class JavascriptPromiseResolveThenableTaskFunction : public RuntimeFunction
  81. {
  82. protected:
  83. DEFINE_VTABLE_CTOR(JavascriptPromiseResolveThenableTaskFunction, RuntimeFunction);
  84. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseResolveThenableTaskFunction);
  85. public:
  86. JavascriptPromiseResolveThenableTaskFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromise* promise, RecyclableObject* thenable, RecyclableObject* thenFunction)
  87. : RuntimeFunction(type, functionInfo), promise(promise), thenable(thenable), thenFunction(thenFunction)
  88. { }
  89. inline static bool Is(Var var)
  90. {
  91. if (JavascriptFunction::Is(var))
  92. {
  93. JavascriptFunction* obj = JavascriptFunction::FromVar(var);
  94. return VirtualTableInfo<JavascriptPromiseResolveThenableTaskFunction>::HasVirtualTable(obj)
  95. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseResolveThenableTaskFunction>>::HasVirtualTable(obj);
  96. }
  97. return false;
  98. }
  99. inline static JavascriptPromiseResolveThenableTaskFunction* FromVar(Var var)
  100. {
  101. Assert(JavascriptPromiseResolveThenableTaskFunction::Is(var));
  102. return static_cast<JavascriptPromiseResolveThenableTaskFunction*>(var);
  103. }
  104. JavascriptPromise* GetPromise();
  105. RecyclableObject* GetThenable();
  106. RecyclableObject* GetThenFunction();
  107. private:
  108. JavascriptPromise* promise;
  109. RecyclableObject* thenable;
  110. RecyclableObject* thenFunction;
  111. };
  112. class JavascriptPromiseReactionTaskFunction : public RuntimeFunction
  113. {
  114. protected:
  115. DEFINE_VTABLE_CTOR(JavascriptPromiseReactionTaskFunction, RuntimeFunction);
  116. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseReactionTaskFunction);
  117. public:
  118. JavascriptPromiseReactionTaskFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromiseReaction* reaction, Var argument)
  119. : RuntimeFunction(type, functionInfo), reaction(reaction), argument(argument)
  120. { }
  121. inline static bool Is(Var var)
  122. {
  123. if (JavascriptFunction::Is(var))
  124. {
  125. JavascriptFunction* obj = JavascriptFunction::FromVar(var);
  126. return VirtualTableInfo<JavascriptPromiseReactionTaskFunction>::HasVirtualTable(obj)
  127. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseReactionTaskFunction>>::HasVirtualTable(obj);
  128. }
  129. return false;
  130. }
  131. inline static JavascriptPromiseReactionTaskFunction* FromVar(Var var)
  132. {
  133. Assert(JavascriptPromiseReactionTaskFunction::Is(var));
  134. return static_cast<JavascriptPromiseReactionTaskFunction*>(var);
  135. }
  136. JavascriptPromiseReaction* GetReaction();
  137. Var GetArgument();
  138. private:
  139. JavascriptPromiseReaction* reaction;
  140. Var argument;
  141. };
  142. struct JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper
  143. {
  144. uint32 remainingElements;
  145. };
  146. class JavascriptPromiseAllResolveElementFunction : public RuntimeFunction
  147. {
  148. protected:
  149. DEFINE_VTABLE_CTOR(JavascriptPromiseAllResolveElementFunction, RuntimeFunction);
  150. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseAllResolveElementFunction);
  151. public:
  152. JavascriptPromiseAllResolveElementFunction(DynamicType* type);
  153. JavascriptPromiseAllResolveElementFunction(DynamicType* type, FunctionInfo* functionInfo, uint32 index, JavascriptArray* values, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper);
  154. inline static bool Is(Var var);
  155. inline static JavascriptPromiseAllResolveElementFunction* FromVar(Var var);
  156. JavascriptPromiseCapability* GetCapabilities();
  157. uint32 GetIndex();
  158. uint32 GetRemainingElements();
  159. JavascriptArray* GetValues();
  160. bool IsAlreadyCalled() const;
  161. void SetAlreadyCalled(const bool is);
  162. uint32 DecrementRemainingElements();
  163. private:
  164. JavascriptPromiseCapability* capabilities;
  165. uint32 index;
  166. JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper;
  167. JavascriptArray* values;
  168. bool alreadyCalled;
  169. };
  170. class JavascriptPromiseCapability : FinalizableObject
  171. {
  172. private:
  173. JavascriptPromiseCapability(Var promise, RecyclableObject* resolve, RecyclableObject* reject)
  174. : promise(promise), resolve(resolve), reject(reject)
  175. { }
  176. public:
  177. static JavascriptPromiseCapability* New(Var promise, RecyclableObject* resolve, RecyclableObject* reject, ScriptContext* scriptContext);
  178. RecyclableObject* GetResolve();
  179. RecyclableObject* GetReject();
  180. Var GetPromise();
  181. void SetPromise(Var);
  182. void SetResolve(RecyclableObject* resolve);
  183. void SetReject(RecyclableObject* reject);
  184. public:
  185. // Finalizable support
  186. virtual void Finalize(bool isShutdown)
  187. {
  188. }
  189. virtual void Dispose(bool isShutdown)
  190. {
  191. }
  192. virtual void Mark(Recycler *recycler) override
  193. {
  194. AssertMsg(false, "Mark called on object that isnt TrackableObject");
  195. }
  196. private:
  197. Var promise;
  198. RecyclableObject* resolve;
  199. RecyclableObject* reject;
  200. };
  201. typedef JsUtil::List<Js::JavascriptPromiseCapability*> JavascriptPromiseCapabilityList;
  202. class JavascriptPromiseReaction : FinalizableObject
  203. {
  204. private:
  205. JavascriptPromiseReaction(JavascriptPromiseCapability* capabilities, RecyclableObject* handler)
  206. : capabilities(capabilities), handler(handler)
  207. { }
  208. public:
  209. static JavascriptPromiseReaction* New(JavascriptPromiseCapability* capabilities, RecyclableObject* handler, ScriptContext* scriptContext);
  210. JavascriptPromiseCapability* GetCapabilities();
  211. RecyclableObject* GetHandler();
  212. public:
  213. // Finalizable support
  214. virtual void Finalize(bool isShutdown)
  215. {
  216. }
  217. virtual void Dispose(bool isShutdown)
  218. {
  219. }
  220. virtual void Mark(Recycler *recycler) override
  221. {
  222. AssertMsg(false, "Mark called on object that isnt TrackableObject");
  223. }
  224. private:
  225. JavascriptPromiseCapability* capabilities;
  226. RecyclableObject* handler;
  227. };
  228. typedef JsUtil::List<Js::JavascriptPromiseReaction*> JavascriptPromiseReactionList;
  229. class JavascriptPromise : public DynamicObject
  230. {
  231. private:
  232. DEFINE_VTABLE_CTOR(JavascriptPromise, DynamicObject);
  233. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromise);
  234. public:
  235. class EntryInfo
  236. {
  237. public:
  238. static FunctionInfo NewInstance;
  239. static FunctionInfo All;
  240. static FunctionInfo Catch;
  241. static FunctionInfo Race;
  242. static FunctionInfo Reject;
  243. static FunctionInfo Resolve;
  244. static FunctionInfo Then;
  245. static FunctionInfo Identity;
  246. static FunctionInfo Thrower;
  247. static FunctionInfo ResolveOrRejectFunction;
  248. static FunctionInfo AllResolveElementFunction;
  249. static FunctionInfo GetterSymbolSpecies;
  250. };
  251. JavascriptPromise(DynamicType * type);
  252. static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);
  253. static Var EntryAll(RecyclableObject* function, CallInfo callInfo, ...);
  254. static Var EntryCatch(RecyclableObject* function, CallInfo callInfo, ...);
  255. static Var EntryRace(RecyclableObject* function, CallInfo callInfo, ...);
  256. static Var EntryReject(RecyclableObject* function, CallInfo callInfo, ...);
  257. static Var EntryResolve(RecyclableObject* function, CallInfo callInfo, ...);
  258. static Var EntryThen(RecyclableObject* function, CallInfo callInfo, ...);
  259. static Var EntryCapabilitiesExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
  260. static Var EntryResolveOrRejectFunction(RecyclableObject* function, CallInfo callInfo, ...);
  261. static Var EntryReactionTaskFunction(RecyclableObject* function, CallInfo callInfo, ...);
  262. static Var EntryResolveThenableTaskFunction(RecyclableObject* function, CallInfo callInfo, ...);
  263. static Var EntryIdentityFunction(RecyclableObject* function, CallInfo callInfo, ...);
  264. static Var EntryThrowerFunction(RecyclableObject* function, CallInfo callInfo, ...);
  265. static Var EntryAllResolveElementFunction(RecyclableObject* function, CallInfo callInfo, ...);
  266. static Var EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...);
  267. static Var EntryJavascriptPromiseAsyncSpawnExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
  268. static Var EntryJavascriptPromiseAsyncSpawnStepNextExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
  269. static Var EntryJavascriptPromiseAsyncSpawnStepThrowExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
  270. static Var EntryJavascriptPromiseAsyncSpawnCallStepExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...);
  271. static bool Is(Var aValue);
  272. static JavascriptPromise* FromVar(Js::Var aValue);
  273. virtual BOOL GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
  274. virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
  275. JavascriptPromiseReactionList* GetResolveReactions();
  276. JavascriptPromiseReactionList* GetRejectReactions();
  277. static JavascriptPromiseCapability* NewPromiseCapability(Var constructor, ScriptContext* scriptContext);
  278. static JavascriptPromiseCapability* CreatePromiseCapabilityRecord(Var promise, RecyclableObject* constructor, ScriptContext* scriptContext);
  279. static bool UpdatePromiseFromPotentialThenable(Var resolution, JavascriptPromiseCapability* promiseCapability, ScriptContext* scriptContext);
  280. static Var TriggerPromiseReactions(JavascriptPromiseReactionList* reactions, Var resolution, ScriptContext* scriptContext);
  281. static void EnqueuePromiseReactionTask(JavascriptPromiseReaction* reaction, Var resolution, ScriptContext* scriptContext);
  282. static void InitializePromise(JavascriptPromise* promise, JavascriptPromiseResolveOrRejectFunction** resolve, JavascriptPromiseResolveOrRejectFunction** reject, ScriptContext* scriptContext);
  283. protected:
  284. enum PromiseStatus
  285. {
  286. PromiseStatusCode_Undefined,
  287. PromiseStatusCode_Unresolved,
  288. PromiseStatusCode_HasResolution,
  289. PromiseStatusCode_HasRejection
  290. };
  291. PromiseStatus status;
  292. Var result;
  293. JavascriptPromiseReactionList* resolveReactions;
  294. JavascriptPromiseReactionList* rejectReactions;
  295. private :
  296. static void AsyncSpawnStep(JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* nextFunction, JavascriptGenerator* gen, JavascriptFunction* resolve, JavascriptFunction* reject);
  297. };
  298. }