Skip to content

Commit 926b948

Browse files
author
Gabriel Schulhof
committed
N-API: Implement Promise for ChakraCore
Re nodejs/abi-stable-node#242
1 parent 4f8f708 commit 926b948

File tree

5 files changed

+173
-1
lines changed

5 files changed

+173
-1
lines changed

src/node_api.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,18 @@ NAPI_EXTERN napi_status napi_queue_async_work(napi_env env,
480480
NAPI_EXTERN napi_status napi_cancel_async_work(napi_env env,
481481
napi_async_work work);
482482

483-
484483
// version management
485484
NAPI_EXTERN napi_status napi_get_version(napi_env env, uint32_t* result);
486485

486+
// Methods to manage promises
487+
NAPI_EXTERN napi_status napi_create_promise(napi_env env,
488+
napi_value* result,
489+
napi_value* resolve_callback,
490+
napi_value* reject_callback);
491+
NAPI_EXTERN napi_status napi_is_promise(napi_env env,
492+
napi_value value,
493+
bool* result);
494+
487495
EXTERN_C_END
488496

489497
#endif // SRC_NODE_API_H_

src/node_api_jsrt.cc

+45
Original file line numberDiff line numberDiff line change
@@ -2010,6 +2010,51 @@ napi_status napi_get_version(napi_env env, uint32_t* result) {
20102010
return napi_ok;
20112011
}
20122012

2013+
NAPI_EXTERN napi_status napi_create_promise(napi_env env,
2014+
napi_value* result,
2015+
napi_value* resolve_callback,
2016+
napi_value* reject_callback) {
2017+
CHECK_ARG(env);
2018+
CHECK_ARG(result);
2019+
CHECK_ARG(resolve_callback);
2020+
CHECK_ARG(reject_callback);
2021+
2022+
JsValueRef promise, reject, resolve;
2023+
2024+
CHECK_JSRT(JsCreatePromise(&promise, &reject, &resolve));
2025+
2026+
(*result) = reinterpret_cast<napi_value>(promise);
2027+
(*resolve_callback) = reinterpret_cast<napi_value>(resolve);
2028+
(*reject_callback) = reinterpret_cast<napi_value>(reject);
2029+
2030+
return napi_ok;
2031+
}
2032+
2033+
NAPI_EXTERN napi_status napi_is_promise(napi_env env,
2034+
napi_value value,
2035+
bool* result) {
2036+
CHECK_ARG(env);
2037+
CHECK_ARG(value);
2038+
CHECK_ARG(result);
2039+
2040+
napi_status status;
2041+
napi_value js_promise_ctor, global;
2042+
bool is_instance;
2043+
2044+
status = napi_get_global(env, &global);
2045+
if (status != napi_ok) return status;
2046+
2047+
status = napi_get_named_property(env, global, "Promise", &js_promise_ctor);
2048+
if (status != napi_ok) return status;
2049+
2050+
status = napi_instanceof(env, value, js_promise_ctor, &is_instance);
2051+
if (status != napi_ok) return status;
2052+
2053+
(*result) = is_instance;
2054+
2055+
return napi_ok;
2056+
}
2057+
20132058
namespace uvimpl {
20142059

20152060
napi_status ConvertUVErrorCode(int code) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"targets": [
3+
{
4+
"target_name": "test_promise",
5+
"sources": [ "test_promise.c" ]
6+
}
7+
]
8+
}

test/addons-napi/test_promise/test.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
'use strict';
2+
3+
const common = require('../../common');
4+
const test_promise = require(`./build/${common.buildType}/test_promise`);
5+
const assert = require('assert');
6+
7+
var native_promise, conclude_value;
8+
9+
// Create a native promise and resolve it.
10+
native_promise = test_promise.napi_create_promise();
11+
conclude_value = "Promise delivered";
12+
native_promise.promise
13+
.then(
14+
function( result ) {
15+
assert.strictEqual( result, conclude_value, "Promise was resolved as expected" );
16+
},
17+
function( error ) {
18+
assert.ok( false, "Promise was rejected when it should have been resolved: " +
19+
error + ": " + JSON.stringify( error, null, 4 ) );
20+
} );
21+
native_promise.resolve( conclude_value );
22+
23+
// Make sure the native promise is recognized as a promise.
24+
assert.strictEqual( test_promise.napi_is_promise( native_promise.promise ), true,
25+
"N-API correctly identifies a promise it created as a promise" );
26+
27+
// Create a native promise and reject it.
28+
native_promise = test_promise.napi_create_promise();
29+
conclude_value = new Error( "I broke my promise" );
30+
native_promise.promise
31+
.then(
32+
function( result ) {
33+
assert.ok( false, "Promise was resolved when it should have been rejected: " +
34+
result + ": " + JSON.stringify( result, null, 4 ) );
35+
},
36+
function( error ) {
37+
assert.strictEqual( error, conclude_value, "Promise was rejected as expected" );
38+
} );
39+
40+
// N-API correctly identifies a JS promise as a promise
41+
assert.strictEqual(
42+
test_promise.napi_is_promise( Promise.reject( new Error( "No reason, just sayin'" ) ) ), true,
43+
"N-API correctly identifies a JS promise as a promise" );
44+
45+
assert.strictEqual( test_promise.napi_is_promise( 42 ), false,
46+
"N-API correctly reports that a number is not a promise" );
47+
48+
assert.strictEqual( test_promise.napi_is_promise( "Gumball" ), false,
49+
"N-API correctly reports that a string is not a promise" );
50+
51+
assert.strictEqual( test_promise.napi_is_promise( undefined ), false,
52+
"N-API correctly reports that undefined is not a promise" );
53+
54+
assert.strictEqual( test_promise.napi_is_promise( null ), false,
55+
"N-API correctly reports that null is not a promise" );
56+
57+
assert.strictEqual( test_promise.napi_is_promise( {} ), false,
58+
"N-API correctly reports that an object is not a promise" );
59+
60+
assert.strictEqual( test_promise.napi_is_promise( Symbol( "Espoo" ) ), false,
61+
"N-API correctly reports that a symbol is not a promise" );
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include <stdio.h>
2+
#include <node_api.h>
3+
#include "../common.h"
4+
5+
napi_value bind_napi_create_promise(napi_env env, napi_callback_info info) {
6+
napi_value promise, resolve, reject, result;
7+
8+
NAPI_CALL(env, napi_create_promise(env, &promise, &resolve, &reject));
9+
NAPI_CALL(env, napi_create_object(env, &result));
10+
11+
fprintf(stderr, "resolve: %p\n", resolve);
12+
13+
napi_valuetype value_type;
14+
NAPI_CALL(env, napi_typeof(env, resolve, &value_type));
15+
fprintf(stderr, "resolve: value_type: %d\n", value_type);
16+
17+
napi_property_descriptor properties[] = {
18+
{ "promise", NULL, NULL, NULL, NULL, promise, napi_default, NULL },
19+
{ "resolve", NULL, NULL, NULL, NULL, resolve, napi_default, NULL },
20+
{ "reject", NULL, NULL, NULL, NULL, reject, napi_default, NULL },
21+
};
22+
23+
NAPI_CALL(env, napi_define_properties(env, result, 3, properties));
24+
25+
return result;
26+
}
27+
28+
napi_value bind_napi_is_promise(napi_env env, napi_callback_info info) {
29+
napi_value promise, result;
30+
size_t argc = 1;
31+
bool is_promise;
32+
33+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &promise, NULL, NULL));
34+
NAPI_CALL(env, napi_is_promise(env, promise, &is_promise));
35+
NAPI_CALL(env, napi_get_boolean(env, is_promise, &result));
36+
37+
return result;
38+
}
39+
40+
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
41+
napi_property_descriptor descriptors[] = {
42+
DECLARE_NAPI_PROPERTY("napi_create_promise", bind_napi_create_promise),
43+
DECLARE_NAPI_PROPERTY("napi_is_promise", bind_napi_is_promise)
44+
};
45+
46+
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
47+
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
48+
}
49+
50+
NAPI_MODULE(addon, Init)

0 commit comments

Comments
 (0)