WASM: move save file encoding from JS into C.

The previous fix worked OK, but it was conceptually wrong. Puzzles
save files are better regarded as binary, not text: the length fields
are measured in bytes, so translating the file into a different
multibyte character encoding would invalidate them.

So it was wrong to fetch a C byte string containing the exactly right
binary data, then translate it into a Javascript string as if decoding
from UTF-8, then retranslate to a representation of a bytewise
encoding via encodeURIComponent, and then label the result as
application/octet-stream.

This probably wouldn't have caused any problems in practice, because I
don't remember any situation in which my save files use characters
outside printable ASCII (plus newline). But it's not actually
forbidden, so a save file might choose to do that some day, so that
UTF-8 decode/reencode hidden in the JS was a latent bug.

Now the URI-encoding is done on the C side, while we still know
exactly what the binary data ought to look like and can be sure we're
translating it byte for byte into the output encoding for the data:
URI. By the time the JS receives a string pointer from get_save_file,
it's already URI-encoded, which _guarantees_ that it's in ASCII and
won't be messed about with by Emscripten's UTF8ToString.
This commit is contained in:
Simon Tatham
2021-05-23 08:45:55 +01:00
parent 1c760b2ee8
commit f729f51e47
2 changed files with 46 additions and 6 deletions

View File

@ -379,8 +379,7 @@ function initPuzzle() {
"Click to download the "));
var a = document.createElement("a");
a.download = "puzzle.sav";
a.href = "data:application/octet-stream," +
encodeURIComponent(savefile_text);
a.href = "data:application/octet-stream," + savefile_text;
a.appendChild(document.createTextNode("saved-game file"));
dlg_form.appendChild(a);
dlg_form.appendChild(document.createTextNode("."));