Fixed PCx86 to recover from situations where a page entered an "unloaded" state but wasn't actually unloaded.

This commit is contained in:
Jeff Parsons 2017-07-19 14:57:19 -07:00 committed by Jeff Parsons
commit 6c6f28c1ef
9 changed files with 2698 additions and 2630 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -893,6 +893,28 @@ class Computer extends Component {
*/ */
checkPower() checkPower()
{ {
if (this.flags.unloading) {
/*
* We happen to know that we're currently only called by the CPU's onClickRun() function, so
* if the unloading flag is set, then we've somehow gotten into a weird state where the machine
* thinks it's being (or has been) unloaded by the browser, but in fact, it has not.
*
* The only time I've seen this happen is when the user clicks a link on a page that the browser
* decided to treat as a download operation, instead of loading a new page. The proper way to
* resolve that confusion is to set the "download" attribute on the link (which will prevent the
* page's "onbeforeunload" handler from being called in the first place), but we cannot guarantee
* that all such links will have their "download" attribute properly set.
*
* Hence, this code: we do the same thing that the show() function does, which is to attempt a
* REPOWER operation. If that doesn't result in the powered flag getting turned back on, well,
* then we're probably screwed.
*/
this.flags.unloading = false;
if (this.flags.initDone && !this.flags.powered) {
this.powerOn(Computer.RESUME_REPOWER);
}
}
if (this.flags.powered) return true; if (this.flags.powered) return true;
var component = null, iComponent; var component = null, iComponent;
@ -1703,6 +1725,9 @@ class Computer extends Component {
var computer = /** @type {Computer} */ (Component.getComponentByType("Computer", parmsComputer['id'])); var computer = /** @type {Computer} */ (Component.getComponentByType("Computer", parmsComputer['id']));
if (computer) { if (computer) {
/*
* Clear new flag that Component functions (eg, notice()) should check before alerting the user.
*/
computer.flags.unloading = false; computer.flags.unloading = false;
if (DEBUG && computer.messageEnabled()) { if (DEBUG && computer.messageEnabled()) {
@ -1710,7 +1735,7 @@ class Computer extends Component {
} }
if (computer.flags.initDone && !computer.flags.powered) { if (computer.flags.initDone && !computer.flags.powered) {
/** /*
* Repower the computer, notifying every component to continue running as-is. * Repower the computer, notifying every component to continue running as-is.
*/ */
computer.powerOn(Computer.RESUME_REPOWER); computer.powerOn(Computer.RESUME_REPOWER);
@ -1755,7 +1780,7 @@ class Computer extends Component {
if (computer) { if (computer) {
/* /*
* Added a new flag that Component functions (eg, notice()) should check before alerting the user. * Set new flag that Component functions (eg, notice()) should check before alerting the user.
*/ */
computer.flags.unloading = true; computer.flags.unloading = true;

View file

@ -472,11 +472,20 @@ class CPU extends Component {
case "run": case "run":
this.bindings[sBinding] = control; this.bindings[sBinding] = control;
control.onclick = function onClickRun() { control.onclick = function onClickRun() {
var fRunning = cpu.flags.running;
if (!cpu.cmp || !cpu.cmp.checkPower()) return; if (!cpu.cmp || !cpu.cmp.checkPower()) return;
if (!cpu.flags.running) /*
cpu.runCPU(true); * We snapped the CPU's running flag before calling checkPower() because there are rare (REPOWER)
else * situations where checkPower() will have started the CPU as well. So toggle the CPU state ONLY
cpu.stopCPU(true); * if the running flag remains unchanged.
*/
if (fRunning == cpu.flags.running) {
if (!cpu.flags.running) {
cpu.runCPU(true);
} else {
cpu.stopCPU(true);
}
}
}; };
fBound = true; fBound = true;
break; break;

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -12146,11 +12146,20 @@ class CPU extends Component {
case "run": case "run":
this.bindings[sBinding] = control; this.bindings[sBinding] = control;
control.onclick = function onClickRun() { control.onclick = function onClickRun() {
var fRunning = cpu.flags.running;
if (!cpu.cmp || !cpu.cmp.checkPower()) return; if (!cpu.cmp || !cpu.cmp.checkPower()) return;
if (!cpu.flags.running) /*
cpu.runCPU(true); * We snapped the CPU's running flag before calling checkPower() because there are rare (REPOWER)
else * situations where checkPower() will have started the CPU as well. So toggle the CPU state ONLY
cpu.stopCPU(true); * if the running flag remains unchanged.
*/
if (fRunning == cpu.flags.running) {
if (!cpu.flags.running) {
cpu.runCPU(true);
} else {
cpu.stopCPU(true);
}
}
}; };
fBound = true; fBound = true;
break; break;
@ -75087,6 +75096,28 @@ class Computer extends Component {
*/ */
checkPower() checkPower()
{ {
if (this.flags.unloading) {
/*
* We happen to know that we're currently only called by the CPU's onClickRun() function, so
* if the unloading flag is set, then we've somehow gotten into a weird state where the machine
* thinks it's being (or has been) unloaded by the browser, but in fact, it has not.
*
* The only time I've seen this happen is when the user clicks a link on a page that the browser
* decided to treat as a download operation, instead of loading a new page. The proper way to
* resolve that confusion is to set the "download" attribute on the link (which will prevent the
* page's "onbeforeunload" handler from being called in the first place), but we cannot guarantee
* that all such links will have their "download" attribute properly set.
*
* Hence, this code: we do the same thing that the show() function does, which is to attempt a
* REPOWER operation. If that doesn't result in the powered flag getting turned back on, well,
* then we're probably screwed.
*/
this.flags.unloading = false;
if (this.flags.initDone && !this.flags.powered) {
this.powerOn(Computer.RESUME_REPOWER);
}
}
if (this.flags.powered) return true; if (this.flags.powered) return true;
var component = null, iComponent; var component = null, iComponent;
@ -75897,6 +75928,9 @@ class Computer extends Component {
var computer = /** @type {Computer} */ (Component.getComponentByType("Computer", parmsComputer['id'])); var computer = /** @type {Computer} */ (Component.getComponentByType("Computer", parmsComputer['id']));
if (computer) { if (computer) {
/*
* Clear new flag that Component functions (eg, notice()) should check before alerting the user.
*/
computer.flags.unloading = false; computer.flags.unloading = false;
if (DEBUG && computer.messageEnabled()) { if (DEBUG && computer.messageEnabled()) {
@ -75904,7 +75938,7 @@ class Computer extends Component {
} }
if (computer.flags.initDone && !computer.flags.powered) { if (computer.flags.initDone && !computer.flags.powered) {
/** /*
* Repower the computer, notifying every component to continue running as-is. * Repower the computer, notifying every component to continue running as-is.
*/ */
computer.powerOn(Computer.RESUME_REPOWER); computer.powerOn(Computer.RESUME_REPOWER);
@ -75949,7 +75983,7 @@ class Computer extends Component {
if (computer) { if (computer) {
/* /*
* Added a new flag that Component functions (eg, notice()) should check before alerting the user. * Set new flag that Component functions (eg, notice()) should check before alerting the user.
*/ */
computer.flags.unloading = true; computer.flags.unloading = true;

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long