Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add promise C API #1796

Merged
merged 1 commit into from
May 4, 2017
Merged

Conversation

jiangzidong
Copy link
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
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.

jerry_value_is_promise (const jerry_value_t value) /**< api value */
{
jerry_assert_api_available ();
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
Copy link
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
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.


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
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.


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
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.

#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 */
return ecma_raise_syntax_error (ECMA_ERR_MSG ("Promise profile has been disabled."));
Copy link
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.

static jerry_value_t
jerry_resolve_or_reject_promise (jerry_value_t promise,
jerry_value_t argument,
bool is_resolve)
Copy link
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
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
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
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
Contributor

@jprestwo any feedback on this API?


```c
jerry_value_t
jerry_promise_get_resolve (jerry_value_t promise)
Copy link
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
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
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
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
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.

@@ -1980,6 +2021,64 @@ jerry_value_to_string (const jerry_value_t value);
- [jerry_value_to_primitive](#jerry_value_to_primitive)


# Functions for promise value
Copy link
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.


...

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

Choose a reason for hiding this comment

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

resolved or rejected


**Summary**

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

Choose a reason for hiding this comment

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

resolved/rejected

jerry_create_promise (void)
```

- return value - value of the created promise
Copy link
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 */
ECMA_PROMISE_EXECUTOR_OBJECT, /**< the executor is a object, it is for the `then` routine */
Copy link
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

} /* jerry_value_is_promise */


/**
Copy link
Member

Choose a reason for hiding this comment

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

Only one newline.

* false - otherwise
*/
bool
jerry_value_is_promise (const jerry_value_t value) /**< api value */
Copy link
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'.

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
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);

...

} /* create_promise1_handler */

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

Choose a reason for hiding this comment

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

ditto

} /* create_promise2_handler */

static jerry_value_t
assert_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */
Copy link
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
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
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
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
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 zidong.jiang@intel.com
Copy link
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
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