Skip to content

Commit d308a41

Browse files
committed
WIP
1 parent 250a382 commit d308a41

File tree

6 files changed

+62
-42
lines changed

6 files changed

+62
-42
lines changed

src/decorators/timed.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ContextTimed } from '../types';
1+
import type { ContextTimedInput } from '../types';
22
import { setupTimedContext } from '../functions/timed';
33
import * as utils from '../utils';
44
import * as errors from '../errors';
@@ -27,7 +27,7 @@ function timed(
2727
const contextIndex = utils.getContextIndex(target, key, targetName);
2828
if (f instanceof utils.AsyncFunction) {
2929
descriptor['value'] = async function (...args) {
30-
let ctx: Partial<ContextTimed> = args[contextIndex];
30+
let ctx: Partial<ContextTimedInput> = args[contextIndex];
3131
if (ctx === undefined) {
3232
ctx = {};
3333
} else {
@@ -51,7 +51,7 @@ function timed(
5151
};
5252
} else if (f instanceof utils.GeneratorFunction) {
5353
descriptor['value'] = function* (...args) {
54-
let ctx: Partial<ContextTimed> = args[contextIndex];
54+
let ctx: Partial<ContextTimedInput> = args[contextIndex];
5555
if (ctx === undefined) {
5656
ctx = {};
5757
} else {
@@ -75,7 +75,7 @@ function timed(
7575
};
7676
} else if (f instanceof utils.AsyncGeneratorFunction) {
7777
descriptor['value'] = async function* (...args) {
78-
let ctx: Partial<ContextTimed> = args[contextIndex];
78+
let ctx: Partial<ContextTimedInput> = args[contextIndex];
7979
if (ctx === undefined) {
8080
ctx = {};
8181
} else {
@@ -99,7 +99,7 @@ function timed(
9999
};
100100
} else {
101101
descriptor['value'] = function (...args) {
102-
let ctx: Partial<ContextTimed> = args[contextIndex];
102+
let ctx: Partial<ContextTimedInput> = args[contextIndex];
103103
if (ctx === undefined) {
104104
ctx = {};
105105
} else {

src/decorators/timedCancellable.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ContextTimed } from '../types';
1+
import type { ContextTimedInput } from '../types';
22
import { setupTimedCancellable } from '../functions/timedCancellable';
33
import * as utils from '../utils';
44
import * as errors from '../errors';
@@ -28,7 +28,7 @@ function timedCancellable(
2828
}
2929
const contextIndex = utils.getContextIndex(target, key, targetName);
3030
descriptor['value'] = function (...args) {
31-
let ctx: Partial<ContextTimed> = args[contextIndex];
31+
let ctx: Partial<ContextTimedInput> = args[contextIndex];
3232
if (ctx === undefined) {
3333
ctx = {};
3434
} else {

src/functions/timed.ts

+17-17
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
import type { ContextTimed } from '../types';
1+
import type { ContextTimed, ContextTimedInput } from '../types';
22
import { Timer } from '@matrixai/timer';
33
import * as errors from '../errors';
44
import * as utils from '../utils';
55

6-
type ContextRemaining<C> = Omit<C, keyof ContextTimed>;
6+
type ContextRemaining<C> = Omit<C, keyof ContextTimedInput>;
77

88
type ContextAndParameters<
99
C,
1010
P extends Array<any>,
1111
> = keyof ContextRemaining<C> extends never
12-
? [Partial<ContextTimed>?, ...P]
13-
: [Partial<ContextTimed> & ContextRemaining<C>, ...P];
12+
? [Partial<ContextTimedInput>?, ...P]
13+
: [Partial<ContextTimedInput> & ContextRemaining<C>, ...P];
1414

1515
function setupTimedContext(
1616
delay: number,
1717
errorTimeoutConstructor: new () => Error,
18-
ctx: Partial<ContextTimed>,
18+
ctx: Partial<ContextTimedInput>,
1919
): () => void {
2020
// There are 3 properties of timer and signal:
2121
//
@@ -36,11 +36,11 @@ function setupTimedContext(
3636
// In situation 4, there's a caveat for property A: it is assumed that the
3737
// caller has already setup the property A relationship, therefore this
3838
// wrapper will not re-setup this property A relationship.
39-
if (ctx.timer === undefined && ctx.signal === undefined) {
39+
if ((ctx.timer === undefined || typeof ctx.timer === 'number') && ctx.signal === undefined) {
4040
const abortController = new AbortController();
4141
const e = new errorTimeoutConstructor();
4242
// Property A
43-
const timer = new Timer(() => void abortController.abort(e), delay);
43+
const timer = new Timer(() => void abortController.abort(e), ctx.timer ?? delay);
4444
abortController.signal.addEventListener('abort', () => {
4545
// Property B
4646
timer.cancel();
@@ -51,11 +51,11 @@ function setupTimedContext(
5151
// Property C
5252
timer.cancel();
5353
};
54-
} else if (ctx.timer === undefined && ctx.signal instanceof AbortSignal) {
54+
} else if ((ctx.timer === undefined || typeof ctx.timer === 'number') && ctx.signal instanceof AbortSignal) {
5555
const abortController = new AbortController();
5656
const e = new errorTimeoutConstructor();
5757
// Property A
58-
const timer = new Timer(() => void abortController.abort(e), delay);
58+
const timer = new Timer(() => void abortController.abort(e), ctx.timer ?? delay);
5959
const signalUpstream = ctx.signal;
6060
const signalHandler = () => {
6161
// Property B
@@ -113,13 +113,13 @@ function setupTimedContext(
113113
* Timed HOF
114114
* This overloaded signature is external signature
115115
*/
116-
function timed<C extends ContextTimed, P extends Array<any>, R>(
117-
f: (ctx: C, ...params: P) => R,
116+
function timed<C extends ContextTimedInput, C_ extends ContextTimed, P extends Array<any>, R>(
117+
f: (ctx: C_, ...params: P) => R,
118118
delay?: number,
119119
errorTimeoutConstructor?: new () => Error,
120120
): (...params: ContextAndParameters<C, P>) => R;
121-
function timed<C extends ContextTimed, P extends Array<any>>(
122-
f: (ctx: C, ...params: P) => any,
121+
function timed<C extends ContextTimedInput, C_ extends ContextTimed, P extends Array<any>>(
122+
f: (ctx: C_, ...params: P) => any,
123123
delay: number = Infinity,
124124
errorTimeoutConstructor: new () => Error = errors.ErrorContextsTimedTimeOut,
125125
): (...params: ContextAndParameters<C, P>) => any {
@@ -133,7 +133,7 @@ function timed<C extends ContextTimed, P extends Array<any>>(
133133
ctx,
134134
);
135135
try {
136-
return await f(ctx as C, ...args);
136+
return await f(ctx as C_, ...args);
137137
} finally {
138138
teardownContext();
139139
}
@@ -148,7 +148,7 @@ function timed<C extends ContextTimed, P extends Array<any>>(
148148
ctx,
149149
);
150150
try {
151-
return yield* f(ctx as C, ...args);
151+
return yield* f(ctx as C_, ...args);
152152
} finally {
153153
teardownContext();
154154
}
@@ -163,7 +163,7 @@ function timed<C extends ContextTimed, P extends Array<any>>(
163163
ctx,
164164
);
165165
try {
166-
return yield* f(ctx as C, ...args);
166+
return yield* f(ctx as C_, ...args);
167167
} finally {
168168
teardownContext();
169169
}
@@ -177,7 +177,7 @@ function timed<C extends ContextTimed, P extends Array<any>>(
177177
errorTimeoutConstructor,
178178
ctx,
179179
);
180-
const result = f(ctx as C, ...args);
180+
const result = f(ctx as C_, ...args);
181181
if (utils.isPromiseLike(result)) {
182182
return result.then(
183183
(r) => {

src/functions/timedCancellable.ts

+31-15
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
import type { ContextTimed } from '../types';
1+
import type { ContextTimed, ContextTimedInput } from '../types';
22
import { PromiseCancellable } from '@matrixai/async-cancellable';
33
import { Timer } from '@matrixai/timer';
44
import * as errors from '../errors';
55

6-
type ContextRemaining<C> = Omit<C, keyof ContextTimed>;
6+
type ContextRemaining<C> = Omit<C, keyof ContextTimedInput>;
77

88
type ContextAndParameters<
99
C,
1010
P extends Array<any>,
1111
> = keyof ContextRemaining<C> extends never
12-
? [Partial<ContextTimed>?, ...P]
13-
: [Partial<ContextTimed> & ContextRemaining<C>, ...P];
12+
? [Partial<ContextTimedInput>?, ...P]
13+
: [Partial<ContextTimedInput> & ContextRemaining<C>, ...P];
1414

1515
function setupTimedCancellable<C extends ContextTimed, P extends Array<any>, R>(
1616
f: (ctx: C, ...params: P) => PromiseLike<R>,
1717
lazy: boolean,
1818
delay: number,
19-
errorTimeoutConstructor: new () => Error = errors.ErrorContextsTimedTimeOut,
20-
ctx: Partial<ContextTimed>,
19+
errorTimeoutConstructor: new () => Error,
20+
ctx: Partial<ContextTimedInput>,
2121
args: P,
2222
): PromiseCancellable<R> {
2323
// There are 3 properties of timer and signal:
@@ -41,11 +41,17 @@ function setupTimedCancellable<C extends ContextTimed, P extends Array<any>, R>(
4141
// wrapper will not re-setup this property A relationship.
4242
let abortController: AbortController;
4343
let teardownContext: () => void;
44-
if (ctx.timer === undefined && ctx.signal === undefined) {
44+
if (
45+
(ctx.timer === undefined || typeof ctx.timer === 'number') &&
46+
ctx.signal === undefined
47+
) {
4548
abortController = new AbortController();
4649
const e = new errorTimeoutConstructor();
4750
// Property A
48-
const timer = new Timer(() => void abortController.abort(e), delay);
51+
const timer = new Timer(
52+
() => void abortController.abort(e),
53+
ctx.timer ?? delay,
54+
);
4955
abortController.signal.addEventListener('abort', () => {
5056
// Property B
5157
timer.cancel();
@@ -56,11 +62,17 @@ function setupTimedCancellable<C extends ContextTimed, P extends Array<any>, R>(
5662
// Property C
5763
timer.cancel();
5864
};
59-
} else if (ctx.timer === undefined && ctx.signal instanceof AbortSignal) {
65+
} else if (
66+
(ctx.timer === undefined || typeof ctx.timer === 'number') &&
67+
ctx.signal instanceof AbortSignal
68+
) {
6069
abortController = new AbortController();
6170
const e = new errorTimeoutConstructor();
6271
// Property A
63-
const timer = new Timer(() => void abortController.abort(e), delay);
72+
const timer = new Timer(
73+
() => void abortController.abort(e),
74+
ctx.timer ?? delay,
75+
);
6476
const signalUpstream = ctx.signal;
6577
const signalHandler = () => {
6678
// Property B
@@ -137,9 +149,13 @@ function setupTimedCancellable<C extends ContextTimed, P extends Array<any>, R>(
137149
if (signal.aborted) {
138150
reject(signal.reason);
139151
} else {
140-
signal.addEventListener('abort', () => {
141-
reject(signal.reason);
142-
});
152+
signal.addEventListener(
153+
'abort',
154+
() => {
155+
reject(signal.reason);
156+
},
157+
{ once: true },
158+
);
143159
}
144160
}
145161
void result.then(resolve, reject);
@@ -148,8 +164,8 @@ function setupTimedCancellable<C extends ContextTimed, P extends Array<any>, R>(
148164
}, abortController);
149165
}
150166

151-
function timedCancellable<C extends ContextTimed, P extends Array<any>, R>(
152-
f: (ctx: C, ...params: P) => PromiseLike<R>,
167+
function timedCancellable<C extends ContextTimedInput, C_ extends ContextTimed, P extends Array<any>, R>(
168+
f: (ctx: C_, ...params: P) => PromiseLike<R>,
153169
lazy: boolean = false,
154170
delay: number = Infinity,
155171
errorTimeoutConstructor: new () => Error = errors.ErrorContextsTimedTimeOut,

src/types.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ type ContextTimed = ContextCancellable & {
88
timer: Timer;
99
};
1010

11-
export type { ContextCancellable, ContextTimed };
11+
type ContextTimedInput = ContextCancellable & {
12+
timer: Timer | number;
13+
};
14+
15+
export type { ContextCancellable, ContextTimed, ContextTimedInput };

src/utils.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ function checkContextTimed(
5555
`\`${targetName}.${key.toString()}\` decorated \`@context\` parameter's \`signal\` property is not an instance of \`AbortSignal\``,
5656
);
5757
}
58-
if (ctx.timer !== undefined && !(ctx.timer instanceof Timer)) {
58+
if (ctx.timer !== undefined && !(typeof ctx.timer === 'number' || ctx.timer instanceof Timer)) {
5959
throw new TypeError(
60-
`\`${targetName}.${key.toString()}\` decorated \`@context\` parameter's \`timer\` property is not an instance of \`Timer\``,
60+
`\`${targetName}.${key.toString()}\` decorated \`@context\` parameter's \`timer\` property is not a number nor an instance of \`Timer\``,
6161
);
6262
}
6363
}

0 commit comments

Comments
 (0)