Pressing a button breaks my website

When I go to my website at https://elemental-conquest.glitch.me, and do the following sequence of buttons and inputs:

  1. Plains
  2. Sector 1
  3. Enter 3 in the input box
  4. Click Attack

The website breaks for some reason. It doesn’t seem to be a bug, as devtools seems completely fine. However, the page breaks completely and I can’t press anything.

Here is the code for the attack() function that is run when the Attack button is pressed:

function attack(region, sector) {
  let attackingUnits = {
    swordsman: document.getElementById("unit-amt-swordsman").value.trim() == "" ? "" : parseInt(document.getElementById("unit-amt-swordsman").value.trim())
  };
  
  let defendingUnits = map[region][sector - 1].army;
  
  for(const unitName in attackingUnits) {
    if(attackingUnits[unitName] == "") {
      delete attackingUnits[unitName];
      continue;
    }
    
    if (attackingUnits[unitName] == NaN || attackingUnits[unitName] <= 0) {
      alert("You have provided an invalid amount of units");
      return;
    }
    
    if (attackingUnits[unitName] > playerUnits[unitName]) {
      alert("You have provided too many units");
      return;
    }
  }
  
  if(Object.keys(attackingUnits).length == 0) {
    alert("You didn't provide any units!");
    return;
  }
  
  battleRound: while(Object.keys(defendingUnits).length > 0) {
    if(Object.keys(attackingUnits).length == 0) {
      // Player loses
      alert("You lost the battle!");
      break battleRound;
    }
    
    for(let i = 0; i < defendingUnits.length; i++) {
      let attackingUnit = Object.keys(attackingUnits)[random(0, attackingUnits.keys().length)];
      let attackingUnitPower = attackingUnits[attackingUnit];

      let defendingUnit = Object.keys(defendingUnits)[random(0, defendingUnits.keys().length)];
      let defendingUnitPower = defendingUnits[defendingUnit];

      // Code to handle bonuses (not yet existent)

      if (attackingUnitPower > defendingUnitPower) {
        // Attacking units win
        attackingUnits[attackingUnit] -= defendingUnits[defendingUnit];
        playerUnits[attackingUnit] -= defendingUnits[defendingUnit];
        delete defendingUnits[defendingUnit];
      } else {
        // Defending units win (this is intended)
        playerUnits[attackingUnit] -= attackingUnits[attackingUnit];
        delete attackingUnits[attackingUnit];
        if(attackingUnitPower == defendingUnitPower) {
          defendingUnits[defendingUnit] = 1;
        } else {
          defendingUnits[defendingUnit] -= attackingUnits[attackingUnit];
        }
        
        if(Object.keys(attackingUnits).length == 0) {
          // Player loses
          alert("You lost the battle!");
          break battleRound;
        }
      }
    }
  }
  
  if(Object.keys(defendingUnits).length == 0 && Object.keys(attackingUnits).length > 0) {
    map[region][sector - 1].progress -= 1;
    if(map[region][sector - 1].progress == 0) {
      alert("You have won the battle and successfully conquered this sector!");
    } else {
      alert("You have won the battle!");
    }
    
    openModal({
      region,
      id: sector,
      ...map[region][sector - 1]
    });
  }
}

I also noticed that the website view inside glitch completely breaks. I don’t think this is an error with my code, however.

Here is a screenshot of the broken page:

No errors appear in the console…

Yeah, I noticed that. But clearly something’s wrong…

You’ve got an infinite loop happening which is why the site’s crashing but the logs aren’t showing anything - in the battleRound function you do a while loop as long as the length >0 but then the for loop never changes length so the while never stops.

Here’s where I set a checkpoint in the browser dev tools to try to stop it before it crashed the page in script.js:

1 Like

Why does the loop never stop?

Wouldn’t the break battleRound at line 197 break out of both loops?

I figured out what the problem is: Line #170.

for(let i = 0; i < defendingUnits.length; i++) {

defendingUnits.length is undefined. The Object doesn’t have a key length

I think what you meant was Object.keys(defendingUnits).length.

Results

That does come with a few errors:
attackingUnits.keys() and defendingUnits.keys() are not functions.
Line #171 and #174.
Just change those to Object.keys(attackingUnits) and Object.keys(defendingUnits.

Hope the game turns out well!

1 Like