1- import type { InPageChannelProtocol , PageScriptChannel , PanelChannel } from './types'
1+ import type { ConnectPanelChannelOptions , CreatePageScriptChannelOptions , InPageChannelProtocol , PageScriptChannel , PanelChannel } from './types'
22import { describe , expect , it , vi } from 'vitest'
3- import { defineChannelFunction } from './index'
43import { InPageChannelError } from './internal'
54import { createPageScriptChannel } from './page-script'
65import { connectPanelChannel } from './panel'
@@ -39,29 +38,42 @@ function until(predicate: () => boolean, timeoutMs = 2000): Promise<void> {
3938
4039const noHandshake = { window : false as const , heartbeat : false as const }
4140
41+ const defaultPageScriptFunctions : NonNullable < CreatePageScriptChannelOptions < TestProtocol > [ 'functions' ] > = {
42+ echo : { handler : value => value } ,
43+ sum : { handler : ( a , b ) => a + b } ,
44+ boom : { handler : ( ) => { } } ,
45+ strict : { handler : payload => payload } ,
46+ note : { type : 'event' , handler : ( ) => { } } ,
47+ }
48+
49+ const defaultPanelFunctions : NonNullable < ConnectPanelChannelOptions < TestProtocol > [ 'functions' ] > = {
50+ 'ping-panel' : { handler : value => `pong:${ value } ` } ,
51+ 'notify' : { type : 'event' , handler : ( ) => { } } ,
52+ }
53+
4254function createLinkedPair ( options ?: {
43- pageScript ?: Partial < Parameters < typeof createPageScriptChannel > [ 0 ] >
44- panel ?: Partial < Parameters < typeof connectPanelChannel > [ 0 ] >
55+ pageScript ?: Partial < CreatePageScriptChannelOptions < TestProtocol > >
56+ panel ?: Partial < ConnectPanelChannelOptions < TestProtocol > >
4557} ) : { pageScript : PageScriptChannel < TestProtocol > , panel : PanelChannel < TestProtocol > , dispose : ( ) => void } {
4658 const { port1, port2 } = new MessageChannel ( )
4759 const pageScript = createPageScriptChannel < TestProtocol > ( {
4860 name : 'devframes:test' ,
4961 ...noHandshake ,
50- functions : [
51- defineChannelFunction ( { name : 'echo' , handler : ( value : string ) => value } ) ,
52- defineChannelFunction ( { name : 'sum' , type : 'query' , handler : ( a : number , b : number ) => a + b } ) ,
53- defineChannelFunction ( { name : 'boom' , handler : ( ) => {
62+ functions : {
63+ ...defaultPageScriptFunctions ,
64+ boom : { handler : ( ) => {
5465 throw new Error ( 'exploded' )
55- } } ) ,
56- defineChannelFunction ( { name : 'strict' , jsonSerializable : true , handler : ( payload : unknown ) => payload } ) ,
57- ] ,
66+ } } ,
67+ strict : { jsonSerializable : true , handler : payload => payload } ,
68+ } ,
5869 ...options ?. pageScript ,
5970 } )
6071 pageScript . addPanelPort ( port1 )
6172 const panel = connectPanelChannel < TestProtocol > ( {
6273 name : 'devframes:test' ,
6374 ...noHandshake ,
6475 transport : port2 ,
76+ functions : defaultPanelFunctions ,
6577 ...options ?. panel ,
6678 } )
6779 return {
@@ -142,20 +154,21 @@ describe('in-page channel over bring-your-own ports', () => {
142154 const pageScript = createPageScriptChannel < TestProtocol > ( {
143155 name : 'devframes:test' ,
144156 ...noHandshake ,
145- functions : [
146- defineChannelFunction ( {
147- name : 'note' ,
157+ functions : {
158+ ... defaultPageScriptFunctions ,
159+ note : {
148160 args : [ s . string ( ) ] as const ,
149161 returns : s . void ( ) ,
150162 handler : ( ) => { } ,
151- } ) ,
152- ] ,
163+ } ,
164+ } ,
153165 } )
154166 pageScript . addPanelPort ( port1 )
155167 const panel = connectPanelChannel < TestProtocol > ( {
156168 name : 'devframes:test' ,
157169 ...noHandshake ,
158170 transport : port2 ,
171+ functions : defaultPanelFunctions ,
159172 } )
160173 try {
161174 await expect ( panel . call ( 'note' , 'fine' ) ) . resolves . toBeUndefined ( )
@@ -174,6 +187,7 @@ describe('in-page channel over bring-your-own ports', () => {
174187 const pageScript = createPageScriptChannel < TestProtocol > ( {
175188 name : 'devframes:test' ,
176189 ...noHandshake ,
190+ functions : defaultPageScriptFunctions ,
177191 } )
178192 pageScript . addPanelPort ( a . port1 )
179193 pageScript . addPanelPort ( b . port1 )
@@ -182,17 +196,19 @@ describe('in-page channel over bring-your-own ports', () => {
182196 name : 'devframes:test' ,
183197 ...noHandshake ,
184198 transport : a . port2 ,
185- functions : [
186- defineChannelFunction ( { name : 'notify' , type : 'event' , handler : ( value : string ) => {
199+ functions : {
200+ ...defaultPanelFunctions ,
201+ notify : { type : 'event' , handler : ( value ) => {
187202 received . push ( `a:${ value } ` )
188- } } ) ,
189- ] ,
203+ } } ,
204+ } ,
190205 } )
191- // Panel B deliberately implements nothing .
192- const panelB = connectPanelChannel < TestProtocol > ( {
206+ // Panel B deliberately has no local functions in its protocol .
207+ const panelB = connectPanelChannel < InPageChannelProtocol > ( {
193208 name : 'devframes:test' ,
194209 ...noHandshake ,
195210 transport : b . port2 ,
211+ functions : { } ,
196212 } )
197213 try {
198214 expect ( pageScript . panels ) . toHaveLength ( 2 )
@@ -212,15 +228,14 @@ describe('in-page channel over bring-your-own ports', () => {
212228 const pageScript = createPageScriptChannel < TestProtocol > ( {
213229 name : 'devframes:test' ,
214230 ...noHandshake ,
231+ functions : defaultPageScriptFunctions ,
215232 } )
216233 pageScript . addPanelPort ( port1 )
217234 const panel = connectPanelChannel < TestProtocol > ( {
218235 name : 'devframes:test' ,
219236 ...noHandshake ,
220237 transport : port2 ,
221- functions : [
222- defineChannelFunction ( { name : 'ping-panel' , handler : ( value : string ) => `pong:${ value } ` } ) ,
223- ] ,
238+ functions : defaultPanelFunctions ,
224239 } )
225240 try {
226241 const peer = pageScript . panels [ 0 ] !
@@ -237,15 +252,14 @@ describe('in-page channel over bring-your-own ports', () => {
237252 const pageScript = createPageScriptChannel < TestProtocol > ( {
238253 name : 'devframes:test' ,
239254 ...noHandshake ,
240- functions : [
241- defineChannelFunction ( { name : 'echo' , handler : ( value : any ) => value } ) ,
242- ] ,
255+ functions : defaultPageScriptFunctions ,
243256 } )
244257 pageScript . addPanelPort ( port1 )
245258 const panel = connectPanelChannel < TestProtocol > ( {
246259 name : 'devframes:test' ,
247260 ...noHandshake ,
248261 transport : port2 ,
262+ functions : defaultPanelFunctions ,
249263 // Unwrap a fake reactivity wrapper on the way out, tag on the way in.
250264 serialize : value => ( value && typeof value === 'object' && '__wrapped' in ( value as any ) )
251265 ? ( value as any ) . __wrapped
@@ -266,6 +280,7 @@ describe('in-page channel over bring-your-own ports', () => {
266280 const pageScript = createPageScriptChannel < TestProtocol > ( {
267281 name : 'devframes:test' ,
268282 ...noHandshake ,
283+ functions : defaultPageScriptFunctions ,
269284 } )
270285 const connected : string [ ] = [ ]
271286 const disconnected : string [ ] = [ ]
@@ -276,6 +291,7 @@ describe('in-page channel over bring-your-own ports', () => {
276291 name : 'devframes:test' ,
277292 ...noHandshake ,
278293 transport : port2 ,
294+ functions : defaultPanelFunctions ,
279295 } )
280296 try {
281297 expect ( connected ) . toHaveLength ( 1 )
@@ -316,11 +332,12 @@ describe('in-page channel shared state', () => {
316332 const pageScript = createPageScriptChannel < TestProtocol > ( {
317333 name : 'devframes:test' ,
318334 ...noHandshake ,
335+ functions : defaultPageScriptFunctions ,
319336 } )
320337 pageScript . addPanelPort ( a . port1 )
321338 pageScript . addPanelPort ( b . port1 )
322- const panelA = connectPanelChannel < TestProtocol > ( { name : 'devframes:test' , ...noHandshake , transport : a . port2 } )
323- const panelB = connectPanelChannel < TestProtocol > ( { name : 'devframes:test' , ...noHandshake , transport : b . port2 } )
339+ const panelA = connectPanelChannel < TestProtocol > ( { name : 'devframes:test' , ...noHandshake , transport : a . port2 , functions : defaultPanelFunctions } )
340+ const panelB = connectPanelChannel < TestProtocol > ( { name : 'devframes:test' , ...noHandshake , transport : b . port2 , functions : defaultPanelFunctions } )
324341 try {
325342 const authority = await pageScript . sharedState . get ( 'doc' , { initialValue : { count : 0 } } )
326343 const mirrorA = await panelA . sharedState . get ( 'doc' )
@@ -341,7 +358,7 @@ describe('in-page channel shared state', () => {
341358
342359 it ( 'seeds a late-joining panel with the current value' , async ( ) => {
343360 const { port1, port2 } = new MessageChannel ( )
344- const pageScript = createPageScriptChannel < TestProtocol > ( { name : 'devframes:test' , ...noHandshake } )
361+ const pageScript = createPageScriptChannel < TestProtocol > ( { name : 'devframes:test' , ...noHandshake , functions : defaultPageScriptFunctions } )
345362 const authority = await pageScript . sharedState . get ( 'doc' , { initialValue : { count : 0 } } )
346363 authority . mutate ( ( draft ) => {
347364 draft . count = 41
@@ -351,7 +368,7 @@ describe('in-page channel shared state', () => {
351368 } )
352369
353370 pageScript . addPanelPort ( port1 )
354- const panel = connectPanelChannel < TestProtocol > ( { name : 'devframes:test' , ...noHandshake , transport : port2 } )
371+ const panel = connectPanelChannel < TestProtocol > ( { name : 'devframes:test' , ...noHandshake , transport : port2 , functions : defaultPanelFunctions } )
355372 try {
356373 const mirror = await panel . sharedState . get ( 'doc' )
357374 expect ( mirror . value ( ) ) . toEqual ( { count : 42 } )
@@ -443,13 +460,14 @@ describe('in-page channel handshake', () => {
443460 name : 'devframes:test' ,
444461 window : hostWin as unknown as Window ,
445462 heartbeat : false ,
446- functions : [ defineChannelFunction ( { name : 'echo' , handler : ( value : string ) => value } ) ] ,
463+ functions : defaultPageScriptFunctions ,
447464 } )
448465 const panel = connectPanelChannel < TestProtocol > ( {
449466 name : 'devframes:test' ,
450467 window : panelWin as unknown as Window ,
451468 targets : [ hostWin as unknown as Window ] ,
452469 ...fastHello ,
470+ functions : defaultPanelFunctions ,
453471 } )
454472 try {
455473 await panel . whenConnected ( 2000 )
@@ -465,7 +483,10 @@ describe('in-page channel handshake', () => {
465483 name : 'devframes:test' ,
466484 window : hostWin as unknown as Window ,
467485 heartbeat : false ,
468- functions : [ defineChannelFunction ( { name : 'echo' , handler : ( value : string ) => `revived:${ value } ` } ) ] ,
486+ functions : {
487+ ...defaultPageScriptFunctions ,
488+ echo : { handler : value => `revived:${ value } ` } ,
489+ } ,
469490 } )
470491 try {
471492 await panel . whenConnected ( 2000 )
@@ -489,6 +510,7 @@ describe('in-page channel handshake', () => {
489510 window : panelWin as unknown as Window ,
490511 targets : [ hostWin as unknown as Window ] ,
491512 ...fastHello ,
513+ functions : defaultPanelFunctions ,
492514 } )
493515 const early = panel . call ( 'echo' , 'early' )
494516 panel . callEvent ( 'note' , 'buffered' )
@@ -497,12 +519,12 @@ describe('in-page channel handshake', () => {
497519 name : 'devframes:test' ,
498520 window : hostWin as unknown as Window ,
499521 heartbeat : false ,
500- functions : [
501- defineChannelFunction ( { name : 'echo' , handler : ( value : string ) => value } ) ,
502- defineChannelFunction ( { name : 'note' , type : 'event' , handler : ( value : string ) => {
522+ functions : {
523+ ... defaultPageScriptFunctions ,
524+ note : { type : 'event' , handler : ( value ) => {
503525 noted . push ( value )
504- } } ) ,
505- ] ,
526+ } } ,
527+ } ,
506528 } )
507529 try {
508530 await expect ( early ) . resolves . toBe ( 'early' )
@@ -522,6 +544,7 @@ describe('in-page channel handshake', () => {
522544 name : 'devframes:test-origin' ,
523545 window : hostWin as unknown as Window ,
524546 heartbeat : false ,
547+ functions : defaultPageScriptFunctions ,
525548 } )
526549 try {
527550 hostWin . __dispatch ( {
@@ -552,6 +575,7 @@ describe('in-page channel handshake', () => {
552575 name : 'devframes:test-version' ,
553576 window : hostWin as unknown as Window ,
554577 heartbeat : false ,
578+ functions : defaultPageScriptFunctions ,
555579 } )
556580 try {
557581 hostWin . __dispatch ( {
@@ -581,13 +605,15 @@ describe('in-page channel handshake', () => {
581605 name : 'devframes:test' ,
582606 window : hostWin as unknown as Window ,
583607 heartbeat : false ,
608+ functions : defaultPageScriptFunctions ,
584609 } )
585610 const pinnedElsewhere = connectPanelChannel < TestProtocol > ( {
586611 name : 'devframes:test' ,
587612 window : panelWin as unknown as Window ,
588613 targets : [ hostWin as unknown as Window ] ,
589614 instanceId : 'some-other-tab' ,
590615 ...fastHello ,
616+ functions : defaultPanelFunctions ,
591617 } )
592618 try {
593619 await expect ( pinnedElsewhere . whenConnected ( 100 ) ) . rejects . toMatchObject ( { code : 'timeout' } )
@@ -598,6 +624,7 @@ describe('in-page channel handshake', () => {
598624 targets : [ hostWin as unknown as Window ] ,
599625 instanceId : pageScript . instanceId ,
600626 ...fastHello ,
627+ functions : defaultPanelFunctions ,
601628 } )
602629 try {
603630 await pinnedHere . whenConnected ( 2000 )
@@ -618,6 +645,7 @@ describe('in-page channel handshake', () => {
618645 name : `devframes:test-lonely-${ Math . random ( ) } ` ,
619646 window : false ,
620647 heartbeat : false ,
648+ functions : defaultPanelFunctions ,
621649 } )
622650 try {
623651 expect ( lonely . status ) . toBe ( 'connecting' )
@@ -636,6 +664,7 @@ describe('in-page channel handshake', () => {
636664 window : false ,
637665 heartbeat : false ,
638666 callTimeoutMs : 50 ,
667+ functions : defaultPanelFunctions ,
639668 } )
640669 try {
641670 const rejection = await lonely . call ( 'echo' , 'nobody' ) . catch ( error => error )
@@ -653,6 +682,7 @@ describe('in-page channel handshake', () => {
653682 name : `devframes:test-lonely-${ Math . random ( ) } ` ,
654683 window : false ,
655684 heartbeat : false ,
685+ functions : defaultPanelFunctions ,
656686 } )
657687 const pending = lonely . call ( 'echo' , 'never' )
658688 const waiting = lonely . whenConnected ( )
0 commit comments