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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 136 additions & 2 deletions docs/02.API-REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,47 @@ jerry_value_is_object (const jerry_value_t value)
- [jerry_release_value](#jerry_release_value)


## jerry_value_is_promise

**Summary**

Returns whether the given `jerry_value_t` is a promise value.

*Note*: This API depends on the ES2015-subset profile.

**Prototype**

```c
bool
jerry_value_is_promise (const jerry_value_t value)
```

- `value` - api value
- return value
- true, if the given `jerry_value_t` is a promise
- false, otherwise

**Example**

```c
{
jerry_value_t value;
... // create or acquire value

if (jerry_value_is_promise (value))
{
...
}

jerry_release_value (value);
}
```

**See also**

- [jerry_release_value](#jerry_release_value)


## jerry_value_is_string

**Summary**
Expand Down Expand Up @@ -1980,6 +2021,64 @@ jerry_value_to_string (const jerry_value_t value);
- [jerry_value_to_primitive](#jerry_value_to_primitive)


# Functions for promise objects

These APIs all depends on the ES2015-subset profile.

## jerry_resolve_or_reject_promise

**Summary**

Resolve or reject the promise with an argument.

**Prototype**

```c
jerry_value_t
jerry_resolve_or_reject_promise (jerry_value_t promise,
jerry_value_t argument,
bool is_resolve)
```

- `promise` - the promise value
- `argument` - the argument for resolve or reject
- `is_resolve` - whether the promise should be resolved or rejected
- return value
- undefined jerry value - resolve or reject successed
- jerry value with error flag - otherwise

**Example**

```c
{
jerry_value_t promise = ... // acquire/create a promise object.

...

bool is_resolve = ... // whether the promise should be resolved or rejected
jerry_value_t argument = ... // prepare the argumnent for the resolve or reject.

jerry_value_t is_ok = jerry_resolve_or_reject_promise (promise,
argument,
is_resolve);

if (jerry_value_has_error_flag (is_ok))
{
// handle the error.
}

jerry_release_value (is_ok);
jerry_release_value (argument);
jerry_release_value (promise);
}
```

**See also**

- [jerry_release_value](#jerry_release_value)
- [jerry_value_has_error_flag](#jerry_value_has_error_flag)


# Acquire and release API values

## jerry_acquire_value
Expand Down Expand Up @@ -2425,6 +2524,41 @@ jerry_create_object (void);
- [jerry_release_value](#jerry_release_value)


## jerry_create_promise

**Summary**

Create an empty promise object which can be resolved or rejected later
by calling jerry_resolve_or_reject_promise.

*Note*: This API depends on the ES2015-subset profile.

**Prototype**

```c
jerry_value_t
jerry_create_promise (void)
```

- return value - value of the newly created promise

**Example**

```c
{
jerry_value_t p = jerry_create_promise ();

...// usage of the promise

jerry_release_value (p);
}

**See also**

- [jerry_resolve_or_reject_promise](#jerry_resolve_or_reject_promise)
- [jerry_release_value](#jerry_release_value)


## jerry_create_string

**Summary**
Expand Down Expand Up @@ -3528,7 +3662,7 @@ static const jerry_object_native_info_t native_obj_type_info =
{
// The type of this's native pointer matches what is expected.
// Only now is it safe to cast to native_obj_t * and dereference the
// pointer:
// pointer:
native_obj_t *native_obj = native_p;
native_obj->bar = ...; // Safe to access now!
}
Expand Down Expand Up @@ -3582,7 +3716,7 @@ jerry_set_object_native_pointer (const jerry_value_t obj_val,
**Example**

See [jerry_get_object_native_pointer](#jerry_get_object_native_pointer) for a
best-practice example.
best-practice example.

**See also**

Expand Down
2 changes: 1 addition & 1 deletion jerry-core/ecma/builtin-objects/ecma-builtin-promise.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ ecma_builtin_promise_dispatch_construct (const ecma_value_t *arguments_list_p, /
return ecma_raise_type_error (ECMA_ERR_MSG ("First parameter must be callable."));
}

return ecma_op_create_promise_object (arguments_list_p[0], true);
return ecma_op_create_promise_object (arguments_list_p[0], ECMA_PROMISE_EXECUTOR_FUNCTION);
} /* ecma_builtin_promise_dispatch_construct */

/**
Expand Down
15 changes: 10 additions & 5 deletions jerry-core/ecma/operations/ecma-jobqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,14 @@ ecma_process_promise_resolve_thenable_job (void *obj_p) /**< the job to be opera
{
ecma_job_promise_resolve_thenable_t *job_p = (ecma_job_promise_resolve_thenable_t *) obj_p;
ecma_object_t *promise_p = ecma_get_object_from_value (job_p->promise);
ecma_promise_resolving_functions_t *funcs;
funcs = ecma_promise_create_resolving_functions (promise_p);
ecma_string_t str_resolve, str_reject;
ecma_init_ecma_magic_string (&str_resolve, LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION);
ecma_init_ecma_magic_string (&str_reject, LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION);

ecma_value_t argv[] = { funcs->resolve, funcs->reject };
ecma_value_t resolve = ecma_op_object_get (promise_p, &str_resolve);
ecma_value_t reject = ecma_op_object_get (promise_p, &str_reject);

ecma_value_t argv[] = { resolve, reject };
ecma_value_t ret;
ecma_value_t then_call_result = ecma_op_function_call (ecma_get_object_from_value (job_p->then),
job_p->thenable,
Expand All @@ -237,15 +241,16 @@ ecma_process_promise_resolve_thenable_job (void *obj_p) /**< the job to be opera

if (ECMA_IS_VALUE_ERROR (then_call_result))
{
ret = ecma_op_function_call (ecma_get_object_from_value (funcs->reject),
ret = ecma_op_function_call (ecma_get_object_from_value (reject),
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
&then_call_result,
1);

ecma_free_value (then_call_result);
}

ecma_promise_free_resolving_functions (funcs);
ecma_free_value (resolve);
ecma_free_value (reject);
ecma_free_promise_resolve_thenable_job (job_p);

return ret;
Expand Down
31 changes: 24 additions & 7 deletions jerry-core/ecma/operations/ecma-promise-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ ecma_call_builtin_executor (ecma_object_t *executor_p, /**< the executor object
*
* @return pointer to the resolving functions
*/
ecma_promise_resolving_functions_t *
static ecma_promise_resolving_functions_t *
ecma_promise_create_resolving_functions (ecma_object_t *object_p) /**< the promise object */
{
/* 1. */
Expand Down Expand Up @@ -455,7 +455,7 @@ ecma_promise_create_resolving_functions (ecma_object_t *object_p) /**< the promi
/**
* Free the heap and the member of the resolving functions.
*/
void
static void
ecma_promise_free_resolving_functions (ecma_promise_resolving_functions_t *funcs) /**< points to the functions */
{
ecma_free_value (funcs->resolve);
Expand All @@ -473,7 +473,7 @@ ecma_promise_free_resolving_functions (ecma_promise_resolving_functions_t *funcs
*/
ecma_value_t
ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function or object */
bool is_func) /**< indicates whether executor is a function */
ecma_promise_executor_type_t type) /**< indicates the type of executor */
{
/* 3. */
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE_PROTOTYPE);
Expand All @@ -496,10 +496,22 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
/* 8. */
ecma_promise_resolving_functions_t *funcs = ecma_promise_create_resolving_functions (object_p);

ecma_string_t str_resolve, str_reject;
ecma_init_ecma_magic_string (&str_resolve, LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION);
ecma_init_ecma_magic_string (&str_reject, LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION);
ecma_op_object_put (object_p,
&str_resolve,
funcs->resolve,
false);
ecma_op_object_put (object_p,
&str_reject,
funcs->reject,
false);

/* 9. */
ecma_value_t completion;
ecma_value_t completion = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);

if (is_func)
if (type == ECMA_PROMISE_EXECUTOR_FUNCTION)
{
JERRY_ASSERT (ecma_op_is_callable (executor));

Expand All @@ -509,14 +521,19 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
argv,
2);
}
else
else if (type == ECMA_PROMISE_EXECUTOR_OBJECT)
{
JERRY_ASSERT (ecma_is_value_object (executor));

completion = ecma_call_builtin_executor (ecma_get_object_from_value (executor),
funcs->resolve,
funcs->reject);
}
else
{
JERRY_ASSERT (type == ECMA_PROMISE_EXECUTOR_EMPTY);
JERRY_UNUSED (executor);
}

ecma_value_t status = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

Expand Down Expand Up @@ -572,7 +589,7 @@ ecma_promise_new_capability (void)
false);

/* 6. */
ecma_value_t promise = ecma_op_create_promise_object (executor, false);
ecma_value_t promise = ecma_op_create_promise_object (executor, ECMA_PROMISE_EXECUTOR_OBJECT);

/* 10. */
ecma_op_object_put (capability_p,
Expand Down
15 changes: 11 additions & 4 deletions jerry-core/ecma/operations/ecma-promise-object.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ typedef enum
ECMA_PROMISE_STATE__COUNT /**< number of states */
} ecma_promise_state_t;

/**
* Indicates the type of the executor in promise construct.
*/
typedef enum
{
ECMA_PROMISE_EXECUTOR_FUNCTION, /**< the executor is a function, it is for the usual constructor */
ECMA_PROMISE_EXECUTOR_OBJECT, /**< the executor is an object, it is for the `then` routine */
ECMA_PROMISE_EXECUTOR_EMPTY /**< the executor is empty, it is for external C API */
} ecma_promise_executor_type_t;

/**
* Description of the promise resolving functions.
*/
Expand Down Expand Up @@ -81,10 +91,7 @@ void ecma_promise_set_result (ecma_object_t *obj_p, ecma_value_t result);
uint8_t ecma_promise_get_state (ecma_object_t *obj_p);
void ecma_promise_set_state (ecma_object_t *obj_p, uint8_t state);
ecma_value_t
ecma_op_create_promise_object (ecma_value_t executor, bool is_func);
ecma_promise_resolving_functions_t *
ecma_promise_create_resolving_functions (ecma_object_t *obj_p);
void ecma_promise_free_resolving_functions (ecma_promise_resolving_functions_t *funcs);
ecma_op_create_promise_object (ecma_value_t executor, ecma_promise_executor_type_t type);
ecma_value_t ecma_promise_new_capability (void);
ecma_value_t
ecma_promise_then (ecma_value_t promise,
Expand Down
Loading