Skip to content

Commit

Permalink
fix: 🐛 correctly store execution results in once decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Mar 14, 2024
1 parent 4bb2c30 commit 9c6d49d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 8 deletions.
58 changes: 58 additions & 0 deletions src/__tests__/once.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,61 @@ test('limits function invocation to one time only an memoizes the first result',
expect(a.test(2)).toBe(123);
expect(executions).toBe(1);
});

test('limits function invocation to one time for two methods', async () => {
let aExec = 0;
let bExec = 0;
class A {
@once
a(value: number) {
aExec++;
return value;
}

@once
b(value: number) {
bExec++;
return value + 1;
}
}
const a = new A();
expect(a.a(123)).toBe(123);
expect(a.a(1)).toBe(123);
expect(a.b(1)).toBe(2);
expect(a.b(1)).toBe(2);
expect(a.b(123123)).toBe(2);
expect(a.a(2)).toBe(123);
expect(a.a(234)).toBe(123);
expect(aExec).toBe(1);
expect(bExec).toBe(1);
});

test('limits function invocation to one time for two methods of two classes', async () => {
let aExec = 0;
let bExec = 0;
class A {
@once
a(value: number) {
aExec++;
return value;
}
}
class B {
@once
b(value: number) {
bExec++;
return value + 1;
}
}
const a = new A();
const b = new B();
expect(a.a(123)).toBe(123);
expect(a.a(1)).toBe(123);
expect(b.b(1)).toBe(2);
expect(b.b(1)).toBe(2);
expect(b.b(123123)).toBe(2);
expect(a.a(2)).toBe(123);
expect(a.a(234)).toBe(123);
expect(aExec).toBe(1);
expect(bExec).toBe(1);
});
2 changes: 2 additions & 0 deletions src/concurrency.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {go} from './go';
import type {Code} from './types';

/* tslint:disable */

class Task<T = unknown> {
public readonly resolve!: (data: T) => void;
public readonly reject!: (error: any) => void;
Expand Down
14 changes: 6 additions & 8 deletions src/once.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
* subsequent calls will return the result of the first call.
*/
export function once<This, Args extends any[], Return>(
target: (this: This, ...args: Args) => Return,
fn: (this: This, ...args: Args) => Return,
context?: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>,
) {
let called = false;
let res: unknown;
const instances = new WeakMap<any, WeakMap<any, any>>();
return function (this: This, ...args: Args): Return {
if (!called) {
called = true;
res = target.call(this, ...args);
}
return res as Return;
if (!instances.has(this)) instances.set(this, new WeakMap<any, any>());
const map = instances.get(this)!;
if (!map.has(fn)) map.set(fn, fn.apply(this, args));
return map.get(fn);
};
}

0 comments on commit 9c6d49d

Please sign in to comment.