mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Fix local variables default values when the wait action is used (#6715)
This commit is contained in:
@@ -709,11 +709,14 @@ EventsCodeGenerator::GenerateCallback(
|
||||
const gd::String actionsDeclarationsCode =
|
||||
GenerateObjectsDeclarationCode(callbackContext);
|
||||
|
||||
const gd::String callbackCode =
|
||||
callbackFunctionName + " = function (" +
|
||||
GenerateEventsParameters(callbackContext) + ") {\n" +
|
||||
restoreLocalVariablesCode +
|
||||
actionsDeclarationsCode + actionsCode + "}\n";
|
||||
const gd::String clearLocalVariablesCode =
|
||||
GenerateLocalVariablesStackAccessor() + ".length = 0;\n";
|
||||
|
||||
const gd::String callbackCode = callbackFunctionName + " = function (" +
|
||||
GenerateEventsParameters(callbackContext) +
|
||||
") {\n" + restoreLocalVariablesCode +
|
||||
actionsDeclarationsCode + actionsCode +
|
||||
clearLocalVariablesCode + "}\n";
|
||||
|
||||
AddCustomCodeOutsideMain(callbackCode);
|
||||
|
||||
|
@@ -23,6 +23,15 @@ describe('libGD.js - GDJS Async Code Generation integration tests', function ()
|
||||
});
|
||||
|
||||
const generateAndRunEventsForLayout = (events, logCode = false) => {
|
||||
const { runtimeScene, runCompiledEvents } = generateEventsForLayout(
|
||||
events,
|
||||
logCode
|
||||
);
|
||||
runCompiledEvents();
|
||||
return runtimeScene;
|
||||
};
|
||||
|
||||
const generateEventsForLayout = (events, logCode = false) => {
|
||||
const serializedProjectElement = new gd.SerializerElement();
|
||||
project.serializeTo(serializedProjectElement);
|
||||
|
||||
@@ -46,8 +55,10 @@ describe('libGD.js - GDJS Async Code Generation integration tests', function ()
|
||||
serializedProjectElement.delete();
|
||||
serializedSceneElement.delete();
|
||||
|
||||
runCompiledEvents(gdjs, runtimeScene, []);
|
||||
return runtimeScene;
|
||||
return {
|
||||
runtimeScene,
|
||||
runCompiledEvents: () => runCompiledEvents(gdjs, runtimeScene, []),
|
||||
};
|
||||
};
|
||||
|
||||
describe('Basics', () => {
|
||||
@@ -364,6 +375,77 @@ describe('libGD.js - GDJS Async Code Generation integration tests', function ()
|
||||
).toBe(2 + 5);
|
||||
});
|
||||
|
||||
it('can execute async events without side effect on local variables of the scene', function () {
|
||||
// Try to reproduce a bug where the async events were not clearing
|
||||
// the local variable stack.
|
||||
// Local variables declarations were added over a not empty stack
|
||||
// whereas actions, conditions and expressions were still using
|
||||
// the expected stack index.
|
||||
|
||||
// The following comments apply to the second run of events.
|
||||
scene.getVariables().insertNew('SuccessVariable', 0).setValue(0);
|
||||
const { runtimeScene, runCompiledEvents } = generateEventsForLayout([
|
||||
{
|
||||
type: 'BuiltinCommonInstructions::Standard',
|
||||
// Expected: Define local variables at stack index 0.
|
||||
// Actual: Define local variables at stack index 1.
|
||||
variables: [{ name: 'MyLocalVariable', type: 'number', value: 0 }],
|
||||
conditions: [],
|
||||
actions: [
|
||||
// Modify local variables at stack index 0.
|
||||
{
|
||||
type: { value: 'SetNumberVariable' },
|
||||
parameters: ['MyLocalVariable', '=', '456'],
|
||||
},
|
||||
],
|
||||
},
|
||||
// Expected: Pop local variables at stack index 0.
|
||||
// Actual: Pop local variables at stack index 1.
|
||||
{
|
||||
type: 'BuiltinCommonInstructions::Standard',
|
||||
// Expected: Define local variables at stack index 0.
|
||||
// Actual: Define local variables at stack index 1.
|
||||
variables: [{ name: 'MyLocalVariable', type: 'number', value: 123 }],
|
||||
conditions: [],
|
||||
actions: [
|
||||
// Get local variables at stack index 0.
|
||||
// Expected : The declaration value
|
||||
// Actual : The value set by the previous event: 456
|
||||
{
|
||||
type: { value: 'SetNumberVariable' },
|
||||
parameters: ['SuccessVariable', '=', 'MyLocalVariable'],
|
||||
},
|
||||
// The only purpose of the wait is to trigger context switches.
|
||||
{
|
||||
type: { value: 'Wait' },
|
||||
parameters: ['1'],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
// Run scene events a first time.
|
||||
runCompiledEvents();
|
||||
expect(
|
||||
runtimeScene.getVariables().get('SuccessVariable').getAsNumber()
|
||||
).toBe(123);
|
||||
|
||||
// Process the tasks (after faking it's finished).
|
||||
// The context switching happens here.
|
||||
runtimeScene.getAsyncTasksManager().markAllFakeAsyncTasksAsFinished();
|
||||
runtimeScene.getAsyncTasksManager().processTasks(runtimeScene);
|
||||
|
||||
// This test can't actually reproduce the issue because
|
||||
// `runCompiledEvents()` instantiate `gdjs.SceneCode.localVariables`
|
||||
// at every call.
|
||||
|
||||
// Run scene events a second time.
|
||||
runCompiledEvents();
|
||||
expect(
|
||||
runtimeScene.getVariables().get('SuccessVariable').getAsNumber()
|
||||
).toBe(123);
|
||||
});
|
||||
|
||||
it('generates an async fork that shares a scene variable a non-async sub-event', function () {
|
||||
scene.getVariables().insertNew('SuccessVariable', 0).setValue(0);
|
||||
scene.getVariables().insertNew('MySceneVariable', 0).setValue(1);
|
||||
|
Reference in New Issue
Block a user