Chrome extension: injected value disappears after content script runs

I am writing a chrome extension (Manifest V3) where I am trying to let the content script know what the tab ID is by setting a window property (because I use it a few times later). I am doing this using executeScript() in the following manner in my background.js:

function setTabIDInContent(id) { 
  window.tabId = id; }

chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
    if (tab.url?.startsWith("chrome://")) return undefined;

    chrome.scripting.executeScript({
      target: { tabId: tabId },
      args: [tabId],
      world: "MAIN",
      func: setTabIDInContent
    });
    
});

In my content script, I have a listener defined in the following manner:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {  
        sendResponse({tabId: window.tabId, 
          info: 'other stuff'});
        
});

I am observing this peculiar behavior:

  • Right after a page loads, typing window.tabId in the console window prints the correct value.
  • However, after the content script runs – specifically, after I send a message to it from the background script, and it invokes the listener, window.tabId becomes undefined. Putting a breakpoint in the content script’s listener method, I verified that window.tabId is indeed undefined during execution. After the listener finishes execution, when I go back to the console window and type out window.tabId, I see it has become undefined there was well.

Why would this happen and what might I do to persist this value?