Skip to content

Introduce jerry_port_track_promise_rejection #4451

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

Merged
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
55 changes: 55 additions & 0 deletions docs/05.PORT-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,32 @@ jerry_port_get_native_module (jerry_value_t name) /**< module specifier */
}
```

## Promise

```c
/**
* HostPromiseRejectionTracker operations
*/
typedef enum
{
JERRY_PROMISE_REJECTION_OPERATION_REJECT, /**< promise is rejected without any handlers */
JERRY_PROMISE_REJECTION_OPERATION_HANDLE, /**< handler is added to a rejected promise for the first time */
} jerry_promise_rejection_operation_t;

/**
* Track unhandled promise rejections.
*
* Note:
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
* is enabled.
*
* @param promise rejected promise
* @param operation HostPromiseRejectionTracker operation
*/
void jerry_port_track_promise_rejection (const 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.

I was also considering suggesting yet another name change, to have the new function named jerry_port_promise_rejection_tracker. That would make the new typedef and the new function names aligned, as well as the name used by the spec. However, existing port API function names usually start with a verb (get this, set that, sleep, print, log, etc. -- the only exception being fatal). So, I'm not sure about this. But we should agree upon a good name so that it doesn't need to be changed, at least in the near future.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd keep this jerry_port_track_promise_rejection for the due to the starting verb convention with the other API functions.

jerry_port_promise_rejection_tracker would be suitable if we would rename jerry_port_log to jerry_port_logger and so on. So I'd leave as it for now.

const jerry_promise_rejection_operation_t operation);
```

## Date

```c
Expand Down Expand Up @@ -392,3 +418,32 @@ void jerry_port_sleep (uint32_t sleep_time)
} /* jerry_port_sleep */
#endif /* defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1) */
```

## Promise

```c
#include "jerryscript-port.h"

/**
* Default implementation of jerry_port_track_promise_rejection.
* Prints the reason of the unhandled rejections.
*/
void
jerry_port_track_promise_rejection (const jerry_value_t promise, /**< rejected promise */
const jerry_promise_rejection_operation_t operation) /**< operation */
{
(void) operation; /* unused */

jerry_value_t reason = jerry_get_promise_result (promise);
jerry_value_t reason_to_string = jerry_value_to_string (reason);
jerry_size_t req_sz = jerry_get_utf8_string_size (reason_to_string);
jerry_char_t str_buf_p[req_sz + 1];
jerry_string_to_utf8_char_buffer (reason_to_string, str_buf_p, req_sz);
str_buf_p[req_sz] = '\0';

jerry_release_value (reason_to_string);
jerry_release_value (reason);

printf ("Uncaught (in promise) %s\n", str_buf_p);
} /* jerry_port_track_promise_rejection */
```
22 changes: 22 additions & 0 deletions jerry-core/ecma/operations/ecma-promise-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,23 @@ ecma_is_resolver_already_called (ecma_object_t *promise_obj_p) /**< promise */
return (ecma_promise_get_flags (promise_obj_p) & ECMA_PROMISE_ALREADY_RESOLVED) != 0;
} /* ecma_is_resolver_already_called */

/**
* HostPromiseRejectionTracker
*
* See also: ES11 25.6.1.9
*/
static void
ecma_track_promise_rejection (ecma_object_t *obj_p, /**< rejected promise */
jerry_promise_rejection_operation_t operation) /**< operation */
{
JERRY_ASSERT (ecma_is_promise (obj_p));

if (!(ecma_promise_get_flags (obj_p) & ECMA_PROMISE_HANDLED))
{
jerry_port_track_promise_rejection (ecma_make_object_value (obj_p), operation);
}
} /* ecma_track_promise_rejection */

/**
* Reject a Promise with a reason.
*
Expand Down Expand Up @@ -208,6 +225,7 @@ ecma_reject_promise (ecma_value_t promise, /**< promise */
promise_p->reactions = ecma_new_collection ();

ecma_collection_destroy (reactions);
ecma_track_promise_rejection (obj_p, JERRY_PROMISE_REJECTION_OPERATION_REJECT);
} /* ecma_reject_promise */

/**
Expand Down Expand Up @@ -818,10 +836,14 @@ ecma_promise_do_then (ecma_value_t promise, /**< the promise which call 'then' *
{
/* 9. */
ecma_value_t reason = ecma_promise_get_result (promise_obj_p);
ecma_track_promise_rejection (promise_obj_p, JERRY_PROMISE_REJECTION_OPERATION_HANDLE);
ecma_enqueue_promise_reaction_job (ecma_make_object_value (result_capability_obj_p), on_rejected, reason);
ecma_free_value (reason);
}

/* ES11: 11. */
promise_p->header.u.class_prop.extra_info |= ECMA_PROMISE_HANDLED;

/* 10. */
return ecma_copy_value (capability_p->header.u.class_prop.u.promise);
} /* ecma_promise_do_then */
Expand Down
1 change: 1 addition & 0 deletions jerry-core/ecma/operations/ecma-promise-object.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedef enum
ECMA_PROMISE_IS_PENDING = (1 << 0), /**< pending state */
ECMA_PROMISE_IS_FULFILLED = (1 << 1), /**< fulfilled state */
ECMA_PROMISE_ALREADY_RESOLVED = (1 << 2), /**< already resolved */
ECMA_PROMISE_HANDLED = (1 << 3), /**< ES11: 25.6.6 [[PromiseIsHandled]] internal slot */
} ecma_promise_flags_t;

/**
Expand Down
22 changes: 22 additions & 0 deletions jerry-core/include/jerryscript-port.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,28 @@ size_t jerry_port_normalize_path (const char *in_path_p,
*/
jerry_value_t jerry_port_get_native_module (jerry_value_t name);

/**
* HostPromiseRejectionTracker operations
*/
typedef enum
{
JERRY_PROMISE_REJECTION_OPERATION_REJECT, /**< promise is rejected without any handlers */
JERRY_PROMISE_REJECTION_OPERATION_HANDLE, /**< handler is added to a rejected promise for the first time */
} jerry_promise_rejection_operation_t;

/**
* Track unhandled promise rejections.
*
* Note:
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
* is enabled.
*
* @param promise rejected promise
* @param operation HostPromiseRejectionTracker operation
*/
void jerry_port_track_promise_rejection (const jerry_value_t promise,
const jerry_promise_rejection_operation_t operation);

/**
* @}
*/
Expand Down
1 change: 1 addition & 0 deletions jerry-port/default/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ set(SOURCE_PORT_DEFAULT
default-fatal.c
default-io.c
default-module.c
default-promise.c
)

# Amalgamated JerryScript source/header build.
Expand Down
39 changes: 39 additions & 0 deletions jerry-port/default/default-promise.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "jerryscript-port.h"

/**
* Default implementation of jerry_port_track_promise_rejection.
* Prints the reason of the unhandled rejections.
*/
void
jerry_port_track_promise_rejection (const jerry_value_t promise, /**< rejected promise */
const jerry_promise_rejection_operation_t operation) /**< operation */
{
(void) operation; /* unused */

jerry_value_t reason = jerry_get_promise_result (promise);
jerry_value_t reason_to_string = jerry_value_to_string (reason);
jerry_size_t req_sz = jerry_get_utf8_string_size (reason_to_string);
JERRY_VLA (jerry_char_t, str_buf_p, req_sz + 1);
jerry_string_to_utf8_char_buffer (reason_to_string, str_buf_p, req_sz);
str_buf_p[req_sz] = '\0';

jerry_release_value (reason_to_string);
jerry_release_value (reason);

jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Uncaught (in promise) %s\n", str_buf_p);
} /* jerry_port_track_promise_rejection */
45 changes: 45 additions & 0 deletions targets/esp-idf/promise.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "jerryscript-port.h"

/**
* Track unhandled promise rejections.
*
* Note:
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
* is enabled.
*
* @param promise rejected promise
* @param operation HostPromiseRejectionTracker operation
*/
void
jerry_port_track_promise_rejection (const jerry_value_t promise,
const jerry_promise_rejection_operation_t operation)
{
(void) operation; /* unused */

jerry_value_t reason = jerry_get_promise_result (promise);
jerry_value_t reason_to_string = jerry_value_to_string (reason);
jerry_size_t req_sz = jerry_get_utf8_string_size (reason_to_string);
jerry_char_t str_buf_p[req_sz + 1];
jerry_string_to_utf8_char_buffer (reason_to_string, str_buf_p, req_sz);
str_buf_p[req_sz] = '\0';

jerry_release_value (reason_to_string);
jerry_release_value (reason);

jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Uncaught (in promise) %s\n", str_buf_p);
} /* jerry_port_track_promise_rejection */
29 changes: 29 additions & 0 deletions targets/nuttx-stm32f4/jerry_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,32 @@ jerry_port_get_current_context (void)
{
return current_context_p;
} /* jerry_port_get_current_context */

/**
* Track unhandled promise rejections.
*
* Note:
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
* is enabled.
*
* @param promise rejected promise
* @param operation HostPromiseRejectionTracker operation
*/
void
jerry_port_track_promise_rejection (const jerry_value_t promise,
const jerry_promise_rejection_operation_t operation)
{
(void) operation; /* unused */

jerry_value_t reason = jerry_get_promise_result (promise);
jerry_value_t reason_to_string = jerry_value_to_string (reason);
jerry_size_t req_sz = jerry_get_utf8_string_size (reason_to_string);
jerry_char_t str_buf_p[req_sz + 1];
jerry_string_to_utf8_char_buffer (reason_to_string, str_buf_p, req_sz);
str_buf_p[req_sz] = '\0';

jerry_release_value (reason_to_string);
jerry_release_value (reason);

jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Uncaught (in promise) %s\n", str_buf_p);
} /* jerry_port_track_promise_rejection */