Open Bug 1750290 Opened 2 years ago Updated 1 year ago

Addons using ReadableStreams with content sources throw permission denied to access property 'then'

Categories

(Core :: DOM: Streams, defect, P3)

defect

Tracking

()

People

(Reporter: mgaudet, Unassigned)

References

(Blocks 2 open bugs)

Details

It is possible (though deeply ill-advised) to convince an add-on and a page to cooperate in the creation of a readable stream where the stream is in the addon, and the source is on the page.

When this is done with JS Streams, it successfully runs.

When this is done with DOM Streams, it throws "Permission denied to access property "then"" (almost certainly during the promise resolution process).

The test I have right now is not rigged up for tree inclusion, but looks roughly like this:

The page under test looks like this:

<html>
    <body id="body">
        <div id="results"></div>
        <script>
            var results = document.getElementById("results");
            function info(m) {
                results.innerHTML += `<p>${m}</p>`
            }

            var source = {
                start(controller) {
                    console.log('Starting')
                    // Note this is an exported function from the addon that does the enqueue. 
                    window.enqueue(controller, "h");
                    window.enqueue(controller, "e");
                    console.log("enqueued");
                }
            }
        </script>
    </body>
</html>

and the content script applied to this by the addon is

var results = document.getElementById("results");
function info(m) {
    results.innerHTML += `<p><b>From AddOn</b>${m}</p>`
}

// Get the source, unwrapped, from the page. 
var source = window.wrappedJSObject.source;

// Export an addon script function to allow the page to enqueue items. 
function enqueue(controller, value) {
    controller.enqueue(value)
}

exportFunction(enqueue, window, { defineAs: 'enqueue' });

// Create our readable stream
var rs = new ReadableStream(source);
var reader = rs.getReader();

var doRead = async () => {
    console.log("reading")
    var read = await reader.read(); // This await complains about the `.then` property. 
    console.log("read")

    info("Read value: " + read.value);
}

setTimeout(doRead, 1);
setTimeout(doRead, 1);

I've marked this P3/S3 because the amount of work required to actually get a setup like this working requires both page and addon collaboration, and I seriously doubt anyone would build something like this.

Nevertheless, it's technically a regression, and could hint at some issues about globals.

I'll note that the Streams spec doesn't actually define in which realm its promises are created. See for example https://streams.spec.whatwg.org/#default-reader-read (Let promise be a new promise.) which links to https://webidl.spec.whatwg.org/#a-new-promise (To create a new Promise<T> in a Realm realm, perform the following steps:).

Yeah, it's a known issue in the Streams spec (https://github.com/whatwg/streams/issues/1213) -- hopefully this will all be clarified later.

You need to log in before you can comment on or make changes to this bug.