tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 17b8f2f85bc2d35f13375d2dde45e7c23203d483
parent ae9c610377718bc0cae69d32519e23eb2daadea4
Author: Julian Descottes <jdescottes@mozilla.com>
Date:   Thu,  8 Jan 2026 11:05:30 +0000

Bug 2004973 - [devtools] Chunk calls to String.fromCharCode in NetworkUtils r=devtools-reviewers,bomsy

Need to chunk calls to String.fromCharCode because data might be a very large array.

Differential Revision: https://phabricator.services.mozilla.com/D277897

Diffstat:
Mdevtools/shared/network-observer/NetworkUtils.sys.mjs | 10+++++++++-
Mdevtools/shared/network-observer/test/browser/browser_networkobserver_response_body_limit.js | 52+++++++++++++++++++++++++++++++++++-----------------
2 files changed, 44 insertions(+), 18 deletions(-)

diff --git a/devtools/shared/network-observer/NetworkUtils.sys.mjs b/devtools/shared/network-observer/NetworkUtils.sys.mjs @@ -867,7 +867,15 @@ async function decodeCompressedStream(stream, length, encodings) { _length, data ) { - resolve(String.fromCharCode.apply(this, data)); + // `data`` might be a very large array, chunk calls to fromCharCode to + // avoid "RangeError: too many arguments provided for a function call". + const CHUNK_SIZE = 65536; + let result = ""; + for (let i = 0; i < data.length; i += CHUNK_SIZE) { + const chunk = data.slice(i, i + CHUNK_SIZE); + result += String.fromCharCode.apply(null, chunk); + } + resolve(result); }, }); }); diff --git a/devtools/shared/network-observer/test/browser/browser_networkobserver_response_body_limit.js b/devtools/shared/network-observer/test/browser/browser_networkobserver_response_body_limit.js @@ -51,6 +51,7 @@ const BYTES_1000 = 1000; const smallSize = BYTES_1000 / 2; const bigSize = BYTES_1000 * 2; const hugeSize = BYTES_1000 * 20; +const tooManyArgumentsSize = BYTES_1000 * 1000; add_task(async function testNetworkObserverWithResponseBodyLimit1000() { info("Test a network observer with specific response body limit (1000)"); @@ -126,23 +127,40 @@ add_task(async function testNetworkObserverWithResponseBodyLimitZero() { info("Test a network observer with a response body limit = zero (unlimited)"); const tab = await addTab(TEST_URL); - const events = []; - const noLimitNetworkObserver = createNetworkObserver({ - events, - responseBodyLimit: 0, - decodeResponseBodies: true, - }); - - await performGetDataRequest(gBrowser, events, smallSize); - await assertNetworkEventContent(events.at(-1), smallSize, false); - - await performGetDataRequest(gBrowser, events, bigSize); - await assertNetworkEventContent(events.at(-1), bigSize, false); - - await performGetDataRequest(gBrowser, events, hugeSize); - await assertNetworkEventContent(events.at(-1), hugeSize, false); - - noLimitNetworkObserver.destroy(); + for (const useGzip of [true, false]) { + for (const decodeResponseBodies of [true, false]) { + info("Test with decodeResponseBodies=" + decodeResponseBodies); + const events = []; + const noLimitNetworkObserver = createNetworkObserver({ + events, + responseBodyLimit: 0, + decodeResponseBodies, + }); + + await performGetDataRequest(gBrowser, events, smallSize, useGzip); + await assertNetworkEventContent(events.at(-1), smallSize, false); + + await performGetDataRequest(gBrowser, events, bigSize, useGzip); + await assertNetworkEventContent(events.at(-1), bigSize, false); + + await performGetDataRequest(gBrowser, events, hugeSize, useGzip); + await assertNetworkEventContent(events.at(-1), hugeSize, false); + + await performGetDataRequest( + gBrowser, + events, + tooManyArgumentsSize, + useGzip + ); + await assertNetworkEventContent( + events.at(-1), + tooManyArgumentsSize, + false + ); + + noLimitNetworkObserver.destroy(); + } + } gBrowser.removeTab(tab); });