Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env node */
module.exports = async function (context, commands) {
context.log.info("Starting a indexedDB write");
const post_startup_delay = context.options.browsertime.post_startup_delay;
console.log("context options", context.options);
const test_url = context.options.browsertime.url;
const chunk_size = context.options.browsertime.chunk_size;
const iterations = context.options.browsertime.iterations;
const buffer_type = context.options.browsertime.buffer_type;
const atomic_value = context.options.browsertime.atomic;
if (atomic_value * atomic_value != atomic_value) {
throw Error("Value of atomic shall be 0 for falsehood, 1 for truth.");
}
const atomic = 0 != atomic_value;
const accepted_buffers = ["Array", "ArrayBuffer", "Blob"];
if (!accepted_buffers.includes(buffer_type)) {
throw Error("Buffer type " + buffer_type + " is unknown.");
}
context.log.info("IndexedDB write URL = " + test_url);
context.log.info("IndexedDB write chunk size = " + chunk_size);
context.log.info("IndexedDB write iterations = " + iterations);
context.log.info(
"IndexedDB writes " +
(atomic ? "all in one big transaction" : "in separate transactions")
);
context.log.info("IndexedDB write data format " + buffer_type);
context.log.info(
"Waiting for %d ms (post_startup_delay)",
post_startup_delay
);
await commands.navigate(test_url);
const seleniumDriver = context.selenium.driver;
await commands.wait.byTime(post_startup_delay);
await commands.measure.start();
const time_duration = await seleniumDriver.executeAsyncScript(`
const notifyDone = arguments[arguments.length - 1];
const iterations = ${iterations};
const sizeInBytes = ${chunk_size};
const bufferType = "${buffer_type}";
const atomic = ${atomic};
const makeData = (() => {
if (bufferType === "ArrayBuffer") {
return () => {
const valueBuffer = new ArrayBuffer(sizeInBytes);
const charCodeView = new Uint16Array(valueBuffer);
const sizeInUint16 = sizeInBytes / 2;
for (let i=0; i < sizeInUint16; ++i) {
charCodeView[i] = "qwerty".charCodeAt(i % 6);
}
return valueBuffer;
};
}
if (bufferType === "Array") {
return () => {
return Array.from({length: sizeInBytes}, (_, i) => "qwerty"[i % 6]);
};
}
if (bufferType !== "Blob") {
throw Error("Unknown buffer type " + bufferType);
}
return () => {
return new Blob([Array.from({length: sizeInBytes}, (_, i) => "qwerty"[i % 6])]);
};
})();
function addData(txSource, txProvider, i) {
try {
const keyName = "doc_" + i;
const valueData = makeData();
const record = { key: keyName, property: valueData };
const rq = txProvider(txSource).add(record);
return new Promise((res_ad, rej_ad) => {
rq.onsuccess = () => { res_ad(); };
rq.onerror = e => { rej_ad(e); };
});
} catch (e) {
return new Promise((_, rej_ad) => rej_ad(e));
}
}
function waitForData(txSource) {
try {
if (!atomic) {
const txProvider = src => src.transaction("store", "readwrite").objectStore("store");
return Promise.all(
Array.from({ length: iterations }, (_, i) => {
return addData(txSource, txProvider, i);
}));
}
const currentTx = txSource.transaction("store", "readwrite").objectStore("store");
return Promise.all(
Array.from({ length: iterations }, (_, i) => {
return addData(currentTx, src => src, i);
}));
} catch (e) {
return new Promise((_, rej_tx) => rej_tx(e));
}
}
function upgradePromise() {
try {
const open_db = indexedDB.open("rootsdb");
return new Promise((res_upgrade, rej_upgrade) => {
open_db.onupgradeneeded = e => {
e.target.result.createObjectStore("store", { keyPath: "key" });
};
open_db.onsuccess = e => { res_upgrade(e.target.result); };
open_db.onerror = e => { rej_upgrade(e); };
});
} catch (e) {
return new Promise((_, rej_upgrade) => rej_upgrade(e));
}
}
const startTime = performance.now();
upgradePromise().then(waitForData).then(() => {
notifyDone(performance.now() - startTime);
});
`);
await commands.measure.stop();
console.log("Time duration was ", time_duration);
await commands.measure.addObject({
custom_data: { time_duration },
});
context.log.info("IndexedDB write ended.");
return true;
};