Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- Manifest: dom/localstorage/test/unit/xpcshell.toml
/**
* Any copyright is dedicated to the Public Domain.
*/
/**
* Test repeatedly setting values that are just under the LocalStorage quota
* limit without yielding control flow in order to verify that the write
* optimizer is present / works. If there was no write optimizer present, the
* IPC message size limit would be exceeded, resulting in a crash.
*/
add_task(async function testSteps() {
const globalLimitKB = 5 * 1024;
// 18 and more iterations would produce an IPC message with size greater than
// 256 MB if write optimizer was not present. This number was determined
// experimentally by running the test with disabled write optimizer.
const numberOfIterations = 18;
const randomStringBlockSize = 65536;
// We need to use a random string because LS internally tries to compress
// values.
function getRandomString(size) {
let crypto = this.window ? this.window.crypto : this.crypto;
let decoder = new TextDecoder("ISO-8859-2");
function getRandomStringBlock(array) {
crypto.getRandomValues(array);
return decoder.decode(array);
}
let string = "";
let quotient = size / randomStringBlockSize;
if (quotient) {
let array = new Uint8Array(randomStringBlockSize);
for (let i = 1; i <= quotient; i++) {
string += getRandomStringBlock(array);
}
}
let remainder = size % randomStringBlockSize;
if (remainder) {
let array = new Uint8Array(remainder);
string += getRandomStringBlock(array);
}
return string;
}
const data = {};
data.key = "foo";
data.value = getRandomString(
globalLimitKB * 1024 -
data.key.length -
numberOfIterations.toString().length
);
info("Setting pref");
// By disabling snapshot reusing, we guarantee that the snapshot will be
// checkpointed once control returns to the event loop.
if (this.window) {
await SpecialPowers.pushPrefEnv({
set: [["dom.storage.snapshot_reusing", false]],
});
} else {
Services.prefs.setBoolPref("dom.storage.snapshot_reusing", false);
}
info("Getting storage");
let storage = getLocalStorage();
info("Adding/updating item");
for (var i = 0; i < numberOfIterations; i++) {
storage.setItem(data.key, data.value + i);
}
info("Returning to event loop");
await returnToEventLoop();
ok(!storage.hasSnapshot, "Snapshot successfully finished");
});