Skip to content

Commit

Permalink
Add promise C API
Browse files Browse the repository at this point in the history
related issue: 1794

JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang zidong.jiang@intel.com
  • Loading branch information
jiangzidong committed May 3, 2017
1 parent 894aa6d commit af07a21
Show file tree
Hide file tree
Showing 11 changed files with 435 additions and 23 deletions.
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

0 comments on commit af07a21

Please sign in to comment.