Bridge JS semicolon warnings fixed

This commit is contained in:
Alexey
2026-10-03 20:29:18 +03:00
parent dcce897d8b
commit e2f1c3f3a9
5 changed files with 24 additions and 11 deletions
+15 -1
View File
@@ -228,7 +228,7 @@ test('multiple precommit lanes survive fallback without losing stream ordering',
env.send(join(frame(2,2,[2]),frame(2,1,[1])));await flush();await env.tick(3001);
const next=env.pending('/api/v1/session')[0];env.answer(next,200,frame(17),{'X-Session-Token':'C'.repeat(43),'X-Down-Cursor':'0','X-Carrier-Mode':'https','X-Carrier-Attempt':'2','X-Carrier-Candidate-Count':'4','X-Carrier-Deadline':'12','X-Carrier-State':'provisional','X-Telemt-Up-Window':'4'});await flush();
const requests=env.requests.filter(r=>r.url.endsWith('/api/v1/up')&&r.options.headers.Authorization==='Bearer '+'C'.repeat(43));
const frames=[];for(const request of requests){const bytes=new Uint8Array(request.options.body);for(let offset=0;offset<bytes.length;){const view=new DataView(bytes.buffer,offset);frames.push([bytes[offset],bytes[offset+3]]);offset+=8+view.getUint32(4)}}
const frames=[];for(const request of requests){const bytes=new Uint8Array(request.options.body);for(let offset=0;offset<bytes.length;){const view=new DataView(bytes.buffer,offset);frames.push([bytes[offset],bytes[offset+3]]);offset+=8+view.getUint32(4);}}
for(const id of [1,2])assert.deepEqual(frames.filter(value=>value[1]===id),[[1,id],[2,id]]);
assert.equal(frames.length,4);env.close();await flush();
});
@@ -248,4 +248,18 @@ test('receiver retirement releases shared prefix capacity without exposing a par
b.owner.close();env.close();await flush();
});
test('native close cancels every HTTP request and pagehide cannot repeat cleanup',async page=>{
for(const android of [false,true])for(const carrier of ['https','https-lanes']){
const env=await session(page,carrier,4,android);env.send(frame(1,1));await flush();env.send(frame(2,1,[7]));await flush();
const up=env.pending('/api/v1/up'),down=env.pending('/api/v1/down'),requests=up.concat(down);
assert.equal(up.length,2);assert.equal(down.length,1);assert.ok(requests.every(request=>!request.options.signal.aborted));
env.send({t:'close'});await flush();
assert.ok(requests.every(request=>request.options.signal.aborted));
assert.equal(env.requests.filter(request=>request.options.method==='DELETE').length,1);
const count=env.requests.length;env.close();await env.tick(120000);
assert.equal(env.requests.filter(request=>request.options.method==='DELETE').length,1);
assert.equal(env.requests.length,count);
}
});
(async()=>{const page=renderedPage();let failed=0;for(const {name,run} of tests){let timer;try{await Promise.race([run(page),new Promise((_,reject)=>{timer=setTimeout(()=>reject(new Error('test made no bounded progress')),5000)})]);console.log('ok - '+name)}catch(error){failed++;console.error('not ok - '+name+'\n'+error.stack)}finally{clearTimeout(timer)}}if(failed)process.exitCode=1})();
+1 -1
View File
@@ -92,7 +92,7 @@ function create(settings){
function retire(channel,restore){
channel.closed=true;if(channel.controller)channel.controller.abort();channel.receiver.close();
const saved=[];
for(const lease of channel.flights.values()){if(restore)saved.push({order:lease.order,data:lease.body});settings.buffers.cancelBatch(lease)}
for(const lease of channel.flights.values()){if(restore)saved.push({order:lease.order,data:lease.body});settings.buffers.cancelBatch(lease);}
channel.flights.clear();channel.acks.clear();
for(const data of channel.pending)if(restore)saved.push({order:order++,data});
settings.buffers.releasePending(channel.pending,channel.lane);return saved;
+4 -4
View File
@@ -38,11 +38,11 @@ function create(settings){
const next=response.headers.get('X-Down-Cursor')||'',base=settings.cursor();
if(!/^[1-9]\d*$/.test(next)||BigInt(next)!==BigInt(base)+1n||BigInt(next)>18446744073709551615n)throw protocol('invalid downlink cursor');
const length=response.headers.get('Content-Length');let declared=null;
if(length!==null){if(!/^(0|[1-9]\d*)$/.test(length))throw protocol('invalid response length');declared=Number(length);if(!Number.isSafeInteger(declared)||declared===0||declared>settings.limit())throw protocol('response body overflow')}
if(length!==null){if(!/^(0|[1-9]\d*)$/.test(length))throw protocol('invalid response length');declared=Number(length);if(!Number.isSafeInteger(declared)||declared===0||declared>settings.limit())throw protocol('response body overflow');}
if(transaction&&(transaction.base!==base||transaction.next!==next||(transaction.declared!==null&&declared!==null&&transaction.declared!==declared)))throw protocol('changed replay metadata');
if(!transaction){
const capacity=declared===null?settings.limit():declared,release=await settings.budget.acquire(capacity,signal);
if(!current(signal)){release();throw new Error('downlink retired')}
if(!current(signal)){release();throw new Error('downlink retired');}
transaction={base,next,declared,bytes:new Uint8Array(capacity),retained:0,delivered:0,release};
}
const owner=transaction;
@@ -53,7 +53,7 @@ function create(settings){
const reader=response.body.getReader();let position=0,offset=0,frames=0,chunks=0,complete=false;
try{
for(;;){
let part;try{part=await reader.read()}catch(error){throw settings.failure('network','response stream interrupted')}
let part;try{part=await reader.read();}catch(error){throw settings.failure('network','response stream interrupted');}
if(!current(signal)||transaction!==owner)throw new Error('downlink retired');
if(part.done)break;
const data=part.value;if(!(data instanceof Uint8Array)||++chunks>65536||data.byteLength>owner.bytes.byteLength-position)throw protocol('response body overflow');
@@ -76,7 +76,7 @@ function create(settings){
if(!position||offset!==position||position<owner.retained||(owner.declared!==null&&position!==owner.declared))throw protocol('incomplete downlink batch');
settings.advance(next);complete=true;dispose();return new ArrayBuffer(0);
}finally{
if(!complete)try{const cancelled=reader.cancel();if(cancelled)cancelled.catch(()=>{})}catch(error){}
if(!complete)try{const cancelled=reader.cancel();if(cancelled)cancelled.catch(()=>{});}catch(error){}
reader.releaseLock();
}
}
+1 -1
View File
@@ -46,7 +46,7 @@ function create(settings){
lastReason='http';wait=retryAfterMs(fetched);settings.cancel(fetched);
}else{
const policy=responsePolicy(path,fetched.status);let body;
try{body=receiver&&(fetched.status===200||fetched.status===204)?await receiver(fetched,controller.signal):await settings.read(fetched,policy.limit,policy.exact,controller.signal)}
try{body=receiver&&(fetched.status===200||fetched.status===204)?await receiver(fetched,controller.signal):await settings.read(fetched,policy.limit,policy.exact,controller.signal);}
catch(error){
controller.abort();
if(external&&external.aborted)throw error;
+3 -4
View File
@@ -19,7 +19,7 @@ let laneQueueLimit=Math.min(queueLimit,8388608),laneItemLimit=Math.min(queueItem
const fragment=location.hash,androidNonce=/^#android=([A-Za-z0-9_-]{43})$/.exec(fragment)?.[1]||'',recoveryPath=location.pathname+location.search;
history.replaceState(null,'',location.pathname);
let initialized=false,closed=false,port=null,sessionToken='',cleanupToken='',createStarted=false,socket=null,socketReady=false,carrier='';
let upSequence=1,downCursor='0',upRunning=false,upLease=null,pollController=null,httpCarrier=null,upWindow=1;
let upSequence=1,downCursor='0',upRunning=false,upLease=null,httpCarrier=null,upWindow=1;
let helloFrame=null,helloTimer=null,welcomeSent=false,carrierAttempt=1,carrierFailure='',carrierCommitted=false,terminalFailure='';
let negotiationStartedAt=0,carrierTimer=null,probeTimer=null,attemptController=null,attemptEpoch=1,candidateRunning=false,switching=false,currentAttempt=null;
let recoveryController=null,recoveryCommit=null,recoveryReplaced=false,lastSchedulerWall=Date.now(),lastSchedulerMonotonic=performance.now(),schedulerGapPending=0,schedulerTimer=null;
@@ -60,7 +60,7 @@ function resolveRecoveryCommit(){
function retireCarrier(policy){
stopHttp(false);upWindow=1;
recoveryReplaced=true;attemptEpoch++;if(carrierTimer)clearTimeout(carrierTimer);carrierTimer=null;clearProbeTimer();
if(attemptController)attemptController.abort();attemptController=null;if(pollController)pollController.abort();pollController=null;
if(attemptController)attemptController.abort();attemptController=null;
if(socket){const previous=socket;socket=null;previous.close()}socketReady=false;cancelBatch(upLease);releasePending(upPending,null);
for(const lane of lanes.values()){
if(lane.controller)lane.controller.abort();cancelBatch(lane.upLease);releasePending(lane.pending,lane);if(lane.socket)lane.socket.close();
@@ -144,7 +144,6 @@ function clearProbeTimer(){if(probeTimer){clearTimeout(probeTimer.timer);probeTi
function resetCandidate(){
stopHttp(true);upWindow=1;
clearProbeTimer();
if(pollController)pollController.abort();pollController=null;
if(socket){const previous=socket;socket=null;previous.close()}socketReady=false;
cancelBatch(upLease);releasePending(upPending,null);
for(const lane of lanes.values()){
@@ -384,7 +383,7 @@ function deleteSession(){
if(token)fetch(relayBase+'/api/v1/session',options('DELETE',token,null,headers,undefined,true)).catch(()=>{});
}
function close(notifyServer){
if(closed)return;closed=true;stopHttp(false);if(recoveryController)recoveryController.cancel();rejectRecoveryCommit(failure('network','bridge closed'));if(helloTimer)clearTimeout(helloTimer);helloTimer=null;if(carrierTimer)clearTimeout(carrierTimer);clearProbeTimer();if(schedulerTimer)clearTimeout(schedulerTimer);schedulerTimer=null;if(attemptController)attemptController.abort();if(pollController)pollController.abort();
if(closed)return;closed=true;stopHttp(false);if(recoveryController)recoveryController.cancel();rejectRecoveryCommit(failure('network','bridge closed'));if(helloTimer)clearTimeout(helloTimer);helloTimer=null;if(carrierTimer)clearTimeout(carrierTimer);clearProbeTimer();if(schedulerTimer)clearTimeout(schedulerTimer);schedulerTimer=null;if(attemptController)attemptController.abort();
if(socket)socket.close();cancelBatch(upLease);releasePending(upPending,null);
for(const lane of lanes.values()){
if(lane.controller)lane.controller.abort();cancelBatch(lane.upLease);releasePending(lane.pending,lane);if(lane.socket)lane.socket.close();