wxt-dev/wxt

browser.tabs.sendMessage cannot get the return value of a two-dimensional array

Closed this issue · 2 comments

Describe the bug

I try to use the following code to send a message from background to content and receive a two-dimensional array returned by the content script, but the following code always fails. However, when I change "browser" back to "chrome," it works successfully. How can WXT solve this?

Reproduction

background.ts

 let result = await browser.tabs.sendMessage(id, { method: "request", payload: null })
        if (result != null) {
            debugger
            await process(result);
        }

content.ts

browser.runtime.onMessage.addListener(  (request, sender, sendResponse) => {
            if (request.method === 'request') {
                if (this.bufferQueue.length > 0) {
                    let result = this.bufferQueue.shift();
                    sendResponse(result)
                } else {
                    sendResponse()
                }
            }
            return true
        })

Steps to reproduce

No response

System Info

System:
    OS: macOS 14.5
    CPU: (10) arm64 Apple M1 Max
    Memory: 191.95 MB / 64.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.7.0 - /opt/homebrew/bin/node
    Yarn: 1.22.17 - /opt/homebrew/bin/yarn
    npm: 10.8.2 - /opt/homebrew/bin/npm
    pnpm: 8.12.1 - ~/Library/pnpm/pnpm
  Browsers:
    Chrome: 128.0.6613.120
    Edge: 128.0.2739.67
    Safari: 17.5
  npmPackages:
    wxt: ^0.19.9 => 0.19.9

Used Package Manager

npm

Validations

Not a bug, the polyfill just behaves a bit differently than you expect. Using chrome for messaging is perfectly fine.

You're also not removing the listener when the content script is invalidated, so during development, old listeners are gonna keep firing first, intercepting the messages and returning undefined by the looks of it.

// Make sure your callback is NOT async
browser.runtime.onMessage.addListener((request, sender) => {
  if (ctx.isInvalidated) return;

  if (request.method === 'request') {
    if (this.bufferQueue.length > 0) {
      let result = this.bufferQueue.shift();
      return Promise.resolve(result) 
    } else {
      return Promise.resolve()
    }
  }
})

Rather than receiving a sendResponse callback to send a response, onMessage listeners simply return a Promise whose resolution value is used as a reply.

https://github.com/mozilla/webextension-polyfill?tab=readme-ov-file#using-the-promise-based-apis

@aklinker1 Thank you very much, it turns out I missed it.

Promise.resolve()

After being modified according to your way, it can work.