7
7
namespace Js
8
8
{
9
9
JavascriptPromise::JavascriptPromise (DynamicType * type)
10
- : DynamicObject(type)
10
+ : DynamicObject(type),
11
+ isHandled (false ),
12
+ status(PromiseStatus::PromiseStatusCode_Undefined),
13
+ result(nullptr ),
14
+ reactions(nullptr )
15
+
11
16
{
12
17
Assert (type->GetTypeId () == TypeIds_Promise);
13
-
14
- this ->status = PromiseStatusCode_Undefined;
15
- this ->isHandled = false ;
16
- this ->result = nullptr ;
17
- this ->resolveReactions = nullptr ;
18
- this ->rejectReactions = nullptr ;
19
18
}
20
19
21
20
// Promise() as defined by ES 2016 Sections 25.4.3.1
@@ -100,17 +99,16 @@ namespace Js
100
99
101
100
void JavascriptPromise::InitializePromise (JavascriptPromise* promise, JavascriptPromiseResolveOrRejectFunction** resolve, JavascriptPromiseResolveOrRejectFunction** reject, ScriptContext* scriptContext)
102
101
{
103
- Assert (promise->status == PromiseStatusCode_Undefined);
102
+ Assert (promise->GetStatus () == PromiseStatusCode_Undefined);
104
103
Assert (resolve);
105
104
Assert (reject);
106
105
107
106
Recycler* recycler = scriptContext->GetRecycler ();
108
107
JavascriptLibrary* library = scriptContext->GetLibrary ();
109
108
110
- promise->status = PromiseStatusCode_Unresolved;
109
+ promise->SetStatus ( PromiseStatusCode_Unresolved) ;
111
110
112
- promise->resolveReactions = RecyclerNew (recycler, JavascriptPromiseReactionList, recycler);
113
- promise->rejectReactions = RecyclerNew (recycler, JavascriptPromiseReactionList, recycler);
111
+ promise->reactions = RecyclerNew (recycler, JavascriptPromiseReactionList, recycler);
114
112
115
113
JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyResolvedRecord = RecyclerNewStructZ (scriptContext->GetRecycler (), JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper);
116
114
alreadyResolvedRecord->alreadyResolved = false ;
@@ -151,14 +149,9 @@ namespace Js
151
149
return TRUE ;
152
150
}
153
151
154
- JavascriptPromiseReactionList* JavascriptPromise::GetResolveReactions ()
155
- {
156
- return this ->resolveReactions ;
157
- }
158
-
159
- JavascriptPromiseReactionList* JavascriptPromise::GetRejectReactions ()
152
+ JavascriptPromiseReactionList* JavascriptPromise::GetReactions ()
160
153
{
161
- return this ->rejectReactions ;
154
+ return this ->reactions ;
162
155
}
163
156
164
157
// Promise.all as described in ES 2015 Section 25.4.4.1
@@ -848,13 +841,12 @@ namespace Js
848
841
}
849
842
}
850
843
851
- JavascriptPromiseReactionList* reactions;
844
+
852
845
PromiseStatus newStatus;
853
846
854
847
// Need to check rejecting state again as it might have changed due to failures
855
848
if (isRejecting)
856
849
{
857
- reactions = this ->GetRejectReactions ();
858
850
newStatus = PromiseStatusCode_HasRejection;
859
851
if (!GetIsHandled ())
860
852
{
@@ -863,18 +855,24 @@ namespace Js
863
855
}
864
856
else
865
857
{
866
- reactions = this ->GetResolveReactions ();
867
858
newStatus = PromiseStatusCode_HasResolution;
868
859
}
869
860
870
861
Assert (resolution != nullptr );
871
862
863
+ // SList only supports "prepend" operation, so we need to reverse the list
864
+ // before triggering reactions
865
+ JavascriptPromiseReactionList* reactions = this ->GetReactions ();
866
+ if (reactions != nullptr )
867
+ {
868
+ reactions->Reverse ();
869
+ }
870
+
872
871
this ->result = resolution;
873
- this ->resolveReactions = nullptr ;
874
- this ->rejectReactions = nullptr ;
875
- this ->status = newStatus;
872
+ this ->reactions = nullptr ;
873
+ this ->SetStatus (newStatus);
876
874
877
- return TriggerPromiseReactions (reactions, resolution, scriptContext);
875
+ return TriggerPromiseReactions (reactions, isRejecting, resolution, scriptContext);
878
876
}
879
877
880
878
// Promise Capabilities Executor Function as described in ES 2015 Section 25.4.1.6.2
@@ -1001,10 +999,12 @@ namespace Js
1001
999
{
1002
1000
JavascriptPromise * curr = stack.Pop ();
1003
1001
{
1004
- JavascriptPromiseReactionList* reactions = curr->GetRejectReactions ();
1005
- for (int i = 0 ; i < reactions->Count (); i++)
1002
+ JavascriptPromiseReactionList* reactions = curr->GetReactions ();
1003
+ JavascriptPromiseReactionList::Iterator it = reactions->GetIterator ();
1004
+ while (it.Next ())
1006
1005
{
1007
- JavascriptPromiseReaction* reaction = reactions->Item (i);
1006
+ JavascriptPromiseReactionPair pair = it.Data ();
1007
+ JavascriptPromiseReaction* reaction = pair.rejectReaction ;
1008
1008
Var promiseVar = reaction->GetCapabilities ()->GetPromise ();
1009
1009
1010
1010
if (JavascriptPromise::Is (promiseVar))
@@ -1132,11 +1132,14 @@ namespace Js
1132
1132
JavascriptPromiseReaction* resolveReaction = JavascriptPromiseReaction::New (promiseCapability, fulfillmentHandler, scriptContext);
1133
1133
JavascriptPromiseReaction* rejectReaction = JavascriptPromiseReaction::New (promiseCapability, rejectionHandler, scriptContext);
1134
1134
1135
- switch (sourcePromise->status )
1135
+ switch (sourcePromise->GetStatus () )
1136
1136
{
1137
1137
case PromiseStatusCode_Unresolved:
1138
- sourcePromise->resolveReactions ->Add (resolveReaction);
1139
- sourcePromise->rejectReactions ->Add (rejectReaction);
1138
+ JavascriptPromiseReactionPair pair;
1139
+ pair.resolveReaction = resolveReaction;
1140
+ pair.rejectReaction = rejectReaction;
1141
+
1142
+ sourcePromise->reactions ->Prepend (pair);
1140
1143
break ;
1141
1144
case PromiseStatusCode_HasResolution:
1142
1145
EnqueuePromiseReactionTask (resolveReaction, sourcePromise->result , scriptContext);
@@ -1478,20 +1481,12 @@ namespace Js
1478
1481
extractor->MarkVisitVar (this ->result );
1479
1482
}
1480
1483
1481
- if (this ->resolveReactions != nullptr )
1482
- {
1483
- for (int32 i = 0 ; i < this ->resolveReactions ->Count (); ++i)
1484
- {
1485
- this ->resolveReactions ->Item (i)->MarkVisitPtrs (extractor);
1486
- }
1487
- }
1488
-
1489
- if (this ->rejectReactions != nullptr )
1484
+ if (this ->reactions != nullptr )
1490
1485
{
1491
- for (int32 i = 0 ; i < this ->rejectReactions -> Count (); ++i)
1492
- {
1493
- this -> rejectReactions -> Item (i) ->MarkVisitPtrs (extractor);
1494
- }
1486
+ this ->reactions -> Map ([&](JavascriptPromiseReactionPair pair) {
1487
+ pair. rejectReaction -> MarkVisitPtrs (extractor);
1488
+ pair. resolveReaction ->MarkVisitPtrs (extractor);
1489
+ });
1495
1490
}
1496
1491
}
1497
1492
@@ -1514,29 +1509,34 @@ namespace Js
1514
1509
depOnList.Add (TTD_CONVERT_VAR_TO_PTR_ID (this ->result ));
1515
1510
}
1516
1511
1517
- spi->Status = this ->status ;
1512
+ spi->Status = this ->GetStatus ();
1513
+ spi->isHandled = this ->GetIsHandled ();
1518
1514
1519
- spi-> ResolveReactionCount = ( this -> resolveReactions != nullptr ) ? this -> resolveReactions -> Count () : 0 ;
1520
- spi->ResolveReactions = nullptr ;
1521
- if (spi-> ResolveReactionCount != 0 )
1515
+ // get count of # of reactions
1516
+ spi->ResolveReactionCount = 0 ;
1517
+ if ( this -> reactions != nullptr )
1522
1518
{
1523
- spi->ResolveReactions = alloc.SlabAllocateArray <TTD::NSSnapValues::SnapPromiseReactionInfo>(spi->ResolveReactionCount );
1524
-
1525
- for (uint32 i = 0 ; i < spi->ResolveReactionCount ; ++i)
1526
- {
1527
- this ->resolveReactions ->Item (i)->ExtractSnapPromiseReactionInto (spi->ResolveReactions + i, depOnList, alloc);
1528
- }
1519
+ this ->reactions ->Map ([&spi](JavascriptPromiseReactionPair pair) {
1520
+ spi->ResolveReactionCount ++;
1521
+ });
1529
1522
}
1523
+ spi->RejectReactionCount = spi->ResolveReactionCount ;
1530
1524
1531
- spi->RejectReactionCount = (this ->rejectReactions != nullptr ) ? this ->rejectReactions ->Count () : 0 ;
1525
+ // move resolve & reject reactions into slab
1526
+ spi->ResolveReactions = nullptr ;
1532
1527
spi->RejectReactions = nullptr ;
1533
- if (spi->RejectReactionCount != 0 )
1528
+ if (spi->ResolveReactionCount != 0 )
1534
1529
{
1530
+ spi->ResolveReactions = alloc.SlabAllocateArray <TTD::NSSnapValues::SnapPromiseReactionInfo>(spi->ResolveReactionCount );
1535
1531
spi->RejectReactions = alloc.SlabAllocateArray <TTD::NSSnapValues::SnapPromiseReactionInfo>(spi->RejectReactionCount );
1536
1532
1537
- for (uint32 i = 0 ; i < spi->RejectReactionCount ; ++i)
1533
+ JavascriptPromiseReactionList::Iterator it = this ->reactions ->GetIterator ();
1534
+ uint32 i = 0 ;
1535
+ while (it.Next ())
1538
1536
{
1539
- this ->rejectReactions ->Item (i)->ExtractSnapPromiseReactionInto (spi->RejectReactions + i, depOnList, alloc);
1537
+ it.Data ().resolveReaction ->ExtractSnapPromiseReactionInto (spi->ResolveReactions + i, depOnList, alloc);
1538
+ it.Data ().rejectReaction ->ExtractSnapPromiseReactionInto (spi->RejectReactions + i, depOnList, alloc);
1539
+ ++i;
1540
1540
}
1541
1541
}
1542
1542
@@ -1559,22 +1559,38 @@ namespace Js
1559
1559
}
1560
1560
}
1561
1561
1562
- JavascriptPromise* JavascriptPromise::InitializePromise_TTD (ScriptContext* scriptContext, uint32 status, Var result, JsUtil::List <Js::JavascriptPromiseReaction*, HeapAllocator>& resolveReactions, JsUtil::List <Js::JavascriptPromiseReaction*, HeapAllocator>& rejectReactions)
1562
+ JavascriptPromise* JavascriptPromise::InitializePromise_TTD (ScriptContext* scriptContext, uint32 status, bool isHandled, Var result, SList <Js::JavascriptPromiseReaction*, HeapAllocator>& resolveReactions,SList <Js::JavascriptPromiseReaction*, HeapAllocator>& rejectReactions)
1563
1563
{
1564
1564
Recycler* recycler = scriptContext->GetRecycler ();
1565
1565
JavascriptLibrary* library = scriptContext->GetLibrary ();
1566
1566
1567
1567
JavascriptPromise* promise = library->CreatePromise ();
1568
1568
1569
- promise->status = (PromiseStatus)status;
1569
+ promise->SetStatus ((PromiseStatus)status);
1570
+ if (isHandled)
1571
+ {
1572
+ promise->SetIsHandled ();
1573
+ }
1570
1574
promise->result = result;
1571
1575
1572
- promise->resolveReactions = RecyclerNew (recycler, JavascriptPromiseReactionList, recycler);
1573
- promise->resolveReactions ->Copy (&resolveReactions);
1574
-
1575
- promise->rejectReactions = RecyclerNew (recycler, JavascriptPromiseReactionList, recycler);
1576
- promise->rejectReactions ->Copy (&rejectReactions);
1576
+ promise->reactions = RecyclerNew (recycler, JavascriptPromiseReactionList, recycler);
1577
+ SList<Js::JavascriptPromiseReaction*, HeapAllocator>::Iterator resolveIterator = resolveReactions.GetIterator ();
1578
+ SList<Js::JavascriptPromiseReaction*, HeapAllocator>::Iterator rejectIterator = rejectReactions.GetIterator ();
1577
1579
1580
+ bool hasResolve = resolveIterator.Next ();
1581
+ bool hasReject = rejectIterator.Next ();
1582
+ while (hasResolve && hasReject)
1583
+ {
1584
+ JavascriptPromiseReactionPair pair;
1585
+ pair.resolveReaction = resolveIterator.Data ();
1586
+ pair.rejectReaction = rejectIterator.Data ();
1587
+ promise->reactions ->Prepend (pair);
1588
+ hasResolve = resolveIterator.Next ();
1589
+ hasReject = rejectIterator.Next ();
1590
+ }
1591
+ AssertMsg (hasResolve == false && hasReject == false , " mismatched resolve/reject reaction counts" );
1592
+ promise->reactions ->Reverse ();
1593
+
1578
1594
return promise;
1579
1595
}
1580
1596
#endif
@@ -1621,15 +1637,24 @@ namespace Js
1621
1637
}
1622
1638
1623
1639
// TriggerPromiseReactions as defined in ES 2015 Section 25.4.1.7
1624
- Var JavascriptPromise::TriggerPromiseReactions (JavascriptPromiseReactionList* reactions, Var resolution, ScriptContext* scriptContext)
1640
+ Var JavascriptPromise::TriggerPromiseReactions (JavascriptPromiseReactionList* reactions, bool isRejecting, Var resolution, ScriptContext* scriptContext)
1625
1641
{
1626
1642
JavascriptLibrary* library = scriptContext->GetLibrary ();
1627
1643
1628
1644
if (reactions != nullptr )
1629
1645
{
1630
- for (int i = 0 ; i < reactions->Count (); i++)
1646
+ JavascriptPromiseReactionList::Iterator it = reactions->GetIterator ();
1647
+ while (it.Next ())
1631
1648
{
1632
- JavascriptPromiseReaction* reaction = reactions->Item (i);
1649
+ JavascriptPromiseReaction* reaction;
1650
+ if (isRejecting)
1651
+ {
1652
+ reaction = it.Data ().rejectReaction ;
1653
+ }
1654
+ else
1655
+ {
1656
+ reaction = it.Data ().resolveReaction ;
1657
+ }
1633
1658
1634
1659
EnqueuePromiseReactionTask (reaction, resolution, scriptContext);
1635
1660
}
0 commit comments