Skip to content

Add promise C API#1796

Merged
jiangzidong merged 1 commit intojerryscript-project:masterfrom
jiangzidong:cpromise
May 4, 2017
Merged

Add promise C API#1796
jiangzidong merged 1 commit intojerryscript-project:masterfrom
jiangzidong:cpromise

Conversation

@jiangzidong
Copy link
Copy Markdown
Contributor

@jiangzidong jiangzidong commented May 2, 2017

related issue: 1794

  • add api:
bool jerry_value_is_promise (const jerry_value_t value);
jerry_value_t jerry_create_promise (void);
jerry_value_t jerry_resolve_promise (jerry_value_t promise, jerry_value_t argument);
jerry_value_t jerry_reject_promise (jerry_value_t promise, jerry_value_t reason);
  • unittest support es2015-subset profile

  • doc will be added later when we reach the consensus

Copy link
Copy Markdown
Member

@zherczeg zherczeg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good patch! Please add documentation for the new functions.

Comment thread jerry-core/jerry.c
bool
jerry_value_is_promise (const jerry_value_t value) /**< api value */
{
jerry_assert_api_available ();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newline before ifdef

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add newlines before other ifdefs in this file.

Comment thread tests/unit-core/test-promise.c Outdated

static jerry_value_t
create_promise1_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
const jerry_value_t this_val __attribute__((unused)), /**< this value */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more space needed.

Comment thread tests/unit-core/test-promise.c Outdated

static jerry_value_t
create_promise2_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
const jerry_value_t this_val __attribute__((unused)), /**< this value */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more space needed.

Comment thread jerry-core/jerry.c Outdated
jerry_assert_api_available ();
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
return ecma_op_create_promise_object (ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY), ECMA_PROMISE_EXECUTOR_EMPTY);
#else /* CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe better to exclude the implementation so you get a linker error?
I don't know... returning an error adds code space.

Comment thread jerry-core/jerry.c Outdated
*/
static jerry_value_t
jerry_resolve_or_reject_promise (jerry_value_t promise,
jerry_value_t argument,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to expose something like this in the public API.

I think people will be writing code like in this example a lot, so you naturally have a bool to make the decision whether resolve or reject should be called.

In an earlier sketch, I used an enum, I think that has a bit better readability vs bool, but I'm not feeling strongly about it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thought is the C api should be similar with js api, so it will be easy to use. In JS world, usually the code is like

var p = new Promise(function(resolve, reject)
{
  ....
  if (some condition)
  {
    var reason = .....//prepare the reason
     reject (reason)
  }
  
  var argument = .... //prepare the argument
   resolve(argument)
})

in your example,

static void my_get_batt_info_cb (const batt_info_t *info, void *cb_data)
{
        jerry_value_t promise = (jerry_value_t)(uintptr_t) cb_data; 
        
        // do stuff with *info and assign result + should_call_resolve:
        jerry_value_t result = ...;
        bool should_call_resolve = ...;
        
        jerry_call_resolve_reject(promise, result, should_call_resolve);
        jerry_value_release(promise);
}

there should be some if-else or branch code in result = and should_call_resolve = , e.g.

if (some condition)
 { result = some_error_reason; should_call_resolve = false; }
else
{result = some_argument; should_call_resolve = true;}

why just directly call the resolve/reject in the branch?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why just directly call the resolve/reject in the branch?

Code space savings. You'd have 2x function calls vs 1x.
Often you already have the bool should_call_resolve one way or another, for example in your snippet, there is some_condition. In this case, some_condition == !should_call_resolve.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it makes sense :)

@martijnthe
Copy link
Copy Markdown
Contributor

@jprestwo any feedback on this API?

Comment thread docs/02.API-REFERENCE.md Outdated

```c
jerry_value_t
jerry_promise_get_resolve (jerry_value_t promise)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I don't understand is that we have one function to resolve/reject, but two functions for getting functions. I think it would be better to have a boolean parameter here as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My gut says that if your project needs access to the functions, you probably are going to need both.

Would it make sense to have:

bool jerry_promise_get_resolve (
     jerry_value_t promise, jerry_value_t *resolve_out_p, jerry_value_t *reject_out_p)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I wonder if we're adding the resolve/reject getter prematurely...
Maybe just remove it and get on with life until someone comes along that has a clear use for it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree

Copy link
Copy Markdown
Member

@zherczeg zherczeg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after some style fixes.

Comment thread docs/02.API-REFERENCE.md Outdated
- [jerry_value_to_primitive](#jerry_value_to_primitive)


# Functions for promise value
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functions for promise objects.

Comment thread docs/02.API-REFERENCE.md Outdated

...

bool is_resolve = ... // whether the promise should be resolve or reject
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved or rejected

Comment thread docs/02.API-REFERENCE.md Outdated

**Summary**

Create an empty Promise object which can be resolve/reject later
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved/rejected

Comment thread docs/02.API-REFERENCE.md Outdated
jerry_create_promise (void)
```

- return value - value of the created promise
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newly created promise

*/
typedef enum
{
ECMA_PROMISE_EXECUTOR_FUNCTION, /**< the executor is a function, it is for the usual constructor */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the executor is an object

Comment thread jerry-core/jerry.c Outdated
} /* jerry_value_is_promise */


/**
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only one newline.

Comment thread jerry-core/jerry.c Outdated
* false - otherwise
*/
bool
jerry_value_is_promise (const jerry_value_t value) /**< api value */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the same order of functions as 'jerryscript.h'.

Comment thread tests/unit-core/test-promise.c Outdated
const jerry_char_t s2[] = "rejected";

static jerry_value_t
create_promise1_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JERRY_UNUSED must be available here since test-common.h includes jrt.h

static jerry_value_t
create_promise1_handler (const jerry_value_t func_obj_val , /**< function object */
                         const jerry_value_t this_val, /**< this value */
                         const jerry_value_t args_p[], /**< arguments list */
                         const jerry_length_t args_cnt) /**< arguments length */
{
JERRY_UNUSED (func_obj_val);
JERRY_UNUSED (this_val);
JERRY_UNUSED (args_p);
JERRY_UNUSED (args_cnt);

...

Comment thread tests/unit-core/test-promise.c Outdated
} /* create_promise1_handler */

static jerry_value_t
create_promise2_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Comment thread tests/unit-core/test-promise.c Outdated
} /* create_promise2_handler */

static jerry_value_t
assert_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

if(NOT ${FEATURE_PROFILE} STREQUAL "${CMAKE_SOURCE_DIR}/jerry-core/profiles/es5.1.profile")
message(FATAL_ERROR "FEATURE_PROFILE='${FEATURE_PROFILE}' isn't supported with UNITTESTS=ON")
if(${FEATURE_PROFILE} STREQUAL "${CMAKE_SOURCE_DIR}/jerry-core/profiles/minimal.profile")
message(FATAL_ERROR "minimal profile isn't supported in unit-core")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change related to this this PR? It looks to me if promise is not available than the test-promise returns zero, which is good. Am I missing something?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this change, I cannot ./tools/build.py --unittest --profile=es2015-subset, because it's profile is not es5.1.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And also I changed the run-test.py, now es2015-subset profile is passed to unittest

# Test options for unittests
JERRY_UNITTESTS_OPTIONS = [
    Options('unittests',
            ['--unittests', '--error-messages=on', '--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on', '--profile=es2015-subset']),
    Options('unittests-debug',
            ['--unittests', '--debug', '--error-messages=on', '--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on', '--profile=es2015-subset'])
]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Thanks for the explanation.

related issue: 1794

JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang [email protected]
Copy link
Copy Markdown
Contributor

@LaszloLango LaszloLango left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update. LGTM

@jiangzidong jiangzidong merged commit ede1383 into jerryscript-project:master May 4, 2017
@jiangzidong jiangzidong deleted the cpromise branch May 4, 2017 08:13
@martijnthe
Copy link
Copy Markdown
Contributor

💯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants