Skip to content

Commit

Permalink
New APIs for getting Promise state and result
Browse files Browse the repository at this point in the history
  • Loading branch information
kfarnung committed May 11, 2018
1 parent 2c6efb5 commit 4b015fa
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 2 deletions.
4 changes: 2 additions & 2 deletions bin/ChakraCore/ChakraCore.def
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ JsLessThan
JsLessThanOrEqual

JsCreateEnhancedFunction

JsSetHostPromiseRejectionTracker

JsGetProxyProperties
JsGetPromiseState
JsGetPromiseResult
71 changes: 71 additions & 0 deletions bin/NativeTests/JsRTApiTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//-------------------------------------------------------------------------------------------------------
#include "stdafx.h"
#include "catch.hpp"
#include <array>
#include <process.h>

#pragma warning(disable:4100) // unreferenced formal parameter
Expand Down Expand Up @@ -2663,4 +2664,74 @@ namespace JsRTApiTest
{
JsRTApiTest::RunWithAttributes(JsRTApiTest::JsCreateStringTest);
}

void JsCreatePromiseTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
{
JsValueRef result = JS_INVALID_REFERENCE;

JsValueRef promise = JS_INVALID_REFERENCE;
JsValueRef resolve = JS_INVALID_REFERENCE;
JsValueRef reject = JS_INVALID_REFERENCE;

// Create resolvable promise
REQUIRE(JsCreatePromise(&promise, &resolve, &reject) == JsNoError);

JsPromiseState state = JsPromiseState_Pending;
REQUIRE(JsGetPromiseState(promise, &state) == JsNoError);
CHECK(state == JsPromiseState_Pending);

result = JS_INVALID_REFERENCE;
CHECK(JsGetPromiseResult(promise, &result) == JsErrorInvalidArgument);
CHECK(result == JS_INVALID_REFERENCE);

JsValueRef num = JS_INVALID_REFERENCE;
REQUIRE(JsIntToNumber(42, &num) == JsNoError);

std::array<JsValueRef, 2> args{ GetUndefined(), num };
REQUIRE(JsCallFunction(resolve, args.data(), static_cast<unsigned short>(args.size()), &result) == JsNoError);

state = JsPromiseState_Pending;
REQUIRE(JsGetPromiseState(promise, &state) == JsNoError);
CHECK(state == JsPromiseState_Fulfilled);

result = JS_INVALID_REFERENCE;
REQUIRE(JsGetPromiseResult(promise, &result) == JsNoError);

int resultNum = 0;
REQUIRE(JsNumberToInt(result, &resultNum) == JsNoError);
CHECK(resultNum == 42);

// Create rejectable promise
REQUIRE(JsCreatePromise(&promise, &resolve, &reject) == JsNoError);

state = JsPromiseState_Pending;
REQUIRE(JsGetPromiseState(promise, &state) == JsNoError);
CHECK(state == JsPromiseState_Pending);

result = JS_INVALID_REFERENCE;
CHECK(JsGetPromiseResult(promise, &result) == JsErrorInvalidArgument);
CHECK(result == JS_INVALID_REFERENCE);

num = JS_INVALID_REFERENCE;
REQUIRE(JsIntToNumber(43, &num) == JsNoError);

args = { GetUndefined(), num };
REQUIRE(JsCallFunction(reject, args.data(), static_cast<unsigned short>(args.size()), &result) == JsNoError);

state = JsPromiseState_Pending;
REQUIRE(JsGetPromiseState(promise, &state) == JsNoError);
CHECK(state == JsPromiseState_Rejected);

result = JS_INVALID_REFERENCE;
REQUIRE(JsGetPromiseResult(promise, &result) == JsNoError);

resultNum = 0;
REQUIRE(JsNumberToInt(result, &resultNum) == JsNoError);
CHECK(resultNum == 43);
}

TEST_CASE("ApiTest_JsCreatePromiseTest", "[ApiTest]")
{
JsRTApiTest::RunWithAttributes(JsRTApiTest::JsCreatePromiseTest);
}
}
42 changes: 42 additions & 0 deletions lib/Jsrt/ChakraCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ typedef enum JsModuleHostInfoKind
JsModuleHostInfo_Url = 0x6
} JsModuleHostInfoKind;

/// <summary>
/// The possible states for a Promise object.
/// </summary>
typedef enum _JsPromiseState
{
JsPromiseState_Pending = 0x0,
JsPromiseState_Fulfilled = 0x1,
JsPromiseState_Rejected = 0x2
} JsPromiseState;

/// <summary>
/// User implemented callback to fetch additional imported modules.
/// </summary>
Expand Down Expand Up @@ -633,6 +643,38 @@ CHAKRA_API
_In_ JsValueRef sourceUrl,
_Out_ JsValueRef *result);

/// <summary>
/// Gets the state of a given Promise object.
/// </summary>
/// <remarks>
/// Requires an active script context.
/// </remarks>
/// <param name="promise">The Promise object.</param>
/// <param name="state">The current state of the Promise.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsGetPromiseState(
_In_ JsValueRef promise,
_Out_ JsPromiseState *state);

/// <summary>
/// Gets the result of a given Promise object.
/// </summary>
/// <remarks>
/// Requires an active script context.
/// </remarks>
/// <param name="promise">The Promise object.</param>
/// <param name="result">The result of the Promise.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsGetPromiseResult(
_In_ JsValueRef promise,
_Out_ JsValueRef *result);

/// <summary>
/// Creates a new JavaScript Promise object.
/// </summary>
Expand Down
61 changes: 61 additions & 0 deletions lib/Jsrt/Jsrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5112,6 +5112,67 @@ CHAKRA_API JsCreatePromise(_Out_ JsValueRef *promise, _Out_ JsValueRef *resolve,
});
}

CHAKRA_API JsGetPromiseState(_In_ JsValueRef promise, _Out_ JsPromiseState *state)
{
return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode {
PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);

VALIDATE_INCOMING_REFERENCE(promise, scriptContext);
PARAM_NOT_NULL(state);

*state = JsPromiseState_Pending;

if (!Js::JavascriptPromise::Is(promise))
{
return JsErrorInvalidArgument;
}

Js::JavascriptPromise *jsPromise = Js::JavascriptPromise::FromVar(promise);
Js::JavascriptPromise::PromiseStatus status = jsPromise->GetStatus();

switch (status)
{
case Js::JavascriptPromise::PromiseStatus::PromiseStatusCode_HasRejection:
*state = JsPromiseState_Rejected;
break;

case Js::JavascriptPromise::PromiseStatus::PromiseStatusCode_HasResolution:
*state = JsPromiseState_Fulfilled;
break;
}

return JsNoError;
});
}

CHAKRA_API JsGetPromiseResult(_In_ JsValueRef promise, _Out_ JsValueRef *result)
{
return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode {
PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);

VALIDATE_INCOMING_REFERENCE(promise, scriptContext);
PARAM_NOT_NULL(result);

*result = JS_INVALID_REFERENCE;

if (!Js::JavascriptPromise::Is(promise))
{
return JsErrorInvalidArgument;
}

Js::JavascriptPromise *jsPromise = Js::JavascriptPromise::FromVar(promise);
Js::Var jsResult = jsPromise->GetResult();

if (jsResult == nullptr)
{
return JsErrorInvalidArgument;
}

*result = (JsValueRef)jsResult;
return JsNoError;
});
}

CHAKRA_API JsCreateWeakReference(
_In_ JsValueRef value,
_Out_ JsWeakRef* weakRef)
Expand Down

0 comments on commit 4b015fa

Please sign in to comment.