Skip to content

Commit c363f0e

Browse files
committed
chore: replicating memory leak
1 parent 95713ae commit c363f0e

File tree

6 files changed

+497
-6
lines changed

6 files changed

+497
-6
lines changed

async-init.patch

Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
diff -crB dist/CreateDestroy.js patched/CreateDestroy.js
2+
*** dist/CreateDestroy.js 2025-05-13 17:01:44.521843798 +1000
3+
--- patched/CreateDestroy.js 2025-05-13 16:43:22.019287860 +1000
4+
***************
5+
*** 1,8 ****
6+
import { Evented } from '@matrixai/events';
7+
import { RWLockWriter } from '@matrixai/async-locks';
8+
! import { _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, promise, resetStackTrace, } from './utils.js';
9+
import { EventAsyncInitDestroy, EventAsyncInitDestroyed } from './events.js';
10+
import { ErrorAsyncInitDestroyed } from './errors.js';
11+
function CreateDestroy({ eventDestroy = EventAsyncInitDestroy, eventDestroyed = EventAsyncInitDestroyed, } = {}) {
12+
return (constructor) => {
13+
const { p, resolveP } = promise();
14+
--- 1,10 ----
15+
import { Evented } from '@matrixai/events';
16+
import { RWLockWriter } from '@matrixai/async-locks';
17+
! import { _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, promise, resetStackTrace, _spanId, spanId, spanContext, } from './utils.js';
18+
import { EventAsyncInitDestroy, EventAsyncInitDestroyed } from './events.js';
19+
import { ErrorAsyncInitDestroyed } from './errors.js';
20+
+ import { tracer } from '@matrixai/logger'
21+
+ let i = 0;
22+
function CreateDestroy({ eventDestroy = EventAsyncInitDestroy, eventDestroyed = EventAsyncInitDestroyed, } = {}) {
23+
return (constructor) => {
24+
const { p, resolveP } = promise();
25+
***************
26+
*** 12,17 ****
27+
--- 14,20 ----
28+
[_statusP] = p;
29+
[resolveStatusP] = resolveP;
30+
[initLock] = new RWLockWriter();
31+
+ [_spanId] = undefined;
32+
get [destroyed]() {
33+
return this[_destroyed];
34+
}
35+
***************
36+
*** 21,26 ****
37+
--- 24,38 ----
38+
get [statusP]() {
39+
return this[_statusP];
40+
}
41+
+ get [spanId]() {
42+
+ return this[_spanId];
43+
+ }
44+
+ constructor(...args) {
45+
+ super(...args);
46+
+ const ctx = spanContext.getStore();
47+
+ const parentSpanId = ctx?.currentSpanId;
48+
+ this[_spanId] = tracer.startSpan(`cd-${this.constructor.name || i++}`, parentSpanId);
49+
+ }
50+
async destroy(...args) {
51+
return this[initLock]
52+
.withWriteF(async () => {
53+
***************
54+
*** 37,42 ****
55+
--- 49,55 ----
56+
if (typeof super['destroy'] === 'function') {
57+
result = await super.destroy(...args);
58+
}
59+
+ tracer.endSpan(this[_spanId]);
60+
this[_destroyed] = true;
61+
this.dispatchEvent(new eventDestroyed());
62+
return result;
63+
diff -crB dist/CreateDestroyStartStop.js patched/CreateDestroyStartStop.js
64+
*** dist/CreateDestroyStartStop.js 2025-05-13 17:01:44.547844173 +1000
65+
--- patched/CreateDestroyStartStop.js 2025-05-13 16:43:34.415385091 +1000
66+
***************
67+
*** 1,8 ****
68+
import { Evented } from '@matrixai/events';
69+
import { RWLockWriter } from '@matrixai/async-locks';
70+
! import { _running, running, _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, promise, resetStackTrace, } from './utils.js';
71+
import { EventAsyncInitStart, EventAsyncInitStarted, EventAsyncInitStop, EventAsyncInitStopped, EventAsyncInitDestroy, EventAsyncInitDestroyed, } from './events.js';
72+
import { ErrorAsyncInitRunning, ErrorAsyncInitNotRunning, ErrorAsyncInitDestroyed, } from './errors.js';
73+
function CreateDestroyStartStop(errorRunning = new ErrorAsyncInitRunning(), errorDestroyed = new ErrorAsyncInitDestroyed(), { eventStart = EventAsyncInitStart, eventStarted = EventAsyncInitStarted, eventStop = EventAsyncInitStop, eventStopped = EventAsyncInitStopped, eventDestroy = EventAsyncInitDestroy, eventDestroyed = EventAsyncInitDestroyed, } = {}) {
74+
return (constructor) => {
75+
const { p, resolveP } = promise();
76+
--- 1,10 ----
77+
import { Evented } from '@matrixai/events';
78+
import { RWLockWriter } from '@matrixai/async-locks';
79+
! import { _running, running, _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, promise, resetStackTrace, _spanId, spanId, spanContext } from './utils.js';
80+
import { EventAsyncInitStart, EventAsyncInitStarted, EventAsyncInitStop, EventAsyncInitStopped, EventAsyncInitDestroy, EventAsyncInitDestroyed, } from './events.js';
81+
import { ErrorAsyncInitRunning, ErrorAsyncInitNotRunning, ErrorAsyncInitDestroyed, } from './errors.js';
82+
+ import { tracer } from '@matrixai/logger'
83+
+ let i = 0;
84+
function CreateDestroyStartStop(errorRunning = new ErrorAsyncInitRunning(), errorDestroyed = new ErrorAsyncInitDestroyed(), { eventStart = EventAsyncInitStart, eventStarted = EventAsyncInitStarted, eventStop = EventAsyncInitStop, eventStopped = EventAsyncInitStopped, eventDestroy = EventAsyncInitDestroy, eventDestroyed = EventAsyncInitDestroyed, } = {}) {
85+
return (constructor) => {
86+
const { p, resolveP } = promise();
87+
***************
88+
*** 13,18 ****
89+
--- 15,21 ----
90+
[_statusP] = p;
91+
[resolveStatusP] = resolveP;
92+
[initLock] = new RWLockWriter();
93+
+ [_spanId] = undefined;
94+
get [running]() {
95+
return this[_running];
96+
}
97+
***************
98+
*** 25,30 ****
99+
--- 28,36 ----
100+
get [statusP]() {
101+
return this[_statusP];
102+
}
103+
+ get [spanId]() {
104+
+ return this[_spanId];
105+
+ }
106+
async destroy(...args) {
107+
return this[initLock]
108+
.withWriteF(async () => {
109+
***************
110+
*** 69,87 ****
111+
resetStackTrace(errorDestroyed);
112+
throw errorDestroyed;
113+
}
114+
! this[_status] = 'starting';
115+
! this[resolveStatusP]('starting');
116+
! const { p, resolveP } = promise();
117+
! this[_statusP] = p;
118+
! this[resolveStatusP] = resolveP;
119+
! this.dispatchEvent(new eventStart());
120+
! let result;
121+
! if (typeof super['start'] === 'function') {
122+
! result = await super.start(...args);
123+
! }
124+
! this[_running] = true;
125+
! this.dispatchEvent(new eventStarted());
126+
! return result;
127+
})
128+
.finally(() => {
129+
this[_status] = null;
130+
--- 75,98 ----
131+
resetStackTrace(errorDestroyed);
132+
throw errorDestroyed;
133+
}
134+
! const ctx = spanContext.getStore();
135+
! const parentSpanId = ctx?.currentSpanId;
136+
! this[_spanId] = tracer.startSpan(`ss-${this.constructor.name || i++}`, parentSpanId);
137+
! return spanContext.run({ currentSpanId: this[_spanId] }, async () => {
138+
! this[_status] = 'starting';
139+
! this[resolveStatusP]('starting');
140+
! const { p, resolveP } = promise();
141+
! this[_statusP] = p;
142+
! this[resolveStatusP] = resolveP;
143+
! this.dispatchEvent(new eventStart());
144+
! let result;
145+
! if (typeof super['start'] === 'function') {
146+
! result = await super.start(...args);
147+
! }
148+
! this[_running] = true;
149+
! this.dispatchEvent(new eventStarted());
150+
! return result;
151+
! });
152+
})
153+
.finally(() => {
154+
this[_status] = null;
155+
***************
156+
*** 114,119 ****
157+
--- 125,131 ----
158+
if (typeof super['stop'] === 'function') {
159+
result = await super.stop(...args);
160+
}
161+
+ tracer.endSpan(this[_spanId]);
162+
this[_running] = false;
163+
this.dispatchEvent(new eventStopped());
164+
return result;
165+
diff -crB dist/StartStop.js patched/StartStop.js
166+
*** dist/StartStop.js 2025-05-13 17:01:44.604844994 +1000
167+
--- patched/StartStop.js 2025-05-13 15:45:54.003601036 +1000
168+
***************
169+
*** 1,8 ****
170+
import { Evented } from '@matrixai/events';
171+
import { RWLockWriter } from '@matrixai/async-locks';
172+
! import { _running, running, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, promise, resetStackTrace, } from './utils.js';
173+
import { EventAsyncInitStart, EventAsyncInitStarted, EventAsyncInitStop, EventAsyncInitStopped, } from './events.js';
174+
import { ErrorAsyncInitNotRunning } from './errors.js';
175+
function StartStop({ eventStart = EventAsyncInitStart, eventStarted = EventAsyncInitStarted, eventStop = EventAsyncInitStop, eventStopped = EventAsyncInitStopped, } = {}) {
176+
return (constructor) => {
177+
const { p, resolveP } = promise();
178+
--- 1,10 ----
179+
import { Evented } from '@matrixai/events';
180+
import { RWLockWriter } from '@matrixai/async-locks';
181+
! import { _running, running, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, promise, resetStackTrace, _spanId, spanId, spanContext, } from './utils.js';
182+
import { EventAsyncInitStart, EventAsyncInitStarted, EventAsyncInitStop, EventAsyncInitStopped, } from './events.js';
183+
import { ErrorAsyncInitNotRunning } from './errors.js';
184+
+ import { tracer } from '@matrixai/logger';
185+
+ let i = 0;
186+
function StartStop({ eventStart = EventAsyncInitStart, eventStarted = EventAsyncInitStarted, eventStop = EventAsyncInitStop, eventStopped = EventAsyncInitStopped, } = {}) {
187+
return (constructor) => {
188+
const { p, resolveP } = promise();
189+
***************
190+
*** 10,15 ****
191+
--- 12,18 ----
192+
[_running] = false;
193+
[_status] = null;
194+
[_statusP] = p;
195+
+ [_spanId] = undefined;
196+
[resolveStatusP] = resolveP;
197+
[initLock] = new RWLockWriter();
198+
get [running]() {
199+
***************
200+
*** 21,45 ****
201+
get [statusP]() {
202+
return this[_statusP];
203+
}
204+
async start(...args) {
205+
return this[initLock]
206+
.withWriteF(async () => {
207+
if (this[_running]) {
208+
return;
209+
}
210+
! this[_status] = 'starting';
211+
! this[resolveStatusP]('starting');
212+
! const { p, resolveP } = promise();
213+
! this[_statusP] = p;
214+
! this[resolveStatusP] = resolveP;
215+
! this.dispatchEvent(new eventStart());
216+
! let result;
217+
! if (typeof super['start'] === 'function') {
218+
! result = await super.start(...args);
219+
! }
220+
! this[_running] = true;
221+
! this.dispatchEvent(new eventStarted());
222+
! return result;
223+
})
224+
.finally(() => {
225+
this[_status] = null;
226+
--- 24,56 ----
227+
get [statusP]() {
228+
return this[_statusP];
229+
}
230+
+ get [spanId]() {
231+
+ return this[_spanId];
232+
+ }
233+
async start(...args) {
234+
return this[initLock]
235+
.withWriteF(async () => {
236+
if (this[_running]) {
237+
return;
238+
}
239+
! const ctx = spanContext.getStore();
240+
! const parentSpanId = ctx?.currentSpanId;
241+
! this[_spanId] = tracer.startSpan(`ss-${this.constructor.name || i++}`, parentSpanId);
242+
! return spanContext.run({ currentSpanId: this[_spanId] }, async () => {
243+
! this[_status] = 'starting';
244+
! this[resolveStatusP]('starting');
245+
! const { p, resolveP } = promise();
246+
! this[_statusP] = p;
247+
! this[resolveStatusP] = resolveP;
248+
! this.dispatchEvent(new eventStart());
249+
! let result;
250+
! if (typeof super['start'] === 'function') {
251+
! result = await super.start(...args);
252+
! }
253+
! this[_running] = true;
254+
! this.dispatchEvent(new eventStarted());
255+
! return result;
256+
! });
257+
})
258+
.finally(() => {
259+
this[_status] = null;
260+
***************
261+
*** 67,72 ****
262+
--- 78,84 ----
263+
}
264+
this[_running] = false;
265+
this.dispatchEvent(new eventStopped());
266+
+ tracer.endSpan(this[_spanId]);
267+
return result;
268+
})
269+
.finally(() => {
270+
diff -crB dist/utils.d.ts patched/utils.d.ts
271+
*** dist/utils.d.ts 2025-05-13 17:01:44.754847155 +1000
272+
--- patched/utils.d.ts 2025-05-13 16:48:52.064927307 +1000
273+
***************
274+
*** 1,3 ****
275+
--- 1,4 ----
276+
+ import type { AsyncLocalStorage } from 'node:async_hooks';
277+
import type { PromiseDeconstructed } from './types.js';
278+
/**
279+
* Symbols prevents name clashes with decorated classes
280+
***************
281+
*** 12,17 ****
282+
--- 13,21 ----
283+
declare const statusP: unique symbol;
284+
declare const resolveStatusP: unique symbol;
285+
declare const initLock: unique symbol;
286+
+ declare const _spanId: unique symbol;
287+
+ declare const spanId: unique symbol;
288+
+ declare const spanContext: AsyncLocalStorage<any>;
289+
declare const AsyncFunction: Function;
290+
declare const GeneratorFunction: Function;
291+
declare const AsyncGeneratorFunction: Function;
292+
***************
293+
*** 27,30 ****
294+
* function is called, giving a more useful stack trace
295+
*/
296+
declare function resetStackTrace(error: Error, decorated?: Function): void;
297+
! export { _running, running, _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, hasCaptureStackTrace, promise, resetStackTrace, };
298+
--- 31,34 ----
299+
* function is called, giving a more useful stack trace
300+
*/
301+
declare function resetStackTrace(error: Error, decorated?: Function): void;
302+
! export { _running, running, _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, hasCaptureStackTrace, _spanId, spanId, spanContext, promise, resetStackTrace, };
303+
diff -crB dist/utils.js patched/utils.js
304+
*** dist/utils.js 2025-05-13 17:01:44.617845181 +1000
305+
--- patched/utils.js 2025-05-13 15:45:45.001524143 +1000
306+
***************
307+
*** 1,3 ****
308+
--- 1,5 ----
309+
+ import { AsyncLocalStorage } from 'node:async_hooks';
310+
+
311+
/**
312+
* Symbols prevents name clashes with decorated classes
313+
*/
314+
***************
315+
*** 9,20 ****
316+
--- 11,25 ----
317+
const status = Symbol('status');
318+
const _statusP = Symbol('_statusP');
319+
const statusP = Symbol('statusP');
320+
+ const _spanId = Symbol('_spanId');
321+
+ const spanId = Symbol('spanId');
322+
const resolveStatusP = Symbol('resolveStatusP');
323+
const initLock = Symbol('initLock');
324+
const AsyncFunction = (async () => { }).constructor;
325+
const GeneratorFunction = function* () { }.constructor;
326+
const AsyncGeneratorFunction = async function* () { }.constructor;
327+
const hasCaptureStackTrace = 'captureStackTrace' in Error;
328+
+ const spanContext = new AsyncLocalStorage();
329+
/**
330+
* Deconstructed promise
331+
*/
332+
***************
333+
*** 53,57 ****
334+
error.stack = error.stack.replace(/[^\n]+\n/, stackTitle);
335+
}
336+
}
337+
! export { _running, running, _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, hasCaptureStackTrace, promise, resetStackTrace, };
338+
//# sourceMappingURL=utils.js.map
339+
\ No newline at end of file
340+
--- 58,62 ----
341+
error.stack = error.stack.replace(/[^\n]+\n/, stackTitle);
342+
}
343+
}
344+
! export { _running, running, _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, hasCaptureStackTrace, _spanId, spanId, spanContext, promise, resetStackTrace, };
345+
//# sourceMappingURL=utils.js.map
346+
\ No newline at end of file

0 commit comments

Comments
 (0)