JavascriptPromise.cpp 108 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661
  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. #include "RuntimeLibraryPch.h"
  6. namespace Js
  7. {
  8. JavascriptPromise::JavascriptPromise(DynamicType * type)
  9. : DynamicObject(type),
  10. isHandled(false),
  11. status(PromiseStatus::PromiseStatusCode_Undefined),
  12. result(nullptr),
  13. reactions(nullptr)
  14. {
  15. Assert(type->GetTypeId() == TypeIds_Promise);
  16. }
  17. // Promise() as defined by ES 2016 Sections 25.4.3.1
  18. Var JavascriptPromise::NewInstance(RecyclableObject* function, CallInfo callInfo, ...)
  19. {
  20. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  21. ARGUMENTS(args, callInfo);
  22. AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
  23. ScriptContext* scriptContext = function->GetScriptContext();
  24. JavascriptLibrary* library = scriptContext->GetLibrary();
  25. CHAKRATEL_LANGSTATS_INC_LANGFEATURECOUNT(ES6, Promise, scriptContext);
  26. // SkipDefaultNewObject function flag should have prevented the default object from
  27. // being created, except when call true a host dispatch
  28. Var newTarget = args.GetNewTarget();
  29. bool isCtorSuperCall = JavascriptOperators::GetAndAssertIsConstructorSuperCall(args);
  30. AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise"));
  31. // 1. If NewTarget is undefined, throw a TypeError exception.
  32. if ((callInfo.Flags & CallFlags_New) != CallFlags_New || (newTarget != nullptr && JavascriptOperators::IsUndefined(newTarget)))
  33. {
  34. JavascriptError::ThrowTypeError(scriptContext, JSERR_ClassConstructorCannotBeCalledWithoutNew, _u("Promise"));
  35. }
  36. // 2. If IsCallable(executor) is false, throw a TypeError exception.
  37. if (args.Info.Count < 2 || !JavascriptConversion::IsCallable(args[1]))
  38. {
  39. JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedFunction, _u("Promise"));
  40. }
  41. RecyclableObject* executor = VarTo<RecyclableObject>(args[1]);
  42. // 3. Let promise be ? OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", <<[[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] >>).
  43. JavascriptPromise* promise = library->CreatePromise();
  44. if (isCtorSuperCall)
  45. {
  46. JavascriptOperators::OrdinaryCreateFromConstructor(VarTo<RecyclableObject>(newTarget), promise, library->GetPromisePrototype(), scriptContext);
  47. }
  48. JavascriptPromiseResolveOrRejectFunction* resolve;
  49. JavascriptPromiseResolveOrRejectFunction* reject;
  50. // 4. Set promise's [[PromiseState]] internal slot to "pending".
  51. // 5. Set promise's [[PromiseFulfillReactions]] internal slot to a new empty List.
  52. // 6. Set promise's [[PromiseRejectReactions]] internal slot to a new empty List.
  53. // 7. Set promise's [[PromiseIsHandled]] internal slot to false.
  54. // 8. Let resolvingFunctions be CreateResolvingFunctions(promise).
  55. InitializePromise(promise, &resolve, &reject, scriptContext);
  56. JavascriptExceptionObject* exception = nullptr;
  57. // 9. Let completion be Call(executor, undefined, << resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] >>).
  58. try
  59. {
  60. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  61. {
  62. CALL_FUNCTION(scriptContext->GetThreadContext(),
  63. executor, CallInfo(CallFlags_Value, 3),
  64. library->GetUndefined(),
  65. resolve,
  66. reject);
  67. }
  68. END_SAFE_REENTRANT_CALL
  69. }
  70. catch (const JavascriptException& err)
  71. {
  72. exception = err.GetAndClear();
  73. }
  74. if (exception != nullptr)
  75. {
  76. // 10. If completion is an abrupt completion, then
  77. // a. Perform ? Call(resolvingFunctions.[[Reject]], undefined, << completion.[[Value]] >>).
  78. TryRejectWithExceptionObject(exception, reject, scriptContext);
  79. }
  80. // 11. Return promise.
  81. return promise;
  82. }
  83. void JavascriptPromise::InitializePromise(JavascriptPromise* promise, JavascriptPromiseResolveOrRejectFunction** resolve, JavascriptPromiseResolveOrRejectFunction** reject, ScriptContext* scriptContext)
  84. {
  85. Assert(promise->GetStatus() == PromiseStatusCode_Undefined);
  86. Assert(resolve);
  87. Assert(reject);
  88. Recycler* recycler = scriptContext->GetRecycler();
  89. JavascriptLibrary* library = scriptContext->GetLibrary();
  90. promise->SetStatus(PromiseStatusCode_Unresolved);
  91. promise->reactions = RecyclerNew(recycler, JavascriptPromiseReactionList, recycler);
  92. JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyResolvedRecord = RecyclerNewStructZ(scriptContext->GetRecycler(), JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper);
  93. alreadyResolvedRecord->alreadyResolved = false;
  94. *resolve = library->CreatePromiseResolveOrRejectFunction(EntryResolveOrRejectFunction, promise, false, alreadyResolvedRecord);
  95. *reject = library->CreatePromiseResolveOrRejectFunction(EntryResolveOrRejectFunction, promise, true, alreadyResolvedRecord);
  96. }
  97. BOOL JavascriptPromise::GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext)
  98. {
  99. stringBuilder->AppendCppLiteral(_u("[...]"));
  100. return TRUE;
  101. }
  102. BOOL JavascriptPromise::GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext)
  103. {
  104. stringBuilder->AppendCppLiteral(_u("Promise"));
  105. return TRUE;
  106. }
  107. JavascriptPromiseReactionList* JavascriptPromise::GetReactions()
  108. {
  109. return this->reactions;
  110. }
  111. // Promise.all as described in ES 2015 Section 25.4.4.1
  112. Var JavascriptPromise::EntryAll(RecyclableObject* function, CallInfo callInfo, ...)
  113. {
  114. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  115. ARGUMENTS(args, callInfo);
  116. Assert(!(callInfo.Flags & CallFlags_New));
  117. ScriptContext* scriptContext = function->GetScriptContext();
  118. AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise.all"));
  119. // 1. Let C be the this value.
  120. Var constructor = args[0];
  121. // 2. If Type(C) is not Object, throw a TypeError exception.
  122. if (!JavascriptOperators::IsObject(constructor))
  123. {
  124. JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedObject, _u("Promise.all"));
  125. }
  126. JavascriptLibrary* library = scriptContext->GetLibrary();
  127. Var iterable;
  128. if (args.Info.Count > 1)
  129. {
  130. iterable = args[1];
  131. }
  132. else
  133. {
  134. iterable = library->GetUndefined();
  135. }
  136. // 3. Let promiseCapability be NewPromiseCapability(C).
  137. JavascriptPromiseCapability* promiseCapability = NewPromiseCapability(constructor, scriptContext);
  138. // We know that constructor is an object at this point - further, we even know that it is a constructor - because NewPromiseCapability
  139. // would throw otherwise. That means we can safely cast constructor into a RecyclableObject* now and avoid having to perform ToObject
  140. // as part of the Invoke operation performed inside the loop below.
  141. RecyclableObject* constructorObject = VarTo<RecyclableObject>(constructor);
  142. uint32 index = 0;
  143. JavascriptArray* values = nullptr;
  144. // We can't use a simple counter for the remaining element count since each Promise.all Resolve Element Function needs to know how many
  145. // elements are remaining when it runs and needs to update that counter for all other functions created by this call to Promise.all.
  146. // We can't just use a static variable, either, since this element count is only used for the Promise.all Resolve Element Functions created
  147. // by this call to Promise.all.
  148. JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper = RecyclerNewStructZ(scriptContext->GetRecycler(), JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper);
  149. remainingElementsWrapper->remainingElements = 1;
  150. JavascriptExceptionObject* exception = nullptr;
  151. try
  152. {
  153. // 4. Let iterator be GetIterator(iterable).
  154. RecyclableObject* iterator = JavascriptOperators::GetIterator(iterable, scriptContext);
  155. Var resolveVar = JavascriptOperators::GetProperty(constructorObject, Js::PropertyIds::resolve, scriptContext);
  156. if (!JavascriptConversion::IsCallable(resolveVar))
  157. {
  158. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
  159. }
  160. RecyclableObject* resolveFunc = VarTo<RecyclableObject>(resolveVar);
  161. values = library->CreateArray(0);
  162. JavascriptOperators::DoIteratorStepAndValue(iterator, scriptContext, [&](Var next)
  163. {
  164. ThreadContext * threadContext = scriptContext->GetThreadContext();
  165. Var nextPromise = nullptr;
  166. BEGIN_SAFE_REENTRANT_CALL(threadContext)
  167. {
  168. nextPromise = CALL_FUNCTION(threadContext,
  169. resolveFunc, Js::CallInfo(CallFlags_Value, 2),
  170. constructorObject,
  171. next);
  172. }
  173. END_SAFE_REENTRANT_CALL
  174. JavascriptPromiseAllResolveElementFunction* resolveElement = library->CreatePromiseAllResolveElementFunction(EntryAllResolveElementFunction, index, values, promiseCapability, remainingElementsWrapper);
  175. remainingElementsWrapper->remainingElements++;
  176. RecyclableObject* nextPromiseObject;
  177. if (!JavascriptConversion::ToObject(nextPromise, scriptContext, &nextPromiseObject))
  178. {
  179. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedObject);
  180. }
  181. Var thenVar = JavascriptOperators::GetProperty(nextPromiseObject, Js::PropertyIds::then, scriptContext);
  182. if (!JavascriptConversion::IsCallable(thenVar))
  183. {
  184. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
  185. }
  186. RecyclableObject* thenFunc = VarTo<RecyclableObject>(thenVar);
  187. BEGIN_SAFE_REENTRANT_CALL(threadContext)
  188. {
  189. CALL_FUNCTION(scriptContext->GetThreadContext(),
  190. thenFunc, Js::CallInfo(CallFlags_Value, 3),
  191. nextPromiseObject,
  192. resolveElement,
  193. promiseCapability->GetReject());
  194. }
  195. END_SAFE_REENTRANT_CALL
  196. index++;
  197. });
  198. remainingElementsWrapper->remainingElements--;
  199. if (remainingElementsWrapper->remainingElements == 0)
  200. {
  201. Assert(values != nullptr);
  202. TryCallResolveOrRejectHandler(promiseCapability->GetResolve(), values, scriptContext);
  203. }
  204. }
  205. catch (const JavascriptException& err)
  206. {
  207. exception = err.GetAndClear();
  208. }
  209. if (exception != nullptr)
  210. {
  211. TryRejectWithExceptionObject(exception, promiseCapability->GetReject(), scriptContext);
  212. }
  213. return promiseCapability->GetPromise();
  214. }
  215. Var JavascriptPromise::EntryAllSettled(RecyclableObject* function, CallInfo callInfo, ...)
  216. {
  217. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  218. ARGUMENTS(args, callInfo);
  219. Assert(!(callInfo.Flags & CallFlags_New));
  220. ScriptContext* scriptContext = function->GetScriptContext();
  221. AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise.allSettled"));
  222. // 1. Let C be the this value.
  223. Var constructor = args[0];
  224. // 2. If Type(C) is not Object, throw a TypeError exception.
  225. if (!JavascriptOperators::IsObject(constructor))
  226. {
  227. JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedObject, _u("Promise.allSettled"));
  228. }
  229. JavascriptLibrary* library = scriptContext->GetLibrary();
  230. Var iterable;
  231. if (args.Info.Count > 1)
  232. {
  233. iterable = args[1];
  234. }
  235. else
  236. {
  237. iterable = library->GetUndefined();
  238. }
  239. // 3. Let promiseCapability be NewPromiseCapability(C).
  240. JavascriptPromiseCapability* promiseCapability = NewPromiseCapability(constructor, scriptContext);
  241. // We know that constructor is an object at this point - further, we even know that it is a constructor - because NewPromiseCapability
  242. // would throw otherwise. That means we can safely cast constructor into a RecyclableObject* now and avoid having to perform ToObject
  243. // as part of the Invoke operation performed inside the loop below.
  244. RecyclableObject* constructorObject = VarTo<RecyclableObject>(constructor);
  245. uint32 index = 0;
  246. JavascriptArray* values = nullptr;
  247. // We can't use a simple counter for the remaining element count since each Promise.all Resolve Element Function needs to know how many
  248. // elements are remaining when it runs and needs to update that counter for all other functions created by this call to Promise.all.
  249. // We can't just use a static variable, either, since this element count is only used for the Promise.all Resolve Element Functions created
  250. // by this call to Promise.all.
  251. JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper = RecyclerNewStructZ(scriptContext->GetRecycler(), JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper);
  252. remainingElementsWrapper->remainingElements = 1;
  253. JavascriptExceptionObject* exception = nullptr;
  254. try
  255. {
  256. // 4. Let iterator be GetIterator(iterable).
  257. RecyclableObject* iterator = JavascriptOperators::GetIterator(iterable, scriptContext);
  258. // Abstract operation PerformPromiseAllSettled
  259. Var resolveVar = JavascriptOperators::GetProperty(constructorObject, Js::PropertyIds::resolve, scriptContext);
  260. if (!JavascriptConversion::IsCallable(resolveVar))
  261. {
  262. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
  263. }
  264. RecyclableObject* resolveFunc = VarTo<RecyclableObject>(resolveVar);
  265. values = library->CreateArray(0);
  266. JavascriptOperators::DoIteratorStepAndValue(iterator, scriptContext, [&](Var next)
  267. {
  268. ThreadContext* threadContext = scriptContext->GetThreadContext();
  269. Var nextPromise = nullptr;
  270. BEGIN_SAFE_REENTRANT_CALL(threadContext)
  271. {
  272. nextPromise = CALL_FUNCTION(threadContext,
  273. resolveFunc, Js::CallInfo(CallFlags_Value, 2),
  274. constructorObject,
  275. next);
  276. }
  277. END_SAFE_REENTRANT_CALL
  278. JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyCalledWrapper = RecyclerNewStructZ(scriptContext->GetRecycler(), JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper);
  279. alreadyCalledWrapper->alreadyResolved = false;
  280. Var resolveElement = library->CreatePromiseAllSettledResolveOrRejectElementFunction(EntryAllSettledResolveOrRejectElementFunction, index, values, promiseCapability, remainingElementsWrapper, alreadyCalledWrapper, false);
  281. Var rejectElement = library->CreatePromiseAllSettledResolveOrRejectElementFunction(EntryAllSettledResolveOrRejectElementFunction, index, values, promiseCapability, remainingElementsWrapper, alreadyCalledWrapper, true);
  282. remainingElementsWrapper->remainingElements++;
  283. RecyclableObject* nextPromiseObject;
  284. if (!JavascriptConversion::ToObject(nextPromise, scriptContext, &nextPromiseObject))
  285. {
  286. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedObject);
  287. }
  288. Var thenVar = JavascriptOperators::GetProperty(nextPromiseObject, Js::PropertyIds::then, scriptContext);
  289. if (!JavascriptConversion::IsCallable(thenVar))
  290. {
  291. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
  292. }
  293. RecyclableObject* thenFunc = VarTo<RecyclableObject>(thenVar);
  294. BEGIN_SAFE_REENTRANT_CALL(threadContext)
  295. {
  296. CALL_FUNCTION(scriptContext->GetThreadContext(),
  297. thenFunc, Js::CallInfo(CallFlags_Value, 3),
  298. nextPromiseObject,
  299. resolveElement,
  300. rejectElement);
  301. }
  302. END_SAFE_REENTRANT_CALL
  303. index++;
  304. });
  305. remainingElementsWrapper->remainingElements--;
  306. if (remainingElementsWrapper->remainingElements == 0)
  307. {
  308. Assert(values != nullptr);
  309. TryCallResolveOrRejectHandler(promiseCapability->GetResolve(), values, scriptContext);
  310. }
  311. }
  312. catch (const JavascriptException& err)
  313. {
  314. exception = err.GetAndClear();
  315. }
  316. if (exception != nullptr)
  317. {
  318. TryRejectWithExceptionObject(exception, promiseCapability->GetReject(), scriptContext);
  319. }
  320. return promiseCapability->GetPromise();
  321. }
  322. // Promise.prototype.catch as defined in ES 2015 Section 25.4.5.1
  323. Var JavascriptPromise::EntryCatch(RecyclableObject* function, CallInfo callInfo, ...)
  324. {
  325. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  326. ARGUMENTS(args, callInfo);
  327. Assert(!(callInfo.Flags & CallFlags_New));
  328. ScriptContext* scriptContext = function->GetScriptContext();
  329. AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise.prototype.catch"));
  330. RecyclableObject* promise;
  331. if (!JavascriptConversion::ToObject(args[0], scriptContext, &promise))
  332. {
  333. JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedObject, _u("Promise.prototype.catch"));
  334. }
  335. Var funcVar = JavascriptOperators::GetProperty(promise, Js::PropertyIds::then, scriptContext);
  336. if (!JavascriptConversion::IsCallable(funcVar))
  337. {
  338. JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedFunction, _u("Promise.prototype.catch"));
  339. }
  340. Var onRejected;
  341. RecyclableObject* undefinedVar = scriptContext->GetLibrary()->GetUndefined();
  342. if (args.Info.Count > 1)
  343. {
  344. onRejected = args[1];
  345. }
  346. else
  347. {
  348. onRejected = undefinedVar;
  349. }
  350. RecyclableObject* func = VarTo<RecyclableObject>(funcVar);
  351. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  352. {
  353. return CALL_FUNCTION(scriptContext->GetThreadContext(),
  354. func, Js::CallInfo(CallFlags_Value, 3),
  355. promise,
  356. undefinedVar,
  357. onRejected);
  358. }
  359. END_SAFE_REENTRANT_CALL
  360. }
  361. // Promise.race as described in ES 2015 Section 25.4.4.3
  362. Var JavascriptPromise::EntryRace(RecyclableObject* function, CallInfo callInfo, ...)
  363. {
  364. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  365. ARGUMENTS(args, callInfo);
  366. Assert(!(callInfo.Flags & CallFlags_New));
  367. ScriptContext* scriptContext = function->GetScriptContext();
  368. AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise.race"));
  369. // 1. Let C be the this value.
  370. Var constructor = args[0];
  371. // 2. If Type(C) is not Object, throw a TypeError exception.
  372. if (!JavascriptOperators::IsObject(constructor))
  373. {
  374. JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedObject, _u("Promise.race"));
  375. }
  376. Var undefinedVar = scriptContext->GetLibrary()->GetUndefined();
  377. Var iterable;
  378. if (args.Info.Count > 1)
  379. {
  380. iterable = args[1];
  381. }
  382. else
  383. {
  384. iterable = undefinedVar;
  385. }
  386. // 3. Let promiseCapability be NewPromiseCapability(C).
  387. JavascriptPromiseCapability* promiseCapability = NewPromiseCapability(constructor, scriptContext);
  388. // We know that constructor is an object at this point - further, we even know that it is a constructor - because NewPromiseCapability
  389. // would throw otherwise. That means we can safely cast constructor into a RecyclableObject* now and avoid having to perform ToObject
  390. // as part of the Invoke operation performed inside the loop below.
  391. RecyclableObject* constructorObject = VarTo<RecyclableObject>(constructor);
  392. JavascriptExceptionObject* exception = nullptr;
  393. try
  394. {
  395. // 4. Let iterator be GetIterator(iterable).
  396. RecyclableObject* iterator = JavascriptOperators::GetIterator(iterable, scriptContext);
  397. Var resolveVar = JavascriptOperators::GetProperty(constructorObject, Js::PropertyIds::resolve, scriptContext);
  398. if (!JavascriptConversion::IsCallable(resolveVar))
  399. {
  400. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
  401. }
  402. RecyclableObject* resolveFunc = VarTo<RecyclableObject>(resolveVar);
  403. JavascriptOperators::DoIteratorStepAndValue(iterator, scriptContext, [&](Var next)
  404. {
  405. ThreadContext * threadContext = scriptContext->GetThreadContext();
  406. Var nextPromise = nullptr;
  407. BEGIN_SAFE_REENTRANT_CALL(threadContext)
  408. {
  409. nextPromise = CALL_FUNCTION(threadContext,
  410. resolveFunc, Js::CallInfo(CallFlags_Value, 2),
  411. constructorObject,
  412. next);
  413. }
  414. END_SAFE_REENTRANT_CALL
  415. RecyclableObject* nextPromiseObject;
  416. if (!JavascriptConversion::ToObject(nextPromise, scriptContext, &nextPromiseObject))
  417. {
  418. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedObject);
  419. }
  420. Var thenVar = JavascriptOperators::GetProperty(nextPromiseObject, Js::PropertyIds::then, scriptContext);
  421. if (!JavascriptConversion::IsCallable(thenVar))
  422. {
  423. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
  424. }
  425. RecyclableObject* thenFunc = VarTo<RecyclableObject>(thenVar);
  426. BEGIN_SAFE_REENTRANT_CALL(threadContext)
  427. {
  428. CALL_FUNCTION(threadContext,
  429. thenFunc, Js::CallInfo(CallFlags_Value, 3),
  430. nextPromiseObject,
  431. promiseCapability->GetResolve(),
  432. promiseCapability->GetReject());
  433. }
  434. END_SAFE_REENTRANT_CALL
  435. });
  436. }
  437. catch (const JavascriptException& err)
  438. {
  439. exception = err.GetAndClear();
  440. }
  441. if (exception != nullptr)
  442. {
  443. TryRejectWithExceptionObject(exception, promiseCapability->GetReject(), scriptContext);
  444. }
  445. return promiseCapability->GetPromise();
  446. }
  447. // Promise.reject as described in ES 2015 Section 25.4.4.4
  448. Var JavascriptPromise::EntryReject(RecyclableObject* function, CallInfo callInfo, ...)
  449. {
  450. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  451. ARGUMENTS(args, callInfo);
  452. Assert(!(callInfo.Flags & CallFlags_New));
  453. ScriptContext* scriptContext = function->GetScriptContext();
  454. AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise.reject"));
  455. // 1. Let C be the this value.
  456. Var constructor = args[0];
  457. // 2. If Type(C) is not Object, throw a TypeError exception.
  458. if (!JavascriptOperators::IsObject(constructor))
  459. {
  460. JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedObject, _u("Promise.reject"));
  461. }
  462. Var r;
  463. if (args.Info.Count > 1)
  464. {
  465. r = args[1];
  466. }
  467. else
  468. {
  469. r = scriptContext->GetLibrary()->GetUndefined();
  470. }
  471. // 3. Let promiseCapability be NewPromiseCapability(C).
  472. // 4. Perform ? Call(promiseCapability.[[Reject]], undefined, << r >>).
  473. // 5. Return promiseCapability.[[Promise]].
  474. return CreateRejectedPromise(r, scriptContext, constructor);
  475. }
  476. // Promise.resolve as described in ES 2015 Section 25.4.4.5
  477. Var JavascriptPromise::EntryResolve(RecyclableObject* function, CallInfo callInfo, ...)
  478. {
  479. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  480. ARGUMENTS(args, callInfo);
  481. Assert(!(callInfo.Flags & CallFlags_New));
  482. ScriptContext* scriptContext = function->GetScriptContext();
  483. AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise.resolve"));
  484. Var x;
  485. // 1. Let C be the this value.
  486. Var constructor = args[0];
  487. // 2. If Type(C) is not Object, throw a TypeError exception.
  488. if (!JavascriptOperators::IsObject(constructor))
  489. {
  490. JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedObject, _u("Promise.resolve"));
  491. }
  492. if (args.Info.Count > 1)
  493. {
  494. x = args[1];
  495. }
  496. else
  497. {
  498. x = scriptContext->GetLibrary()->GetUndefined();
  499. }
  500. return PromiseResolve(constructor, x, scriptContext);
  501. }
  502. JavascriptPromise* JavascriptPromise::InternalPromiseResolve(Var value, ScriptContext* scriptContext)
  503. {
  504. Var constructor = scriptContext->GetLibrary()->GetPromiseConstructor();
  505. Var promise = PromiseResolve(constructor, value, scriptContext);
  506. return UnsafeVarTo<JavascriptPromise>(promise);
  507. }
  508. Var JavascriptPromise::PromiseResolve(Var constructor, Var value, ScriptContext* scriptContext)
  509. {
  510. if (VarIs<JavascriptPromise>(value))
  511. {
  512. Var valueConstructor = JavascriptOperators::GetProperty(
  513. (RecyclableObject*)value,
  514. PropertyIds::constructor,
  515. scriptContext);
  516. // If `value` is a Promise or Promise subclass instance and its "constructor"
  517. // property is `constructor`, then return the value unchanged
  518. if (JavascriptConversion::SameValue(valueConstructor, constructor))
  519. {
  520. return value;
  521. }
  522. }
  523. return CreateResolvedPromise(value, scriptContext, constructor);
  524. }
  525. // Promise.prototype.then as described in ES 2015 Section 25.4.5.3
  526. Var JavascriptPromise::EntryThen(RecyclableObject* function, CallInfo callInfo, ...)
  527. {
  528. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  529. ARGUMENTS(args, callInfo);
  530. Assert(!(callInfo.Flags & CallFlags_New));
  531. ScriptContext* scriptContext = function->GetScriptContext();
  532. AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise.prototype.then"));
  533. if (args.Info.Count < 1 || !VarIs<JavascriptPromise>(args[0]))
  534. {
  535. JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedPromise, _u("Promise.prototype.then"));
  536. }
  537. JavascriptLibrary* library = scriptContext->GetLibrary();
  538. JavascriptPromise* promise = VarTo<JavascriptPromise>(args[0]);
  539. RecyclableObject* rejectionHandler;
  540. RecyclableObject* fulfillmentHandler;
  541. if (args.Info.Count > 1 && JavascriptConversion::IsCallable(args[1]))
  542. {
  543. fulfillmentHandler = VarTo<RecyclableObject>(args[1]);
  544. }
  545. else
  546. {
  547. fulfillmentHandler = library->GetIdentityFunction();
  548. }
  549. if (args.Info.Count > 2 && JavascriptConversion::IsCallable(args[2]))
  550. {
  551. rejectionHandler = VarTo<RecyclableObject>(args[2]);
  552. }
  553. else
  554. {
  555. rejectionHandler = library->GetThrowerFunction();
  556. }
  557. return CreateThenPromise(promise, fulfillmentHandler, rejectionHandler, scriptContext);
  558. }
  559. // Promise.prototype.finally as described in the draft ES 2018 #sec-promise.prototype.finally
  560. Var JavascriptPromise::EntryFinally(RecyclableObject* function, CallInfo callInfo, ...)
  561. {
  562. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  563. ARGUMENTS(args, callInfo);
  564. Assert(!(callInfo.Flags & CallFlags_New));
  565. ScriptContext* scriptContext = function->GetScriptContext();
  566. AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise.prototype.finally"));
  567. // 1. Let promise be the this value
  568. // 2. If Type(promise) is not Object, throw a TypeError exception
  569. if (args.Info.Count < 1 || !JavascriptOperators::IsObject(args[0]))
  570. {
  571. JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedObject, _u("Promise.prototype.finally"));
  572. }
  573. JavascriptLibrary* library = scriptContext->GetLibrary();
  574. RecyclableObject* promise = UnsafeVarTo<RecyclableObject>(args[0]);
  575. // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
  576. RecyclableObject* constructor = JavascriptOperators::SpeciesConstructor(promise, scriptContext->GetLibrary()->GetPromiseConstructor(), scriptContext);
  577. // 4. Assert IsConstructor(C)
  578. Assert(JavascriptOperators::IsConstructor(constructor));
  579. // 5. If IsCallable(onFinally) is false
  580. // a. Let thenFinally be onFinally
  581. // b. Let catchFinally be onFinally
  582. // 6. Else,
  583. // a. Let thenFinally be a new built-in function object as defined in ThenFinally Function.
  584. // b. Let catchFinally be a new built-in function object as defined in CatchFinally Function.
  585. // c. Set thenFinally and catchFinally's [[Constructor]] internal slots to C.
  586. // d. Set thenFinally and catchFinally's [[OnFinally]] internal slots to onFinally.
  587. Var thenFinally = nullptr;
  588. Var catchFinally = nullptr;
  589. if (args.Info.Count > 1)
  590. {
  591. if (JavascriptConversion::IsCallable(args[1]))
  592. {
  593. //note to avoid duplicating code the ThenFinallyFunction works as both thenFinally and catchFinally using a flag
  594. thenFinally = library->CreatePromiseThenFinallyFunction(EntryThenFinallyFunction, VarTo<RecyclableObject>(args[1]), constructor, false);
  595. catchFinally = library->CreatePromiseThenFinallyFunction(EntryThenFinallyFunction, VarTo<RecyclableObject>(args[1]), constructor, true);
  596. }
  597. else
  598. {
  599. thenFinally = args[1];
  600. catchFinally = args[1];
  601. }
  602. }
  603. else
  604. {
  605. thenFinally = library->GetUndefined();
  606. catchFinally = library->GetUndefined();
  607. }
  608. Assert(thenFinally != nullptr && catchFinally != nullptr);
  609. // 7. Return ? Invoke(promise, "then", << thenFinally, catchFinally >>).
  610. Var funcVar = JavascriptOperators::GetProperty(promise, Js::PropertyIds::then, scriptContext);
  611. if (!JavascriptConversion::IsCallable(funcVar))
  612. {
  613. JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedFunction, _u("Promise.prototype.finally"));
  614. }
  615. RecyclableObject* func = UnsafeVarTo<RecyclableObject>(funcVar);
  616. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  617. {
  618. return CALL_FUNCTION(scriptContext->GetThreadContext(),
  619. func, Js::CallInfo(CallFlags_Value, 3),
  620. promise,
  621. thenFinally,
  622. catchFinally);
  623. }
  624. END_SAFE_REENTRANT_CALL
  625. }
  626. // ThenFinallyFunction as described in draft ES2018 #sec-thenfinallyfunctions
  627. // AND CatchFinallyFunction as described in draft ES2018 #sec-catchfinallyfunctions
  628. Var JavascriptPromise::EntryThenFinallyFunction(RecyclableObject* function, CallInfo callInfo, ...)
  629. {
  630. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  631. ARGUMENTS(args, callInfo);
  632. Assert(!(callInfo.Flags & CallFlags_New));
  633. ScriptContext* scriptContext = function->GetScriptContext();
  634. JavascriptLibrary* library = scriptContext->GetLibrary();
  635. JavascriptPromiseThenFinallyFunction* thenFinallyFunction = VarTo<JavascriptPromiseThenFinallyFunction>(function);
  636. // 1. Let onFinally be F.[[OnFinally]]
  637. // 2. Assert: IsCallable(onFinally)=true
  638. Assert(JavascriptConversion::IsCallable(thenFinallyFunction->GetOnFinally()));
  639. // 3. Let result be ? Call(onFinally, undefined)
  640. Var result = nullptr;
  641. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  642. {
  643. result = CALL_FUNCTION(scriptContext->GetThreadContext(), thenFinallyFunction->GetOnFinally(), CallInfo(CallFlags_Value, 1), library->GetUndefined());
  644. }
  645. END_SAFE_REENTRANT_CALL
  646. Assert(result);
  647. // 4. Let C be F.[[Constructor]]
  648. // 5. Assert IsConstructor(C)
  649. Assert(JavascriptOperators::IsConstructor(thenFinallyFunction->GetConstructor()));
  650. // 6. Let promise be ? PromiseResolve(c, result)
  651. Var promiseVar = CreateResolvedPromise(result, scriptContext, thenFinallyFunction->GetConstructor());
  652. // 7. Let valueThunk be equivalent to a function that returns value
  653. // OR 7. Let thrower be equivalent to a function that throws reason
  654. Var valueOrReason = nullptr;
  655. if (args.Info.Count > 1)
  656. {
  657. valueOrReason = args[1];
  658. }
  659. else
  660. {
  661. valueOrReason = scriptContext->GetLibrary()->GetUndefined();
  662. }
  663. JavascriptPromiseThunkFinallyFunction* thunkFinallyFunction = library->CreatePromiseThunkFinallyFunction(EntryThunkFinallyFunction, valueOrReason, thenFinallyFunction->GetShouldThrow());
  664. // 8. Return ? Invoke(promise, "then", <<valueThunk>>)
  665. RecyclableObject* promise = JavascriptOperators::ToObject(promiseVar, scriptContext);
  666. Var funcVar = JavascriptOperators::GetProperty(promise, Js::PropertyIds::then, scriptContext);
  667. if (!JavascriptConversion::IsCallable(funcVar))
  668. {
  669. JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedFunction, _u("Promise.prototype.finally"));
  670. }
  671. RecyclableObject* func = VarTo<RecyclableObject>(funcVar);
  672. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  673. {
  674. return CALL_FUNCTION(scriptContext->GetThreadContext(),
  675. func, Js::CallInfo(CallFlags_Value, 2),
  676. promiseVar,
  677. thunkFinallyFunction);
  678. }
  679. END_SAFE_REENTRANT_CALL
  680. }
  681. // valueThunk Function as referenced within draft ES2018 #sec-thenfinallyfunctions
  682. // and thrower as referenced within draft ES2018 #sec-catchfinallyfunctions
  683. Var JavascriptPromise::EntryThunkFinallyFunction(RecyclableObject* function, CallInfo callInfo, ...)
  684. {
  685. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  686. ARGUMENTS(args, callInfo);
  687. Assert(!(callInfo.Flags & CallFlags_New));
  688. JavascriptPromiseThunkFinallyFunction* thunkFinallyFunction = VarTo<JavascriptPromiseThunkFinallyFunction>(function);
  689. if (!thunkFinallyFunction->GetShouldThrow())
  690. {
  691. return thunkFinallyFunction->GetValue();
  692. }
  693. else
  694. {
  695. JavascriptExceptionOperators::Throw(thunkFinallyFunction->GetValue(), function->GetScriptContext());
  696. }
  697. }
  698. // Promise Reject and Resolve Functions as described in ES 2015 Section 25.4.1.4.1 and 25.4.1.4.2
  699. Var JavascriptPromise::EntryResolveOrRejectFunction(RecyclableObject* function, CallInfo callInfo, ...)
  700. {
  701. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  702. ARGUMENTS(args, callInfo);
  703. Assert(!(callInfo.Flags & CallFlags_New));
  704. ScriptContext* scriptContext = function->GetScriptContext();
  705. JavascriptLibrary* library = scriptContext->GetLibrary();
  706. Var undefinedVar = library->GetUndefined();
  707. Var resolution;
  708. if (args.Info.Count > 1)
  709. {
  710. resolution = args[1];
  711. }
  712. else
  713. {
  714. resolution = undefinedVar;
  715. }
  716. JavascriptPromiseResolveOrRejectFunction* resolveOrRejectFunction = VarTo<JavascriptPromiseResolveOrRejectFunction>(function);
  717. if (resolveOrRejectFunction->IsAlreadyResolved())
  718. {
  719. return undefinedVar;
  720. }
  721. resolveOrRejectFunction->SetAlreadyResolved(true);
  722. bool rejecting = resolveOrRejectFunction->IsRejectFunction();
  723. JavascriptPromise* promise = resolveOrRejectFunction->GetPromise();
  724. return promise->ResolveHelper(resolution, rejecting, scriptContext);
  725. }
  726. Var JavascriptPromise::Resolve(Var resolution, ScriptContext* scriptContext)
  727. {
  728. return this->ResolveHelper(resolution, false, scriptContext);
  729. }
  730. Var JavascriptPromise::Reject(Var resolution, ScriptContext* scriptContext)
  731. {
  732. return this->ResolveHelper(resolution, true, scriptContext);
  733. }
  734. Var JavascriptPromise::ResolveHelper(Var resolution, bool isRejecting, ScriptContext* scriptContext)
  735. {
  736. JavascriptLibrary* library = scriptContext->GetLibrary();
  737. Var undefinedVar = library->GetUndefined();
  738. // We only need to check SameValue and check for thenable resolution in the Resolve function case (not Reject)
  739. if (!isRejecting)
  740. {
  741. if (JavascriptConversion::SameValue(resolution, this))
  742. {
  743. JavascriptError* selfResolutionError = scriptContext->GetLibrary()->CreateTypeError();
  744. JavascriptError::SetErrorMessage(selfResolutionError, JSERR_PromiseSelfResolution, _u(""), scriptContext);
  745. resolution = selfResolutionError;
  746. isRejecting = true;
  747. }
  748. else if (VarIs<RecyclableObject>(resolution))
  749. {
  750. try
  751. {
  752. RecyclableObject* thenable = VarTo<RecyclableObject>(resolution);
  753. Var then = JavascriptOperators::GetPropertyNoCache(thenable, Js::PropertyIds::then, scriptContext);
  754. if (JavascriptConversion::IsCallable(then))
  755. {
  756. JavascriptPromiseResolveThenableTaskFunction* resolveThenableTaskFunction = library->CreatePromiseResolveThenableTaskFunction(EntryResolveThenableTaskFunction, this, thenable, VarTo<RecyclableObject>(then));
  757. library->EnqueueTask(resolveThenableTaskFunction);
  758. return undefinedVar;
  759. }
  760. }
  761. catch (const JavascriptException& err)
  762. {
  763. resolution = err.GetAndClear()->GetThrownObject(scriptContext);
  764. if (resolution == nullptr)
  765. {
  766. resolution = undefinedVar;
  767. }
  768. isRejecting = true;
  769. }
  770. }
  771. }
  772. PromiseStatus newStatus;
  773. // Need to check rejecting state again as it might have changed due to failures
  774. if (isRejecting)
  775. {
  776. newStatus = PromiseStatusCode_HasRejection;
  777. if (!GetIsHandled())
  778. {
  779. scriptContext->GetLibrary()->CallNativeHostPromiseRejectionTracker(this, resolution, false);
  780. }
  781. }
  782. else
  783. {
  784. newStatus = PromiseStatusCode_HasResolution;
  785. }
  786. Assert(resolution != nullptr);
  787. // SList only supports "prepend" operation, so we need to reverse the list
  788. // before triggering reactions
  789. JavascriptPromiseReactionList* reactions = this->GetReactions();
  790. if (reactions != nullptr)
  791. {
  792. reactions->Reverse();
  793. }
  794. this->result = resolution;
  795. this->reactions = nullptr;
  796. this->SetStatus(newStatus);
  797. return TriggerPromiseReactions(reactions, isRejecting, resolution, scriptContext);
  798. }
  799. // Promise Capabilities Executor Function as described in ES 2015 Section 25.4.1.6.2
  800. Var JavascriptPromise::EntryCapabilitiesExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...)
  801. {
  802. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  803. ARGUMENTS(args, callInfo);
  804. Assert(!(callInfo.Flags & CallFlags_New));
  805. ScriptContext* scriptContext = function->GetScriptContext();
  806. Var undefinedVar = scriptContext->GetLibrary()->GetUndefined();
  807. Var resolve = undefinedVar;
  808. Var reject = undefinedVar;
  809. if (args.Info.Count > 1)
  810. {
  811. resolve = args[1];
  812. if (args.Info.Count > 2)
  813. {
  814. reject = args[2];
  815. }
  816. }
  817. JavascriptPromiseCapabilitiesExecutorFunction* capabilitiesExecutorFunction = VarTo<JavascriptPromiseCapabilitiesExecutorFunction>(function);
  818. JavascriptPromiseCapability* promiseCapability = capabilitiesExecutorFunction->GetCapability();
  819. if (!JavascriptOperators::IsUndefined(promiseCapability->GetResolve()) || !JavascriptOperators::IsUndefined(promiseCapability->GetReject()))
  820. {
  821. JavascriptError::ThrowTypeErrorVar(scriptContext, JSERR_UnexpectedMetadataFailure, _u("Promise"));
  822. }
  823. promiseCapability->SetResolve(resolve);
  824. promiseCapability->SetReject(reject);
  825. return undefinedVar;
  826. }
  827. // Promise Reaction Task Function as described in ES 2015 Section 25.4.2.1
  828. Var JavascriptPromise::EntryReactionTaskFunction(RecyclableObject* function, CallInfo callInfo, ...)
  829. {
  830. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  831. ARGUMENTS(args, callInfo);
  832. Assert(!(callInfo.Flags & CallFlags_New));
  833. ScriptContext* scriptContext = function->GetScriptContext();
  834. Var undefinedVar = scriptContext->GetLibrary()->GetUndefined();
  835. JavascriptPromiseReactionTaskFunction* reactionTaskFunction = VarTo<JavascriptPromiseReactionTaskFunction>(function);
  836. JavascriptPromiseReaction* reaction = reactionTaskFunction->GetReaction();
  837. Var argument = reactionTaskFunction->GetArgument();
  838. JavascriptPromiseCapability* promiseCapability = reaction->GetCapabilities();
  839. RecyclableObject* handler = reaction->GetHandler();
  840. Var handlerResult = nullptr;
  841. JavascriptExceptionObject* exception = nullptr;
  842. {
  843. bool isPromiseRejectionHandled = true;
  844. if (scriptContext->IsScriptContextInDebugMode())
  845. {
  846. // only necessary to determine if false if debugger is attached. This way we'll
  847. // correctly break on exceptions raised in promises that result in uhandled rejection
  848. // notifications
  849. Var promiseVar = promiseCapability->GetPromise();
  850. if (VarIs<JavascriptPromise>(promiseVar))
  851. {
  852. JavascriptPromise* promise = VarTo<JavascriptPromise>(promiseVar);
  853. isPromiseRejectionHandled = !promise->WillRejectionBeUnhandled();
  854. }
  855. }
  856. Js::JavascriptExceptionOperators::AutoCatchHandlerExists autoCatchHandlerExists(scriptContext, isPromiseRejectionHandled);
  857. try
  858. {
  859. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  860. {
  861. handlerResult = CALL_FUNCTION(scriptContext->GetThreadContext(),
  862. handler, Js::CallInfo(Js::CallFlags::CallFlags_Value, 2),
  863. undefinedVar,
  864. argument);
  865. }
  866. END_SAFE_REENTRANT_CALL
  867. }
  868. catch (const JavascriptException& err)
  869. {
  870. exception = err.GetAndClear();
  871. }
  872. }
  873. if (exception != nullptr)
  874. {
  875. return TryRejectWithExceptionObject(exception, promiseCapability->GetReject(), scriptContext);
  876. }
  877. Assert(handlerResult != nullptr);
  878. return TryCallResolveOrRejectHandler(promiseCapability->GetResolve(), handlerResult, scriptContext);
  879. }
  880. /**
  881. * Determine if at the current point in time, the given promise has a path of reactions that result
  882. * in an unhandled rejection. This doesn't account for potential of a rejection handler added later
  883. * in time.
  884. */
  885. bool JavascriptPromise::WillRejectionBeUnhandled()
  886. {
  887. bool willBeUnhandled = !this->GetIsHandled();
  888. if (!willBeUnhandled)
  889. {
  890. // if this promise is handled, then we need to do a depth-first search over this promise's reject
  891. // reactions. If we find a reaction that
  892. // - associated promise is "unhandled" (ie, it's never been "then'd")
  893. // - AND its rejection handler is our default "thrower function"
  894. // then this promise results in an unhandled rejection path.
  895. JsUtil::Stack<JavascriptPromise*, HeapAllocator> stack(&HeapAllocator::Instance);
  896. SimpleHashTable<JavascriptPromise*, int, HeapAllocator> visited(&HeapAllocator::Instance);
  897. stack.Push(this);
  898. visited.Add(this, 1);
  899. while (!willBeUnhandled && !stack.Empty())
  900. {
  901. JavascriptPromise * curr = stack.Pop();
  902. {
  903. JavascriptPromiseReactionList* reactions = curr->GetReactions();
  904. JavascriptPromiseReactionList::Iterator it = reactions->GetIterator();
  905. while (it.Next())
  906. {
  907. JavascriptPromiseReactionPair pair = it.Data();
  908. JavascriptPromiseReaction* reaction = pair.rejectReaction;
  909. Var promiseVar = reaction->GetCapabilities()->GetPromise();
  910. if (VarIs<JavascriptPromise>(promiseVar))
  911. {
  912. JavascriptPromise* p = VarTo<JavascriptPromise>(promiseVar);
  913. if (!p->GetIsHandled())
  914. {
  915. RecyclableObject* handler = reaction->GetHandler();
  916. if (VarIs<JavascriptFunction>(handler))
  917. {
  918. JavascriptFunction* func = VarTo<JavascriptFunction>(handler);
  919. FunctionInfo* functionInfo = func->GetFunctionInfo();
  920. #ifdef DEBUG
  921. if (!func->IsCrossSiteObject())
  922. {
  923. // assert that Thrower function's FunctionInfo hasn't changed
  924. AssertMsg(func->GetScriptContext()->GetLibrary()->GetThrowerFunction()->GetFunctionInfo() == &JavascriptPromise::EntryInfo::Thrower, "unexpected FunctionInfo for thrower function!");
  925. }
  926. #endif
  927. // If the function info is the default thrower function's function info, then assume that this is unhandled
  928. // this will work across script contexts
  929. if (functionInfo == &JavascriptPromise::EntryInfo::Thrower)
  930. {
  931. willBeUnhandled = true;
  932. break;
  933. }
  934. }
  935. }
  936. AssertMsg(visited.HasEntry(p) == false, "Unexpected cycle in promise reaction tree!");
  937. if (!visited.HasEntry(p))
  938. {
  939. stack.Push(p);
  940. visited.Add(p, 1);
  941. }
  942. }
  943. }
  944. }
  945. }
  946. }
  947. return willBeUnhandled;
  948. }
  949. Var JavascriptPromise::TryCallResolveOrRejectHandler(Var handler, Var value, ScriptContext* scriptContext)
  950. {
  951. Var undefinedVar = scriptContext->GetLibrary()->GetUndefined();
  952. if (!JavascriptConversion::IsCallable(handler))
  953. {
  954. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
  955. }
  956. RecyclableObject* handlerFunc = VarTo<RecyclableObject>(handler);
  957. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  958. {
  959. return CALL_FUNCTION(scriptContext->GetThreadContext(),
  960. handlerFunc, CallInfo(CallFlags_Value, 2),
  961. undefinedVar,
  962. value);
  963. }
  964. END_SAFE_REENTRANT_CALL
  965. }
  966. Var JavascriptPromise::TryRejectWithExceptionObject(JavascriptExceptionObject* exceptionObject, Var handler, ScriptContext* scriptContext)
  967. {
  968. Var thrownObject = exceptionObject->GetThrownObject(scriptContext);
  969. if (thrownObject == nullptr)
  970. {
  971. thrownObject = scriptContext->GetLibrary()->GetUndefined();
  972. }
  973. return TryCallResolveOrRejectHandler(handler, thrownObject, scriptContext);
  974. }
  975. Var JavascriptPromise::CreateRejectedPromise(Var resolution, ScriptContext* scriptContext, Var promiseConstructor)
  976. {
  977. if (promiseConstructor == nullptr)
  978. {
  979. promiseConstructor = scriptContext->GetLibrary()->GetPromiseConstructor();
  980. }
  981. JavascriptPromiseCapability* promiseCapability = NewPromiseCapability(promiseConstructor, scriptContext);
  982. TryCallResolveOrRejectHandler(promiseCapability->GetReject(), resolution, scriptContext);
  983. return promiseCapability->GetPromise();
  984. }
  985. Var JavascriptPromise::CreateResolvedPromise(Var resolution, ScriptContext* scriptContext, Var promiseConstructor)
  986. {
  987. if (promiseConstructor == nullptr)
  988. {
  989. promiseConstructor = scriptContext->GetLibrary()->GetPromiseConstructor();
  990. }
  991. JavascriptPromiseCapability* promiseCapability = NewPromiseCapability(promiseConstructor, scriptContext);
  992. TryCallResolveOrRejectHandler(promiseCapability->GetResolve(), resolution, scriptContext);
  993. return promiseCapability->GetPromise();
  994. }
  995. Var JavascriptPromise::CreatePassThroughPromise(JavascriptPromise* sourcePromise, ScriptContext* scriptContext)
  996. {
  997. JavascriptLibrary* library = scriptContext->GetLibrary();
  998. return CreateThenPromise(sourcePromise, library->GetIdentityFunction(), library->GetThrowerFunction(), scriptContext);
  999. }
  1000. Var JavascriptPromise::CreateThenPromise(JavascriptPromise* sourcePromise, RecyclableObject* fulfillmentHandler, RecyclableObject* rejectionHandler, ScriptContext* scriptContext)
  1001. {
  1002. JavascriptFunction* defaultConstructor = scriptContext->GetLibrary()->GetPromiseConstructor();
  1003. RecyclableObject* constructor = JavascriptOperators::SpeciesConstructor(sourcePromise, defaultConstructor, scriptContext);
  1004. AssertOrFailFast(JavascriptOperators::IsConstructor(constructor));
  1005. bool isDefaultConstructor = constructor == defaultConstructor;
  1006. JavascriptPromiseCapability* promiseCapability = (JavascriptPromiseCapability*)JavascriptOperators::NewObjectCreationHelper_ReentrancySafe(constructor, isDefaultConstructor, scriptContext->GetThreadContext(), [=]()->JavascriptPromiseCapability*
  1007. {
  1008. return NewPromiseCapability(constructor, scriptContext);
  1009. });
  1010. PerformPromiseThen(sourcePromise, promiseCapability, fulfillmentHandler, rejectionHandler, scriptContext);
  1011. return promiseCapability->GetPromise();
  1012. }
  1013. void JavascriptPromise::PerformPromiseThen(
  1014. JavascriptPromise* sourcePromise,
  1015. JavascriptPromiseCapability* capability,
  1016. RecyclableObject* fulfillmentHandler,
  1017. RecyclableObject* rejectionHandler,
  1018. ScriptContext* scriptContext)
  1019. {
  1020. auto* resolveReaction = JavascriptPromiseReaction::New(capability, fulfillmentHandler, scriptContext);
  1021. auto* rejectReaction = JavascriptPromiseReaction::New(capability, rejectionHandler, scriptContext);
  1022. switch (sourcePromise->GetStatus())
  1023. {
  1024. case PromiseStatusCode_Unresolved:
  1025. JavascriptPromiseReactionPair pair;
  1026. pair.resolveReaction = resolveReaction;
  1027. pair.rejectReaction = rejectReaction;
  1028. sourcePromise->reactions->Prepend(pair);
  1029. break;
  1030. case PromiseStatusCode_HasResolution:
  1031. EnqueuePromiseReactionTask(
  1032. resolveReaction,
  1033. CrossSite::MarshalVar(scriptContext, sourcePromise->result),
  1034. scriptContext);
  1035. break;
  1036. case PromiseStatusCode_HasRejection:
  1037. {
  1038. if (!sourcePromise->GetIsHandled())
  1039. {
  1040. scriptContext->GetLibrary()->CallNativeHostPromiseRejectionTracker(
  1041. sourcePromise,
  1042. CrossSite::MarshalVar(scriptContext, sourcePromise->result),
  1043. true);
  1044. }
  1045. EnqueuePromiseReactionTask(
  1046. rejectReaction,
  1047. CrossSite::MarshalVar(scriptContext, sourcePromise->result),
  1048. scriptContext);
  1049. break;
  1050. }
  1051. default:
  1052. AssertMsg(false, "Promise status is in an invalid state");
  1053. break;
  1054. }
  1055. sourcePromise->SetIsHandled();
  1056. }
  1057. // Promise Resolve Thenable Job as described in ES 2015 Section 25.4.2.2
  1058. Var JavascriptPromise::EntryResolveThenableTaskFunction(RecyclableObject* function, CallInfo callInfo, ...)
  1059. {
  1060. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  1061. ARGUMENTS(args, callInfo);
  1062. Assert(!(callInfo.Flags & CallFlags_New));
  1063. ScriptContext* scriptContext = function->GetScriptContext();
  1064. JavascriptLibrary* library = scriptContext->GetLibrary();
  1065. JavascriptPromiseResolveThenableTaskFunction* resolveThenableTaskFunction = VarTo<JavascriptPromiseResolveThenableTaskFunction>(function);
  1066. JavascriptPromise* promise = resolveThenableTaskFunction->GetPromise();
  1067. RecyclableObject* thenable = resolveThenableTaskFunction->GetThenable();
  1068. RecyclableObject* thenFunction = resolveThenableTaskFunction->GetThenFunction();
  1069. JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyResolvedRecord = RecyclerNewStructZ(scriptContext->GetRecycler(), JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper);
  1070. alreadyResolvedRecord->alreadyResolved = false;
  1071. JavascriptPromiseResolveOrRejectFunction* resolve = library->CreatePromiseResolveOrRejectFunction(EntryResolveOrRejectFunction, promise, false, alreadyResolvedRecord);
  1072. JavascriptPromiseResolveOrRejectFunction* reject = library->CreatePromiseResolveOrRejectFunction(EntryResolveOrRejectFunction, promise, true, alreadyResolvedRecord);
  1073. JavascriptExceptionObject* exception = nullptr;
  1074. {
  1075. bool isPromiseRejectionHandled = true;
  1076. if (scriptContext->IsScriptContextInDebugMode())
  1077. {
  1078. // only necessary to determine if false if debugger is attached. This way we'll
  1079. // correctly break on exceptions raised in promises that result in uhandled rejections
  1080. isPromiseRejectionHandled = !promise->WillRejectionBeUnhandled();
  1081. }
  1082. Js::JavascriptExceptionOperators::AutoCatchHandlerExists autoCatchHandlerExists(scriptContext, isPromiseRejectionHandled);
  1083. try
  1084. {
  1085. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  1086. {
  1087. return CALL_FUNCTION(scriptContext->GetThreadContext(),
  1088. thenFunction, Js::CallInfo(Js::CallFlags::CallFlags_Value, 3),
  1089. thenable,
  1090. resolve,
  1091. reject);
  1092. }
  1093. END_SAFE_REENTRANT_CALL
  1094. }
  1095. catch (const JavascriptException& err)
  1096. {
  1097. exception = err.GetAndClear();
  1098. }
  1099. }
  1100. Assert(exception != nullptr);
  1101. return TryRejectWithExceptionObject(exception, reject, scriptContext);
  1102. }
  1103. // Promise Identity Function as described in ES 2015Section 25.4.5.3.1
  1104. Var JavascriptPromise::EntryIdentityFunction(RecyclableObject* function, CallInfo callInfo, ...)
  1105. {
  1106. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  1107. ARGUMENTS(args, callInfo);
  1108. Assert(!(callInfo.Flags & CallFlags_New));
  1109. if (args.Info.Count > 1)
  1110. {
  1111. Assert(args[1] != nullptr);
  1112. return args[1];
  1113. }
  1114. else
  1115. {
  1116. return function->GetScriptContext()->GetLibrary()->GetUndefined();
  1117. }
  1118. }
  1119. // Promise Thrower Function as described in ES 2015Section 25.4.5.3.3
  1120. Var JavascriptPromise::EntryThrowerFunction(RecyclableObject* function, CallInfo callInfo, ...)
  1121. {
  1122. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  1123. ARGUMENTS(args, callInfo);
  1124. Assert(!(callInfo.Flags & CallFlags_New));
  1125. ScriptContext* scriptContext = function->GetScriptContext();
  1126. Var arg;
  1127. if (args.Info.Count > 1)
  1128. {
  1129. Assert(args[1] != nullptr);
  1130. arg = args[1];
  1131. }
  1132. else
  1133. {
  1134. arg = scriptContext->GetLibrary()->GetUndefined();
  1135. }
  1136. JavascriptExceptionOperators::Throw(arg, scriptContext);
  1137. }
  1138. // Promise.all Resolve Element Function as described in ES6.0 (Release Candidate 3) Section 25.4.4.1.2
  1139. Var JavascriptPromise::EntryAllResolveElementFunction(RecyclableObject* function, CallInfo callInfo, ...)
  1140. {
  1141. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  1142. ARGUMENTS(args, callInfo);
  1143. Assert(!(callInfo.Flags & CallFlags_New));
  1144. ScriptContext* scriptContext = function->GetScriptContext();
  1145. Var undefinedVar = scriptContext->GetLibrary()->GetUndefined();
  1146. Var x;
  1147. if (args.Info.Count > 1)
  1148. {
  1149. x = args[1];
  1150. }
  1151. else
  1152. {
  1153. x = undefinedVar;
  1154. }
  1155. JavascriptPromiseAllResolveElementFunction* allResolveElementFunction = VarTo<JavascriptPromiseAllResolveElementFunction>(function);
  1156. if (allResolveElementFunction->IsAlreadyCalled())
  1157. {
  1158. return undefinedVar;
  1159. }
  1160. allResolveElementFunction->SetAlreadyCalled(true);
  1161. uint32 index = allResolveElementFunction->GetIndex();
  1162. JavascriptArray* values = allResolveElementFunction->GetValues();
  1163. JavascriptPromiseCapability* promiseCapability = allResolveElementFunction->GetCapabilities();
  1164. JavascriptExceptionObject* exception = nullptr;
  1165. try
  1166. {
  1167. values->SetItem(index, x, PropertyOperation_None);
  1168. }
  1169. catch (const JavascriptException& err)
  1170. {
  1171. exception = err.GetAndClear();
  1172. }
  1173. if (exception != nullptr)
  1174. {
  1175. return TryRejectWithExceptionObject(exception, promiseCapability->GetReject(), scriptContext);
  1176. }
  1177. if (allResolveElementFunction->DecrementRemainingElements() == 0)
  1178. {
  1179. return TryCallResolveOrRejectHandler(promiseCapability->GetResolve(), values, scriptContext);
  1180. }
  1181. return undefinedVar;
  1182. }
  1183. Var JavascriptPromise::EntryAllSettledResolveOrRejectElementFunction(RecyclableObject* function, CallInfo callInfo, ...)
  1184. {
  1185. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  1186. ARGUMENTS(args, callInfo);
  1187. Assert(!(callInfo.Flags & CallFlags_New));
  1188. ScriptContext* scriptContext = function->GetScriptContext();
  1189. Var undefinedVar = scriptContext->GetLibrary()->GetUndefined();
  1190. Var x;
  1191. if (args.Info.Count > 1)
  1192. {
  1193. x = args[1];
  1194. }
  1195. else
  1196. {
  1197. x = undefinedVar;
  1198. }
  1199. JavascriptPromiseAllSettledResolveOrRejectElementFunction* allSettledResolveElementFunction = VarTo<JavascriptPromiseAllSettledResolveOrRejectElementFunction>(function);
  1200. if (allSettledResolveElementFunction->IsAlreadyCalled())
  1201. {
  1202. return undefinedVar;
  1203. }
  1204. allSettledResolveElementFunction->SetAlreadyCalled(true);
  1205. bool isRejecting = allSettledResolveElementFunction->IsRejectFunction();
  1206. uint32 index = allSettledResolveElementFunction->GetIndex();
  1207. JavascriptArray* values = allSettledResolveElementFunction->GetValues();
  1208. JavascriptPromiseCapability* promiseCapability = allSettledResolveElementFunction->GetCapabilities();
  1209. JavascriptExceptionObject* exception = nullptr;
  1210. try
  1211. {
  1212. RecyclableObject* obj = scriptContext->GetLibrary()->CreateObject();
  1213. Var statusString = isRejecting ?
  1214. scriptContext->GetPropertyString(PropertyIds::rejected) :
  1215. scriptContext->GetPropertyString(PropertyIds::fulfilled);
  1216. JavascriptOperators::SetProperty(obj, obj, PropertyIds::status, statusString, scriptContext);
  1217. PropertyIds valuePropId = isRejecting ? PropertyIds::reason : PropertyIds::value;
  1218. JavascriptOperators::SetProperty(obj, obj, valuePropId, x, scriptContext);
  1219. values->SetItem(index, obj, PropertyOperation_None);
  1220. }
  1221. catch (const JavascriptException& err)
  1222. {
  1223. exception = err.GetAndClear();
  1224. }
  1225. if (exception != nullptr)
  1226. {
  1227. return TryRejectWithExceptionObject(exception, promiseCapability->GetReject(), scriptContext);
  1228. }
  1229. if (allSettledResolveElementFunction->DecrementRemainingElements() == 0)
  1230. {
  1231. return TryCallResolveOrRejectHandler(promiseCapability->GetResolve(), values, scriptContext);
  1232. }
  1233. return undefinedVar;
  1234. }
  1235. Var JavascriptPromise::EntryJavascriptPromiseAsyncSpawnExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...)
  1236. {
  1237. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  1238. ARGUMENTS(args, callInfo);
  1239. ScriptContext* scriptContext = function->GetScriptContext();
  1240. JavascriptLibrary* library = scriptContext->GetLibrary();
  1241. Var undefinedVar = library->GetUndefined();
  1242. Var resolve = undefinedVar;
  1243. Var reject = undefinedVar;
  1244. Assert(args.Info.Count == 3);
  1245. resolve = args[1];
  1246. reject = args[2];
  1247. Assert(VarIs<JavascriptPromiseAsyncSpawnExecutorFunction>(function));
  1248. JavascriptPromiseAsyncSpawnExecutorFunction* asyncSpawnExecutorFunction = VarTo<JavascriptPromiseAsyncSpawnExecutorFunction>(function);
  1249. Var self = asyncSpawnExecutorFunction->GetTarget();
  1250. Var varCallArgs[] = { undefinedVar, self };
  1251. JavascriptGenerator* gen = asyncSpawnExecutorFunction->GetGenerator();
  1252. JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* nextFunction = library->CreatePromiseAsyncSpawnStepArgumentExecutorFunction(EntryJavascriptPromiseAsyncSpawnStepNextExecutorFunction, gen, varCallArgs);
  1253. Assert(JavascriptConversion::IsCallable(resolve) && JavascriptConversion::IsCallable(reject));
  1254. AsyncSpawnStep(nextFunction, gen, resolve, reject);
  1255. return undefinedVar;
  1256. }
  1257. Var JavascriptPromise::EntryJavascriptPromiseAsyncSpawnStepNextExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...)
  1258. {
  1259. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  1260. JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* asyncSpawnStepArgumentExecutorFunction = VarTo<JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction>(function);
  1261. Var argument = asyncSpawnStepArgumentExecutorFunction->GetArgument();
  1262. JavascriptFunction* next = function->GetScriptContext()->GetLibrary()->EnsureGeneratorNextFunction();
  1263. BEGIN_SAFE_REENTRANT_CALL(function->GetScriptContext()->GetThreadContext())
  1264. {
  1265. return CALL_FUNCTION(function->GetScriptContext()->GetThreadContext(), next, CallInfo(CallFlags_Value, 2), asyncSpawnStepArgumentExecutorFunction->GetGenerator(), argument);
  1266. }
  1267. END_SAFE_REENTRANT_CALL
  1268. }
  1269. Var JavascriptPromise::EntryJavascriptPromiseAsyncSpawnStepThrowExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...)
  1270. {
  1271. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  1272. JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* asyncSpawnStepArgumentExecutorFunction = VarTo<JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction>(function);
  1273. JavascriptFunction* throw_ = function->GetScriptContext()->GetLibrary()->EnsureGeneratorThrowFunction();
  1274. BEGIN_SAFE_REENTRANT_CALL(function->GetScriptContext()->GetThreadContext())
  1275. {
  1276. return CALL_FUNCTION(function->GetScriptContext()->GetThreadContext(), throw_, CallInfo(CallFlags_Value, 2), asyncSpawnStepArgumentExecutorFunction->GetGenerator(), asyncSpawnStepArgumentExecutorFunction->GetArgument());
  1277. }
  1278. END_SAFE_REENTRANT_CALL
  1279. }
  1280. Var JavascriptPromise::EntryJavascriptPromiseAsyncSpawnCallStepExecutorFunction(RecyclableObject* function, CallInfo callInfo, ...)
  1281. {
  1282. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  1283. ARGUMENTS(args, callInfo);
  1284. ScriptContext* scriptContext = function->GetScriptContext();
  1285. JavascriptLibrary* library = scriptContext->GetLibrary();
  1286. Var undefinedVar = library->GetUndefined();
  1287. Var argument = undefinedVar;
  1288. if (args.Info.Count > 1)
  1289. {
  1290. argument = args[1];
  1291. }
  1292. JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* asyncSpawnStepExecutorFunction = VarTo<JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction>(function);
  1293. JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* functionArg;
  1294. JavascriptGenerator* gen = asyncSpawnStepExecutorFunction->GetGenerator();
  1295. Var reject = asyncSpawnStepExecutorFunction->GetReject();
  1296. Var resolve = asyncSpawnStepExecutorFunction->GetResolve();
  1297. if (asyncSpawnStepExecutorFunction->GetIsReject())
  1298. {
  1299. functionArg = library->CreatePromiseAsyncSpawnStepArgumentExecutorFunction(EntryJavascriptPromiseAsyncSpawnStepThrowExecutorFunction, gen, argument, NULL, NULL, false);
  1300. }
  1301. else
  1302. {
  1303. functionArg = library->CreatePromiseAsyncSpawnStepArgumentExecutorFunction(EntryJavascriptPromiseAsyncSpawnStepNextExecutorFunction, gen, argument, NULL, NULL, false);
  1304. }
  1305. AsyncSpawnStep(functionArg, gen, resolve, reject);
  1306. return undefinedVar;
  1307. }
  1308. void JavascriptPromise::AsyncSpawnStep(
  1309. JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction* nextFunction,
  1310. JavascriptGenerator* gen,
  1311. Var resolve,
  1312. Var reject)
  1313. {
  1314. ScriptContext* scriptContext = gen->GetScriptContext();
  1315. BEGIN_SAFE_REENTRANT_REGION(scriptContext->GetThreadContext())
  1316. JavascriptLibrary* library = scriptContext->GetLibrary();
  1317. Var undefinedVar = library->GetUndefined();
  1318. JavascriptExceptionObject* exception = nullptr;
  1319. RecyclableObject* next = nullptr;
  1320. try
  1321. {
  1322. Var nextVar = CALL_FUNCTION(
  1323. scriptContext->GetThreadContext(),
  1324. nextFunction,
  1325. CallInfo(CallFlags_Value, 1),
  1326. undefinedVar);
  1327. next = VarTo<RecyclableObject>(nextVar);
  1328. }
  1329. catch (const JavascriptException& err)
  1330. {
  1331. exception = err.GetAndClear();
  1332. }
  1333. if (exception != nullptr)
  1334. {
  1335. // If the generator threw an exception, reject the promise
  1336. TryRejectWithExceptionObject(exception, reject, scriptContext);
  1337. return;
  1338. }
  1339. Assert(next != nullptr);
  1340. Var done = JavascriptOperators::GetProperty(next, PropertyIds::done, scriptContext);
  1341. if (JavascriptConversion::ToBool(done, scriptContext))
  1342. {
  1343. // If the generator is done, resolve the promise
  1344. Var value = JavascriptOperators::GetProperty(next, PropertyIds::value, scriptContext);
  1345. if (!JavascriptConversion::IsCallable(resolve))
  1346. {
  1347. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
  1348. }
  1349. CALL_FUNCTION(
  1350. scriptContext->GetThreadContext(),
  1351. VarTo<RecyclableObject>(resolve),
  1352. CallInfo(CallFlags_Value, 2),
  1353. undefinedVar,
  1354. value);
  1355. return;
  1356. }
  1357. // Chain off the yielded promise and step again
  1358. auto* successFunction = library->CreatePromiseAsyncSpawnStepArgumentExecutorFunction(
  1359. EntryJavascriptPromiseAsyncSpawnCallStepExecutorFunction,
  1360. gen,
  1361. undefinedVar,
  1362. resolve,
  1363. reject);
  1364. auto* failFunction = library->CreatePromiseAsyncSpawnStepArgumentExecutorFunction(
  1365. EntryJavascriptPromiseAsyncSpawnCallStepExecutorFunction,
  1366. gen,
  1367. undefinedVar,
  1368. resolve,
  1369. reject,
  1370. true);
  1371. Var value = JavascriptOperators::GetProperty(next, PropertyIds::value, scriptContext);
  1372. JavascriptPromise* promise = InternalPromiseResolve(value, scriptContext);
  1373. JavascriptPromiseCapability* unused = UnusedPromiseCapability(scriptContext);
  1374. PerformPromiseThen(promise, unused, successFunction, failFunction, scriptContext);
  1375. END_SAFE_REENTRANT_REGION
  1376. }
  1377. #if ENABLE_TTD
  1378. void JavascriptPromise::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  1379. {
  1380. if(this->result != nullptr)
  1381. {
  1382. extractor->MarkVisitVar(this->result);
  1383. }
  1384. if(this->reactions != nullptr)
  1385. {
  1386. this->reactions->Map([&](JavascriptPromiseReactionPair pair) {
  1387. pair.rejectReaction->MarkVisitPtrs(extractor);
  1388. pair.resolveReaction->MarkVisitPtrs(extractor);
  1389. });
  1390. }
  1391. }
  1392. TTD::NSSnapObjects::SnapObjectType JavascriptPromise::GetSnapTag_TTD() const
  1393. {
  1394. return TTD::NSSnapObjects::SnapObjectType::SnapPromiseObject;
  1395. }
  1396. void JavascriptPromise::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  1397. {
  1398. JsUtil::List<TTD_PTR_ID, HeapAllocator> depOnList(&HeapAllocator::Instance);
  1399. TTD::NSSnapObjects::SnapPromiseInfo* spi = alloc.SlabAllocateStruct<TTD::NSSnapObjects::SnapPromiseInfo>();
  1400. spi->Result = this->result;
  1401. //Primitive kinds always inflated first so we only need to deal with complex kinds as depends on
  1402. if(this->result != nullptr && TTD::JsSupport::IsVarComplexKind(this->result))
  1403. {
  1404. depOnList.Add(TTD_CONVERT_VAR_TO_PTR_ID(this->result));
  1405. }
  1406. spi->Status = this->GetStatus();
  1407. spi->isHandled = this->GetIsHandled();
  1408. // get count of # of reactions
  1409. spi->ResolveReactionCount = 0;
  1410. if (this->reactions != nullptr)
  1411. {
  1412. this->reactions->Map([&spi](JavascriptPromiseReactionPair pair) {
  1413. spi->ResolveReactionCount++;
  1414. });
  1415. }
  1416. spi->RejectReactionCount = spi->ResolveReactionCount;
  1417. // move resolve & reject reactions into slab
  1418. spi->ResolveReactions = nullptr;
  1419. spi->RejectReactions = nullptr;
  1420. if(spi->ResolveReactionCount != 0)
  1421. {
  1422. spi->ResolveReactions = alloc.SlabAllocateArray<TTD::NSSnapValues::SnapPromiseReactionInfo>(spi->ResolveReactionCount);
  1423. spi->RejectReactions = alloc.SlabAllocateArray<TTD::NSSnapValues::SnapPromiseReactionInfo>(spi->RejectReactionCount);
  1424. JavascriptPromiseReactionList::Iterator it = this->reactions->GetIterator();
  1425. uint32 i = 0;
  1426. while (it.Next())
  1427. {
  1428. it.Data().resolveReaction->ExtractSnapPromiseReactionInto(spi->ResolveReactions + i, depOnList, alloc);
  1429. it.Data().rejectReaction->ExtractSnapPromiseReactionInto(spi->RejectReactions + i, depOnList, alloc);
  1430. ++i;
  1431. }
  1432. }
  1433. //see what we need to do wrt dependencies
  1434. if(depOnList.Count() == 0)
  1435. {
  1436. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapPromiseInfo*, TTD::NSSnapObjects::SnapObjectType::SnapPromiseObject>(objData, spi);
  1437. }
  1438. else
  1439. {
  1440. uint32 depOnCount = depOnList.Count();
  1441. TTD_PTR_ID* depOnArray = alloc.SlabAllocateArray<TTD_PTR_ID>(depOnCount);
  1442. for(uint32 i = 0; i < depOnCount; ++i)
  1443. {
  1444. depOnArray[i] = depOnList.Item(i);
  1445. }
  1446. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapPromiseInfo*, TTD::NSSnapObjects::SnapObjectType::SnapPromiseObject>(objData, spi, alloc, depOnCount, depOnArray);
  1447. }
  1448. }
  1449. JavascriptPromise* JavascriptPromise::InitializePromise_TTD(ScriptContext* scriptContext, uint32 status, bool isHandled, Var result, SList<Js::JavascriptPromiseReaction*, HeapAllocator>& resolveReactions,SList<Js::JavascriptPromiseReaction*, HeapAllocator>& rejectReactions)
  1450. {
  1451. Recycler* recycler = scriptContext->GetRecycler();
  1452. JavascriptLibrary* library = scriptContext->GetLibrary();
  1453. JavascriptPromise* promise = library->CreatePromise();
  1454. promise->SetStatus((PromiseStatus)status);
  1455. if (isHandled)
  1456. {
  1457. promise->SetIsHandled();
  1458. }
  1459. promise->result = result;
  1460. promise->reactions = RecyclerNew(recycler, JavascriptPromiseReactionList, recycler);
  1461. SList<Js::JavascriptPromiseReaction*, HeapAllocator>::Iterator resolveIterator = resolveReactions.GetIterator();
  1462. SList<Js::JavascriptPromiseReaction*, HeapAllocator>::Iterator rejectIterator = rejectReactions.GetIterator();
  1463. bool hasResolve = resolveIterator.Next();
  1464. bool hasReject = rejectIterator.Next();
  1465. while (hasResolve && hasReject)
  1466. {
  1467. JavascriptPromiseReactionPair pair;
  1468. pair.resolveReaction = resolveIterator.Data();
  1469. pair.rejectReaction = rejectIterator.Data();
  1470. promise->reactions->Prepend(pair);
  1471. hasResolve = resolveIterator.Next();
  1472. hasReject = rejectIterator.Next();
  1473. }
  1474. AssertMsg(hasResolve == false && hasReject == false, "mismatched resolve/reject reaction counts");
  1475. promise->reactions->Reverse();
  1476. return promise;
  1477. }
  1478. #endif
  1479. // NewPromiseCapability as described in ES6.0 (draft 29) Section 25.4.1.6
  1480. JavascriptPromiseCapability* JavascriptPromise::NewPromiseCapability(Var constructor, ScriptContext* scriptContext)
  1481. {
  1482. if (!JavascriptOperators::IsConstructor(constructor))
  1483. {
  1484. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
  1485. }
  1486. RecyclableObject* constructorFunc = VarTo<RecyclableObject>(constructor);
  1487. BEGIN_SAFE_REENTRANT_CALL(scriptContext->GetThreadContext())
  1488. {
  1489. return CreatePromiseCapabilityRecord(constructorFunc, scriptContext);
  1490. }
  1491. END_SAFE_REENTRANT_CALL
  1492. }
  1493. JavascriptPromiseCapability* JavascriptPromise::UnusedPromiseCapability(ScriptContext* scriptContext)
  1494. {
  1495. // TODO(zenparsing): Optimize me
  1496. return NewPromiseCapability(scriptContext->GetLibrary()->GetPromiseConstructor(), scriptContext);
  1497. }
  1498. // CreatePromiseCapabilityRecord as described in ES6.0 (draft 29) Section 25.4.1.6.1
  1499. JavascriptPromiseCapability* JavascriptPromise::CreatePromiseCapabilityRecord(RecyclableObject* constructor, ScriptContext* scriptContext)
  1500. {
  1501. JavascriptLibrary* library = scriptContext->GetLibrary();
  1502. Var undefinedVar = library->GetUndefined();
  1503. JavascriptPromiseCapability* promiseCapability = JavascriptPromiseCapability::New(undefinedVar, undefinedVar, undefinedVar, scriptContext);
  1504. JavascriptPromiseCapabilitiesExecutorFunction* executor = library->CreatePromiseCapabilitiesExecutorFunction(EntryCapabilitiesExecutorFunction, promiseCapability);
  1505. CallInfo callinfo = Js::CallInfo((Js::CallFlags)(Js::CallFlags::CallFlags_Value | Js::CallFlags::CallFlags_New), 2);
  1506. Var argVars[] = { constructor, executor };
  1507. Arguments args(callinfo, argVars);
  1508. Var promise = JavascriptFunction::CallAsConstructor(constructor, nullptr, args, scriptContext);
  1509. if (!JavascriptConversion::IsCallable(promiseCapability->GetResolve()) || !JavascriptConversion::IsCallable(promiseCapability->GetReject()))
  1510. {
  1511. JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction, _u("Promise"));
  1512. }
  1513. promiseCapability->SetPromise(promise);
  1514. return promiseCapability;
  1515. }
  1516. // TriggerPromiseReactions as defined in ES 2015 Section 25.4.1.7
  1517. Var JavascriptPromise::TriggerPromiseReactions(JavascriptPromiseReactionList* reactions, bool isRejecting, Var resolution, ScriptContext* scriptContext)
  1518. {
  1519. JavascriptLibrary* library = scriptContext->GetLibrary();
  1520. if (reactions != nullptr)
  1521. {
  1522. JavascriptPromiseReactionList::Iterator it = reactions->GetIterator();
  1523. while (it.Next())
  1524. {
  1525. JavascriptPromiseReaction* reaction;
  1526. if (isRejecting)
  1527. {
  1528. reaction = it.Data().rejectReaction;
  1529. }
  1530. else
  1531. {
  1532. reaction = it.Data().resolveReaction;
  1533. }
  1534. EnqueuePromiseReactionTask(reaction, resolution, scriptContext);
  1535. }
  1536. }
  1537. return library->GetUndefined();
  1538. }
  1539. void JavascriptPromise::EnqueuePromiseReactionTask(JavascriptPromiseReaction* reaction, Var resolution, ScriptContext* scriptContext)
  1540. {
  1541. Assert(resolution != nullptr);
  1542. JavascriptLibrary* library = scriptContext->GetLibrary();
  1543. JavascriptPromiseReactionTaskFunction* reactionTaskFunction = library->CreatePromiseReactionTaskFunction(EntryReactionTaskFunction, reaction, resolution);
  1544. library->EnqueueTask(reactionTaskFunction);
  1545. }
  1546. JavascriptPromiseResolveOrRejectFunction::JavascriptPromiseResolveOrRejectFunction(DynamicType* type)
  1547. : RuntimeFunction(type, &Js::JavascriptPromise::EntryInfo::ResolveOrRejectFunction), promise(nullptr), isReject(false), alreadyResolvedWrapper(nullptr)
  1548. { }
  1549. JavascriptPromiseResolveOrRejectFunction::JavascriptPromiseResolveOrRejectFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromise* promise, bool isReject, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyResolvedRecord)
  1550. : RuntimeFunction(type, functionInfo), promise(promise), isReject(isReject), alreadyResolvedWrapper(alreadyResolvedRecord)
  1551. { }
  1552. template <> bool VarIsImpl<JavascriptPromiseResolveOrRejectFunction>(RecyclableObject* obj)
  1553. {
  1554. if (VarIs<JavascriptFunction>(obj))
  1555. {
  1556. return VirtualTableInfo<JavascriptPromiseResolveOrRejectFunction>::HasVirtualTable(obj)
  1557. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseResolveOrRejectFunction>>::HasVirtualTable(obj);
  1558. }
  1559. return false;
  1560. }
  1561. JavascriptPromise* JavascriptPromiseResolveOrRejectFunction::GetPromise()
  1562. {
  1563. return this->promise;
  1564. }
  1565. bool JavascriptPromiseResolveOrRejectFunction::IsRejectFunction()
  1566. {
  1567. return this->isReject;
  1568. }
  1569. bool JavascriptPromiseResolveOrRejectFunction::IsAlreadyResolved()
  1570. {
  1571. Assert(this->alreadyResolvedWrapper);
  1572. return this->alreadyResolvedWrapper->alreadyResolved;
  1573. }
  1574. void JavascriptPromiseResolveOrRejectFunction::SetAlreadyResolved(bool is)
  1575. {
  1576. Assert(this->alreadyResolvedWrapper);
  1577. this->alreadyResolvedWrapper->alreadyResolved = is;
  1578. }
  1579. #if ENABLE_TTD
  1580. void JavascriptPromiseResolveOrRejectFunction::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  1581. {
  1582. TTDAssert(this->promise != nullptr, "Was not expecting that!!!");
  1583. extractor->MarkVisitVar(this->promise);
  1584. }
  1585. TTD::NSSnapObjects::SnapObjectType JavascriptPromiseResolveOrRejectFunction::GetSnapTag_TTD() const
  1586. {
  1587. return TTD::NSSnapObjects::SnapObjectType::SnapPromiseResolveOrRejectFunctionObject;
  1588. }
  1589. void JavascriptPromiseResolveOrRejectFunction::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  1590. {
  1591. TTD::NSSnapObjects::SnapPromiseResolveOrRejectFunctionInfo* sprri = alloc.SlabAllocateStruct<TTD::NSSnapObjects::SnapPromiseResolveOrRejectFunctionInfo>();
  1592. uint32 depOnCount = 1;
  1593. TTD_PTR_ID* depOnArray = alloc.SlabAllocateArray<TTD_PTR_ID>(depOnCount);
  1594. sprri->PromiseId = TTD_CONVERT_VAR_TO_PTR_ID(this->promise);
  1595. depOnArray[0] = sprri->PromiseId;
  1596. sprri->IsReject = this->isReject;
  1597. sprri->AlreadyResolvedWrapperId = TTD_CONVERT_PROMISE_INFO_TO_PTR_ID(this->alreadyResolvedWrapper);
  1598. sprri->AlreadyResolvedValue = this->alreadyResolvedWrapper->alreadyResolved;
  1599. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapPromiseResolveOrRejectFunctionInfo*, TTD::NSSnapObjects::SnapObjectType::SnapPromiseResolveOrRejectFunctionObject>(objData, sprri, alloc, depOnCount, depOnArray);
  1600. }
  1601. #endif
  1602. JavascriptPromiseAsyncSpawnExecutorFunction::JavascriptPromiseAsyncSpawnExecutorFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptGenerator* generator, Var target)
  1603. : RuntimeFunction(type, functionInfo), generator(generator), target(target)
  1604. { }
  1605. template <> bool VarIsImpl<JavascriptPromiseAsyncSpawnExecutorFunction>(RecyclableObject* obj)
  1606. {
  1607. if (VarIs<JavascriptFunction>(obj))
  1608. {
  1609. return VirtualTableInfo<JavascriptPromiseAsyncSpawnExecutorFunction>::HasVirtualTable(obj)
  1610. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseAsyncSpawnExecutorFunction>>::HasVirtualTable(obj);
  1611. }
  1612. return false;
  1613. }
  1614. JavascriptGenerator* JavascriptPromiseAsyncSpawnExecutorFunction::GetGenerator()
  1615. {
  1616. return this->generator;
  1617. }
  1618. Var JavascriptPromiseAsyncSpawnExecutorFunction::GetTarget()
  1619. {
  1620. return this->target;
  1621. }
  1622. #if ENABLE_TTD
  1623. void JavascriptPromiseAsyncSpawnExecutorFunction::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  1624. {
  1625. if (this->generator != nullptr)
  1626. {
  1627. extractor->MarkVisitVar(this->generator);
  1628. }
  1629. if (this->target != nullptr)
  1630. {
  1631. extractor->MarkVisitVar(this->target);
  1632. }
  1633. }
  1634. TTD::NSSnapObjects::SnapObjectType JavascriptPromiseAsyncSpawnExecutorFunction::GetSnapTag_TTD() const
  1635. {
  1636. return TTD::NSSnapObjects::SnapObjectType::JavascriptPromiseAsyncSpawnExecutorFunction;
  1637. }
  1638. void JavascriptPromiseAsyncSpawnExecutorFunction::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  1639. {
  1640. TTD::NSSnapObjects::SnapJavascriptPromiseAsyncSpawnExecutorFunctionInfo* info = alloc.SlabAllocateStruct<TTD::NSSnapObjects::SnapJavascriptPromiseAsyncSpawnExecutorFunctionInfo>();
  1641. info->generator= TTD_CONVERT_VAR_TO_PTR_ID(this->generator);
  1642. info->target = TTD_CONVERT_JSVAR_TO_TTDVAR(this->target);
  1643. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapJavascriptPromiseAsyncSpawnExecutorFunctionInfo*, TTD::NSSnapObjects::SnapObjectType::JavascriptPromiseAsyncSpawnExecutorFunction>(objData, info);
  1644. }
  1645. #endif
  1646. JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction::JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptGenerator* generator, Var argument, Var resolve, Var reject, bool isReject)
  1647. : RuntimeFunction(type, functionInfo), generator(generator), argument(argument), resolve(resolve), reject(reject), isReject(isReject)
  1648. { }
  1649. template <> bool VarIsImpl<JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction>(RecyclableObject* obj)
  1650. {
  1651. if (VarIs<JavascriptFunction>(obj))
  1652. {
  1653. return VirtualTableInfo<JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction>::HasVirtualTable(obj)
  1654. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction>>::HasVirtualTable(obj);
  1655. }
  1656. return false;
  1657. }
  1658. JavascriptGenerator* JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction::GetGenerator()
  1659. {
  1660. return this->generator;
  1661. }
  1662. Var JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction::GetResolve()
  1663. {
  1664. return this->resolve;
  1665. }
  1666. Var JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction::GetReject()
  1667. {
  1668. return this->reject;
  1669. }
  1670. bool JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction::GetIsReject()
  1671. {
  1672. return this->isReject;
  1673. }
  1674. Var JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction::GetArgument()
  1675. {
  1676. return this->argument;
  1677. }
  1678. #if ENABLE_TTD
  1679. void JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  1680. {
  1681. if (this->generator != nullptr)
  1682. {
  1683. extractor->MarkVisitVar(this->generator);
  1684. }
  1685. if (this->reject != nullptr)
  1686. {
  1687. extractor->MarkVisitVar(this->reject);
  1688. }
  1689. if (this->resolve != nullptr)
  1690. {
  1691. extractor->MarkVisitVar(this->resolve);
  1692. }
  1693. if (this->argument != nullptr)
  1694. {
  1695. extractor->MarkVisitVar(this->argument);
  1696. }
  1697. }
  1698. TTD::NSSnapObjects::SnapObjectType JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction::GetSnapTag_TTD() const
  1699. {
  1700. return TTD::NSSnapObjects::SnapObjectType::JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction;
  1701. }
  1702. void JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  1703. {
  1704. TTD::NSSnapObjects::SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo* info = alloc.SlabAllocateStruct<TTD::NSSnapObjects::SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo>();
  1705. info->generator = TTD_CONVERT_VAR_TO_PTR_ID(this->generator);
  1706. info->reject = this->reject;
  1707. info->resolve = this->resolve;
  1708. info->argument = this->argument;
  1709. info->isReject = this->isReject;
  1710. info->entryPoint = 0;
  1711. JavascriptMethod entryPoint = this->GetFunctionInfo()->GetOriginalEntryPoint();
  1712. if (entryPoint == JavascriptPromise::EntryJavascriptPromiseAsyncSpawnStepNextExecutorFunction)
  1713. {
  1714. info->entryPoint = 1;
  1715. }
  1716. else if (entryPoint == JavascriptPromise::EntryJavascriptPromiseAsyncSpawnStepThrowExecutorFunction)
  1717. {
  1718. info->entryPoint = 2;
  1719. }
  1720. else if (entryPoint == JavascriptPromise::EntryJavascriptPromiseAsyncSpawnCallStepExecutorFunction)
  1721. {
  1722. info->entryPoint = 3;
  1723. }
  1724. else
  1725. {
  1726. TTDAssert(false, "Unexpected entrypoint found JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction");
  1727. }
  1728. const uint32 maxDeps = 4;
  1729. uint32 depCount = 0;
  1730. TTD_PTR_ID* depArray = alloc.SlabReserveArraySpace<TTD_PTR_ID>(maxDeps);
  1731. if (this->reject != nullptr && TTD::JsSupport::IsVarComplexKind(this->reject))
  1732. {
  1733. depArray[depCount] = TTD_CONVERT_VAR_TO_PTR_ID(this->reject);
  1734. depCount++;
  1735. }
  1736. if (this->resolve != nullptr && TTD::JsSupport::IsVarComplexKind(this->resolve))
  1737. {
  1738. depArray[depCount] = TTD_CONVERT_VAR_TO_PTR_ID(this->resolve);
  1739. depCount++;
  1740. }
  1741. if (this->argument != nullptr && TTD::JsSupport::IsVarComplexKind(this->argument))
  1742. {
  1743. depArray[depCount] = TTD_CONVERT_VAR_TO_PTR_ID(this->argument);
  1744. depCount++;
  1745. }
  1746. if (this->generator != nullptr)
  1747. {
  1748. depArray[depCount] = TTD_CONVERT_VAR_TO_PTR_ID(this->generator);
  1749. depCount++;
  1750. }
  1751. if (depCount > 0)
  1752. {
  1753. alloc.SlabCommitArraySpace<TTD_PTR_ID>(depCount, maxDeps);
  1754. }
  1755. else
  1756. {
  1757. alloc.SlabAbortArraySpace<TTD_PTR_ID>(maxDeps);
  1758. }
  1759. if (depCount == 0)
  1760. {
  1761. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo*, TTD::NSSnapObjects::SnapObjectType::JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction>(objData, info);
  1762. }
  1763. else
  1764. {
  1765. TTDAssert(depArray != nullptr, "depArray should be non-null if depCount is > 0");
  1766. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo*, TTD::NSSnapObjects::SnapObjectType::JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction>(objData, info, alloc, depCount, depArray);
  1767. }
  1768. }
  1769. #endif
  1770. JavascriptPromiseCapabilitiesExecutorFunction::JavascriptPromiseCapabilitiesExecutorFunction(DynamicType* type, FunctionInfo* functionInfo, JavascriptPromiseCapability* capability)
  1771. : RuntimeFunction(type, functionInfo), capability(capability)
  1772. { }
  1773. template <> bool VarIsImpl<JavascriptPromiseCapabilitiesExecutorFunction>(RecyclableObject* obj)
  1774. {
  1775. if (VarIs<JavascriptFunction>(obj))
  1776. {
  1777. return VirtualTableInfo<JavascriptPromiseCapabilitiesExecutorFunction>::HasVirtualTable(obj)
  1778. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseCapabilitiesExecutorFunction>>::HasVirtualTable(obj);
  1779. }
  1780. return false;
  1781. }
  1782. JavascriptPromiseCapability* JavascriptPromiseCapabilitiesExecutorFunction::GetCapability()
  1783. {
  1784. return this->capability;
  1785. }
  1786. #if ENABLE_TTD
  1787. void JavascriptPromiseCapabilitiesExecutorFunction::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  1788. {
  1789. TTDAssert(false, "Not Implemented Yet");
  1790. }
  1791. TTD::NSSnapObjects::SnapObjectType JavascriptPromiseCapabilitiesExecutorFunction::GetSnapTag_TTD() const
  1792. {
  1793. TTDAssert(false, "Not Implemented Yet");
  1794. return TTD::NSSnapObjects::SnapObjectType::Invalid;
  1795. }
  1796. void JavascriptPromiseCapabilitiesExecutorFunction::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  1797. {
  1798. TTDAssert(false, "Not Implemented Yet");
  1799. }
  1800. #endif
  1801. JavascriptPromiseCapability* JavascriptPromiseCapability::New(Var promise, Var resolve, Var reject, ScriptContext* scriptContext)
  1802. {
  1803. return RecyclerNew(scriptContext->GetRecycler(), JavascriptPromiseCapability, promise, resolve, reject);
  1804. }
  1805. Var JavascriptPromiseCapability::GetResolve()
  1806. {
  1807. return this->resolve;
  1808. }
  1809. Var JavascriptPromiseCapability::GetReject()
  1810. {
  1811. return this->reject;
  1812. }
  1813. Var JavascriptPromiseCapability::GetPromise()
  1814. {
  1815. return this->promise;
  1816. }
  1817. void JavascriptPromiseCapability::SetPromise(Var promise)
  1818. {
  1819. this->promise = promise;
  1820. }
  1821. void JavascriptPromiseCapability::SetResolve(Var resolve)
  1822. {
  1823. this->resolve = resolve;
  1824. }
  1825. void JavascriptPromiseCapability::SetReject(Var reject)
  1826. {
  1827. this->reject = reject;
  1828. }
  1829. #if ENABLE_TTD
  1830. void JavascriptPromiseCapability::MarkVisitPtrs(TTD::SnapshotExtractor* extractor)
  1831. {
  1832. TTDAssert(this->promise != nullptr && this->resolve != nullptr && this->reject != nullptr, "Seems odd, I was not expecting this!!!");
  1833. extractor->MarkVisitVar(this->promise);
  1834. extractor->MarkVisitVar(this->resolve);
  1835. extractor->MarkVisitVar(this->reject);
  1836. }
  1837. void JavascriptPromiseCapability::ExtractSnapPromiseCapabilityInto(TTD::NSSnapValues::SnapPromiseCapabilityInfo* snapPromiseCapability, JsUtil::List<TTD_PTR_ID, HeapAllocator>& depOnList, TTD::SlabAllocator& alloc)
  1838. {
  1839. snapPromiseCapability->CapabilityId = TTD_CONVERT_PROMISE_INFO_TO_PTR_ID(this);
  1840. snapPromiseCapability->PromiseVar = this->promise;
  1841. if(TTD::JsSupport::IsVarComplexKind(this->promise))
  1842. {
  1843. depOnList.Add(TTD_CONVERT_VAR_TO_PTR_ID(this->resolve));
  1844. }
  1845. snapPromiseCapability->ResolveVar = this->resolve;
  1846. if(TTD::JsSupport::IsVarComplexKind(this->resolve))
  1847. {
  1848. depOnList.Add(TTD_CONVERT_VAR_TO_PTR_ID(this->resolve));
  1849. }
  1850. snapPromiseCapability->RejectVar = this->reject;
  1851. if(TTD::JsSupport::IsVarComplexKind(this->reject))
  1852. {
  1853. depOnList.Add(TTD_CONVERT_VAR_TO_PTR_ID(this->reject));
  1854. }
  1855. }
  1856. #endif
  1857. JavascriptPromiseReaction* JavascriptPromiseReaction::New(JavascriptPromiseCapability* capabilities, RecyclableObject* handler, ScriptContext* scriptContext)
  1858. {
  1859. return RecyclerNew(scriptContext->GetRecycler(), JavascriptPromiseReaction, capabilities, handler);
  1860. }
  1861. JavascriptPromiseCapability* JavascriptPromiseReaction::GetCapabilities()
  1862. {
  1863. return this->capabilities;
  1864. }
  1865. RecyclableObject* JavascriptPromiseReaction::GetHandler()
  1866. {
  1867. return this->handler;
  1868. }
  1869. #if ENABLE_TTD
  1870. void JavascriptPromiseReaction::MarkVisitPtrs(TTD::SnapshotExtractor* extractor)
  1871. {
  1872. TTDAssert(this->handler != nullptr && this->capabilities != nullptr, "Seems odd, I was not expecting this!!!");
  1873. extractor->MarkVisitVar(this->handler);
  1874. this->capabilities->MarkVisitPtrs(extractor);
  1875. }
  1876. void JavascriptPromiseReaction::ExtractSnapPromiseReactionInto(TTD::NSSnapValues::SnapPromiseReactionInfo* snapPromiseReaction, JsUtil::List<TTD_PTR_ID, HeapAllocator>& depOnList, TTD::SlabAllocator& alloc)
  1877. {
  1878. TTDAssert(this->handler != nullptr && this->capabilities != nullptr, "Seems odd, I was not expecting this!!!");
  1879. snapPromiseReaction->PromiseReactionId = TTD_CONVERT_PROMISE_INFO_TO_PTR_ID(this);
  1880. snapPromiseReaction->HandlerObjId = TTD_CONVERT_VAR_TO_PTR_ID(this->handler);
  1881. depOnList.Add(snapPromiseReaction->HandlerObjId);
  1882. this->capabilities->ExtractSnapPromiseCapabilityInto(&snapPromiseReaction->Capabilities, depOnList, alloc);
  1883. }
  1884. #endif
  1885. template <> bool VarIsImpl<JavascriptPromiseReactionTaskFunction>(RecyclableObject* obj)
  1886. {
  1887. if (VarIs<JavascriptFunction>(obj))
  1888. {
  1889. return VirtualTableInfo<JavascriptPromiseReactionTaskFunction>::HasVirtualTable(obj)
  1890. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseReactionTaskFunction>>::HasVirtualTable(obj);
  1891. }
  1892. return false;
  1893. }
  1894. JavascriptPromiseReaction* JavascriptPromiseReactionTaskFunction::GetReaction()
  1895. {
  1896. return this->reaction;
  1897. }
  1898. Var JavascriptPromiseReactionTaskFunction::GetArgument()
  1899. {
  1900. return this->argument;
  1901. }
  1902. #if ENABLE_TTD
  1903. void JavascriptPromiseReactionTaskFunction::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  1904. {
  1905. TTDAssert(this->argument != nullptr && this->reaction != nullptr, "Was not expecting this!!!");
  1906. extractor->MarkVisitVar(this->argument);
  1907. this->reaction->MarkVisitPtrs(extractor);
  1908. }
  1909. TTD::NSSnapObjects::SnapObjectType JavascriptPromiseReactionTaskFunction::GetSnapTag_TTD() const
  1910. {
  1911. return TTD::NSSnapObjects::SnapObjectType::SnapPromiseReactionTaskFunctionObject;
  1912. }
  1913. void JavascriptPromiseReactionTaskFunction::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  1914. {
  1915. TTD::NSSnapObjects::SnapPromiseReactionTaskFunctionInfo* sprtfi = alloc.SlabAllocateStruct<TTD::NSSnapObjects::SnapPromiseReactionTaskFunctionInfo>();
  1916. JsUtil::List<TTD_PTR_ID, HeapAllocator> depOnList(&HeapAllocator::Instance);
  1917. sprtfi->Argument = this->argument;
  1918. if(this->argument != nullptr && TTD::JsSupport::IsVarComplexKind(this->argument))
  1919. {
  1920. depOnList.Add(TTD_CONVERT_VAR_TO_PTR_ID(this->argument));
  1921. }
  1922. this->reaction->ExtractSnapPromiseReactionInto(&sprtfi->Reaction, depOnList, alloc);
  1923. //see what we need to do wrt dependencies
  1924. if(depOnList.Count() == 0)
  1925. {
  1926. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapPromiseReactionTaskFunctionInfo*, TTD::NSSnapObjects::SnapObjectType::SnapPromiseReactionTaskFunctionObject>(objData, sprtfi);
  1927. }
  1928. else
  1929. {
  1930. uint32 depOnCount = depOnList.Count();
  1931. TTD_PTR_ID* depOnArray = alloc.SlabAllocateArray<TTD_PTR_ID>(depOnCount);
  1932. for(uint32 i = 0; i < depOnCount; ++i)
  1933. {
  1934. depOnArray[i] = depOnList.Item(i);
  1935. }
  1936. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapPromiseReactionTaskFunctionInfo*, TTD::NSSnapObjects::SnapObjectType::SnapPromiseReactionTaskFunctionObject>(objData, sprtfi, alloc, depOnCount, depOnArray);
  1937. }
  1938. }
  1939. #endif
  1940. template <> bool VarIsImpl<JavascriptPromiseThenFinallyFunction>(RecyclableObject* obj)
  1941. {
  1942. if (VarIs<JavascriptFunction>(obj))
  1943. {
  1944. return VirtualTableInfo<JavascriptPromiseThenFinallyFunction>::HasVirtualTable(obj)
  1945. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseThenFinallyFunction>>::HasVirtualTable(obj);
  1946. }
  1947. return false;
  1948. }
  1949. template <> bool VarIsImpl<JavascriptPromiseThunkFinallyFunction>(RecyclableObject* obj)
  1950. {
  1951. if (VarIs<JavascriptFunction>(obj))
  1952. {
  1953. return VirtualTableInfo<JavascriptPromiseThunkFinallyFunction>::HasVirtualTable(obj)
  1954. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseThunkFinallyFunction>>::HasVirtualTable(obj);
  1955. }
  1956. return false;
  1957. }
  1958. template <> bool VarIsImpl<JavascriptPromiseResolveThenableTaskFunction>(RecyclableObject* obj)
  1959. {
  1960. if (VarIs<JavascriptFunction>(obj))
  1961. {
  1962. return VirtualTableInfo<JavascriptPromiseResolveThenableTaskFunction>::HasVirtualTable(obj)
  1963. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseResolveThenableTaskFunction>>::HasVirtualTable(obj);
  1964. }
  1965. return false;
  1966. }
  1967. JavascriptPromise* JavascriptPromiseResolveThenableTaskFunction::GetPromise()
  1968. {
  1969. return this->promise;
  1970. }
  1971. RecyclableObject* JavascriptPromiseResolveThenableTaskFunction::GetThenable()
  1972. {
  1973. return this->thenable;
  1974. }
  1975. RecyclableObject* JavascriptPromiseResolveThenableTaskFunction::GetThenFunction()
  1976. {
  1977. return this->thenFunction;
  1978. }
  1979. #if ENABLE_TTD
  1980. void JavascriptPromiseResolveThenableTaskFunction::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  1981. {
  1982. TTDAssert(false, "Not Implemented Yet");
  1983. }
  1984. TTD::NSSnapObjects::SnapObjectType JavascriptPromiseResolveThenableTaskFunction::GetSnapTag_TTD() const
  1985. {
  1986. TTDAssert(false, "Not Implemented Yet");
  1987. return TTD::NSSnapObjects::SnapObjectType::Invalid;
  1988. }
  1989. void JavascriptPromiseResolveThenableTaskFunction::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  1990. {
  1991. TTDAssert(false, "Not Implemented Yet");
  1992. }
  1993. #endif
  1994. JavascriptPromiseAllSettledResolveOrRejectElementFunction::JavascriptPromiseAllSettledResolveOrRejectElementFunction(DynamicType* type)
  1995. : JavascriptPromiseAllResolveElementFunction(type), alreadyCalledWrapper(nullptr), isRejecting(false)
  1996. { }
  1997. JavascriptPromiseAllSettledResolveOrRejectElementFunction::JavascriptPromiseAllSettledResolveOrRejectElementFunction(DynamicType* type, FunctionInfo* functionInfo, uint32 index, JavascriptArray* values, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyCalledWrapper, bool isRejecting)
  1998. : JavascriptPromiseAllResolveElementFunction(type, functionInfo, index, values, capabilities, remainingElementsWrapper), alreadyCalledWrapper(alreadyCalledWrapper), isRejecting(isRejecting)
  1999. { }
  2000. bool JavascriptPromiseAllSettledResolveOrRejectElementFunction::IsAlreadyCalled() const
  2001. {
  2002. Assert(this->alreadyCalledWrapper);
  2003. return this->alreadyCalledWrapper->alreadyResolved;
  2004. }
  2005. void JavascriptPromiseAllSettledResolveOrRejectElementFunction::SetAlreadyCalled(const bool is)
  2006. {
  2007. Assert(this->alreadyCalledWrapper);
  2008. this->alreadyCalledWrapper->alreadyResolved = is;
  2009. }
  2010. bool JavascriptPromiseAllSettledResolveOrRejectElementFunction::IsRejectFunction()
  2011. {
  2012. return this->isRejecting;
  2013. }
  2014. template <> bool VarIsImpl<JavascriptPromiseAllSettledResolveOrRejectElementFunction>(RecyclableObject* obj)
  2015. {
  2016. if (VarIs<JavascriptFunction>(obj))
  2017. {
  2018. return VirtualTableInfo<JavascriptPromiseAllSettledResolveOrRejectElementFunction>::HasVirtualTable(obj)
  2019. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseAllSettledResolveOrRejectElementFunction>>::HasVirtualTable(obj);
  2020. }
  2021. return false;
  2022. }
  2023. #if ENABLE_TTD
  2024. void JavascriptPromiseAllSettledResolveOrRejectElementFunction::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  2025. {
  2026. TTDAssert(this->capabilities != nullptr && this->remainingElementsWrapper != nullptr && this->alreadyCalledWrapper != nullptr && this->values != nullptr, "Don't think these can be null");
  2027. this->capabilities->MarkVisitPtrs(extractor);
  2028. extractor->MarkVisitVar(this->values);
  2029. }
  2030. TTD::NSSnapObjects::SnapObjectType JavascriptPromiseAllSettledResolveOrRejectElementFunction::GetSnapTag_TTD() const
  2031. {
  2032. return TTD::NSSnapObjects::SnapObjectType::SnapPromiseAllSettledResolveOrRejectElementFunctionObject;
  2033. }
  2034. void JavascriptPromiseAllSettledResolveOrRejectElementFunction::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  2035. {
  2036. TTD::NSSnapObjects::SnapPromiseAllResolveElementFunctionInfo* sprai = alloc.SlabAllocateStruct<TTD::NSSnapObjects::SnapPromiseAllResolveElementFunctionInfo>();
  2037. JsUtil::List<TTD_PTR_ID, HeapAllocator> depOnList(&HeapAllocator::Instance);
  2038. this->capabilities->ExtractSnapPromiseCapabilityInto(&sprai->Capabilities, depOnList, alloc);
  2039. sprai->Index = this->index;
  2040. sprai->RemainingElementsWrapperId = TTD_CONVERT_PROMISE_INFO_TO_PTR_ID(this->remainingElementsWrapper);
  2041. sprai->RemainingElementsValue = this->remainingElementsWrapper->remainingElements;
  2042. sprai->Values = TTD_CONVERT_VAR_TO_PTR_ID(this->values);
  2043. depOnList.Add(sprai->Values);
  2044. sprai->AlreadyCalled = this->alreadyCalled;
  2045. uint32 depOnCount = depOnList.Count();
  2046. TTD_PTR_ID* depOnArray = alloc.SlabAllocateArray<TTD_PTR_ID>(depOnCount);
  2047. for (uint32 i = 0; i < depOnCount; ++i)
  2048. {
  2049. depOnArray[i] = depOnList.Item(i);
  2050. }
  2051. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapPromiseAllResolveElementFunctionInfo*, TTD::NSSnapObjects::SnapObjectType::SnapPromiseAllResolveElementFunctionObject>(objData, sprai, alloc, depOnCount, depOnArray);
  2052. }
  2053. #endif
  2054. JavascriptPromiseAllResolveElementFunction::JavascriptPromiseAllResolveElementFunction(DynamicType* type)
  2055. : RuntimeFunction(type, &Js::JavascriptPromise::EntryInfo::AllResolveElementFunction), index(0), values(nullptr), capabilities(nullptr), remainingElementsWrapper(nullptr), alreadyCalled(false)
  2056. { }
  2057. JavascriptPromiseAllResolveElementFunction::JavascriptPromiseAllResolveElementFunction(DynamicType* type, FunctionInfo* functionInfo, uint32 index, JavascriptArray* values, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper)
  2058. : RuntimeFunction(type, functionInfo), index(index), values(values), capabilities(capabilities), remainingElementsWrapper(remainingElementsWrapper), alreadyCalled(false)
  2059. { }
  2060. template <> bool VarIsImpl<JavascriptPromiseAllResolveElementFunction>(RecyclableObject* obj)
  2061. {
  2062. if (VarIs<JavascriptFunction>(obj))
  2063. {
  2064. return VirtualTableInfo<JavascriptPromiseAllResolveElementFunction>::HasVirtualTable(obj)
  2065. || VirtualTableInfo<CrossSiteObject<JavascriptPromiseAllResolveElementFunction>>::HasVirtualTable(obj);
  2066. }
  2067. return false;
  2068. }
  2069. JavascriptPromiseCapability* JavascriptPromiseAllResolveElementFunction::GetCapabilities()
  2070. {
  2071. return this->capabilities;
  2072. }
  2073. uint32 JavascriptPromiseAllResolveElementFunction::GetIndex()
  2074. {
  2075. return this->index;
  2076. }
  2077. uint32 JavascriptPromiseAllResolveElementFunction::GetRemainingElements()
  2078. {
  2079. return this->remainingElementsWrapper->remainingElements;
  2080. }
  2081. JavascriptArray* JavascriptPromiseAllResolveElementFunction::GetValues()
  2082. {
  2083. return this->values;
  2084. }
  2085. uint32 JavascriptPromiseAllResolveElementFunction::DecrementRemainingElements()
  2086. {
  2087. return --(this->remainingElementsWrapper->remainingElements);
  2088. }
  2089. bool JavascriptPromiseAllResolveElementFunction::IsAlreadyCalled() const
  2090. {
  2091. return this->alreadyCalled;
  2092. }
  2093. void JavascriptPromiseAllResolveElementFunction::SetAlreadyCalled(const bool is)
  2094. {
  2095. this->alreadyCalled = is;
  2096. }
  2097. #if ENABLE_TTD
  2098. void JavascriptPromiseAllResolveElementFunction::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
  2099. {
  2100. TTDAssert(this->capabilities != nullptr && this->remainingElementsWrapper != nullptr && this->values != nullptr, "Don't think these can be null");
  2101. this->capabilities->MarkVisitPtrs(extractor);
  2102. extractor->MarkVisitVar(this->values);
  2103. }
  2104. TTD::NSSnapObjects::SnapObjectType JavascriptPromiseAllResolveElementFunction::GetSnapTag_TTD() const
  2105. {
  2106. return TTD::NSSnapObjects::SnapObjectType::SnapPromiseAllResolveElementFunctionObject;
  2107. }
  2108. void JavascriptPromiseAllResolveElementFunction::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
  2109. {
  2110. TTD::NSSnapObjects::SnapPromiseAllResolveElementFunctionInfo* sprai = alloc.SlabAllocateStruct<TTD::NSSnapObjects::SnapPromiseAllResolveElementFunctionInfo>();
  2111. JsUtil::List<TTD_PTR_ID, HeapAllocator> depOnList(&HeapAllocator::Instance);
  2112. this->capabilities->ExtractSnapPromiseCapabilityInto(&sprai->Capabilities, depOnList, alloc);
  2113. sprai->Index = this->index;
  2114. sprai->RemainingElementsWrapperId = TTD_CONVERT_PROMISE_INFO_TO_PTR_ID(this->remainingElementsWrapper);
  2115. sprai->RemainingElementsValue = this->remainingElementsWrapper->remainingElements;
  2116. sprai->Values = TTD_CONVERT_VAR_TO_PTR_ID(this->values);
  2117. depOnList.Add(sprai->Values);
  2118. sprai->AlreadyCalled = this->alreadyCalled;
  2119. uint32 depOnCount = depOnList.Count();
  2120. TTD_PTR_ID* depOnArray = alloc.SlabAllocateArray<TTD_PTR_ID>(depOnCount);
  2121. for(uint32 i = 0; i < depOnCount; ++i)
  2122. {
  2123. depOnArray[i] = depOnList.Item(i);
  2124. }
  2125. TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapPromiseAllResolveElementFunctionInfo*, TTD::NSSnapObjects::SnapObjectType::SnapPromiseAllResolveElementFunctionObject>(objData, sprai, alloc, depOnCount, depOnArray);
  2126. }
  2127. #endif
  2128. Var JavascriptPromise::EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...)
  2129. {
  2130. ARGUMENTS(args, callInfo);
  2131. Assert(args.Info.Count > 0);
  2132. return args[0];
  2133. }
  2134. //static
  2135. JavascriptPromise* JavascriptPromise::CreateEnginePromise(ScriptContext *scriptContext)
  2136. {
  2137. JavascriptPromiseResolveOrRejectFunction *resolve = nullptr;
  2138. JavascriptPromiseResolveOrRejectFunction *reject = nullptr;
  2139. JavascriptPromise *promise = scriptContext->GetLibrary()->CreatePromise();
  2140. JavascriptPromise::InitializePromise(promise, &resolve, &reject, scriptContext);
  2141. return promise;
  2142. }
  2143. } // namespace Js