Skip to content

Commit 59483cd

Browse files
committed
Introduce jerry_port_report_unhandled_promise_rejection
This patch resolves #2931. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
1 parent 8ddd24f commit 59483cd

File tree

7 files changed

+162
-0
lines changed

7 files changed

+162
-0
lines changed

docs/05.PORT-API.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,24 @@ jerry_port_get_native_module (jerry_value_t name) /**< module specifier */
151151
}
152152
```
153153
154+
## Promise
155+
156+
Allow user to get notified whenever an unhandled promise rejection happens.
157+
158+
```c
159+
/**
160+
* Report the reason of the unhandled promise rejections.
161+
*
162+
* Note:
163+
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
164+
* is enabled.
165+
*
166+
* @param promise rejected promise.
167+
* @param reason reason of the rejection.
168+
*/
169+
void jerry_port_report_unhandled_promise_rejection (jerry_value_t promise, jerry_value_t reason);
170+
```
171+
154172
## Date
155173

156174
```c

jerry-core/ecma/operations/ecma-promise-object.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,23 @@ ecma_is_resolver_already_called (ecma_object_t *promise_obj_p) /**< promise */
181181
return (ecma_promise_get_flags (promise_obj_p) & ECMA_PROMISE_ALREADY_RESOLVED) != 0;
182182
} /* ecma_is_resolver_already_called */
183183

184+
/**
185+
* HostPromiseRejectionTracker
186+
*
187+
* See also: ES11 25.6.1.9
188+
*/
189+
static void
190+
ecma_promise_track_rejection (ecma_object_t *obj_p, /**< promise */
191+
ecma_value_t reason) /**< reason for reject */
192+
{
193+
JERRY_ASSERT (ecma_is_promise (obj_p));
194+
195+
if (!(ecma_promise_get_flags (obj_p) & ECMA_PROMISE_HANDLED))
196+
{
197+
jerry_port_report_unhandled_promise_rejection (ecma_make_object_value (obj_p), reason);
198+
}
199+
} /* ecma_promise_track_rejection */
200+
184201
/**
185202
* Reject a Promise with a reason.
186203
*
@@ -208,6 +225,7 @@ ecma_reject_promise (ecma_value_t promise, /**< promise */
208225
promise_p->reactions = ecma_new_collection ();
209226

210227
ecma_collection_destroy (reactions);
228+
ecma_promise_track_rejection (obj_p, reason);
211229
} /* ecma_reject_promise */
212230

213231
/**
@@ -818,10 +836,14 @@ ecma_promise_do_then (ecma_value_t promise, /**< the promise which call 'then' *
818836
{
819837
/* 9. */
820838
ecma_value_t reason = ecma_promise_get_result (promise_obj_p);
839+
ecma_promise_track_rejection (promise_obj_p, reason);
821840
ecma_enqueue_promise_reaction_job (ecma_make_object_value (result_capability_obj_p), on_rejected, reason);
822841
ecma_free_value (reason);
823842
}
824843

844+
/* ES11: 11. */
845+
promise_p->header.u.class_prop.extra_info |= ECMA_PROMISE_HANDLED;
846+
825847
/* 10. */
826848
return ecma_copy_value (capability_p->header.u.class_prop.u.promise);
827849
} /* ecma_promise_do_then */

jerry-core/ecma/operations/ecma-promise-object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ typedef enum
3434
ECMA_PROMISE_IS_PENDING = (1 << 0), /**< pending state */
3535
ECMA_PROMISE_IS_FULFILLED = (1 << 1), /**< fulfilled state */
3636
ECMA_PROMISE_ALREADY_RESOLVED = (1 << 2), /**< already resolved */
37+
ECMA_PROMISE_HANDLED = (1 << 3), /**< ES11: 25.6.6 [[PromiseIsHandled]] internal slot */
3738
} ecma_promise_flags_t;
3839

3940
/**

jerry-core/include/jerryscript-port.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,18 @@ size_t jerry_port_normalize_path (const char *in_path_p,
252252
*/
253253
jerry_value_t jerry_port_get_native_module (jerry_value_t name);
254254

255+
/**
256+
* Report the reason of the unhandled promise rejections.
257+
*
258+
* Note:
259+
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
260+
* is enabled.
261+
*
262+
* @param promise rejected promise.
263+
* @param reason reason of the rejection.
264+
*/
265+
void jerry_port_report_unhandled_promise_rejection (jerry_value_t promise, jerry_value_t reason);
266+
255267
/**
256268
* @}
257269
*/

jerry-port/default/default-promise.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* Copyright JS Foundation and other contributors, http://js.foundation
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
#include "jerryscript-port.h"
17+
#include "jerryscript-port-default.h"
18+
19+
/**
20+
* Default implementation of jerry_port_report_unhandled_promise_rejection.
21+
* Prints the reason of the unhandled rejections.
22+
*
23+
* This function called when:
24+
* - A promise is rejected without any handlers
25+
* - A handler is added to a rejected promise for the first time
26+
*/
27+
void
28+
jerry_port_report_unhandled_promise_rejection (const jerry_value_t promise, /**< rejected promise */
29+
const jerry_value_t reason) /**< reason of the rejection */
30+
{
31+
(void) promise;
32+
33+
jerry_value_t reason_to_string = jerry_value_to_string (reason);
34+
jerry_size_t req_sz = jerry_get_utf8_string_size (reason_to_string);
35+
JERRY_VLA (jerry_char_t, str_buf_p, req_sz + 1);
36+
jerry_string_to_utf8_char_buffer (reason_to_string, str_buf_p, req_sz);
37+
str_buf_p[req_sz] = '\0';
38+
39+
jerry_release_value (reason_to_string);
40+
41+
jerry_port_log (jerry_port_default_get_log_level (), "Uncaught (in promise) %s\n", str_buf_p);
42+
} /* jerry_port_report_unhandled_promise_rejection */

targets/esp-idf/promise.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* Copyright JS Foundation and other contributors, http://js.foundation
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
#include "jerryscript-port.h"
17+
18+
/**
19+
* Report the reason of the unhandled promise rejections.
20+
*
21+
* Note:
22+
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
23+
* is enabled.
24+
*
25+
* @param promise rejected promise.
26+
* @param reason reason of the rejection.
27+
*/
28+
void jerry_port_report_unhandled_promise_rejection (jerry_value_t promise, jerry_value_t reason)
29+
{
30+
(void) promise;
31+
32+
jerry_value_t reason_to_string = jerry_value_to_string (reason);
33+
jerry_size_t req_sz = jerry_get_utf8_string_size (reason_to_string);
34+
jerry_char_t str_buf_p[req_sz + 1];
35+
jerry_string_to_utf8_char_buffer (reason_to_string, str_buf_p, req_sz);
36+
str_buf_p[req_sz] = '\0';
37+
38+
jerry_release_value (reason_to_string);
39+
40+
jerry_port_log (jerry_port_default_get_log_level (), "Uncaught (in promise) %s\n", str_buf_p);
41+
} /* jerry_port_report_unhandled_promise_rejection */

targets/nuttx-stm32f4/jerry_port.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,29 @@ jerry_port_get_current_context (void)
227227
{
228228
return current_context_p;
229229
} /* jerry_port_get_current_context */
230+
231+
/**
232+
* Report the reason of the unhandled promise rejections.
233+
*
234+
* Note:
235+
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
236+
* is enabled.
237+
*
238+
* @param promise rejected promise.
239+
* @param reason reason of the rejection.
240+
*/
241+
void
242+
jerry_port_report_unhandled_promise_rejection (jerry_value_t promise, jerry_value_t reason)
243+
{
244+
(void) promise;
245+
246+
jerry_value_t reason_to_string = jerry_value_to_string (reason);
247+
jerry_size_t req_sz = jerry_get_utf8_string_size (reason_to_string);
248+
jerry_char_t str_buf_p[req_sz + 1];
249+
jerry_string_to_utf8_char_buffer (reason_to_string, str_buf_p, req_sz);
250+
str_buf_p[req_sz] = '\0';
251+
252+
jerry_release_value (reason_to_string);
253+
254+
jerry_port_log (jerry_log_level, "Uncaught (in promise) %s\n", str_buf_p);
255+
} /* jerry_port_report_unhandled_promise_rejection */

0 commit comments

Comments
 (0)