Limit the WebKit response handoff to uncontrolled visits
This commit is contained in:
@@ -125,7 +125,7 @@
|
||||
// Own this response once. Classic-script and fetch preloads do not share
|
||||
// their cached bodies in WebKit; the later bootstrap consumes this promise.
|
||||
const agent=root.navigator.userAgent || '';
|
||||
api.captureApp=!!(manifest.appCache && root.crypto?.subtle && /AppleWebKit\//.test(agent) && !/(?:Chrome|Chromium|Edg|OPR)\//.test(agent));
|
||||
api.captureApp=!!(manifest.appCache && !root.navigator.serviceWorker?.controller && root.crypto?.subtle && /AppleWebKit\//.test(agent) && !/(?:Chrome|Chromium|Edg|OPR)\//.test(agent));
|
||||
if(api.captureApp) {
|
||||
api.appResponse=(async()=>{
|
||||
const key=url('/app.js');
|
||||
|
||||
@@ -2,12 +2,12 @@ const { test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const { readFileSync } = require('node:fs');
|
||||
const vm = require('node:vm');
|
||||
function fixture(current, held = [], appCache = false, userAgent = 'AppleWebKit/605.1 Safari/605.1') {
|
||||
function fixture(current, held = [], appCache = false, userAgent = 'AppleWebKit/605.1 Safari/605.1', controlled = false) {
|
||||
const inserted = [], listeners = {}, writes = [], fetched = [];
|
||||
const manifest = { buildTag: 'own', appCache, groups: { core: { files: [] }, 'layout:classic': { files: ['/classic.css'] }, 'layout:glass-stage': { files: ['/glass.css', '/one.js', '/two.js'] }, 'feature:test': { contract:1, files: ['/one.js', '/two.js'] } }, files: { '/app.js':{h:'a'}, '/classic.css': {h:'c'}, '/glass.css':{h:'g'}, '/one.js':{h:'1'}, '/two.js':{h:'2'} } };
|
||||
const doc = { readyState:'loading', documentElement: { dataset:{} }, getElementById: () => ({ textContent:JSON.stringify(manifest) }), querySelectorAll: () => [], createElement: tag => ({ tagName:tag.toUpperCase() }), write: value => writes.push(value), addEventListener: (t,f) => listeners[t]=f };
|
||||
doc.head = { append: node => { inserted.push(node); queueMicrotask(() => node.onload?.()); } };
|
||||
const root = { document:doc, localStorage:{ getItem:() => '{"settings":{"layout":"glass-stage"}}' }, console, Promise, URL, crypto:{subtle:{}}, fetch:async key=>{fetched.push(key);return new Response('app');}, setTimeout, clearTimeout, navigator:{userAgent}, addEventListener(){} };
|
||||
const root = { document:doc, localStorage:{ getItem:() => '{"settings":{"layout":"glass-stage"}}' }, console, Promise, URL, crypto:{subtle:{}}, fetch:async key=>{fetched.push(key);return new Response('app');}, setTimeout, clearTimeout, navigator:{userAgent,serviceWorker:{controller:controlled?{}:null,addEventListener(){}}}, addEventListener(){} };
|
||||
if (current) root.caches = { open: async () => ({ match: async key => key === '/__ytp_asset_state' ? new Response(JSON.stringify({current})) : held.includes(key) ? new Response('', {headers:{'X-Asset-Hash':key.split('=')[1]}}) : undefined }) };
|
||||
root.window=root; root.globalThis=root;
|
||||
vm.runInNewContext(readFileSync(require.resolve('./lazy.js'),'utf8'), root);
|
||||
@@ -108,3 +108,9 @@ test('iOS Chromium-branded browsers still use their WebKit response capture',asy
|
||||
const f=fixture(null,[],true,'AppleWebKit/605.1 CriOS/140.0 Mobile Safari/605.1');await f.root.Lazy.appResponse;
|
||||
assert.equal(f.root.Lazy.captureApp,true);assert.deepEqual(f.fetched,['/app.js?v=a']);
|
||||
});
|
||||
|
||||
test('controlled WebKit visits use worker-cached native app scripts without a response handoff',async()=>{
|
||||
const f=fixture(null,[],true,'AppleWebKit/605.1 Safari/605.1',true);
|
||||
assert.equal(f.root.Lazy.captureApp,false);assert.equal(f.root.Lazy.appResponse,undefined);assert.deepEqual(f.fetched,[]);
|
||||
assert.equal(f.inserted[0].as,'script');assert.equal(f.inserted[0].href,'/app.js?v=a');
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"results": [
|
||||
{
|
||||
"browser": "chromium",
|
||||
"sourceBuildTag": "22eb7414f94c",
|
||||
"sourceBuildTag": "38131d1a6b5e",
|
||||
"classicSharedDefaults": true,
|
||||
"cssOrderPreserved": true,
|
||||
"settingsSearch": true,
|
||||
@@ -28,7 +28,7 @@
|
||||
},
|
||||
{
|
||||
"browser": "webkit",
|
||||
"sourceBuildTag": "22eb7414f94c",
|
||||
"sourceBuildTag": "38131d1a6b5e",
|
||||
"classicSharedDefaults": true,
|
||||
"cssOrderPreserved": true,
|
||||
"settingsSearch": true,
|
||||
@@ -56,7 +56,7 @@
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "/127.0.0.1:33445/api/version.",
|
||||
"message": "/127.0.0.1:43269/api/recommendations?fp=163577c02a53bc40.",
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
@@ -64,7 +64,7 @@
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "/127.0.0.1:33445/api/recommendations?fp=163577c02a53bc40.",
|
||||
"message": "/127.0.0.1:43269/api/version.",
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
@@ -72,7 +72,7 @@
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "/127.0.0.1:33445/api/version.",
|
||||
"message": "/127.0.0.1:43269/api/version.",
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
@@ -80,7 +80,7 @@
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "/127.0.0.1:33445/api/recommendations?fp=163577c02a53bc40.",
|
||||
"message": "/127.0.0.1:43269/api/recommendations?fp=163577c02a53bc40.",
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
@@ -88,7 +88,7 @@
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "/127.0.0.1:33445/api/version.",
|
||||
"message": "/127.0.0.1:43269/api/version.",
|
||||
"disconnected": true
|
||||
}
|
||||
]
|
||||
|
||||
@@ -106,3 +106,10 @@ CacheStorage or hashing work. WebKit's byte-verified owned response path is
|
||||
unchanged. The native fixture models the actual worker fallback decision instead
|
||||
of a second page-side decision. All 221 frontend tests and 184 server tests pass;
|
||||
both-engine lazy/offline/eviction/pinning/contracts/playback smoke passes.
|
||||
|
||||
The WebKit warm prototype also paid repeated handoff/cache/hash work (warm
|
||||
~98 ms versus Phase 5 83 ms). Capture now applies only to uncontrolled WebKit
|
||||
visits. Controlled warm/offline/update pages use the worker's native exact-URL
|
||||
script path, including its strengthened contract guard. A failing head-loader
|
||||
test precedes this change; all 222 frontend and 184 server tests and both-engine
|
||||
lazy smoke pass. Cold capture and both rollback flags are unchanged.
|
||||
|
||||
Reference in New Issue
Block a user