Skip to content

Commit

Permalink
N-API: Implement Promise for ChakraCore
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Schulhof committed Jun 16, 2017
1 parent 4f8f708 commit 926b948
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/node_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -480,10 +480,18 @@ NAPI_EXTERN napi_status napi_queue_async_work(napi_env env,
NAPI_EXTERN napi_status napi_cancel_async_work(napi_env env,
napi_async_work work);


// version management
NAPI_EXTERN napi_status napi_get_version(napi_env env, uint32_t* result);

// Methods to manage promises
NAPI_EXTERN napi_status napi_create_promise(napi_env env,
napi_value* result,
napi_value* resolve_callback,
napi_value* reject_callback);
NAPI_EXTERN napi_status napi_is_promise(napi_env env,
napi_value value,
bool* result);

EXTERN_C_END

#endif // SRC_NODE_API_H_
45 changes: 45 additions & 0 deletions src/node_api_jsrt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2010,6 +2010,51 @@ napi_status napi_get_version(napi_env env, uint32_t* result) {
return napi_ok;
}

NAPI_EXTERN napi_status napi_create_promise(napi_env env,
napi_value* result,
napi_value* resolve_callback,
napi_value* reject_callback) {
CHECK_ARG(env);
CHECK_ARG(result);
CHECK_ARG(resolve_callback);
CHECK_ARG(reject_callback);

JsValueRef promise, reject, resolve;

CHECK_JSRT(JsCreatePromise(&promise, &reject, &resolve));

(*result) = reinterpret_cast<napi_value>(promise);
(*resolve_callback) = reinterpret_cast<napi_value>(resolve);
(*reject_callback) = reinterpret_cast<napi_value>(reject);

return napi_ok;
}

NAPI_EXTERN napi_status napi_is_promise(napi_env env,
napi_value value,
bool* result) {
CHECK_ARG(env);
CHECK_ARG(value);
CHECK_ARG(result);

napi_status status;
napi_value js_promise_ctor, global;
bool is_instance;

status = napi_get_global(env, &global);
if (status != napi_ok) return status;

status = napi_get_named_property(env, global, "Promise", &js_promise_ctor);
if (status != napi_ok) return status;

status = napi_instanceof(env, value, js_promise_ctor, &is_instance);
if (status != napi_ok) return status;

(*result) = is_instance;

return napi_ok;
}

namespace uvimpl {

napi_status ConvertUVErrorCode(int code) {
Expand Down
8 changes: 8 additions & 0 deletions test/addons-napi/test_promise/binding.gyp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"targets": [
{
"target_name": "test_promise",
"sources": [ "test_promise.c" ]
}
]
}
61 changes: 61 additions & 0 deletions test/addons-napi/test_promise/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use strict';

const common = require('../../common');
const test_promise = require(`./build/${common.buildType}/test_promise`);
const assert = require('assert');

var native_promise, conclude_value;

// Create a native promise and resolve it.
native_promise = test_promise.napi_create_promise();
conclude_value = "Promise delivered";
native_promise.promise
.then(
function( result ) {
assert.strictEqual( result, conclude_value, "Promise was resolved as expected" );
},
function( error ) {
assert.ok( false, "Promise was rejected when it should have been resolved: " +
error + ": " + JSON.stringify( error, null, 4 ) );
} );
native_promise.resolve( conclude_value );

// Make sure the native promise is recognized as a promise.
assert.strictEqual( test_promise.napi_is_promise( native_promise.promise ), true,
"N-API correctly identifies a promise it created as a promise" );

// Create a native promise and reject it.
native_promise = test_promise.napi_create_promise();
conclude_value = new Error( "I broke my promise" );
native_promise.promise
.then(
function( result ) {
assert.ok( false, "Promise was resolved when it should have been rejected: " +
result + ": " + JSON.stringify( result, null, 4 ) );
},
function( error ) {
assert.strictEqual( error, conclude_value, "Promise was rejected as expected" );
} );

// N-API correctly identifies a JS promise as a promise
assert.strictEqual(
test_promise.napi_is_promise( Promise.reject( new Error( "No reason, just sayin'" ) ) ), true,
"N-API correctly identifies a JS promise as a promise" );

assert.strictEqual( test_promise.napi_is_promise( 42 ), false,
"N-API correctly reports that a number is not a promise" );

assert.strictEqual( test_promise.napi_is_promise( "Gumball" ), false,
"N-API correctly reports that a string is not a promise" );

assert.strictEqual( test_promise.napi_is_promise( undefined ), false,
"N-API correctly reports that undefined is not a promise" );

assert.strictEqual( test_promise.napi_is_promise( null ), false,
"N-API correctly reports that null is not a promise" );

assert.strictEqual( test_promise.napi_is_promise( {} ), false,
"N-API correctly reports that an object is not a promise" );

assert.strictEqual( test_promise.napi_is_promise( Symbol( "Espoo" ) ), false,
"N-API correctly reports that a symbol is not a promise" );
50 changes: 50 additions & 0 deletions test/addons-napi/test_promise/test_promise.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <stdio.h>
#include <node_api.h>
#include "../common.h"

napi_value bind_napi_create_promise(napi_env env, napi_callback_info info) {
napi_value promise, resolve, reject, result;

NAPI_CALL(env, napi_create_promise(env, &promise, &resolve, &reject));
NAPI_CALL(env, napi_create_object(env, &result));

fprintf(stderr, "resolve: %p\n", resolve);

napi_valuetype value_type;
NAPI_CALL(env, napi_typeof(env, resolve, &value_type));
fprintf(stderr, "resolve: value_type: %d\n", value_type);

napi_property_descriptor properties[] = {
{ "promise", NULL, NULL, NULL, NULL, promise, napi_default, NULL },
{ "resolve", NULL, NULL, NULL, NULL, resolve, napi_default, NULL },
{ "reject", NULL, NULL, NULL, NULL, reject, napi_default, NULL },
};

NAPI_CALL(env, napi_define_properties(env, result, 3, properties));

return result;
}

napi_value bind_napi_is_promise(napi_env env, napi_callback_info info) {
napi_value promise, result;
size_t argc = 1;
bool is_promise;

NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &promise, NULL, NULL));
NAPI_CALL(env, napi_is_promise(env, promise, &is_promise));
NAPI_CALL(env, napi_get_boolean(env, is_promise, &result));

return result;
}

void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_PROPERTY("napi_create_promise", bind_napi_create_promise),
DECLARE_NAPI_PROPERTY("napi_is_promise", bind_napi_is_promise)
};

NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}

NAPI_MODULE(addon, Init)

0 comments on commit 926b948

Please sign in to comment.