Skip to content

Commit 4b015fa

Browse files
committed
New APIs for getting Promise state and result
1 parent 2c6efb5 commit 4b015fa

File tree

4 files changed

+176
-2
lines changed

4 files changed

+176
-2
lines changed

bin/ChakraCore/ChakraCore.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ JsLessThan
6262
JsLessThanOrEqual
6363

6464
JsCreateEnhancedFunction
65-
6665
JsSetHostPromiseRejectionTracker
67-
6866
JsGetProxyProperties
67+
JsGetPromiseState
68+
JsGetPromiseResult

bin/NativeTests/JsRTApiTest.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//-------------------------------------------------------------------------------------------------------
55
#include "stdafx.h"
66
#include "catch.hpp"
7+
#include <array>
78
#include <process.h>
89

910
#pragma warning(disable:4100) // unreferenced formal parameter
@@ -2663,4 +2664,74 @@ namespace JsRTApiTest
26632664
{
26642665
JsRTApiTest::RunWithAttributes(JsRTApiTest::JsCreateStringTest);
26652666
}
2667+
2668+
void JsCreatePromiseTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
2669+
{
2670+
JsValueRef result = JS_INVALID_REFERENCE;
2671+
2672+
JsValueRef promise = JS_INVALID_REFERENCE;
2673+
JsValueRef resolve = JS_INVALID_REFERENCE;
2674+
JsValueRef reject = JS_INVALID_REFERENCE;
2675+
2676+
// Create resolvable promise
2677+
REQUIRE(JsCreatePromise(&promise, &resolve, &reject) == JsNoError);
2678+
2679+
JsPromiseState state = JsPromiseState_Pending;
2680+
REQUIRE(JsGetPromiseState(promise, &state) == JsNoError);
2681+
CHECK(state == JsPromiseState_Pending);
2682+
2683+
result = JS_INVALID_REFERENCE;
2684+
CHECK(JsGetPromiseResult(promise, &result) == JsErrorInvalidArgument);
2685+
CHECK(result == JS_INVALID_REFERENCE);
2686+
2687+
JsValueRef num = JS_INVALID_REFERENCE;
2688+
REQUIRE(JsIntToNumber(42, &num) == JsNoError);
2689+
2690+
std::array<JsValueRef, 2> args{ GetUndefined(), num };
2691+
REQUIRE(JsCallFunction(resolve, args.data(), static_cast<unsigned short>(args.size()), &result) == JsNoError);
2692+
2693+
state = JsPromiseState_Pending;
2694+
REQUIRE(JsGetPromiseState(promise, &state) == JsNoError);
2695+
CHECK(state == JsPromiseState_Fulfilled);
2696+
2697+
result = JS_INVALID_REFERENCE;
2698+
REQUIRE(JsGetPromiseResult(promise, &result) == JsNoError);
2699+
2700+
int resultNum = 0;
2701+
REQUIRE(JsNumberToInt(result, &resultNum) == JsNoError);
2702+
CHECK(resultNum == 42);
2703+
2704+
// Create rejectable promise
2705+
REQUIRE(JsCreatePromise(&promise, &resolve, &reject) == JsNoError);
2706+
2707+
state = JsPromiseState_Pending;
2708+
REQUIRE(JsGetPromiseState(promise, &state) == JsNoError);
2709+
CHECK(state == JsPromiseState_Pending);
2710+
2711+
result = JS_INVALID_REFERENCE;
2712+
CHECK(JsGetPromiseResult(promise, &result) == JsErrorInvalidArgument);
2713+
CHECK(result == JS_INVALID_REFERENCE);
2714+
2715+
num = JS_INVALID_REFERENCE;
2716+
REQUIRE(JsIntToNumber(43, &num) == JsNoError);
2717+
2718+
args = { GetUndefined(), num };
2719+
REQUIRE(JsCallFunction(reject, args.data(), static_cast<unsigned short>(args.size()), &result) == JsNoError);
2720+
2721+
state = JsPromiseState_Pending;
2722+
REQUIRE(JsGetPromiseState(promise, &state) == JsNoError);
2723+
CHECK(state == JsPromiseState_Rejected);
2724+
2725+
result = JS_INVALID_REFERENCE;
2726+
REQUIRE(JsGetPromiseResult(promise, &result) == JsNoError);
2727+
2728+
resultNum = 0;
2729+
REQUIRE(JsNumberToInt(result, &resultNum) == JsNoError);
2730+
CHECK(resultNum == 43);
2731+
}
2732+
2733+
TEST_CASE("ApiTest_JsCreatePromiseTest", "[ApiTest]")
2734+
{
2735+
JsRTApiTest::RunWithAttributes(JsRTApiTest::JsCreatePromiseTest);
2736+
}
26662737
}

lib/Jsrt/ChakraCore.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ typedef enum JsModuleHostInfoKind
5858
JsModuleHostInfo_Url = 0x6
5959
} JsModuleHostInfoKind;
6060

61+
/// <summary>
62+
/// The possible states for a Promise object.
63+
/// </summary>
64+
typedef enum _JsPromiseState
65+
{
66+
JsPromiseState_Pending = 0x0,
67+
JsPromiseState_Fulfilled = 0x1,
68+
JsPromiseState_Rejected = 0x2
69+
} JsPromiseState;
70+
6171
/// <summary>
6272
/// User implemented callback to fetch additional imported modules.
6373
/// </summary>
@@ -633,6 +643,38 @@ CHAKRA_API
633643
_In_ JsValueRef sourceUrl,
634644
_Out_ JsValueRef *result);
635645

646+
/// <summary>
647+
/// Gets the state of a given Promise object.
648+
/// </summary>
649+
/// <remarks>
650+
/// Requires an active script context.
651+
/// </remarks>
652+
/// <param name="promise">The Promise object.</param>
653+
/// <param name="state">The current state of the Promise.</param>
654+
/// <returns>
655+
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
656+
/// </returns>
657+
CHAKRA_API
658+
JsGetPromiseState(
659+
_In_ JsValueRef promise,
660+
_Out_ JsPromiseState *state);
661+
662+
/// <summary>
663+
/// Gets the result of a given Promise object.
664+
/// </summary>
665+
/// <remarks>
666+
/// Requires an active script context.
667+
/// </remarks>
668+
/// <param name="promise">The Promise object.</param>
669+
/// <param name="result">The result of the Promise.</param>
670+
/// <returns>
671+
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
672+
/// </returns>
673+
CHAKRA_API
674+
JsGetPromiseResult(
675+
_In_ JsValueRef promise,
676+
_Out_ JsValueRef *result);
677+
636678
/// <summary>
637679
/// Creates a new JavaScript Promise object.
638680
/// </summary>

lib/Jsrt/Jsrt.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5112,6 +5112,67 @@ CHAKRA_API JsCreatePromise(_Out_ JsValueRef *promise, _Out_ JsValueRef *resolve,
51125112
});
51135113
}
51145114

5115+
CHAKRA_API JsGetPromiseState(_In_ JsValueRef promise, _Out_ JsPromiseState *state)
5116+
{
5117+
return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode {
5118+
PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);
5119+
5120+
VALIDATE_INCOMING_REFERENCE(promise, scriptContext);
5121+
PARAM_NOT_NULL(state);
5122+
5123+
*state = JsPromiseState_Pending;
5124+
5125+
if (!Js::JavascriptPromise::Is(promise))
5126+
{
5127+
return JsErrorInvalidArgument;
5128+
}
5129+
5130+
Js::JavascriptPromise *jsPromise = Js::JavascriptPromise::FromVar(promise);
5131+
Js::JavascriptPromise::PromiseStatus status = jsPromise->GetStatus();
5132+
5133+
switch (status)
5134+
{
5135+
case Js::JavascriptPromise::PromiseStatus::PromiseStatusCode_HasRejection:
5136+
*state = JsPromiseState_Rejected;
5137+
break;
5138+
5139+
case Js::JavascriptPromise::PromiseStatus::PromiseStatusCode_HasResolution:
5140+
*state = JsPromiseState_Fulfilled;
5141+
break;
5142+
}
5143+
5144+
return JsNoError;
5145+
});
5146+
}
5147+
5148+
CHAKRA_API JsGetPromiseResult(_In_ JsValueRef promise, _Out_ JsValueRef *result)
5149+
{
5150+
return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode {
5151+
PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);
5152+
5153+
VALIDATE_INCOMING_REFERENCE(promise, scriptContext);
5154+
PARAM_NOT_NULL(result);
5155+
5156+
*result = JS_INVALID_REFERENCE;
5157+
5158+
if (!Js::JavascriptPromise::Is(promise))
5159+
{
5160+
return JsErrorInvalidArgument;
5161+
}
5162+
5163+
Js::JavascriptPromise *jsPromise = Js::JavascriptPromise::FromVar(promise);
5164+
Js::Var jsResult = jsPromise->GetResult();
5165+
5166+
if (jsResult == nullptr)
5167+
{
5168+
return JsErrorInvalidArgument;
5169+
}
5170+
5171+
*result = (JsValueRef)jsResult;
5172+
return JsNoError;
5173+
});
5174+
}
5175+
51155176
CHAKRA_API JsCreateWeakReference(
51165177
_In_ JsValueRef value,
51175178
_Out_ JsWeakRef* weakRef)

0 commit comments

Comments
 (0)