Verify device autosave behavior across frontend revisions
This commit is contained in:
@@ -335,3 +335,71 @@ No product behavior changes are involved in these measurement corrections.
|
||||
Keep browser/build/test processes idle during full timing measurements. WebKit's
|
||||
zero long-task field means unavailable, not zero work. Autoplay-blocked/media-ready
|
||||
null results do not establish playback performance or iPhone audio continuity.
|
||||
|
||||
## Device autosave investigation (2026-10-09)
|
||||
|
||||
`autosave.mjs` starts an isolated real Bun server inside this worktree, seeds its
|
||||
media-cache DB with a three-second H.264/AAC clip, and uses 414×896 Playwright
|
||||
contexts with the Framework7 Swipe layout. It checks OPFS bytes, `cachedIds`,
|
||||
Saved and Downloads views, and both Settings handlers. Public network requests
|
||||
are blocked. No production access or YouTube download is needed.
|
||||
|
||||
```bash
|
||||
bash perf/make-shell-fixture.sh b77938a 1175f1a1d2c1
|
||||
node perf/autosave.mjs --frontend perf/fixtures/shell-1175f1a1d2c1 \
|
||||
--asset-hashing 0 --asset-sync 0 --allow-unsupported-webkit \
|
||||
--out perf/results/autosave-b77938a.json
|
||||
node perf/autosave.mjs --frontend-commit main --allow-unsupported-webkit \
|
||||
--out perf/results/autosave-main.json
|
||||
node perf/autosave.mjs --browser chromium --out perf/results/autosave-current.json
|
||||
node --test frontend/autosave.test.js
|
||||
```
|
||||
|
||||
Options: `--frontend <directory>` or `--frontend-commit <revision>`;
|
||||
`--browser chromium|webkit|all`; `--scenarios <comma-separated names>`;
|
||||
`--asset-hashing 0|1`, `--asset-sync 0|1`; `--out <json>`.
|
||||
A failed assertion exits 1. Missing native OPFS exits 2 unless explicitly
|
||||
allowed with `--allow-unsupported-webkit`. On this Linux Playwright WebKit build,
|
||||
`navigator.storage` is absent, including in persistent contexts; enabling its
|
||||
MiniBrowser storage feature flags also did not expose it. WebKit therefore
|
||||
checks real UI/settings/save guards and records `supported:false`; those results
|
||||
**do not establish a successful WebKit OPFS save**. No storage shim is installed.
|
||||
Run without the allowance on a Safari-capable environment to require native OPFS.
|
||||
|
||||
Observed contracts in both b77938a and current code:
|
||||
|
||||
| Action | Device save |
|
||||
| --- | --- |
|
||||
| Open a video with default settings | No |
|
||||
| Open with `saveBeforePlay:true`, video mode | Yes |
|
||||
| Open audio-only, or `preferStream:true` | No |
|
||||
| Create/add to a playlist, even with `autoPreload:false` | Yes |
|
||||
| Launch with playlist videos and `autoPreload:true` | Yes |
|
||||
| Launch with `autoPreload:false`, unpinned playlist | No |
|
||||
| Launch with a pinned playlist, even with auto-preload off | Yes |
|
||||
| Enable either save setting through Settings | Saves as above; persisted |
|
||||
|
||||
Chromium: all 12 cases pass for old/current builds and Phase 1/2 tips.
|
||||
Phase 3/4/5 tips and both rollback flags pass the six positive cases
|
||||
(`open-save-first,playlist-add,playlist-boot,pinned-boot,settings-enable,settings-save-first`).
|
||||
JSON evidence is in `perf/results/autosave-*.json`. No old=saves/new=doesn't
|
||||
transition was found, so there is no defensible breaking commit or product fix.
|
||||
The unit tests cover playlist/pinning policy, duplicate saves, and failed or
|
||||
paused saves remaining retryable without being marked Saved.
|
||||
|
||||
Neighbour audit: Downloads, Saved, OPFS, download controls and error helpers
|
||||
remain eager core assets. Export awaits `feature:export`; Share/External await
|
||||
`feature:share-external`; worker creation is synchronous and receives build-local
|
||||
hash/resume URLs. DirectMedia's unloaded `hasSource()` facade returns false, so
|
||||
an early paired-source lookup can choose the server instead; this does not
|
||||
prevent the server save. P2P settings counts queried before its delayed lazy
|
||||
startup can initially show no registration. These remain follow-up candidates,
|
||||
not demonstrated causes of missing OPFS saves. The scout's proposed Data Saver
|
||||
cause was rejected: its guards affect static warming and stream pre-resolution,
|
||||
not `preload()` or `saveBeforePlay`.
|
||||
|
||||
Still required on the owner's installed iPhone PWA: record the running build,
|
||||
check Save before playing / Audio-only / Auto-save settings, open a fresh video,
|
||||
add it to a playlist, and inspect Downloads failure details and Saved after a
|
||||
relaunch/offline playback. Verify available storage and whether iOS evicted
|
||||
previous copies. A failing iPhone sequence is needed to continue the bisect.
|
||||
|
||||
128
perf/autosave.mjs
Normal file
128
perf/autosave.mjs
Normal file
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env node
|
||||
// Device autosave checks against a real, isolated Bun server and a local H.264 clip.
|
||||
import assert from 'node:assert/strict';
|
||||
import { spawn, execFileSync } from 'node:child_process';
|
||||
import { mkdirSync, mkdtempSync, symlinkSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { createServer } from 'node:net';
|
||||
import { createRequire } from 'node:module';
|
||||
import { chromium, webkit } from 'playwright';
|
||||
const root = path.resolve(import.meta.dirname, '..');
|
||||
const require = createRequire(import.meta.url);
|
||||
const { createClient } = require(path.join(root, 'server/node_modules/@libsql/client'));
|
||||
const args = process.argv.slice(2);
|
||||
function option(name, fallback) { const i = args.indexOf(name); return i < 0 ? fallback : args[i + 1]; }
|
||||
const target = option('--browser', 'all');
|
||||
assert.ok(['all', 'chromium', 'webkit'].includes(target));
|
||||
mkdirSync(path.join(root, 'perf/.tmp'), { recursive: true });
|
||||
const scratch = mkdtempSync(path.join(root, 'perf/.tmp/autosave-'));
|
||||
const revision = option('--frontend-commit', null);
|
||||
let tree = path.resolve(option('--frontend', path.join(root, 'frontend')));
|
||||
if (revision) {
|
||||
const archive = path.join(scratch, 'frontend.tar');
|
||||
writeFileSync(archive, execFileSync('git', ['archive', revision, 'frontend'], { cwd: root, maxBuffer: 30 * 1024 * 1024 }));
|
||||
execFileSync('tar', ['-xf', archive, '-C', scratch]);
|
||||
tree = path.join(scratch, 'frontend');
|
||||
}
|
||||
const portProbe = createServer();
|
||||
await new Promise(r => portProbe.listen(0, '127.0.0.1', r));
|
||||
const port = portProbe.address().port;
|
||||
await new Promise(r => portProbe.close(r));
|
||||
const origin = `http://127.0.0.1:${port}`;
|
||||
const clip = { id: 'benchmedia01', title: 'Autosave local clip', channel: 'Regression', duration: 3, thumbnail: '' };
|
||||
const media = path.join(scratch, 'data/media');
|
||||
mkdirSync(media, { recursive: true });
|
||||
symlinkSync(tree, path.join(scratch, 'public'));
|
||||
const mp4 = path.join(media, clip.id + '.1.mp4');
|
||||
const dbPath = path.join(scratch, 'data/test.db');
|
||||
const child = spawn('bun', [path.join(root, 'server/server.js')], { cwd: scratch, env: { ...process.env, PORT: String(port), DB_PATH: dbPath, MEDIA_DIR: media, UPLOAD_DIR: path.join(scratch, 'uploads'), DATA_DIR: path.join(scratch, 'data'), ASSET_HASHING: option('--asset-hashing', '1'), ASSET_SYNC: option('--asset-sync', '1'), BUILD_TAG: '' }, stdio: ['ignore', 'pipe', 'pipe'] });
|
||||
let serverLog = '';
|
||||
for (const stream of [child.stdout, child.stderr]) stream.on('data', c => { serverLog = (serverLog + c).slice(-5000); });
|
||||
const results = { revision: revision || tree, browsers: {}, failures: [], unsupported: [] };
|
||||
const scenarios = ['open-default', 'open-save-first', 'open-audio-only', 'open-prefer-stream', 'playlist-add', 'playlist-add-setting-off', 'playlist-existing-add', 'playlist-boot', 'playlist-boot-off', 'pinned-boot', 'settings-enable', 'settings-save-first'];
|
||||
try {
|
||||
for (let i = 0; ; i++) {
|
||||
try { if ((await fetch(origin + '/api/version')).ok) break; } catch {}
|
||||
if (i === 100 || child.exitCode !== null) throw Error('Bun server failed: ' + serverLog);
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
}
|
||||
results.buildTag = (await (await fetch(origin + '/api/version')).json()).buildTag;
|
||||
execFileSync('ffmpeg', ['-y', '-f', 'lavfi', '-i', 'color=c=blue:s=160x90:r=10:d=3', '-f', 'lavfi', '-i', 'sine=frequency=440:duration=3', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-c:a', 'aac', '-movflags', '+faststart', '-shortest', mp4], { stdio: 'ignore' });
|
||||
execFileSync('ffmpeg', ['-y', '-i', mp4, '-vn', '-c:a', 'copy', path.join(media, clip.id + '.1.m4a')], { stdio: 'ignore' });
|
||||
const db = createClient({ url: 'file:' + dbPath });
|
||||
await db.execute({ sql: 'INSERT OR REPLACE INTO media_cache (video_id,status,gen,size,height,vcodec,acodec,duration,meta,last_access) VALUES (?,?,?,?,?,?,?,?,?,?)', args: [clip.id, 'ready', 1, statSync(mp4).size, 90, 'h264', 'aac', 3, JSON.stringify(clip), Date.now()] });
|
||||
db.close();
|
||||
for (const [name, type] of Object.entries({ chromium, webkit })) {
|
||||
if (target !== 'all' && target !== name) continue;
|
||||
const browser = await type.launch({ headless: true });
|
||||
results.browsers[name] = [];
|
||||
try {
|
||||
for (const scenario of scenarios.filter(s => !option('--scenarios', null) || option('--scenarios').split(',').includes(s))) {
|
||||
const context = await browser.newContext({ viewport: { width: 414, height: 896 }, serviceWorkers: 'allow' });
|
||||
const page = await context.newPage(), errors = [];
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
const autoPreload = !['pinned-boot', 'playlist-boot-off', 'playlist-add-setting-off', 'settings-enable'].includes(scenario);
|
||||
const settings = { layout: 'f7-swipe', autoPreload, saveBeforePlay: ['open-save-first', 'open-audio-only', 'open-prefer-stream'].includes(scenario), audioOnly: scenario === 'open-audio-only' };
|
||||
const hasPlaylist = scenario.endsWith('boot') || ['playlist-boot-off', 'settings-enable', 'playlist-existing-add'].includes(scenario);
|
||||
const playlists = hasPlaylist ? [{ id: 'test', name: 'Autosave playlist', videos: scenario === 'playlist-existing-add' ? [] : [clip] }] : [];
|
||||
await context.addInitScript(({ settings, playlists, clip, scenario }) => localStorage.setItem('_ytpdata', JSON.stringify({ settings, playlists, history: [clip], pinnedPlaylists: scenario === 'pinned-boot' ? ['test'] : [] })), { settings, playlists, clip, scenario });
|
||||
// No public service/YouTube requests; the local clip uses real prepare/range endpoints.
|
||||
await context.route('**/*', r => r.request().url().startsWith(origin) ? r.continue() : r.abort());
|
||||
await context.route('**/api/streams/warm**', r => r.fulfill({ json: { ok: true } }));
|
||||
try {
|
||||
await page.goto(origin, { waitUntil: 'domcontentloaded' });
|
||||
await page.waitForFunction(() => typeof data !== 'undefined' && window.SettingsSections?.get('downloads-storage'));
|
||||
const supported = await page.evaluate(() => OPFS.isSupported());
|
||||
if (!supported && !results.unsupported.includes(name)) results.unsupported.push(name);
|
||||
// Count invocations in browsers without native OPFS; never treat this as stored bytes.
|
||||
await page.evaluate(() => { window.__saveCalls = 0; const original = API.cacheDownload; API.cacheDownload = (...a) => { window.__saveCalls++; return original(...a); }; });
|
||||
if (scenario.startsWith('open')) await page.evaluate(({ clip, scenario }) => { Player.loadVideo(clip, { preferStream: scenario === 'open-prefer-stream' }); }, { clip, scenario });
|
||||
if (scenario.startsWith('playlist-add')) {
|
||||
await page.evaluate(clip => newPlaylist(clip), clip);
|
||||
await page.locator('#modal input').fill('Autosave playlist');
|
||||
await page.getByRole('button', { name: 'Create', exact: true }).evaluate(b => b.click());
|
||||
}
|
||||
if (scenario === 'playlist-existing-add') {
|
||||
await page.evaluate(clip => openCardMenu(clip), clip);
|
||||
await page.getByRole('button', { name: '+ Autosave playlist', exact: true }).evaluate(b => b.click());
|
||||
}
|
||||
if (scenario.startsWith('settings-')) {
|
||||
await page.evaluate(() => { view = { type: 'settings' }; renderList(); });
|
||||
const id = scenario === 'settings-enable' ? 'setAutoPreload' : 'setSaveBeforePlay';
|
||||
await page.locator('#' + id).evaluate(e => { e.checked = true; e.dispatchEvent(new Event('change', { bubbles: true })); });
|
||||
const key = scenario === 'settings-enable' ? 'autoPreload' : 'saveBeforePlay';
|
||||
await page.waitForFunction(key => JSON.parse(localStorage.getItem('_ytpdata')).settings[key] === true, key);
|
||||
if (scenario === 'settings-save-first') await page.evaluate(clip => { Player.loadVideo(clip); }, clip);
|
||||
}
|
||||
const expected = !['open-default', 'open-audio-only', 'open-prefer-stream', 'playlist-boot-off'].includes(scenario);
|
||||
if (supported && expected) await page.waitForFunction(id => cachedIds.has(id), clip.id, { timeout: 15000 });
|
||||
else await page.waitForTimeout(1000);
|
||||
const state = await page.evaluate(async id => ({ cached: cachedIds.has(id), files: OPFS.isSupported() ? await OPFS.listVideos() : [], queue: SaveQueue.pending(), calls: window.__saveCalls }), clip.id);
|
||||
assert.equal(state.cached, expected && supported, JSON.stringify(state));
|
||||
assert.equal(state.files.some(f => f.id === clip.id && f.size > 0), expected && supported, JSON.stringify(state));
|
||||
if (!supported && expected && !['open-save-first', 'settings-save-first', 'playlist-boot', 'pinned-boot'].includes(scenario)) assert.ok(state.calls > 0, 'save action was not invoked');
|
||||
if (supported && expected) {
|
||||
assert.equal(state.files.find(f => f.id === clip.id).size, statSync(mp4).size, 'stored file is incomplete');
|
||||
await page.evaluate(() => { view = { type: 'saved' }; renderList(); });
|
||||
await page.waitForFunction(() => document.getElementById('cards').textContent.includes('Autosave local clip'));
|
||||
await page.evaluate(() => { view = { type: 'downloads' }; renderList(); });
|
||||
await page.waitForFunction(() => document.getElementById('listTitle').textContent === 'Downloads');
|
||||
}
|
||||
const result = { scenario, supported, saved: state.cached, bytes: state.files.find(f => f.id === clip.id)?.size || 0, calls: state.calls, errors };
|
||||
results.browsers[name].push(result);
|
||||
console.log(`${name} ${scenario}: PASS ${supported ? 'saved=' + state.cached : 'UI/save guard only; OPFS unavailable'}`);
|
||||
} catch (e) {
|
||||
results.failures.push({ browser: name, scenario, error: e.message, errors });
|
||||
console.log(`${name} ${scenario}: FAIL ${e.message.split('\n')[0]}`);
|
||||
} finally { await context.close(); }
|
||||
}
|
||||
} finally { await browser.close(); }
|
||||
}
|
||||
} finally {
|
||||
if (child.exitCode === null) { child.kill('SIGTERM'); await new Promise(r => child.once('exit', r)); }
|
||||
rmSync(scratch, { recursive: true, force: true });
|
||||
const out = option('--out', null);
|
||||
if (out) { mkdirSync(path.dirname(path.resolve(out)), { recursive: true }); writeFileSync(out, JSON.stringify(results, null, 2) + '\n'); }
|
||||
}
|
||||
if (results.failures.length) process.exitCode = 1;
|
||||
else if (results.unsupported.length && !args.includes('--allow-unsupported-webkit')) { console.error('Native OPFS not verified in: ' + results.unsupported.join(', ')); process.exitCode = 2; }
|
||||
208
perf/results/autosave-b77938a.json
Normal file
208
perf/results/autosave-b77938a.json
Normal file
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"revision": "/home/josh/development/personal/ytplayer-codex/wt-autosave/perf/fixtures/shell-1175f1a1d2c1",
|
||||
"browsers": {
|
||||
"chromium": [
|
||||
{
|
||||
"scenario": "open-default",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-audio-only",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-prefer-stream",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add-setting-off",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-existing-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot-off",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
}
|
||||
],
|
||||
"webkit": [
|
||||
{
|
||||
"scenario": "open-default",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-audio-only",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-prefer-stream",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add-setting-off",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-existing-add",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot-off",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"failures": [],
|
||||
"unsupported": [
|
||||
"webkit"
|
||||
],
|
||||
"buildTag": "1175f1a1d2c1"
|
||||
}
|
||||
110
perf/results/autosave-current.json
Normal file
110
perf/results/autosave-current.json
Normal file
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"revision": "/home/josh/development/personal/ytplayer-codex/wt-autosave/frontend",
|
||||
"browsers": {
|
||||
"chromium": [
|
||||
{
|
||||
"scenario": "open-default",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-audio-only",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-prefer-stream",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add-setting-off",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-existing-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot-off",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"failures": [],
|
||||
"unsupported": [],
|
||||
"buildTag": "e93dbca4dc5a"
|
||||
}
|
||||
208
perf/results/autosave-main.json
Normal file
208
perf/results/autosave-main.json
Normal file
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"revision": "main",
|
||||
"browsers": {
|
||||
"chromium": [
|
||||
{
|
||||
"scenario": "open-default",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-audio-only",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-prefer-stream",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add-setting-off",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-existing-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot-off",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
}
|
||||
],
|
||||
"webkit": [
|
||||
{
|
||||
"scenario": "open-default",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-audio-only",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-prefer-stream",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add-setting-off",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-existing-add",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot-off",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": false,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"failures": [],
|
||||
"unsupported": [
|
||||
"webkit"
|
||||
],
|
||||
"buildTag": "c3dbdd7039db"
|
||||
}
|
||||
110
perf/results/autosave-phase1.json
Normal file
110
perf/results/autosave-phase1.json
Normal file
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"revision": "codex/phase1",
|
||||
"browsers": {
|
||||
"chromium": [
|
||||
{
|
||||
"scenario": "open-default",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-audio-only",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-prefer-stream",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add-setting-off",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-existing-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot-off",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"failures": [],
|
||||
"unsupported": [],
|
||||
"buildTag": "288787b9f7db"
|
||||
}
|
||||
110
perf/results/autosave-phase2.json
Normal file
110
perf/results/autosave-phase2.json
Normal file
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"revision": "codex/phase2",
|
||||
"browsers": {
|
||||
"chromium": [
|
||||
{
|
||||
"scenario": "open-default",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-audio-only",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "open-prefer-stream",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add-setting-off",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-existing-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot-off",
|
||||
"supported": true,
|
||||
"saved": false,
|
||||
"bytes": 0,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"failures": [],
|
||||
"unsupported": [],
|
||||
"buildTag": "4f7090fff60c"
|
||||
}
|
||||
60
perf/results/autosave-phase3.json
Normal file
60
perf/results/autosave-phase3.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"revision": "codex/phase3",
|
||||
"browsers": {
|
||||
"chromium": [
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"failures": [],
|
||||
"unsupported": [],
|
||||
"buildTag": "bea1f63eba85"
|
||||
}
|
||||
60
perf/results/autosave-phase4.json
Normal file
60
perf/results/autosave-phase4.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"revision": "codex/phase4",
|
||||
"browsers": {
|
||||
"chromium": [
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"failures": [],
|
||||
"unsupported": [],
|
||||
"buildTag": "c3dbdd7039db"
|
||||
}
|
||||
60
perf/results/autosave-phase5.json
Normal file
60
perf/results/autosave-phase5.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"revision": "codex/phase5",
|
||||
"browsers": {
|
||||
"chromium": [
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"failures": [],
|
||||
"unsupported": [],
|
||||
"buildTag": "c3dbdd7039db"
|
||||
}
|
||||
62
perf/results/autosave-rollback.json
Normal file
62
perf/results/autosave-rollback.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"revision": "/home/josh/development/personal/ytplayer-codex/wt-autosave/frontend",
|
||||
"browsers": {
|
||||
"chromium": [
|
||||
{
|
||||
"scenario": "open-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-add",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "playlist-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "pinned-boot",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"scenario": "settings-enable",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"scenario": "settings-save-first",
|
||||
"supported": true,
|
||||
"saved": true,
|
||||
"bytes": 30290,
|
||||
"calls": 1,
|
||||
"errors": [
|
||||
"Cannot read properties of null (reading 'addEventListener')"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"failures": [],
|
||||
"unsupported": [],
|
||||
"buildTag": "2b1c433b19aa"
|
||||
}
|
||||
Reference in New Issue
Block a user