@dougongjs/reactive 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Independent synchronous signals and structurally owned reactive generations. No external runtime dependencies.
4
4
 
5
- Upgrading from 0.8.3? Read the [migration guide](https://tangerg.github.io/dougong/en/guide/migrating-to-0.9) and [0.9.0 release notes](https://tangerg.github.io/dougong/en/reference/release-0.9.0).
5
+ Upgrading from 0.9? Read the [migration guide](https://tangerg.github.io/dougong/en/guide/migrating-to-0.10) and [0.10.0 release notes](https://tangerg.github.io/dougong/en/reference/release-0.10.0). From 0.8.3, complete [Migrating to 0.9.0](https://tangerg.github.io/dougong/en/guide/migrating-to-0.9) first.
6
6
 
7
7
  ```ts
8
8
  import { batch, computed, disposeSymbol, signal } from "@dougongjs/reactive";
package/dist/abort.d.ts CHANGED
@@ -1,4 +1,5 @@
1
+ import { SynchronousResult } from './async-result.js';
1
2
  export declare function isAborted(signal: AbortSignal): boolean;
2
3
  export declare function abortReason(signal: AbortSignal): unknown;
3
- export declare function onAbort(signal: AbortSignal, callback: (reason: unknown) => void): () => void;
4
+ export declare function onAbort<Result>(signal: AbortSignal, callback: (reason: unknown) => SynchronousResult<Result>): () => void;
4
5
  //# sourceMappingURL=abort.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"abort.d.ts","sourceRoot":"","sources":["../src/abort.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAEtD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAExD;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CA6B5F"}
1
+ {"version":3,"file":"abort.d.ts","sourceRoot":"","sources":["../src/abort.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG9E,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAEtD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAExD;AAED,wBAAgB,OAAO,CAAC,MAAM,EAC5B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,iBAAiB,CAAC,MAAM,CAAC,GACvD,MAAM,IAAI,CA6BZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,eAAe,EAEpB,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAU,KAAK,cAAc,EAAe,MAAM,cAAc,CAAC;AAGxE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,OAAO,KAAK,eAAe,CAAC;CAC7D;AA4ID,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAmBpF"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,eAAe,EAEpB,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAiB,KAAK,cAAc,EAAe,MAAM,cAAc,CAAC;AAG/E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,OAAO,KAAK,eAAe,CAAC;CAC7D;AAyJD,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAmBpF"}
package/dist/index.js CHANGED
@@ -228,7 +228,7 @@ var M = class {
228
228
  }
229
229
  #d() {
230
230
  let e = this.#r;
231
- if (e.phase === "error") throw e.error;
231
+ if (e.outcome === "error") throw e.error;
232
232
  return e.value;
233
233
  }
234
234
  subscribeInvalidation(e) {
@@ -265,7 +265,7 @@ var M = class {
265
265
  return;
266
266
  }
267
267
  let t = /* @__PURE__ */ new Set(), n = this.#v(t);
268
- this.#y(t), (!e || (n.phase === "value" ? e.phase !== "value" || !Object.is(e.value, n.value) : e.phase !== "error" || !Object.is(e.error, n.error))) && this.#c++, this.#r = n, this.#i = g, this.#t.size && this.#h();
268
+ this.#y(t), (!e || (n.outcome === "value" ? e.outcome !== "value" || !Object.is(e.value, n.value) : e.outcome !== "error" || !Object.is(e.error, n.error))) && this.#c++, this.#r = n, this.#i = g, this.#t.size && this.#h();
269
269
  }
270
270
  #_() {
271
271
  for (let [t, n] of this.#n) if (t instanceof e && t.#a !== void 0 || (t.refresh(), n.version !== t.version)) return !0;
@@ -277,12 +277,12 @@ var M = class {
277
277
  try {
278
278
  let e = this.#e, t = e();
279
279
  return c(t, "Computed signal calculations must be synchronous"), {
280
- phase: "value",
280
+ outcome: "value",
281
281
  value: t
282
282
  };
283
283
  } catch (e) {
284
284
  return {
285
- phase: "error",
285
+ outcome: "error",
286
286
  error: e
287
287
  };
288
288
  } finally {
@@ -299,7 +299,7 @@ var M = class {
299
299
  });
300
300
  }
301
301
  }
302
- }, P = class {
302
+ }, P = "Readable bridge has been disposed", F = class {
303
303
  #e;
304
304
  #t;
305
305
  #n;
@@ -307,14 +307,14 @@ var M = class {
307
307
  view;
308
308
  constructor(e) {
309
309
  this.#e = A({
310
- phase: "value",
310
+ outcome: "value",
311
311
  source: e,
312
312
  value: e.get()
313
313
  }), this.view = Object.freeze({
314
314
  get: () => {
315
315
  let e = this.#e?.get();
316
- if (!e) throw Error("Readable bridge has been disposed");
317
- if (e.phase === "error") throw e.error;
316
+ if (!e) throw Error(P);
317
+ if (e.outcome === "error") throw e.error;
318
318
  return e.value;
319
319
  },
320
320
  subscribe: (e) => this.#o(e)
@@ -325,7 +325,7 @@ var M = class {
325
325
  try {
326
326
  n = p(e.defer(() => (this[r](), t ? Promise.resolve().then(() => this.#i()) : void 0)), "BridgeOwner.defer() must return an AsyncDisposable");
327
327
  let i = this.#e?.get();
328
- if (!i) throw Error("Readable bridge has been disposed");
328
+ if (!i) throw Error(P);
329
329
  let a = f(i.source.subscribe(() => this.#a()));
330
330
  if (this.#t = a, !this.#e?.get()) {
331
331
  try {
@@ -333,7 +333,7 @@ var M = class {
333
333
  } catch (e) {
334
334
  this.#r = { value: e };
335
335
  }
336
- throw Error("Readable bridge has been disposed");
336
+ throw Error(P);
337
337
  }
338
338
  this.#a(), this.view.get();
339
339
  } catch (e) {
@@ -347,34 +347,36 @@ var M = class {
347
347
  if (this.#r) throw this.#r.value;
348
348
  }
349
349
  #a() {
350
- let e = this.#e?.get();
351
- if (!e) return;
352
- let t = Symbol();
353
- this.#n = t;
354
- try {
355
- let { source: n } = e, r;
350
+ k(() => {
351
+ let e = this.#e?.get();
352
+ if (!e) return;
353
+ let t = Symbol();
354
+ this.#n = t;
356
355
  try {
357
- r = {
358
- phase: "value",
359
- source: n,
360
- value: n.get()
361
- };
362
- } catch (e) {
363
- r = {
364
- phase: "error",
365
- source: n,
366
- error: e
367
- };
356
+ let { source: n } = e, r;
357
+ try {
358
+ r = {
359
+ outcome: "value",
360
+ source: n,
361
+ value: n.get()
362
+ };
363
+ } catch (e) {
364
+ r = {
365
+ outcome: "error",
366
+ source: n,
367
+ error: e
368
+ };
369
+ }
370
+ if (this.#n !== t || this.#e?.get() !== e || e.outcome === "value" && r.outcome === "value" && Object.is(e.value, r.value) || e.outcome === "error" && r.outcome === "error" && Object.is(e.error, r.error)) return;
371
+ this.#e?.set(r);
372
+ } finally {
373
+ this.#n = void 0;
368
374
  }
369
- if (this.#n !== t || this.#e?.get() !== e || e.phase === "value" && r.phase === "value" && Object.is(e.value, r.value) || e.phase === "error" && r.phase === "error" && Object.is(e.error, r.error)) return;
370
- this.#e?.set(r);
371
- } finally {
372
- this.#n = void 0;
373
- }
375
+ });
374
376
  }
375
377
  #o(e) {
376
378
  let t = this.#e;
377
- if (!t?.get()) throw Error("Readable bridge has been disposed");
379
+ if (!t?.get()) throw Error(P);
378
380
  h(e);
379
381
  let n = t.subscribe(() => (this.#e?.get() || n[r](), e()));
380
382
  return n;
@@ -401,10 +403,10 @@ var M = class {
401
403
  }
402
404
  }
403
405
  };
404
- function F(e, t) {
406
+ function I(e, t) {
405
407
  let n = e?.defer;
406
408
  if (typeof n != "function") throw TypeError("bridge() expects a resource owner");
407
- let i = d(t, "bridge()"), a = { defer: (t) => Reflect.apply(n, e, [t]) }, o = new P(i);
409
+ let i = d(t, "bridge()"), a = { defer: (t) => Reflect.apply(n, e, [t]) }, o = new F(i);
408
410
  try {
409
411
  return o.start(a), o.view;
410
412
  } catch (e) {
@@ -417,15 +419,15 @@ function F(e, t) {
417
419
  }
418
420
  }
419
421
  // src/abort.ts
420
- function I(e) {
422
+ function L(e) {
421
423
  return Reflect.get(AbortSignal.prototype, "aborted", e);
422
424
  }
423
- function L(e) {
425
+ function R(e) {
424
426
  return Reflect.get(AbortSignal.prototype, "reason", e);
425
427
  }
426
- function R(t, n) {
428
+ function z(t, n) {
427
429
  if (typeof n != "function") throw TypeError("Abort listener must be a function");
428
- if (I(t)) return n(L(t)), () => {};
430
+ if (L(t)) return B(n, R(t)), () => {};
429
431
  let r = {
430
432
  signal: t,
431
433
  callback: n
@@ -434,14 +436,17 @@ function R(t, n) {
434
436
  r = void 0, i?.(), i = void 0;
435
437
  }
436
438
  function o() {
437
- if (!r || !I(r.signal)) return;
438
- let { signal: e, callback: t } = r, n = L(e);
439
- a(), t(n);
439
+ if (!r || !L(r.signal)) return;
440
+ let { signal: e, callback: t } = r, n = R(e);
441
+ a(), B(t, n);
440
442
  }
441
443
  return i = e(t, o), r ? o() : a(), a;
442
444
  }
445
+ function B(e, t) {
446
+ c(e(t), "Abort listeners must be synchronous");
447
+ }
443
448
  // src/observe.ts
444
- var z = class {
449
+ var V = "observation", H = class {
445
450
  #e;
446
451
  #t;
447
452
  #n;
@@ -510,7 +515,7 @@ var z = class {
510
515
  } catch (t) {
511
516
  e.push(t);
512
517
  }
513
- await V(this.#x(), e);
518
+ await W(this.#x(), e);
514
519
  try {
515
520
  await this.#b();
516
521
  } catch (t) {
@@ -523,14 +528,14 @@ var z = class {
523
528
  this.#e.phase === "active" && (this.#o = !0, this.#u?.());
524
529
  }
525
530
  async #g(e) {
526
- let t = R(e, () => this.#u?.());
531
+ let t = z(e, () => this.#u?.());
527
532
  try {
528
- for (; this.#e.phase === "active" && !I(e);) {
533
+ for (; this.#e.phase === "active" && !L(e);) {
529
534
  if (!this.#o) {
530
535
  let e = Promise.withResolvers();
531
536
  this.#u = e.resolve, await e.promise, this.#u = void 0;
532
537
  }
533
- for (; this.#e.phase === "active" && !I(e) && this.#o;) this.#o = !1, await this.#_(e);
538
+ for (; this.#e.phase === "active" && !L(e) && this.#o;) this.#o = !1, await this.#_(e);
534
539
  }
535
540
  } catch (e) {
536
541
  if (this.#e.phase !== "active") throw e;
@@ -545,7 +550,7 @@ var z = class {
545
550
  }
546
551
  }
547
552
  async #_(e) {
548
- if (this.#e.phase !== "active" || I(e)) return;
553
+ if (this.#e.phase !== "active" || L(e)) return;
549
554
  let t = this.#e.binding.source.get();
550
555
  if (!(this.#a.present && Object.is(t, this.#a.value))) {
551
556
  try {
@@ -553,14 +558,14 @@ var z = class {
553
558
  } catch (e) {
554
559
  throw this.#e.phase === "active" && await this.#C(), e;
555
560
  }
556
- this.#a = { present: !1 }, !(this.#e.phase !== "active" || I(e)) && this.#v(e);
561
+ this.#a = { present: !1 }, !(this.#e.phase !== "active" || L(e)) && this.#v(e);
557
562
  }
558
563
  }
559
564
  #v(e) {
560
- let { owner: t } = this.#w(), n = t.child("observation");
561
- if (this.#n = p(n, "ObservationOwner.child() must return an AsyncDisposable"), e && I(e)) return;
565
+ let { owner: t } = this.#w(), n = t.child(V);
566
+ if (this.#n = p(n, "ObservationOwner.child() must return an AsyncDisposable"), e && L(e)) return;
562
567
  let r = this.#w().source.get();
563
- e && I(e) || (this.#y(r, n), this.#e.phase === "active" && (this.#a = {
568
+ e && L(e) || (this.#y(r, n), this.#e.phase === "active" && (this.#a = {
564
569
  present: !0,
565
570
  value: r
566
571
  }));
@@ -594,7 +599,7 @@ var z = class {
594
599
  this.#e = { phase: e }, this.#a = { present: !1 }, this.#o = !1;
595
600
  }
596
601
  };
597
- function B(e, t, n) {
602
+ function U(e, t, n) {
598
603
  let r = d(t, "observe()");
599
604
  if (typeof n != "function") throw TypeError("Observer must be a function");
600
605
  let i = e?.defer, a = e?.child, o = e?.spawn;
@@ -603,10 +608,9 @@ function B(e, t, n) {
603
608
  defer: (t) => Reflect.apply(i, e, [t]),
604
609
  child: (t) => Reflect.apply(a, e, [t]),
605
610
  spawn: (t) => Reflect.apply(o, e, [t])
606
- }, l = new z(c, r, n), u = p(c.defer(() => l.dispose()), "ObservationOwner.defer() must return an AsyncDisposable");
607
- l.attachOwnerCleanup(u);
611
+ }, l = new H(c, r, n), u = l.dispose.bind(l);
608
612
  try {
609
- return l.start(), l.handle;
613
+ return u = p(c.defer(u), "ObservationOwner.defer() must return an AsyncDisposable"), l.attachOwnerCleanup(u), l.start(), l.handle;
610
614
  } catch (e) {
611
615
  try {
612
616
  s(u()).catch(() => void 0);
@@ -616,11 +620,11 @@ function B(e, t, n) {
616
620
  throw e;
617
621
  }
618
622
  }
619
- async function V(e, t) {
623
+ async function W(e, t) {
620
624
  if (e) try {
621
625
  await s(e());
622
626
  } catch (e) {
623
627
  t.push(e);
624
628
  }
625
629
  }
626
- export { i as asyncDisposeSymbol, k as batch, F as bridge, j as computed, r as disposeSymbol, B as observe, A as signal };
630
+ export { i as asyncDisposeSymbol, k as batch, I as bridge, j as computed, r as disposeSymbol, U as observe, A as signal };
@@ -1 +1 @@
1
- {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../src/observe.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAI3B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB,CAAC,KAAK,SAAS,eAAe,GAAG,eAAe;IAC/E,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,OAAO,KAAK,eAAe,CAAC;IAC5D,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,eAAe,CAAC;CAC9F;AAED,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,KAAK,SAAS,eAAe,EAAE,MAAM,GAAG,IAAI,IAAI,CACtE,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,KAAK,KACZ,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAyP/B,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,SAAS,eAAe,EAAE,MAAM,GAAG,IAAI,EACrE,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAC9B,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EACnB,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GACnC,eAAe,CAgCjB"}
1
+ {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../src/observe.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAI3B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB,CAAC,KAAK,SAAS,eAAe,GAAG,eAAe;IAC/E,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,OAAO,KAAK,eAAe,CAAC;IAC5D,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,eAAe,CAAC;CAC9F;AAED,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,KAAK,SAAS,eAAe,EAAE,MAAM,GAAG,IAAI,IAAI,CACtE,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,KAAK,KACZ,iBAAiB,CAAC,MAAM,CAAC,CAAC;AA2P/B,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,SAAS,eAAe,EAAE,MAAM,GAAG,IAAI,EACrE,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAC9B,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EACnB,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GACnC,eAAe,CAkCjB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dougongjs/reactive",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": "^24.22.0 || >=26.10.0"
@@ -1,2 +1,3 @@
1
1
  // Generated from tooling/internal/abort-listener.d.mts. Run pnpm generate:internal.
2
+ export function assertAbortRuntime(any: unknown): void;
2
3
  export function listenForAbort(signal: AbortSignal, notify: () => void): () => void;
@@ -1,4 +1,22 @@
1
1
  // Generated from tooling/internal/abort-listener.mjs. Run pnpm generate:internal.
2
+ // The private dependent must take its state from the source's controller. A runtime whose
3
+ // AbortSignal.any reads the public, shadowable properties instead would create a dependent
4
+ // already aborted with a forged reason, which never reports the real cancellation.
5
+ export function assertAbortRuntime(any) {
6
+ if (typeof any !== "function") {
7
+ throw new Error("Unsupported JavaScript runtime: AbortSignal.any is required");
8
+ }
9
+ const source = new AbortController().signal;
10
+ Object.defineProperty(source, "aborted", { value: true });
11
+ if (Reflect.get(AbortSignal.prototype, "aborted", any.call(AbortSignal, [source]))) {
12
+ throw new Error(
13
+ "Unsupported JavaScript runtime: AbortSignal.any must read native signal state",
14
+ );
15
+ }
16
+ }
17
+
18
+ assertAbortRuntime(AbortSignal.any);
19
+
2
20
  // A separate closure prevents the dependent from retaining the source through its registration.
3
21
  function weakAbortListener(reference) {
4
22
  return () => reference.deref()?.();