11import type { SerovalNode } from 'seroval' ;
22import { createPlugin } from 'seroval' ;
33
4+ const PROMISE_TO_ABORT_SIGNAL = ( promise : Promise < unknown > ) => {
5+ const controller = new AbortController ( ) ;
6+ const abort = controller . abort . bind ( controller ) ;
7+ promise . then ( abort , abort ) ;
8+ return controller ;
9+ } ;
10+
411function resolveAbortSignalResult (
512 this : AbortSignal ,
613 resolve : ( value : any ) => void ,
@@ -17,87 +24,42 @@ function resolveAbortSignal(
1724 } ) ;
1825}
1926
20- export function abortSignalToPromise ( signal : AbortSignal ) : Promise < any > {
27+ function abortSignalToPromise ( signal : AbortSignal ) : Promise < any > {
2128 return new Promise ( resolveAbortSignal . bind ( signal ) ) ;
2229}
2330
24- class AbortSignalController {
25- controller = new AbortController ( ) ;
26- }
31+ const ABORT_CONTROLLER = { } ;
2732
28- const AbortSignalControllerPlugin = createPlugin < AbortSignalController , { } > ( {
29- tag : 'seroval-plugins/web/AbortSignalController ' ,
33+ const AbortControllerFactoryPlugin = /* @__PURE__ */ createPlugin < object , { } > ( {
34+ tag : 'seroval-plugins/web/AbortControllerFactoryPlugin ' ,
3035 test ( value ) {
31- // We didn't actually use the AbortController class
32- // directly because of some assumptions
33- return value instanceof AbortSignalController ;
36+ return value === ABORT_CONTROLLER ;
3437 } ,
3538 parse : {
36- stream ( ) {
37- return { } ;
39+ sync ( ) {
40+ return ABORT_CONTROLLER ;
3841 } ,
39- } ,
40- serialize ( _node ) {
41- return 'new AbortController' ;
42- } ,
43- deserialize ( _node ) {
44- return new AbortSignalController ( ) ;
45- } ,
46- } ) ;
47-
48- type AbortSignalAbortNode = {
49- controller : SerovalNode ;
50- reason : SerovalNode ;
51- } ;
52-
53- class AbortSignalAbort {
54- constructor (
55- public controller : AbortSignalController ,
56- public reason : unknown ,
57- ) { }
58- }
59-
60- const AbortSignalAbortPlugin = createPlugin <
61- AbortSignalAbort ,
62- AbortSignalAbortNode
63- > ( {
64- extends : [ AbortSignalControllerPlugin ] ,
65- tag : 'seroval-plugins/web/AbortSignalAbort' ,
66- test ( value ) {
67- return value instanceof AbortSignalAbort ;
68- } ,
69- parse : {
70- stream ( value , ctx ) {
71- return {
72- controller : ctx . parse ( value . controller ) ,
73- reason : ctx . parse ( value . reason ) ,
74- } ;
42+ async async ( ) {
43+ return await Promise . resolve ( ABORT_CONTROLLER ) ;
44+ } ,
45+ stream ( ) {
46+ return ABORT_CONTROLLER ;
7547 } ,
7648 } ,
77- serialize ( node , ctx ) {
78- return (
79- ctx . serialize ( node . controller ) +
80- '.abort(' +
81- ctx . serialize ( node . reason ) +
82- ')'
83- ) ;
49+ serialize ( ) {
50+ return PROMISE_TO_ABORT_SIGNAL . toString ( ) ;
8451 } ,
85- deserialize ( node , ctx ) {
86- const controller = ctx . deserialize (
87- node . controller ,
88- ) as AbortSignalController ;
89- const reason = ctx . deserialize ( node . reason ) ;
90- controller . controller . abort ( reason ) ;
91- return new AbortSignalAbort ( controller , reason ) ;
52+ deserialize ( ) {
53+ return PROMISE_TO_ABORT_SIGNAL ;
9254 } ,
9355} ) ;
9456
9557const AbortSignalPlugin = createPlugin <
9658 AbortSignal ,
97- { reason ?: SerovalNode ; controller ?: SerovalNode }
59+ { reason ?: SerovalNode ; controller ?: SerovalNode ; factory ?: SerovalNode }
9860> ( {
9961 tag : 'seroval-plugins/web/AbortSignal' ,
100- extends : [ AbortSignalAbortPlugin ] ,
62+ extends : [ AbortControllerFactoryPlugin ] ,
10163 test ( value ) {
10264 if ( typeof AbortSignal === 'undefined' ) {
10365 return false ;
@@ -130,34 +92,27 @@ const AbortSignalPlugin = createPlugin<
13092 reason : ctx . parse ( value . reason ) ,
13193 } ;
13294 }
133- const controller = new AbortSignalController ( ) ;
13495
135- ctx . pushPendingState ( ) ;
136- value . addEventListener (
137- 'abort' ,
138- ( ) => {
139- const result = ctx . parseWithError (
140- new AbortSignalAbort ( controller , value . reason ) ,
141- ) ;
142- if ( result ) {
143- ctx . onParse ( result ) ;
144- }
145- ctx . popPendingState ( ) ;
146- } ,
147- { once : true } ,
148- ) ;
96+ const promise = abortSignalToPromise ( value ) ;
14997
15098 return {
151- controller : ctx . parse ( controller ) ,
99+ factory : ctx . parse ( ABORT_CONTROLLER ) ,
100+ controller : ctx . parse ( promise ) ,
152101 } ;
153102 } ,
154103 } ,
155104 serialize ( node , ctx ) {
156105 if ( node . reason ) {
157106 return 'AbortSignal.abort(' + ctx . serialize ( node . reason ) + ')' ;
158107 }
159- if ( node . controller ) {
160- return '(' + ctx . serialize ( node . controller ) + ').signal' ;
108+ if ( node . controller && node . factory ) {
109+ return (
110+ '(' +
111+ ctx . serialize ( node . factory ) +
112+ ')(' +
113+ ctx . serialize ( node . controller ) +
114+ ').signal'
115+ ) ;
161116 }
162117 return '(new AbortController).signal' ;
163118 } ,
@@ -166,10 +121,7 @@ const AbortSignalPlugin = createPlugin<
166121 return AbortSignal . abort ( ctx . deserialize ( node . reason ) ) ;
167122 }
168123 if ( node . controller ) {
169- const controller = ctx . deserialize (
170- node . controller ,
171- ) as AbortSignalController ;
172- return controller . controller . signal ;
124+ return PROMISE_TO_ABORT_SIGNAL ( ctx . deserialize ( node . controller ) ) . signal ;
173125 }
174126 const controller = new AbortController ( ) ;
175127 return controller . signal ;
0 commit comments