What is the JavaScript equivalent of C++ std::flush?

Tags: , ,



I am trying to port one of the programs I’ve written in my own programming language to the web using WebAssembly. However, I’ve run into a problem. Namely, one of my programs is supposed to print all the permutations of the digits of a number entered by the user. You can see the live version.
The problem is that, when you enter some number with a relatively large number of digits, such as “1234567”, even though the program starts finding permutations almost immediately, and prints them immediately into innerHTML, the browser doesn’t display any permutations at all until all of them are found. That’s not the desired behavior, the desired behavior is to print a permutation as soon as it’s found. How can I do that? The code I use for printing strings is here:

function printString(ptr) {
    let buffer=new Uint8Array(memory.buffer);
    let str="";
    while (buffer[ptr]) {
        str+=String.fromCharCode(buffer[ptr]);
        ptr++;
    }
    document.getElementById("format_as_code").innerHTML+=str;
}

Here is the code I am using to find the permutations:

/*
 * This will be a test to see whether calling JavaScript functions from AEC
 * works as expected. It will also attempt to expose as many potential compiler
 * bugs as possible by implementing the permutations algorithm.
 */

//So, those are JavaScript functions which I am planning to call from AEC:
Function printInt(Integer32 int) Which Returns Nothing Is External;
Function printString(CharacterPointer ptr) Which Returns Nothing Is External;
Function clearScreen() Which Returns Nothing Is External;

//JavaScript equivalent of C "strlen" is the "length" property of a string
// and there is, as far as I know, no way to call it from outside of JS.
//Nevertheless, I think I can easily write it myself.
Function strlen(CharacterPointer ptr) Which Returns Integer32 Does
    Return ValueAt(ptr) = 0 ?
                                0
                            :
                                1 + strlen(ptr + 1);
EndFunction

Integer32 originalNumberOfDigits[10];
Integer32 NDEBUG := 1;
Integer32 numberOfPermutations;

Function recursiveProcedure(CharacterPointer currentAttempt)
    Which Returns Nothing Does
    Integer32 lengthOfTheCurrentAttempt := strlen(currentAttempt);
    If not(NDEBUG) Then
        printString(
            "DEBUG: "recursiveProcedure" has been invoked with the argument: ""
            );
        printString(currentAttempt);
        printString("". "strlen" says it has length of ");
        printInt(lengthOfTheCurrentAttempt);
        printString(".n");
    EndIf
    Integer32 currentNumberOfDigits[10] :=
        {0, 0, 0, 0, 0,
         0, 0, 0, 0, 0};
    Integer32 i := 0;
    While i<lengthOfTheCurrentAttempt Loop
        currentNumberOfDigits[ValueAt(currentAttempt + i) - '0'] :=
            currentNumberOfDigits[ValueAt(currentAttempt + i) - '0'] + 1;
        i := i + 1;
    EndWhile
    If not(NDEBUG) Then
        i := 0;
        While i < 10 Loop
            printString("DEBUG: The current number has ");
            printInt(currentNumberOfDigits[i]);
            printString(" digits '");
            printInt(i);
            printString("'.n");
            i := i + 1;
        EndWhile
    EndIf
    i := 0;
    While i < 10 Loop
        If currentNumberOfDigits[i] > originalNumberOfDigits[i] Then
            If not(NDEBUG) Then
                printString("DEBUG: There are too many digits '");
                printInt(i);
                printString("', ending "recursiveProcedure".n");
            EndIf
            Return;
        EndIf
        i := i + 1;
    EndWhile
    Integer32 haveWeFoundAPermutation := 1;
    i := 0;
    While i < 10 Loop
        If currentNumberOfDigits[i] < originalNumberOfDigits[i] Then
            haveWeFoundAPermutation := 0;
        EndIf
        i := i + 1;
    EndWhile
    If haveWeFoundAPermutation Then
        printString("Permutation #");
        numberOfPermutations:=numberOfPermutations+1;
        printInt(numberOfPermutations);
        printString(": ");
        printString(currentAttempt);
        printString("n");
        Return;
    EndIf
    Character digitWeAreAdding := '0';
    While digitWeAreAdding < '9' + 1 Loop //The less-than-or-equal operator
                                          //">=" hasn't yet been implemented.
        Character newAttempt[12];
        i := 0;
        While i < 12 Loop
            If i < lengthOfTheCurrentAttempt Then
                newAttempt[i] := ValueAt(currentAttempt + i);
            Else
                newAttempt[i] := 0;
            EndIf
            i := i + 1;
        EndWhile
        newAttempt[lengthOfTheCurrentAttempt] := digitWeAreAdding;
        If currentNumberOfDigits[digitWeAreAdding - '0'] < 
            originalNumberOfDigits[digitWeAreAdding - '0'] Then //To speed
                                                                //things up
                                                                //a bit.
            recursiveProcedure(AddressOf(newAttempt[0]));
        EndIf
        digitWeAreAdding := digitWeAreAdding + 1;
    EndWhile
EndFunction

Function printPermutationsOfDigits(Integer32 original)
    Which Returns Nothing Does
    clearScreen();
    If original < 0 Then
        original := -original;
    EndIf
    printString("Printing all the permutations of digits of the number: ");
    printInt(original); //Unfortunately, the JavaScript standard library
                        //doesn't have "printf".
    printString("n");
    Integer32 i := 0;
    While i < 10 Loop
        originalNumberOfDigits[i] :=     0;
        i                         := i + 1;
    EndWhile
    If original = 0 Then
        originalNumberOfDigits[0] := 1;
    EndIf
    While original > 0 Loop
        originalNumberOfDigits[mod(original, 10)] :=
            originalNumberOfDigits[mod(original, 10)] + 1;
        original := original / 10;
    EndWhile
    If not(NDEBUG) Then
        i := 0;
        While i < 10 Loop
            printString("DEBUG: The original number has ");
            printInt(originalNumberOfDigits[i]);
            printString(" digits '");
            printInt(i);
            printString("'.n");
            i := i + 1;
        EndWhile
    EndIf
    numberOfPermutations := 0;
    recursiveProcedure("");
    printString("The end!");
EndFunction

Answer

The issue you are having is your code never gives the browser any time to update the UI. As others have pointed out, if you used a setTimeout in your code, you could give the browser some breathing room. But this would only work if the timeout occurred inside of recursiveProcedure and was used to call the next iteration of recursiveProcedure. This doesn’t seem very easy or viable. But there’s another solution:

Run your web assembly in a web worker.

Your HTML file would create a worker. Inside the worker you would require your was file and have your printString. printString would call back to the page to update the output. Something like this:

index.html

<script>
var myWorker = new Worker('worker.js');
// When we get a message from the worker, update the format_as_code element with the data sent
myWorker.onmessage = function(e) {
    document.getElementById("format_as_code").innerHTML += e.data;
}
</script>

worker.js

function printString(ptr) {
    let buffer=new Uint8Array(memory.buffer);
    let str="";
    while (buffer[ptr]) {
        str+=String.fromCharCode(buffer[ptr]);
        ptr++;
    }
    // We post back to the page the contents of the string
    postMessage(str);
}
// This is the file that contains your wasm compilation result
importScripts('wasm_compiled.js');


Source: stackoverflow