Skip to content

Commit b29c56f

Browse files
committed
Change AbortSignal to Promise
1 parent 312935b commit b29c56f

File tree

2 files changed

+91
-91
lines changed

2 files changed

+91
-91
lines changed

packages/plugins/tests/web/__snapshots__/abort-signal.test.ts.snap

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,33 @@ exports[`AbortSignal > crossSerializeStream > scoped > supports aborted AbortSig
3939
})($R[1],$R[3]=AbortSignal.abort("aborted!")))($R["example"])"
4040
`;
4141

42-
exports[`AbortSignal > crossSerializeStream > scoped > supports future AbortSignal 1`] = `"($R=>$R[0]=($R[1]=new AbortController).signal)($R["example"])"`;
42+
exports[`AbortSignal > crossSerializeStream > scoped > supports future AbortSignal 1`] = `
43+
"($R=>$R[0]=($R[1]=(promise) => {
44+
const controller = new AbortController();
45+
const abort = controller.abort.bind(controller);
46+
promise.then(abort, abort);
47+
return controller;
48+
})($R[2]=($R[3]=($R[4]=() => {
49+
const resolver = {
50+
p: 0,
51+
s: 0,
52+
f: 0
53+
};
54+
resolver.p = new Promise((resolve, reject) => {
55+
resolver.s = resolve;
56+
resolver.f = reject;
57+
});
58+
return resolver;
59+
})()).p).signal)($R["example"])"
60+
`;
4361

44-
exports[`AbortSignal > crossSerializeStream > scoped > supports future AbortSignal 2`] = `"($R=>$R[2]=$R[1].abort("aborted!"))($R["example"])"`;
62+
exports[`AbortSignal > crossSerializeStream > scoped > supports future AbortSignal 2`] = `
63+
"($R=>($R[5]=(resolver, data) => {
64+
resolver.s(data);
65+
resolver.p.s = 1;
66+
resolver.p.v = data;
67+
})($R[3],"aborted!"))($R["example"])"
68+
`;
4569

4670
exports[`AbortSignal > crossSerializeStream > supports aborted AbortSignal 1`] = `
4771
"$R[0]=($R[1]=($R[2]=() => {
@@ -66,9 +90,33 @@ exports[`AbortSignal > crossSerializeStream > supports aborted AbortSignal 2`] =
6690
})($R[1],$R[3]=AbortSignal.abort("aborted!"))"
6791
`;
6892

69-
exports[`AbortSignal > crossSerializeStream > supports future AbortSignal 1`] = `"$R[0]=($R[1]=new AbortController).signal"`;
93+
exports[`AbortSignal > crossSerializeStream > supports future AbortSignal 1`] = `
94+
"$R[0]=($R[1]=(promise) => {
95+
const controller = new AbortController();
96+
const abort = controller.abort.bind(controller);
97+
promise.then(abort, abort);
98+
return controller;
99+
})($R[2]=($R[3]=($R[4]=() => {
100+
const resolver = {
101+
p: 0,
102+
s: 0,
103+
f: 0
104+
};
105+
resolver.p = new Promise((resolve, reject) => {
106+
resolver.s = resolve;
107+
resolver.f = reject;
108+
});
109+
return resolver;
110+
})()).p).signal"
111+
`;
70112

71-
exports[`AbortSignal > crossSerializeStream > supports future AbortSignal 2`] = `"$R[2]=$R[1].abort("aborted!")"`;
113+
exports[`AbortSignal > crossSerializeStream > supports future AbortSignal 2`] = `
114+
"($R[5]=(resolver, data) => {
115+
resolver.s(data);
116+
resolver.p.s = 1;
117+
resolver.p.v = data;
118+
})($R[3],"aborted!")"
119+
`;
72120

73121
exports[`AbortSignal > serialize > supports aborted AbortSignal 1`] = `"AbortSignal.abort("aborted!")"`;
74122

@@ -90,9 +138,9 @@ exports[`AbortSignal > toCrossJSONStream > supports aborted AbortSignal 1`] = `"
90138

91139
exports[`AbortSignal > toCrossJSONStream > supports aborted AbortSignal 2`] = `"{"t":23,"i":1,"a":[{"t":26,"i":4,"s":2},{"t":25,"i":3,"s":{"reason":{"t":1,"s":"aborted!"}},"c":"seroval-plugins/web/AbortSignal"}]}"`;
92140

93-
exports[`AbortSignal > toCrossJSONStream > supports future AbortSignal 1`] = `"{"t":25,"i":0,"s":{"controller":{"t":25,"i":1,"s":{},"c":"seroval-plugins/web/AbortSignalController"}},"c":"seroval-plugins/web/AbortSignal"}"`;
141+
exports[`AbortSignal > toCrossJSONStream > supports future AbortSignal 1`] = `"{"t":25,"i":0,"s":{"factory":{"t":25,"i":1,"s":{},"c":"seroval-plugins/web/AbortControllerFactoryPlugin"},"controller":{"t":22,"i":2,"s":3,"f":{"t":26,"i":4,"s":1}}},"c":"seroval-plugins/web/AbortSignal"}"`;
94142

95-
exports[`AbortSignal > toCrossJSONStream > supports future AbortSignal 2`] = `"{"t":25,"i":2,"s":{"controller":{"t":4,"i":1},"reason":{"t":1,"s":"aborted!"}},"c":"seroval-plugins/web/AbortSignalAbort"}"`;
143+
exports[`AbortSignal > toCrossJSONStream > supports future AbortSignal 2`] = `"{"t":23,"i":3,"a":[{"t":26,"i":5,"s":2},{"t":1,"s":"aborted!"}]}"`;
96144

97145
exports[`AbortSignal > toJSON > supports aborted AbortSignal 1`] = `"{"t":{"t":25,"i":0,"s":{"reason":{"t":1,"s":"aborted!"}},"c":"seroval-plugins/web/AbortSignal"},"f":63,"m":[]}"`;
98146

packages/plugins/web/abort-signal.ts

Lines changed: 37 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import type { SerovalNode } from 'seroval';
22
import { 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+
411
function 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

9557
const 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

Comments
 (0)