Skip to content

Commit

Permalink
Fix this in normal function notify (#160)
Browse files Browse the repository at this point in the history
* Fix `this` in normal function `notify`

Before `notify` was called from the `ReactiveNode` context and was
calling with the node as `this` instead of the expected watcher.
Instead, set `consumerMarkedDirty` to a function that wraps notify with
a proper call with `this`.

Also add unit tests for our expected behavior here including closure for
an arrow function.

* Move the fix deeper into graph to pass wrapper
  • Loading branch information
yeomanse authored Apr 12, 2024
1 parent 09f7a13 commit 6c1b06a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
4 changes: 2 additions & 2 deletions packages/signal-polyfill/src/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export interface ReactiveNode {
*/
producerMustRecompute(node: unknown): boolean;
producerRecomputeValue(node: unknown): void;
consumerMarkedDirty(node: unknown): void;
consumerMarkedDirty(this: unknown): void;

/**
* Called when a signal is read within this consumer.
Expand Down Expand Up @@ -335,7 +335,7 @@ export function producerUpdatesAllowed(): boolean {
export function consumerMarkDirty(node: ReactiveNode): void {
node.dirty = true;
producerNotifyConsumers(node);
node.consumerMarkedDirty?.(node);
node.consumerMarkedDirty?.call(node.wrapper ?? node);
}

/**
Expand Down
30 changes: 30 additions & 0 deletions packages/signal-polyfill/src/wrapper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,36 @@ describe("Watcher", () => {
flushPending();

});

it("provides `this` to notify as normal function", () => {
const mockGetPending = vi.fn();

const watcher = new Signal.subtle.Watcher(function() {
this.getPending();
});
watcher.getPending = mockGetPending;

const signal = new Signal.State<number>(0);
watcher.watch(signal);

signal.set(1);
expect(mockGetPending).toBeCalled();
});

it("can be closed in if needed in notify as an arrow function", () => {
const mockGetPending = vi.fn();

const watcher = new Signal.subtle.Watcher(() => {
watcher.getPending();
});
watcher.getPending = mockGetPending;

const signal = new Signal.State<number>(0);
watcher.watch(signal);

signal.set(1);
expect(mockGetPending).toBeCalled();
});
});

describe("Expected class shape", () => {
Expand Down

0 comments on commit 6c1b06a

Please sign in to comment.