Skip to content
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
2 changes: 2 additions & 0 deletions src/vm_builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -7215,6 +7215,7 @@ static RValue builtin_ini_close(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE
if (runner->currentIni == nullptr) {
free(runner->currentIniPath);
runner->currentIniPath = nullptr;
runner->currentIniDirty = false;
// No ini open = empty
return RValue_makeOwnedString(safeStrdup(""));
}
Expand All @@ -7227,6 +7228,7 @@ static RValue builtin_ini_close(VMContext* ctx, MAYBE_UNUSED RValue* args, MAYBE
FileSystem* fs = runner->fileSystem;
fs->vtable->writeFileText(fs, runner->currentIniPath, serialized);
}
runner->currentIniDirty = false;

// Move to cache instead of freeing
discardIniCache(runner);
Expand Down
1 change: 1 addition & 0 deletions src/web/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void platformLog(const logType type, const char *format, va_list va) {
out = stdout;
break;
case LOG_TYPE_WARNING:
out = stdout;
fputs("Warning: ", out);
break;
case LOG_TYPE_ERROR:
Expand Down
18 changes: 18 additions & 0 deletions tests/test_retrom_web_host.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
class RetromWebHostTests(unittest.TestCase):
def setUp(self) -> None:
self.source = (ROOT / "src/web/main.c").read_text(encoding="utf-8")
self.builtins = (ROOT / "src/vm_builtins.c").read_text(encoding="utf-8")
self.cmake = (ROOT / "CMakeLists.txt").read_text(encoding="utf-8")
self.release_workflow = (ROOT / ".github/workflows/rpg-runtime-release.yml").read_text(encoding="utf-8")
self.build_script = (ROOT / ".github/rpg-runtime/build-web.sh").read_text(encoding="utf-8")
Expand All @@ -35,6 +36,16 @@ def test_ready_and_exit_are_explicit_host_events(self) -> None:
self.assertEqual(self.source.count("type: 'runnerReady'"), 1)
self.assertEqual(self.source.count("type: 'runnerExit'"), 1)

def test_web_warnings_do_not_use_the_browser_error_stream(self) -> None:
start = self.source.index("void platformLog")
end = self.source.index("// Configures the sample rate", start)
logger = self.source[start:end]
warning = logger.index("case LOG_TYPE_WARNING:")
error = logger.index("case LOG_TYPE_ERROR:")
warning_body = logger[warning:error]
self.assertIn("out = stdout;", warning_body)
self.assertIn('fputs("Warning: ", out);', warning_body)

def test_web_exports_are_stable(self) -> None:
for name in (
"_setRunnerPaused", "_setGamepadConnected",
Expand All @@ -49,6 +60,13 @@ def test_checkpoint_is_bounded_and_requires_a_paused_frame_boundary(self) -> Non
self.assertIn('memcmp(bytes, "BSCP", 4) != 0', self.source)
self.assertIn("Runner_restoreStateJson(gRunner, json)", self.source)

def test_closing_a_dirty_ini_clears_the_transient_checkpoint_blocker(self) -> None:
start = self.builtins.index("static RValue builtin_ini_close")
end = self.builtins.index("static RValue builtin_ini_read_string", start)
close_body = self.builtins[start:end]
cache_move = close_body.index("runner->cachedIni = runner->currentIni;")
self.assertLess(close_body.index("runner->currentIniDirty = false;"), cache_move)

def test_release_workflow_supports_immutable_integration_candidates(self) -> None:
self.assertIn("(-rc\\.[1-9][0-9]*)?", self.release_workflow)
self.assertIn("prerelease+=(--prerelease)", self.release_workflow)
Expand Down
Loading