Why can't I use let in different cases after a switch statement

I’m getting the following error message in the firefox debug console:

SyntaxError: redeclaration of let settings background.js:149:16
note: Previously declared at line 141, column 16background.js:141:16

Below is my code. I tried assigning {} to both settings and options and removing let in the cases, but then I got another error saying that settings wasn’t defined!

async function handleMessages(message, sender, sendResponse) {
    let id = "";
    let domain = "";
    switch (message.action) {
        case "doSearch":
            id = message.data.id;
            if (logToConsole) console.log("Search engine id: " + id);
            let tabs = await browser.tabs.query({
                active: true, 
                currentWindow: true
            });
            if (logToConsole) console.log(tabs);
            let tabIndex = 0;
            for (let tab of tabs) {
                if (tab.active) {
                    if (logToConsole) console.log("Active tab url: " + tab.url);
                    tabIndex = tab.index;
                    if (logToConsole) console.log("tabIndex: " + tabIndex);
                    break;
                }
            }
            await searchUsing(id, tabIndex, true);
            break;
        case "notify":
            notify(message.data);
            break;
        case "setImageData":
            imageUrl = message.data.imageUrl;
            imageTags = JSON.parse(JSON.stringify(message.data.imageTags));
            if (logToConsole) console.log(imageUrl);
            if (logToConsole) console.log(imageTags);
            break;
        case "returnImageData":
            sendResponse({imageUrl: imageUrl, imageTags: imageTags});
            break;      
        case "returnSearchResults":
            if (logToConsole) console.log(`Target url: ${targetUrl}\n`);
            let response = await fetchMobileWebPage(targetUrl);
            let content = response.text();
            if (logToConsole) console.log(`Response:\n\n${content}`);
            sendResponse(content);
            return true;
            break;    
        case "setSelection":
            if (logToConsole) console.log(`Selected text: ${message.data}`);
            selection = message.data;
            break;
        case "reset":
            await init();
            sendResponse("resetCompleted");
            return true;
            break;
        case "sendCurrentTabUrl":
            if (message.data) targetUrl = message.data;
            break;
        case "testSearchEngine":
            testSearchEngine(message.data);
            break;
        case "saveSearchEngines":
            searchEngines = message.data;
            if (logToConsole) console.log(searchEngines);
            await saveSearchEnginesToStorageSync(false, true);
            await rebuildContextMenu();
			break;
        case "addNewSearchEngine":
            id = message.data.id;
            domain = getDomain(message.data.searchEngine.url);
            if (logToConsole) console.log(id, domain);
            searchEngines[id] = message.data.searchEngine;
            searchEngines = sortByIndex(searchEngines);
            let value = await addNewFavicon(id, domain);
            searchEngines[id]["base64"] = value.base64;
            await saveSearchEnginesToStorageSync(false, true);
            await rebuildContextMenu();
            break;
        case "updateCacheFavicons":
            let settings = await getOptions();
            let options = settings.options;
            if (logToConsole) console.log(`Preferences retrieved from storage sync: ${JSON.stringify(options)}`);
            options.cacheFavicons = message.data.cacheFavicons;
            await setCacheFavicons(options);
            await saveOptions(options, false);
			break;
        case "updateDisplayFavicons":
            let settings = await getOptions();
            let options = settings.options;
            if (logToConsole) console.log(`Preferences retrieved from storage sync: ${JSON.stringify(options)}`);
            options.displayFavicons = message.data.displayFavicons;
            setDisplayFavicons(options);
            await saveOptions(options, true);
            break;
        case "updateTabMode":
            let settings = await getOptions();
            let options = settings.options;
            if (logToConsole) console.log(`Preferences retrieved from storage sync: ${JSON.stringify(options)}`);
            options.tabMode = message.data.tabMode;
            options.tabActive = message.data.tabActive;
            setTabMode(options);
            await saveOptions(options, false);
			break;
        case "updateOptionsMenuLocation":
            let settings = await getOptions();
            let options = settings.options;
            if (logToConsole) console.log(`Preferences retrieved from storage sync: ${JSON.stringify(options)}`);
            options.optionsMenuLocation = message.data.optionsMenuLocation;
            setOptionsMenuLocation(options);
            await saveOptions(options, true);
            break;
        case "updateResetOptions":
            let settings = await getOptions();
            let options = settings.options;
            if (logToConsole) console.log(`Preferences retrieved from storage sync: ${JSON.stringify(options)}`);
            options.forceSearchEnginesReload = message.data.resetOptions.forceSearchEnginesReload;
            options.resetPreferences = message.data.resetOptions.resetPreferences;
            options.forceFaviconsReload = message.data.resetOptions.forceFaviconsReload;
            setResetOptions(options);
            await saveOptions(options, true);
			break;
		case "saveSearchEnginesToDisk":
			await browser.downloads.download({url: message.data, saveAs: true, filename: "searchEngines.json"});
			break;
		default:
			break;
	}
}

Since let and const have a block scope (unlike var or function that have a function scope), all you need to do is wrap each case into its own block like this:

switch(x) {
  case 'a': {  // HERE, see? We are in the block now :)
    const settings = await getOptions();
    break;
  }
  case 'b': {
    const settings = await getOptions();
    break;
  }
}

Also I would suggest to use const instead of let unless you really need a variable.

2 Likes

Thanks Juraj. You’re a great help.