scripting: Switch to standard async/await pattern

The original scripting framework was based on SpiderMonkey's
pre-standard generators, and was simply translated to the
corresponding standard syntax when updating it to work with
recent JS versions.

We can do even better by using the standard async/await pattern
instead of generators/yield.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1396
This commit is contained in:
Florian Müllner 2020-07-30 18:41:11 +02:00 committed by Georges Basile Stavracas Neto
parent 33ff3dc44f
commit a436226266
3 changed files with 52 additions and 53 deletions

View File

@ -70,7 +70,8 @@ let WINDOW_CONFIGS = [
{ width: 640, height: 480, alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha' }, { width: 640, height: 480, alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha' },
]; ];
function *run() { async function run() {
/* eslint-disable no-await-in-loop */
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview"); Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing"); Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview"); Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
@ -84,7 +85,7 @@ function *run() {
Scripting.scriptEvent('overviewShowDone'); Scripting.scriptEvent('overviewShowDone');
}); });
yield Scripting.sleep(1000); await Scripting.sleep(1000);
for (let i = 0; i < 2 * WINDOW_CONFIGS.length; i++) { for (let i = 0; i < 2 * WINDOW_CONFIGS.length; i++) {
// We go to the overview twice for each configuration; the first time // We go to the overview twice for each configuration; the first time
@ -92,49 +93,50 @@ function *run() {
// a clean set of numbers. // a clean set of numbers.
if ((i % 2) == 0) { if ((i % 2) == 0) {
let config = WINDOW_CONFIGS[i / 2]; let config = WINDOW_CONFIGS[i / 2];
yield Scripting.destroyTestWindows(); await Scripting.destroyTestWindows();
for (let k = 0; k < config.count; k++) { for (let k = 0; k < config.count; k++) {
yield Scripting.createTestWindow({ width: config.width, await Scripting.createTestWindow({ width: config.width,
height: config.height, height: config.height,
alpha: config.alpha, alpha: config.alpha,
maximized: config.maximized }); maximized: config.maximized });
} }
yield Scripting.waitTestWindows(); await Scripting.waitTestWindows();
yield Scripting.sleep(1000); await Scripting.sleep(1000);
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
} }
Scripting.scriptEvent('overviewShowStart'); Scripting.scriptEvent('overviewShowStart');
Main.overview.show(); Main.overview.show();
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
Main.overview.hide(); Main.overview.hide();
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
System.gc(); System.gc();
yield Scripting.sleep(1000); await Scripting.sleep(1000);
Scripting.collectStatistics(); Scripting.collectStatistics();
Scripting.scriptEvent('afterShowHide'); Scripting.scriptEvent('afterShowHide');
} }
yield Scripting.destroyTestWindows(); await Scripting.destroyTestWindows();
yield Scripting.sleep(1000); await Scripting.sleep(1000);
Main.overview.show(); Main.overview.show();
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
for (let i = 0; i < 2; i++) { for (let i = 0; i < 2; i++) {
Scripting.scriptEvent('applicationsShowStart'); Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates // eslint-disable-next-line require-atomic-updates
Main.overview.dash.showAppsButton.checked = true; Main.overview.dash.showAppsButton.checked = true;
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone'); Scripting.scriptEvent('applicationsShowDone');
// eslint-disable-next-line require-atomic-updates // eslint-disable-next-line require-atomic-updates
Main.overview.dash.showAppsButton.checked = false; Main.overview.dash.showAppsButton.checked = false;
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
} }
/* eslint-enable no-await-in-loop */
} }
let showingOverview = false; let showingOverview = false;

View File

@ -94,7 +94,8 @@ function extractBootTimestamp() {
return result; return result;
} }
function *run() { async function run() {
/* eslint-disable no-await-in-loop */
Scripting.defineScriptEvent("desktopShown", "Finished initial animation"); Scripting.defineScriptEvent("desktopShown", "Finished initial animation");
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview"); Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing"); Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
@ -110,7 +111,7 @@ function *run() {
Scripting.defineScriptEvent("geditLaunch", "gedit application launch"); Scripting.defineScriptEvent("geditLaunch", "gedit application launch");
Scripting.defineScriptEvent("geditFirstFrame", "first frame of gedit window drawn"); Scripting.defineScriptEvent("geditFirstFrame", "first frame of gedit window drawn");
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
Scripting.scriptEvent('desktopShown'); Scripting.scriptEvent('desktopShown');
let interfaceSettings = new Gio.Settings({ let interfaceSettings = new Gio.Settings({
@ -120,22 +121,22 @@ function *run() {
Scripting.scriptEvent('overviewShowStart'); Scripting.scriptEvent('overviewShowStart');
Main.overview.show(); Main.overview.show();
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
Scripting.scriptEvent('overviewShowDone'); Scripting.scriptEvent('overviewShowDone');
yield Scripting.sleep(1000); await Scripting.sleep(1000);
Scripting.scriptEvent('applicationsShowStart'); Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates // eslint-disable-next-line require-atomic-updates
Main.overview.dash.showAppsButton.checked = true; Main.overview.dash.showAppsButton.checked = true;
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone'); Scripting.scriptEvent('applicationsShowDone');
yield Scripting.sleep(1000); await Scripting.sleep(1000);
Main.overview.hide(); Main.overview.hide();
yield Scripting.waitLeisure(); await Scripting.waitLeisure();
// --------------------- // // --------------------- //
// Tests of redraw speed // // Tests of redraw speed //
@ -145,46 +146,46 @@ function *run() {
global.frame_finish_timestamp = true; global.frame_finish_timestamp = true;
for (let k = 0; k < 5; k++) for (let k = 0; k < 5; k++)
yield Scripting.createTestWindow({ maximized: true }); await Scripting.createTestWindow({ maximized: true });
yield Scripting.waitTestWindows(); await Scripting.waitTestWindows();
yield Scripting.sleep(1000); await Scripting.sleep(1000);
Scripting.scriptEvent('mainViewDrawStart'); Scripting.scriptEvent('mainViewDrawStart');
yield waitAndDraw(1000); await waitAndDraw(1000);
Scripting.scriptEvent('mainViewDrawDone'); Scripting.scriptEvent('mainViewDrawDone');
Main.overview.show(); Main.overview.show();
Scripting.waitLeisure(); Scripting.waitLeisure();
yield Scripting.sleep(1500); await Scripting.sleep(1500);
Scripting.scriptEvent('overviewDrawStart'); Scripting.scriptEvent('overviewDrawStart');
yield waitAndDraw(1000); await waitAndDraw(1000);
Scripting.scriptEvent('overviewDrawDone'); Scripting.scriptEvent('overviewDrawDone');
yield Scripting.destroyTestWindows(); await Scripting.destroyTestWindows();
Main.overview.hide(); Main.overview.hide();
yield Scripting.createTestWindow({ maximized: true, await Scripting.createTestWindow({ maximized: true,
redraws: true }); redraws: true });
yield Scripting.waitTestWindows(); await Scripting.waitTestWindows();
yield Scripting.sleep(1000); await Scripting.sleep(1000);
Scripting.scriptEvent('redrawTestStart'); Scripting.scriptEvent('redrawTestStart');
yield Scripting.sleep(1000); await Scripting.sleep(1000);
Scripting.scriptEvent('redrawTestDone'); Scripting.scriptEvent('redrawTestDone');
yield Scripting.sleep(1000); await Scripting.sleep(1000);
Scripting.scriptEvent('collectTimings'); Scripting.scriptEvent('collectTimings');
yield Scripting.destroyTestWindows(); await Scripting.destroyTestWindows();
global.frame_timestamps = false; global.frame_timestamps = false;
global.frame_finish_timestamp = false; global.frame_finish_timestamp = false;
yield Scripting.sleep(1000); await Scripting.sleep(1000);
let appSys = Shell.AppSystem.get_default(); let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.gedit.desktop'); let app = appSys.lookup_app('org.gnome.gedit.desktop');
@ -197,21 +198,22 @@ function *run() {
throw new Error('gedit was already running'); throw new Error('gedit was already running');
while (windows.length == 0) { while (windows.length == 0) {
yield waitSignal(global.display, 'window-created'); await waitSignal(global.display, 'window-created');
windows = app.get_windows(); windows = app.get_windows();
} }
let actor = windows[0].get_compositor_private(); let actor = windows[0].get_compositor_private();
yield waitSignal(actor, 'first-frame'); await waitSignal(actor, 'first-frame');
Scripting.scriptEvent('geditFirstFrame'); Scripting.scriptEvent('geditFirstFrame');
yield Scripting.sleep(1000); await Scripting.sleep(1000);
windows[0].delete(global.get_current_time()); windows[0].delete(global.get_current_time());
yield Scripting.sleep(1000); await Scripting.sleep(1000);
interfaceSettings.set_boolean('enable-animations', true); interfaceSettings.set_boolean('enable-animations', true);
/* eslint-enable no-await-in-loop */
} }
let overviewShowStart; let overviewShowStart;

View File

@ -21,16 +21,13 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
// When scripting an automated test we want to make a series of calls // When scripting an automated test we want to make a series of calls
// in a linear fashion, but we also want to be able to let the main // in a linear fashion, but we also want to be able to let the main
// loop run so actions can finish. For this reason we write the script // loop run so actions can finish. For this reason we write the script
// as a generator function that yields when it want to let the main // as an async function that uses await when it wants to let the main
// loop run. // loop run.
// //
// yield Scripting.sleep(1000); // await Scripting.sleep(1000);
// main.overview.show(); // main.overview.show();
// yield Scripting.waitLeisure(); // await Scripting.waitLeisure();
// //
// While it isn't important to the person writing the script, the actual
// yielded result is a function that the caller uses to provide the
// callback for resuming the script.
/** /**
* sleep: * sleep:
@ -285,14 +282,12 @@ function _collect(scriptModule, outputFile) {
} }
async function _runPerfScript(scriptModule, outputFile) { async function _runPerfScript(scriptModule, outputFile) {
for (let step of scriptModule.run()) {
try { try {
await step; // eslint-disable-line no-await-in-loop await scriptModule.run();
} catch (err) { } catch (err) {
log(`Script failed: ${err}\n${err.stack}`); log(`Script failed: ${err}\n${err.stack}`);
Meta.exit(Meta.ExitCode.ERROR); Meta.exit(Meta.ExitCode.ERROR);
} }
}
try { try {
_collect(scriptModule, outputFile); _collect(scriptModule, outputFile);