| 1438 | } |
| 1439 | |
| 1440 | GErrorResult<> GjsContextPrivate::eval(const char* script, size_t script_len, |
| 1441 | const char* filename, |
| 1442 | int* exit_status_p) { |
| 1443 | AutoResetExit reset(this); |
| 1444 | |
| 1445 | bool auto_profile = auto_profile_enter(); |
| 1446 | |
| 1447 | Gjs::AutoMainRealm ar{this}; |
| 1448 | |
| 1449 | JS::RootedValue retval(m_cx); |
| 1450 | bool ok = eval_with_scope(nullptr, script, script_len, filename, &retval); |
| 1451 | |
| 1452 | // If there are no errors and the mainloop hook is set, call it. |
| 1453 | if (ok && m_main_loop_hook) |
| 1454 | ok = run_main_loop_hook(); |
| 1455 | |
| 1456 | bool exiting = false; |
| 1457 | |
| 1458 | // Spin the internal loop until the main loop hook is set or no holds |
| 1459 | // remain. |
| 1460 | // If the main loop returns false we cannot guarantee the state of our |
| 1461 | // promise queue (a module promise could be pending) so instead of draining |
| 1462 | // draining the queue we instead just exit. |
| 1463 | if (ok && !m_main_loop.spin(this)) { |
| 1464 | exiting = true; |
| 1465 | } |
| 1466 | |
| 1467 | // If the hook has been set again, enter a loop until an error is |
| 1468 | // encountered or the main loop is quit. |
| 1469 | while (ok && !exiting && m_main_loop_hook) { |
| 1470 | ok = run_main_loop_hook(); |
| 1471 | |
| 1472 | // Additional jobs could have been enqueued from the |
| 1473 | // main loop hook |
| 1474 | if (ok && !m_main_loop.spin(this)) { |
| 1475 | exiting = true; |
| 1476 | } |
| 1477 | } |
| 1478 | |
| 1479 | // The promise job queue should be drained even on error, to finish |
| 1480 | // outstanding async tasks before the context is torn down. Drain after |
| 1481 | // uncaught exceptions have been reported since draining runs callbacks. |
| 1482 | // We do not drain if we are exiting. |
| 1483 | if (!ok && !exiting) { |
| 1484 | JS::AutoSaveExceptionState saved_exc(m_cx); |
| 1485 | ok = run_jobs_fallible() && ok; |
| 1486 | } |
| 1487 | |
| 1488 | auto_profile_exit(auto_profile); |
| 1489 | |
| 1490 | uint8_t out_code; |
| 1491 | GErrorResult<> result = handle_exit_code(ok, "Script", filename, &out_code); |
| 1492 | |
| 1493 | if (exit_status_p) { |
| 1494 | if (result.isOk() && retval.isInt32()) { |
| 1495 | int code = retval.toInt32(); |
| 1496 | gjs_debug(GJS_DEBUG_CONTEXT, |
| 1497 | "Script returned integer code %d", code); |
no test coverage detected