Discord
Login
Community
DARK THEME

Incorrect order of sources

microStudio seems unable to use sources in a proper order.

I create a javascript project and in "main" source I put this:

init = function() {
    screen.clear()
}

update = function() {
}

draw = function() {
    screen.drawText("main", 0,0,20,"white")
}

Then I add another source "main2" and add this:

init = function() {
    screen.clear()
}

update = function() {
}

draw = function() {
    screen.drawText("main2", 0,0,20,"white")
}

Running the app will sometimes print "main" and sometimes print "main2". In a real project it means sometimes it will error out and sometimes not. I am using Vivaldi on Windows 11. The issue happens using microscript or Lua too.

I confirm that I also observed this effect in MicroScript2.

Typically, you do not write code with identically named functions - because one of the functions will be obscured. The entire Javascript code is interpreted by the browser and the order in which it will be interpreted depends on it

  • the order in which the browser will ask the server for files (http/2 has many options)
  • in what order will the server send the response (connection load status).
  • the state of the browser's cache memory (the requested files may be in the cache and then the browser does not send requests for them).

Right-click on the project address above the field where you can see the project result - select run in "private mode". Now my project always behaves the same.

I just used similar code so it would run rather than give an error, but the issue is still there without having the same function names.

I tried right-clicking the project address, and there was no "private mode" but I have "Open Link in Private Window". Using that I still get the issue.

Show this code with race conditions in which there is no function overriding.

See how MicroStudio works when you run the code. When I press the spacebar in the source, MicroStudio analyzes the code and changes the bytecode to take into account the changes (it doesn't always work).

When I run your code >> https://microstudio.io/i/Loginus/main/ go to the source and press space. Go to the second source and press spacebar. Go back to the first source and press spacebar. For me, after each modification of the code, the "draw" function called changes to the one from the source that I recently modified.

Here's another example using microScript this time.

In source "main" i have

init = function()
   print('init')
end

update = function()
end

draw = function()
end

In source "source" i have

print('source')

in source "source2" i have

print('source2')

I press the "run" button and I get output

microScript 2.0
source2
source
init

Restart it a few times and I get

microScript 2.0
source
source2
init

If I just close the tab and re-open the project it's not guaranteed one order or the other. Nothing in this example involves a source being the last one edited (this is all without editing).

Here's a more real example, using code the way I'd normally set up a game. In source "game" I have:

game = object
    title = "Foo Bar: The Return of Baz"
end

// wrapping to keep some basic engine stuff out of main code

init = function()
    // do some stuff    
    if game.init then
        game.init()
    end
    // do some more stuff
end

update = function()
    // do some stuff    
    if game.update then
        game.update()
    end
    // do some more stuff
end

draw = function()
    // do some stuff    
    if game.draw then
        game.draw()
    end
    // do some more stuff
end

In source "main" I have:

game.init = function()
    print("game.init!")
end

game.update = function()
end

game.draw = function()
end

I get one of two results, without editing a source:

microScript 2.0
game.init!
microScript 2.0
Warning: game is not defined, will be initialized to an empty object, in file "main" at line 1, column 11

I confirm this effect on Firefox 115. As for the variable not existing, I also saw this problem, but I explained it this way:

  • MicroStudio Initializes its parameters and determines that the "update" and "draw" functions are to be executed 60 times per second.
  • MicroStudio proceeds to code parsing and image downloading.
  • it's time to execute the "update" and "draw" functions, the code analysis is still in progress and some of the data may not exist, the function refers to non-existent data - MicroStudio displays an error.
  • MicroStudio finishes parsing the code.

Apparently I explained this mistake incorrectly. Whenever this error appeared, I added a loop to the code in the "init" section that checked whether all objects were ready for work.

I modified your example code here: https://microstudio.io/i/Loginus/race/ Tests in Firefox 115. When I modify the code, in the file named "source"+number, this piece of code is analyzed first. And it will be displayed in the console first. Another refresh and the result is 95% correct. in the remaining 5% there is always an error message and the variable "s" does not exist.

In Chrome 109 - it's worse, after editing the code in the "source" + number file, this code appears first. Refresh - and there is a 50% chance that the order of displaying subtitles in the console will change or an error will appear.

@gilles explain how to prevent this error!!!

I've done some testing myself and this is what I observe (apologies if this is explained confusingly):

  1. Sources are loaded seemingly randomly
  2. As sources are loaded, the code in their global context is executed (which is technically normal behavior)
  3. init draw and update are called after all sources become available

Meaning that code outside of the normal callbacks can be put in the state where it is loaded before a dependency is. You can avoid this by putting all the code inside of your sources in a function and not leaving any in the global context. You can then run those functions in the desired order.

This code should work the same every time without any errors.

game

function game()

    gameTitle = "The Mystery of Motel 77"
    -- and other stuff

end

main

function init()

    game()

    print(gameTitle)

end

function update()

end

function draw()

end

Putting print(gameTitle) outside of init and not putting all of the code in game into a function results in the output being sometimes undefined. I'm not sure how well if at all this translates into JS and MicroScript but it might. I use Lua primarily.

TL;DR Wrap everything in your sources in functions and call those functions from init in order of desired execution

EDIT: I've realized this works better as a a fix for a preexisting game as editing code will not reflect changes unless restarted and/or completely break it. Just avoid calling or accessing something outside of init update and draw and it should all work. You might still need to do my initial solution in some cases, though.

Post a reply

Progress

Status

Preview
Cancel
Post
Validate your e-mail address to participate in the community