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):
- Sources are loaded seemingly randomly
- As sources are loaded, the code in their global context is executed (which is technically normal behavior)
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.