Skip to content

Commit

Permalink
Run .subscribe callbacks in an untracked context
Browse files Browse the repository at this point in the history
  • Loading branch information
jviide committed Sep 19, 2022
1 parent 7860a86 commit 89654ed
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
12 changes: 11 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,17 @@ Signal.prototype._unsubscribe = function (node) {
};

Signal.prototype.subscribe = function (fn) {
return effect(() => fn(this.value));
const signal = this;
return effect(function (this: Effect) {
const value = signal.value;
const flag = this._flags & AUTO_SUBSCRIBE;
this._flags &= ~AUTO_SUBSCRIBE;
try {
fn(value);
} finally {
this._flags |= flag;
}
});
};

Signal.prototype.valueOf = function () {
Expand Down
93 changes: 93 additions & 0 deletions packages/core/test/signal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,99 @@ describe("signal", () => {
a.value = 2;
expect(spy).not.to.be.called;
});

it("should be autodisposed when the surrounding effect is rerun", () => {
const spy = sinon.spy();
const a = signal(0);
const b = signal(0);

effect(() => {
if (b.value === 0) {
a.subscribe(() => {
spy();
});
}
});
expect(spy).to.be.calledOnce;
spy.resetHistory();

b.value = 1;
a.value = 1;
expect(spy).not.to.be.called;
});

it("should be autodispose effects created inside the callback", () => {
const spy = sinon.spy();
const a = signal(0);

const dispose = a.subscribe(() => {
effect(() => {
return spy;
});
});
expect(spy).not.to.be.called;
spy.resetHistory();

a.value++;
expect(spy).to.be.calledOnce;

dispose();
expect(spy).to.be.calledTwice;
});

it("should be autodisposed when the surrounding effect is disposed", () => {
const spy = sinon.spy();
const a = signal(0);
const b = signal(0);

const dispose = effect(() => {
if (b.value === 0) {
a.subscribe(() => {
spy();
});
}
});
expect(spy).to.be.calledOnce;
spy.resetHistory();

dispose();
a.value = 1;
expect(spy).not.to.be.called;
});

it("should not start triggering on when a signal accessed in the callback changes", () => {
const spy = sinon.spy();
const a = signal(0);
const b = signal(0);

a.subscribe(() => {
b.value;
spy();
});
expect(spy).to.be.calledOnce;
spy.resetHistory();

b.value++;
expect(spy).not.to.be.called;
});

it("should not cause surrounding effect subscribe to changes to a signal accessed in the callback", () => {
const spy = sinon.spy();
const a = signal(0);
const b = signal(0);

effect(() => {
a.subscribe(() => {
b.value;
});
spy();
});
expect(spy).to.be.calledOnce;
spy.resetHistory();

b.value++;
expect(spy).not.to.be.called;
});
});
});

Expand Down

0 comments on commit 89654ed

Please sign in to comment.