jerryscript/tests/unit-core/test-promise-callback.c
Szilagyi Adam 4924f9fd31
Remove ES_NEXT macro (#4915)
- remove all '#JERRY_ESNEXT' macro
- remove 5.1 build profile, update test runner accordingly (Note: all builtins are turn on by default)
- move tests from tests/jerry/esnext into tests/jerry, concatenate files with same names
- add skiplist to some snapshot tests that were supported only in 5.1
- fix doxygen issues that were hidden before (bc. of es.next macro)

Co-authored-by: Martin Negyokru negyokru@inf.u-szeged.hu
JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
2022-01-31 16:46:00 +01:00

361 lines
12 KiB
C

/* 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.h"
#include "test-common.h"
/* Note: RS = ReSolve, RJ = ReJect */
typedef enum
{
C = JERRY_PROMISE_EVENT_CREATE, /**< same as JERRY_PROMISE_CALLBACK_CREATE with undefined value */
RS = JERRY_PROMISE_EVENT_RESOLVE, /**< same as JERRY_PROMISE_CALLBACK_RESOLVE */
RJ = JERRY_PROMISE_EVENT_REJECT, /**< same as JERRY_PROMISE_CALLBACK_REJECT */
RSF = JERRY_PROMISE_EVENT_RESOLVE_FULFILLED, /**< same as JERRY_PROMISE_EVENT_RESOLVE_FULFILLED */
RJF = JERRY_PROMISE_EVENT_REJECT_FULFILLED, /**< same as JERRY_PROMISE_EVENT_REJECT_FULFILLED */
RWH = JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER, /**< same as JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER */
CHA = JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED, /**< same as JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED */
BR = JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB, /**< same as JERRY_PROMISE_CALLBACK_BEFORE_REACTION_JOB */
AR = JERRY_PROMISE_EVENT_AFTER_REACTION_JOB, /**< same as JERRY_PROMISE_CALLBACK_AFTER_REACTION_JOB */
A = JERRY_PROMISE_EVENT_ASYNC_AWAIT, /**< same as JERRY_PROMISE_CALLBACK_ASYNC_AWAIT */
BRS = JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE, /**< same as JERRY_PROMISE_CALLBACK_ASYNC_BEFORE_RESOLVE */
BRJ = JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT, /**< same as JERRY_PROMISE_CALLBACK_ASYNC_BEFORE_REJECT */
ARS = JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE, /**< same as JERRY_PROMISE_CALLBACK_ASYNC_AFTER_RESOLVE */
ARJ = JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT, /**< same as JERRY_PROMISE_CALLBACK_ASYNC_AFTER_REJECT */
CP = UINT8_MAX - 1, /**< same as JERRY_PROMISE_CALLBACK_CREATE with Promise value */
E = UINT8_MAX, /**< marks the end of the event list */
} jerry_promise_callback_event_abbreviations_t;
static int user;
static const uint8_t *next_event_p;
static void
promise_callback (jerry_promise_event_type_t event_type, /**< event type */
const jerry_value_t object, /**< target object */
const jerry_value_t value, /**< optional argument */
void *user_p) /**< user pointer passed to the callback */
{
TEST_ASSERT (user_p == (void *) &user);
switch (event_type)
{
case JERRY_PROMISE_EVENT_CREATE:
{
TEST_ASSERT (jerry_value_is_promise (object));
if (jerry_value_is_undefined (value))
{
break;
}
TEST_ASSERT (jerry_value_is_promise (value));
TEST_ASSERT (*next_event_p++ == CP);
return;
}
case JERRY_PROMISE_EVENT_RESOLVE:
case JERRY_PROMISE_EVENT_REJECT:
case JERRY_PROMISE_EVENT_RESOLVE_FULFILLED:
case JERRY_PROMISE_EVENT_REJECT_FULFILLED:
case JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER:
{
TEST_ASSERT (jerry_value_is_promise (object));
break;
}
case JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED:
case JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB:
case JERRY_PROMISE_EVENT_AFTER_REACTION_JOB:
{
TEST_ASSERT (jerry_value_is_promise (object));
TEST_ASSERT (jerry_value_is_undefined (value));
break;
}
case JERRY_PROMISE_EVENT_ASYNC_AWAIT:
{
TEST_ASSERT (jerry_value_is_object (object));
TEST_ASSERT (jerry_value_is_promise (value));
break;
}
default:
{
TEST_ASSERT (event_type == JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE
|| event_type == JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT
|| event_type == JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE
|| event_type == JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT);
TEST_ASSERT (jerry_value_is_object (object));
break;
}
}
TEST_ASSERT (*next_event_p++ == (uint8_t) event_type);
} /* promise_callback */
static void
run_eval (const uint8_t *event_list_p, /**< event list */
const char *source_p) /**< source code */
{
next_event_p = event_list_p;
jerry_value_t result = jerry_eval ((const jerry_char_t *) source_p, strlen (source_p), 0);
TEST_ASSERT (!jerry_value_is_exception (result));
jerry_value_free (result);
result = jerry_run_jobs ();
TEST_ASSERT (!jerry_value_is_exception (result));
jerry_value_free (result);
TEST_ASSERT (*next_event_p == UINT8_MAX);
} /* run_eval */
int
main (void)
{
TEST_INIT ();
/* The test system enables this feature when Promises are enabled. */
TEST_ASSERT (jerry_feature_enabled (JERRY_FEATURE_PROMISE_CALLBACK));
jerry_init (JERRY_INIT_EMPTY);
jerry_promise_event_filter_t filters =
(JERRY_PROMISE_EVENT_FILTER_CREATE | JERRY_PROMISE_EVENT_FILTER_RESOLVE | JERRY_PROMISE_EVENT_FILTER_REJECT
| JERRY_PROMISE_EVENT_FILTER_ERROR | JERRY_PROMISE_EVENT_FILTER_REACTION_JOB
| JERRY_PROMISE_EVENT_FILTER_ASYNC_MAIN | JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB);
jerry_promise_on_event (filters, promise_callback, (void *) &user);
/* Test promise creation. */
static uint8_t events1[] = { C, C, C, E };
run_eval (events1,
"'use strict'\n"
"new Promise((res, rej) => {})\n"
"new Promise((res, rej) => {})\n"
"new Promise((res, rej) => {})\n");
/* Test then call. */
static uint8_t events2[] = { C, CP, E };
run_eval (events2,
"'use strict'\n"
"var promise = new Promise((res, rej) => {})\n"
"promise.then(() => {}, () => {})\n");
/* Test then call with extended Promise. */
static uint8_t events3[] = { C, C, E };
run_eval (events3,
"'use strict'\n"
"var P = class extends Promise {}\n"
"var promise = new P((res, rej) => {})\n"
"promise.then(() => {})\n");
/* Test resolve and reject calls. */
static uint8_t events4[] = { C, C, RS, RJ, RWH, E };
run_eval (events4,
"'use strict'\n"
"var resolve\n"
"var reject\n"
"new Promise((res, rej) => resolve = res)\n"
"new Promise((res, rej) => reject = rej)\n"
"resolve(1)\n"
"reject(1)\n");
/* Test then and resolve calls. */
static uint8_t events5[] = { C, CP, RS, BR, RS, AR, E };
run_eval (events5,
"'use strict'\n"
"var resolve\n"
"var promise = new Promise((res, rej) => resolve = res)\n"
"promise.then(() => {})\n"
"resolve(1)\n");
/* Test resolve and then calls. */
static uint8_t events6[] = { C, RS, CP, BR, RS, AR, E };
run_eval (events6,
"'use strict'\n"
"var promise = new Promise((res, rej) => res(1))\n"
"promise.then(() => {})\n");
/* Test Promise.resolve. */
static uint8_t events7[] = { C, RS, CP, BR, RS, AR, E };
run_eval (events7, "Promise.resolve(4).then(() => {})\n");
/* Test Promise.reject. */
static uint8_t events8[] = { C, RJ, RWH, CP, CHA, BR, RJ, RWH, AR, E };
run_eval (events8, "Promise.reject(4).catch(() => { throw 'Error' })\n");
/* Test Promise.race without resolve */
static uint8_t events9[] = { C, C, C, CP, CP, E };
run_eval (events9,
"'use strict'\n"
"var p1 = new Promise((res, rej) => {})\n"
"var p2 = new Promise((res, rej) => {})\n"
"Promise.race([p1,p2])\n");
/* Test Promise.race with resolve. */
static uint8_t events10[] = { C, RS, C, RJ, RWH, C, CP, CP, CHA, BR, RS, RS, AR, BR, RJF, RS, AR, E };
run_eval (events10,
"'use strict'\n"
"var p1 = new Promise((res, rej) => res(1))\n"
"var p2 = new Promise((res, rej) => rej(1))\n"
"Promise.race([p1,p2])\n");
/* Test Promise.all without resolve. */
static uint8_t events11[] = { C, C, C, CP, CP, E };
run_eval (events11,
"'use strict'\n"
"var p1 = new Promise((res, rej) => {})\n"
"var p2 = new Promise((res, rej) => {})\n"
"Promise.all([p1,p2])\n");
/* Test Promise.all with resolve. */
static uint8_t events12[] = { C, RS, C, RJ, RWH, C, CP, CP, CHA, BR, RS, AR, BR, RJ, RWH, RS, AR, E };
run_eval (events12,
"'use strict'\n"
"var p1 = new Promise((res, rej) => res(1))\n"
"var p2 = new Promise((res, rej) => rej(1))\n"
"Promise.all([p1,p2])\n");
/* Test async function. */
static uint8_t events13[] = { C, RS, E };
run_eval (events13,
"'use strict'\n"
"async function f() {}\n"
"f()\n");
/* Test await with resolved Promise. */
static uint8_t events14[] = { C, RS, A, C, BRS, RS, ARS, E };
run_eval (events14,
"'use strict'\n"
"async function f(p) { await p }\n"
"f(Promise.resolve(1))\n");
/* Test await with non-Promise value. */
static uint8_t events15[] = { C, RS, A, C, BRS, C, RS, A, ARS, BRS, RS, ARS, E };
run_eval (events15,
"'use strict'\n"
"async function f(p) { await p; await 'X' }\n"
"f(Promise.resolve(1))\n");
/* Test await with rejected Promise. */
static uint8_t events16[] = { C, RJ, RWH, A, CHA, C, BRJ, C, RS, RS, ARJ, E };
run_eval (events16,
"'use strict'\n"
"async function f(p) { try { await p; } catch (e) { Promise.resolve(1) } }\n"
"f(Promise.reject(1))\n");
/* Test async generator function. */
static uint8_t events17[] = { C, RS, C, A, BRS, RS, ARS, E };
run_eval (events17,
"'use strict'\n"
"async function *f(p) { await p; return 4 }\n"
"f(Promise.resolve(1)).next()\n");
/* Test yield* operation. */
static uint8_t events18[] = { C, C, RS, A, BRS, C, RS, A, ARS, BRS, RS, ARS, E };
run_eval (events18,
"'use strict'\n"
"async function *f(p) { yield 1 }\n"
"async function *g() { yield* f() }\n"
"g().next()\n");
/* Test multiple fulfill operations. */
static uint8_t events19[] = { C, RS, RSF, RJF, E };
run_eval (events19,
"'use strict'\n"
"var resolve, reject\n"
"var p1 = new Promise((res, rej) => { resolve = res, reject = rej })\n"
"resolve(1)\n"
"resolve(2)\n"
"reject(3)\n");
/* Test multiple fulfill operations. */
static uint8_t events20[] = { C, RJ, RWH, RSF, RJF, E };
run_eval (events20,
"'use strict'\n"
"var resolve, reject\n"
"var p1 = new Promise((res, rej) => { resolve = res, reject = rej })\n"
"reject(1)\n"
"resolve(2)\n"
"reject(3)\n");
/* Test catch handler added later is reported only once. */
static uint8_t events21[] = { C, RJ, RWH, CP, CHA, CP, CP, BR, RS, AR, BR, RS, AR, BR, RS, AR, E };
run_eval (events21,
"'use strict'\n"
"var rej = Promise.reject(4)\n"
"rej.catch(() => {})\n"
"rej.catch(() => {})\n"
"rej.catch(() => {})\n");
/* Test catch handler added later is reported only once. */
static uint8_t events22[] = { C, RJ, RWH, A, CHA, C, BRJ, A, ARJ, BRJ, RJ, RWH, ARJ, E };
run_eval (events22,
"'use strict'\n"
"async function f(p) { try { await p; } catch(e) { await p; } }"
"f(Promise.reject(4))\n");
/* Test chained then. */
static uint8_t events23[] = { C, RJ, RWH, CP, CHA, CP, BR, RJ, AR, BR, RS, AR, E };
run_eval (events23,
"'use strict'\n"
"var p = Promise.reject(0)\n"
"p.then(() => {}).catch(() => {})\n");
/* Test disabled filters. */
jerry_promise_on_event (JERRY_PROMISE_EVENT_FILTER_DISABLE, promise_callback, (void *) &user);
static uint8_t events24[] = { E };
run_eval (events24,
"'use strict'\n"
"async function f(p) { await p }"
"f(Promise.resolve(1))\n");
/* Test filtered events. */
filters = JERRY_PROMISE_EVENT_FILTER_REACTION_JOB | JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB;
jerry_promise_on_event (filters, promise_callback, (void *) &user);
static uint8_t events25[] = { BR, AR, BRS, ARS, E };
run_eval (events25,
"'use strict'\n"
"async function f(p) { await p }"
"f(Promise.resolve(1).then(() => {}))\n");
jerry_cleanup ();
return 0;
} /* main */