Initial commit
This commit is contained in:
21
node_modules/alien-signals/LICENSE
generated
vendored
Normal file
21
node_modules/alien-signals/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024-present Johnson Chu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
198
node_modules/alien-signals/README.md
generated
vendored
Normal file
198
node_modules/alien-signals/README.md
generated
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
<p align="center">
|
||||
<img src="assets/logo.png" width="250"><br>
|
||||
<p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://npmjs.com/package/alien-signals"><img src="https://badgen.net/npm/v/alien-signals" alt="npm package"></a>
|
||||
</p>
|
||||
|
||||
<h3 align="center">
|
||||
<p>[<a href="https://github.com/YanqingXu/alien-signals-in-lua">Alien Signals in Lua</a>]</p>
|
||||
<p>[<a href="https://github.com/medz/alien-signals-dart">Alien Signals in Dart</a>]</p>
|
||||
<p>[<a href="https://github.com/Rajaniraiyn/react-alien-signals">React Binding</a>]</p>
|
||||
</h3>
|
||||
|
||||
# alien-signals
|
||||
|
||||
The goal of `alien-signals` is to create a ~~push-pull~~ [push-pull-push model](https://github.com/stackblitz/alien-signals/pull/19) based signal library with the lowest overhead.
|
||||
|
||||
We have set the following constraints in scheduling logic:
|
||||
|
||||
1. No dynamic object fields
|
||||
2. No use of Array/Set/Map
|
||||
3. No recursion calls
|
||||
4. Class properties must be fewer than 10 (https://v8.dev/blog/fast-properties)
|
||||
|
||||
Experimental results have shown that with these constraints, it is possible to achieve excellent performance for a Signal library without using sophisticated scheduling strategies. The overall performance of `alien-signals` is approximately 400% that of Vue 3.4's reactivity system.
|
||||
|
||||
For more detailed performance comparisons, please visit: https://github.com/transitive-bullshit/js-reactivity-benchmark
|
||||
|
||||
## Motivation
|
||||
|
||||
To achieve high-performance code generation in https://github.com/vuejs/language-tools, I needed to write some on-demand computed logic using Signals, but I couldn't find a low-cost Signal library that satisfied me.
|
||||
|
||||
In the past, I accumulated some knowledge of reactivity systems in https://github.com/vuejs/core/pull/5912, so I attempted to develop `alien-signals` with the goal of creating a Signal library with minimal memory usage and excellent performance.
|
||||
|
||||
Since Vue 3.5 switched to a Pull reactivity system in https://github.com/vuejs/core/pull/10397, I continued to research the Push-Pull reactivity system here. It is worth mentioning that I was inspired by the doubly-linked concept, but `alien-signals` does not use a similar implementation.
|
||||
|
||||
## Adoptions
|
||||
|
||||
- Used in Vue language tools (https://github.com/vuejs/language-tools) for virtual code generation.
|
||||
|
||||
- The core reactivity system code was ported to Vue 3.6 and later. (https://github.com/vuejs/core/pull/12349)
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic
|
||||
|
||||
```ts
|
||||
import { signal, computed, effect } from 'alien-signals';
|
||||
|
||||
const count = signal(1);
|
||||
const doubleCount = computed(() => count.get() * 2);
|
||||
|
||||
effect(() => {
|
||||
console.log(`Count is: ${count.get()}`);
|
||||
}); // Console: Count is: 1
|
||||
|
||||
console.log(doubleCount.get()); // 2
|
||||
|
||||
count.set(2); // Console: Count is: 2
|
||||
|
||||
console.log(doubleCount.get()); // 4
|
||||
```
|
||||
|
||||
### Effect Scope
|
||||
|
||||
```ts
|
||||
import { signal, effectScope } from 'alien-signals';
|
||||
|
||||
const count = signal(1);
|
||||
const scope = effectScope();
|
||||
|
||||
scope.run(() => {
|
||||
effect(() => {
|
||||
console.log(`Count in scope: ${count.get()}`);
|
||||
}); // Console: Count in scope: 1
|
||||
|
||||
count.set(2); // Console: Count in scope: 2
|
||||
});
|
||||
|
||||
scope.stop();
|
||||
|
||||
count.set(3); // No console output
|
||||
```
|
||||
|
||||
## About `propagate` and `checkDirty` functions
|
||||
|
||||
In order to eliminate recursive calls and improve performance, we record the last link node of the previous loop in `propagate` and `checkDirty` functions, and implement the rollback logic to return to this node.
|
||||
|
||||
This results in code that is difficult to understand, and you don't necessarily get the same performance improvements in other languages, so we record the original implementation without eliminating recursive calls here for reference.
|
||||
|
||||
#### `propagate`
|
||||
|
||||
```ts
|
||||
export function propagate(link: Link, targetFlag: SubscriberFlags = SubscriberFlags.Dirty): void {
|
||||
do {
|
||||
const sub = link.sub;
|
||||
const subFlags = sub.flags;
|
||||
|
||||
if (
|
||||
(
|
||||
!(subFlags & (SubscriberFlags.Tracking | SubscriberFlags.Recursed | SubscriberFlags.InnerEffectsPending | SubscriberFlags.ToCheckDirty | SubscriberFlags.Dirty))
|
||||
&& (sub.flags = subFlags | targetFlag, true)
|
||||
)
|
||||
|| (
|
||||
(subFlags & (SubscriberFlags.Tracking | SubscriberFlags.Recursed)) === SubscriberFlags.Recursed
|
||||
&& (sub.flags = (subFlags & ~SubscriberFlags.Recursed) | targetFlag, true)
|
||||
)
|
||||
|| (
|
||||
!(subFlags & (SubscriberFlags.InnerEffectsPending | SubscriberFlags.ToCheckDirty | SubscriberFlags.Dirty))
|
||||
&& isValidLink(link, sub)
|
||||
&& (
|
||||
sub.flags = subFlags | SubscriberFlags.Recursed | targetFlag,
|
||||
(sub as Dependency).subs !== undefined
|
||||
)
|
||||
)
|
||||
) {
|
||||
const subSubs = (sub as Dependency).subs;
|
||||
if (subSubs !== undefined) {
|
||||
propagate(
|
||||
subSubs,
|
||||
'notify' in sub
|
||||
? SubscriberFlags.InnerEffectsPending
|
||||
: SubscriberFlags.ToCheckDirty
|
||||
);
|
||||
} else if ('notify' in sub) {
|
||||
if (queuedEffectsTail !== undefined) {
|
||||
queuedEffectsTail.nextNotify = sub;
|
||||
} else {
|
||||
queuedEffects = sub;
|
||||
}
|
||||
queuedEffectsTail = sub;
|
||||
}
|
||||
} else if (
|
||||
!(subFlags & (SubscriberFlags.Tracking | targetFlag))
|
||||
|| (
|
||||
!(subFlags & targetFlag)
|
||||
&& (subFlags & (SubscriberFlags.InnerEffectsPending | SubscriberFlags.ToCheckDirty | SubscriberFlags.Dirty))
|
||||
&& isValidLink(link, sub)
|
||||
)
|
||||
) {
|
||||
sub.flags = subFlags | targetFlag;
|
||||
}
|
||||
|
||||
link = link.nextSub!;
|
||||
} while (link !== undefined);
|
||||
|
||||
if (targetFlag === SubscriberFlags.Dirty && !batchDepth) {
|
||||
drainQueuedEffects();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `checkDirty`
|
||||
|
||||
```ts
|
||||
export function checkDirty(link: Link): boolean {
|
||||
do {
|
||||
const dep = link.dep;
|
||||
if ('update' in dep) {
|
||||
const depFlags = dep.flags;
|
||||
if (depFlags & SubscriberFlags.Dirty) {
|
||||
if (dep.update()) {
|
||||
const subs = dep.subs!;
|
||||
if (subs.nextSub !== undefined) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (depFlags & SubscriberFlags.ToCheckDirty) {
|
||||
if (checkDirty(dep.deps!)) {
|
||||
if (dep.update()) {
|
||||
const subs = dep.subs!;
|
||||
if (subs.nextSub !== undefined) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
dep.flags = depFlags & ~SubscriberFlags.ToCheckDirty;
|
||||
}
|
||||
}
|
||||
}
|
||||
link = link.nextDep!;
|
||||
} while (link !== undefined);
|
||||
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
## Roadmap
|
||||
|
||||
| Version | Savings |
|
||||
|---------|-----------------------------------------------------------------------------------------------|
|
||||
| 0.3 | Satisfy all 4 constraints |
|
||||
| 0.2 | Correctly schedule computed side effects |
|
||||
| 0.1 | Correctly schedule inner effect callbacks |
|
||||
| 0.0 | Add APIs: `signal()`, `computed()`, `effect()`, `effectScope()`, `startBatch()`, `endBatch()` |
|
||||
24
node_modules/alien-signals/benchs/complex.mjs
generated
vendored
Normal file
24
node_modules/alien-signals/benchs/complex.mjs
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import { run, bench, boxplot } from 'mitata';
|
||||
import { computed, effect, signal } from '../esm/index.mjs';
|
||||
|
||||
boxplot(() => {
|
||||
bench('complex: $w * $h', function* (state) {
|
||||
const w = state.get('w');
|
||||
const h = state.get('h');
|
||||
const src = signal({ w, h });
|
||||
for (let i = 0; i < w; i++) {
|
||||
let last = src;
|
||||
for (let j = 0; j < h; j++) {
|
||||
const prev = last;
|
||||
last = computed(() => ({ [`${i}-${j}`]: prev.get() }));
|
||||
}
|
||||
effect(() => last.get());
|
||||
}
|
||||
|
||||
yield () => src.set({ upstream: src.get() });
|
||||
})
|
||||
.args('h', [1, 10, 100])
|
||||
.args('w', [1, 10, 100]);
|
||||
});
|
||||
|
||||
run({ format: 'markdown' });
|
||||
23
node_modules/alien-signals/benchs/memoryUsage.mjs
generated
vendored
Normal file
23
node_modules/alien-signals/benchs/memoryUsage.mjs
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { computed, effect, signal } from '../esm/index.mjs';
|
||||
|
||||
globalThis.gc();
|
||||
const start = process.memoryUsage().heapUsed;
|
||||
|
||||
const w = 100;
|
||||
const h = 100;
|
||||
const src = signal(1);
|
||||
|
||||
for (let i = 0; i < w; i++) {
|
||||
let last = src;
|
||||
for (let j = 0; j < h; j++) {
|
||||
const prev = last;
|
||||
last = computed(() => prev.get() + 1);
|
||||
}
|
||||
effect(() => last.get());
|
||||
}
|
||||
|
||||
src.set(src.get() + 1);
|
||||
|
||||
globalThis.gc();
|
||||
const end = process.memoryUsage().heapUsed;
|
||||
console.log(`Memory Usage: ${((end - start) / 1024).toFixed(2)} KB`);
|
||||
23
node_modules/alien-signals/benchs/propagate.mjs
generated
vendored
Normal file
23
node_modules/alien-signals/benchs/propagate.mjs
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { run, bench, boxplot } from 'mitata';
|
||||
import { computed, effect, signal } from '../esm/index.mjs';
|
||||
|
||||
boxplot(() => {
|
||||
bench('propagate: $w * $h', function* (state) {
|
||||
const w = state.get('w');
|
||||
const h = state.get('h');
|
||||
const src = signal(1);
|
||||
for (let i = 0; i < w; i++) {
|
||||
let last = src;
|
||||
for (let j = 0; j < h; j++) {
|
||||
const prev = last;
|
||||
last = computed(() => prev.get() + 1);
|
||||
}
|
||||
effect(() => last.get());
|
||||
}
|
||||
yield () => src.set(src.get() + 1);
|
||||
})
|
||||
.args('h', [1, 10, 100])
|
||||
.args('w', [1, 10, 100]);
|
||||
});
|
||||
|
||||
run({ format: 'markdown' });
|
||||
19
node_modules/alien-signals/cjs/computed.d.ts
generated
vendored
Normal file
19
node_modules/alien-signals/cjs/computed.d.ts
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DirtyLevels, IComputed, Link } from './system.js';
|
||||
export interface ISignal<T = any> {
|
||||
get(): T;
|
||||
}
|
||||
export declare function computed<T>(getter: (cachedValue?: T) => T): ISignal<T>;
|
||||
export declare class Computed<T = any> implements IComputed {
|
||||
getter: (cachedValue?: T) => T;
|
||||
cachedValue: T | undefined;
|
||||
subs: Link | undefined;
|
||||
subsTail: Link | undefined;
|
||||
deps: Link | undefined;
|
||||
depsTail: Link | undefined;
|
||||
trackId: number;
|
||||
dirtyLevel: DirtyLevels;
|
||||
canPropagate: boolean;
|
||||
constructor(getter: (cachedValue?: T) => T);
|
||||
get(): T;
|
||||
update(): boolean;
|
||||
}
|
||||
17
node_modules/alien-signals/cjs/effect.d.ts
generated
vendored
Normal file
17
node_modules/alien-signals/cjs/effect.d.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Dependency, DirtyLevels, IEffect, Link } from './system.js';
|
||||
export declare function effect(fn: () => void): Effect<void>;
|
||||
export declare class Effect<T = any> implements IEffect, Dependency {
|
||||
fn: () => T;
|
||||
nextNotify: IEffect | undefined;
|
||||
subs: Link | undefined;
|
||||
subsTail: Link | undefined;
|
||||
deps: Link | undefined;
|
||||
depsTail: Link | undefined;
|
||||
trackId: number;
|
||||
dirtyLevel: DirtyLevels;
|
||||
canPropagate: boolean;
|
||||
constructor(fn: () => T);
|
||||
notify(): void;
|
||||
run(): T;
|
||||
stop(): void;
|
||||
}
|
||||
13
node_modules/alien-signals/cjs/effectScope.d.ts
generated
vendored
Normal file
13
node_modules/alien-signals/cjs/effectScope.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { DirtyLevels, Link, Subscriber } from './system.js';
|
||||
export declare let activeEffectScope: EffectScope | undefined;
|
||||
export declare function effectScope(): EffectScope;
|
||||
export declare class EffectScope implements Subscriber {
|
||||
deps: Link | undefined;
|
||||
depsTail: Link | undefined;
|
||||
trackId: number;
|
||||
dirtyLevel: DirtyLevels;
|
||||
canPropagate: boolean;
|
||||
notify(): void;
|
||||
run<T>(fn: () => T): T;
|
||||
stop(): void;
|
||||
}
|
||||
895
node_modules/alien-signals/cjs/index.cjs
generated
vendored
Normal file
895
node_modules/alien-signals/cjs/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,895 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
Computed: () => Computed,
|
||||
Effect: () => Effect,
|
||||
EffectScope: () => EffectScope,
|
||||
Signal: () => Signal,
|
||||
SubscriberFlags: () => SubscriberFlags,
|
||||
activeEffectScope: () => activeEffectScope,
|
||||
activeScopeTrackId: () => activeScopeTrackId,
|
||||
activeSub: () => activeSub,
|
||||
activeTrackId: () => activeTrackId,
|
||||
checkDirty: () => checkDirty,
|
||||
computed: () => computed,
|
||||
effect: () => effect,
|
||||
effectScope: () => effectScope,
|
||||
endBatch: () => endBatch,
|
||||
endTrack: () => endTrack,
|
||||
lastTrackId: () => lastTrackId,
|
||||
link: () => link,
|
||||
nextTrackId: () => nextTrackId,
|
||||
propagate: () => propagate,
|
||||
setActiveScope: () => setActiveScope,
|
||||
setActiveSub: () => setActiveSub,
|
||||
shallowPropagate: () => shallowPropagate,
|
||||
signal: () => signal,
|
||||
startBatch: () => startBatch,
|
||||
startTrack: () => startTrack,
|
||||
unstable: () => unstable,
|
||||
untrack: () => untrack,
|
||||
untrackScope: () => untrackScope
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
|
||||
// src/system.ts
|
||||
var SubscriberFlags = /* @__PURE__ */ ((SubscriberFlags2) => {
|
||||
SubscriberFlags2[SubscriberFlags2["None"] = 0] = "None";
|
||||
SubscriberFlags2[SubscriberFlags2["Tracking"] = 1] = "Tracking";
|
||||
SubscriberFlags2[SubscriberFlags2["Recursed"] = 2] = "Recursed";
|
||||
SubscriberFlags2[SubscriberFlags2["InnerEffectsPending"] = 4] = "InnerEffectsPending";
|
||||
SubscriberFlags2[SubscriberFlags2["ToCheckDirty"] = 8] = "ToCheckDirty";
|
||||
SubscriberFlags2[SubscriberFlags2["Dirty"] = 16] = "Dirty";
|
||||
return SubscriberFlags2;
|
||||
})(SubscriberFlags || {});
|
||||
var batchDepth = 0;
|
||||
var queuedEffects;
|
||||
var queuedEffectsTail;
|
||||
var linkPool;
|
||||
function startBatch() {
|
||||
++batchDepth;
|
||||
}
|
||||
function endBatch() {
|
||||
if (!--batchDepth) {
|
||||
drainQueuedEffects();
|
||||
}
|
||||
}
|
||||
function drainQueuedEffects() {
|
||||
while (queuedEffects !== void 0) {
|
||||
const effect2 = queuedEffects;
|
||||
const queuedNext = effect2.nextNotify;
|
||||
if (queuedNext !== void 0) {
|
||||
effect2.nextNotify = void 0;
|
||||
queuedEffects = queuedNext;
|
||||
} else {
|
||||
queuedEffects = void 0;
|
||||
queuedEffectsTail = void 0;
|
||||
}
|
||||
effect2.notify();
|
||||
}
|
||||
}
|
||||
function link(dep, sub) {
|
||||
const currentDep = sub.depsTail;
|
||||
const nextDep = currentDep !== void 0 ? currentDep.nextDep : sub.deps;
|
||||
if (nextDep !== void 0 && nextDep.dep === dep) {
|
||||
sub.depsTail = nextDep;
|
||||
} else {
|
||||
linkNewDep(dep, sub, nextDep, currentDep);
|
||||
}
|
||||
}
|
||||
function linkNewDep(dep, sub, nextDep, depsTail) {
|
||||
let newLink;
|
||||
if (linkPool !== void 0) {
|
||||
newLink = linkPool;
|
||||
linkPool = newLink.nextDep;
|
||||
newLink.nextDep = nextDep;
|
||||
newLink.dep = dep;
|
||||
newLink.sub = sub;
|
||||
} else {
|
||||
newLink = {
|
||||
dep,
|
||||
sub,
|
||||
nextDep,
|
||||
prevSub: void 0,
|
||||
nextSub: void 0
|
||||
};
|
||||
}
|
||||
if (depsTail === void 0) {
|
||||
sub.deps = newLink;
|
||||
} else {
|
||||
depsTail.nextDep = newLink;
|
||||
}
|
||||
if (dep.subs === void 0) {
|
||||
dep.subs = newLink;
|
||||
} else {
|
||||
const oldTail = dep.subsTail;
|
||||
newLink.prevSub = oldTail;
|
||||
oldTail.nextSub = newLink;
|
||||
}
|
||||
sub.depsTail = newLink;
|
||||
dep.subsTail = newLink;
|
||||
}
|
||||
function propagate(link2) {
|
||||
let targetFlag = 16 /* Dirty */;
|
||||
let subs = link2;
|
||||
let stack = 0;
|
||||
top: do {
|
||||
const sub = link2.sub;
|
||||
const subFlags = sub.flags;
|
||||
if (!(subFlags & (1 /* Tracking */ | 2 /* Recursed */ | 4 /* InnerEffectsPending */ | 8 /* ToCheckDirty */ | 16 /* Dirty */)) && (sub.flags = subFlags | targetFlag, true) || (subFlags & (1 /* Tracking */ | 2 /* Recursed */)) === 2 /* Recursed */ && (sub.flags = subFlags & ~2 /* Recursed */ | targetFlag, true) || !(subFlags & (4 /* InnerEffectsPending */ | 8 /* ToCheckDirty */ | 16 /* Dirty */)) && isValidLink(link2, sub) && (sub.flags = subFlags | 2 /* Recursed */ | targetFlag, sub.subs !== void 0)) {
|
||||
const subSubs = sub.subs;
|
||||
if (subSubs !== void 0) {
|
||||
if (subSubs.nextSub !== void 0) {
|
||||
subSubs.prevSub = subs;
|
||||
link2 = subs = subSubs;
|
||||
targetFlag = 8 /* ToCheckDirty */;
|
||||
++stack;
|
||||
} else {
|
||||
link2 = subSubs;
|
||||
targetFlag = "notify" in sub ? 4 /* InnerEffectsPending */ : 8 /* ToCheckDirty */;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ("notify" in sub) {
|
||||
if (queuedEffectsTail !== void 0) {
|
||||
queuedEffectsTail.nextNotify = sub;
|
||||
} else {
|
||||
queuedEffects = sub;
|
||||
}
|
||||
queuedEffectsTail = sub;
|
||||
}
|
||||
} else if (!(subFlags & (1 /* Tracking */ | targetFlag)) || !(subFlags & targetFlag) && subFlags & (4 /* InnerEffectsPending */ | 8 /* ToCheckDirty */ | 16 /* Dirty */) && isValidLink(link2, sub)) {
|
||||
sub.flags = subFlags | targetFlag;
|
||||
}
|
||||
if ((link2 = subs.nextSub) !== void 0) {
|
||||
subs = link2;
|
||||
targetFlag = stack ? 8 /* ToCheckDirty */ : 16 /* Dirty */;
|
||||
continue;
|
||||
}
|
||||
while (stack) {
|
||||
--stack;
|
||||
const dep = subs.dep;
|
||||
const depSubs = dep.subs;
|
||||
subs = depSubs.prevSub;
|
||||
depSubs.prevSub = void 0;
|
||||
if ((link2 = subs.nextSub) !== void 0) {
|
||||
subs = link2;
|
||||
targetFlag = stack ? 8 /* ToCheckDirty */ : 16 /* Dirty */;
|
||||
continue top;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} while (true);
|
||||
if (!batchDepth) {
|
||||
drainQueuedEffects();
|
||||
}
|
||||
}
|
||||
function shallowPropagate(link2) {
|
||||
do {
|
||||
const updateSub = link2.sub;
|
||||
const updateSubFlags = updateSub.flags;
|
||||
if ((updateSubFlags & (8 /* ToCheckDirty */ | 16 /* Dirty */)) === 8 /* ToCheckDirty */) {
|
||||
updateSub.flags = updateSubFlags | 16 /* Dirty */;
|
||||
}
|
||||
link2 = link2.nextSub;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
function isValidLink(subLink, sub) {
|
||||
const depsTail = sub.depsTail;
|
||||
if (depsTail !== void 0) {
|
||||
let link2 = sub.deps;
|
||||
do {
|
||||
if (link2 === subLink) {
|
||||
return true;
|
||||
}
|
||||
if (link2 === depsTail) {
|
||||
break;
|
||||
}
|
||||
link2 = link2.nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function checkDirty(link2) {
|
||||
let stack = 0;
|
||||
let dirty;
|
||||
top: do {
|
||||
dirty = false;
|
||||
const dep = link2.dep;
|
||||
if ("update" in dep) {
|
||||
const depFlags = dep.flags;
|
||||
if (depFlags & 16 /* Dirty */) {
|
||||
if (dep.update()) {
|
||||
const subs = dep.subs;
|
||||
if (subs.nextSub !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
} else if (depFlags & 8 /* ToCheckDirty */) {
|
||||
const depSubs = dep.subs;
|
||||
if (depSubs.nextSub !== void 0) {
|
||||
depSubs.prevSub = link2;
|
||||
}
|
||||
link2 = dep.deps;
|
||||
++stack;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!dirty && link2.nextDep !== void 0) {
|
||||
link2 = link2.nextDep;
|
||||
continue;
|
||||
}
|
||||
if (stack) {
|
||||
let sub = link2.sub;
|
||||
do {
|
||||
--stack;
|
||||
const subSubs = sub.subs;
|
||||
if (dirty) {
|
||||
if (sub.update()) {
|
||||
if ((link2 = subSubs.prevSub) !== void 0) {
|
||||
subSubs.prevSub = void 0;
|
||||
shallowPropagate(sub.subs);
|
||||
sub = link2.sub;
|
||||
} else {
|
||||
sub = subSubs.sub;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
sub.flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
if ((link2 = subSubs.prevSub) !== void 0) {
|
||||
subSubs.prevSub = void 0;
|
||||
if (link2.nextDep !== void 0) {
|
||||
link2 = link2.nextDep;
|
||||
continue top;
|
||||
}
|
||||
sub = link2.sub;
|
||||
} else {
|
||||
if ((link2 = subSubs.nextDep) !== void 0) {
|
||||
continue top;
|
||||
}
|
||||
sub = subSubs.sub;
|
||||
}
|
||||
dirty = false;
|
||||
} while (stack);
|
||||
}
|
||||
return dirty;
|
||||
} while (true);
|
||||
}
|
||||
function startTrack(sub) {
|
||||
sub.depsTail = void 0;
|
||||
sub.flags = 1 /* Tracking */;
|
||||
}
|
||||
function endTrack(sub) {
|
||||
const depsTail = sub.depsTail;
|
||||
if (depsTail !== void 0) {
|
||||
const nextDep = depsTail.nextDep;
|
||||
if (nextDep !== void 0) {
|
||||
clearTrack(nextDep);
|
||||
depsTail.nextDep = void 0;
|
||||
}
|
||||
} else if (sub.deps !== void 0) {
|
||||
clearTrack(sub.deps);
|
||||
sub.deps = void 0;
|
||||
}
|
||||
sub.flags &= ~1 /* Tracking */;
|
||||
}
|
||||
function clearTrack(link2) {
|
||||
do {
|
||||
const dep = link2.dep;
|
||||
const nextDep = link2.nextDep;
|
||||
const nextSub = link2.nextSub;
|
||||
const prevSub = link2.prevSub;
|
||||
if (nextSub !== void 0) {
|
||||
nextSub.prevSub = prevSub;
|
||||
link2.nextSub = void 0;
|
||||
} else {
|
||||
dep.subsTail = prevSub;
|
||||
if ("lastTrackedId" in dep) {
|
||||
dep.lastTrackedId = 0;
|
||||
}
|
||||
}
|
||||
if (prevSub !== void 0) {
|
||||
prevSub.nextSub = nextSub;
|
||||
link2.prevSub = void 0;
|
||||
} else {
|
||||
dep.subs = nextSub;
|
||||
}
|
||||
link2.dep = void 0;
|
||||
link2.sub = void 0;
|
||||
link2.nextDep = linkPool;
|
||||
linkPool = link2;
|
||||
if (dep.subs === void 0 && "deps" in dep) {
|
||||
if ("notify" in dep) {
|
||||
dep.flags = 0 /* None */;
|
||||
} else {
|
||||
const depFlags = dep.flags;
|
||||
if (!(depFlags & 16 /* Dirty */)) {
|
||||
dep.flags = depFlags | 16 /* Dirty */;
|
||||
}
|
||||
}
|
||||
const depDeps = dep.deps;
|
||||
if (depDeps !== void 0) {
|
||||
link2 = depDeps;
|
||||
dep.depsTail.nextDep = nextDep;
|
||||
dep.deps = void 0;
|
||||
dep.depsTail = void 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
link2 = nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
|
||||
// src/effectScope.ts
|
||||
var activeEffectScope = void 0;
|
||||
var activeScopeTrackId = 0;
|
||||
function untrackScope(fn) {
|
||||
const prevSub = activeEffectScope;
|
||||
const prevTrackId = activeScopeTrackId;
|
||||
setActiveScope(void 0, 0);
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
setActiveScope(prevSub, prevTrackId);
|
||||
}
|
||||
}
|
||||
function setActiveScope(sub, trackId) {
|
||||
activeEffectScope = sub;
|
||||
activeScopeTrackId = trackId;
|
||||
}
|
||||
function effectScope() {
|
||||
return new EffectScope();
|
||||
}
|
||||
var EffectScope = class {
|
||||
constructor() {
|
||||
// Subscriber
|
||||
this.deps = void 0;
|
||||
this.depsTail = void 0;
|
||||
this.flags = 0 /* None */;
|
||||
this.trackId = nextTrackId();
|
||||
}
|
||||
notify() {
|
||||
const flags = this.flags;
|
||||
if (flags & 4 /* InnerEffectsPending */) {
|
||||
this.flags = flags & ~4 /* InnerEffectsPending */;
|
||||
let link2 = this.deps;
|
||||
do {
|
||||
const dep = link2.dep;
|
||||
if ("notify" in dep) {
|
||||
dep.notify();
|
||||
}
|
||||
link2 = link2.nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
}
|
||||
run(fn) {
|
||||
const prevSub = activeEffectScope;
|
||||
const prevTrackId = activeScopeTrackId;
|
||||
setActiveScope(this, this.trackId);
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
setActiveScope(prevSub, prevTrackId);
|
||||
}
|
||||
}
|
||||
stop() {
|
||||
startTrack(this);
|
||||
endTrack(this);
|
||||
}
|
||||
};
|
||||
|
||||
// src/effect.ts
|
||||
var activeSub;
|
||||
var activeTrackId = 0;
|
||||
var lastTrackId = 0;
|
||||
function untrack(fn) {
|
||||
const prevSub = activeSub;
|
||||
const prevTrackId = activeTrackId;
|
||||
setActiveSub(void 0, 0);
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
setActiveSub(prevSub, prevTrackId);
|
||||
}
|
||||
}
|
||||
function setActiveSub(sub, trackId) {
|
||||
activeSub = sub;
|
||||
activeTrackId = trackId;
|
||||
}
|
||||
function nextTrackId() {
|
||||
return ++lastTrackId;
|
||||
}
|
||||
function effect(fn) {
|
||||
const e = new Effect(fn);
|
||||
e.run();
|
||||
return e;
|
||||
}
|
||||
var Effect = class {
|
||||
constructor(fn) {
|
||||
this.fn = fn;
|
||||
this.nextNotify = void 0;
|
||||
// Dependency
|
||||
this.subs = void 0;
|
||||
this.subsTail = void 0;
|
||||
// Subscriber
|
||||
this.deps = void 0;
|
||||
this.depsTail = void 0;
|
||||
this.flags = 16 /* Dirty */;
|
||||
if (activeTrackId) {
|
||||
link(this, activeSub);
|
||||
} else if (activeScopeTrackId) {
|
||||
link(this, activeEffectScope);
|
||||
}
|
||||
}
|
||||
notify() {
|
||||
let flags = this.flags;
|
||||
if (flags & 16 /* Dirty */) {
|
||||
this.run();
|
||||
return;
|
||||
}
|
||||
if (flags & 8 /* ToCheckDirty */) {
|
||||
if (checkDirty(this.deps)) {
|
||||
this.run();
|
||||
return;
|
||||
} else {
|
||||
this.flags = flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
}
|
||||
if (flags & 4 /* InnerEffectsPending */) {
|
||||
this.flags = flags & ~4 /* InnerEffectsPending */;
|
||||
let link2 = this.deps;
|
||||
do {
|
||||
const dep = link2.dep;
|
||||
if ("notify" in dep) {
|
||||
dep.notify();
|
||||
}
|
||||
link2 = link2.nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
}
|
||||
run() {
|
||||
const prevSub = activeSub;
|
||||
const prevTrackId = activeTrackId;
|
||||
setActiveSub(this, nextTrackId());
|
||||
startTrack(this);
|
||||
try {
|
||||
return this.fn();
|
||||
} finally {
|
||||
setActiveSub(prevSub, prevTrackId);
|
||||
endTrack(this);
|
||||
}
|
||||
}
|
||||
stop() {
|
||||
startTrack(this);
|
||||
endTrack(this);
|
||||
}
|
||||
};
|
||||
|
||||
// src/computed.ts
|
||||
function computed(getter) {
|
||||
return new Computed(getter);
|
||||
}
|
||||
var Computed = class {
|
||||
constructor(getter) {
|
||||
this.getter = getter;
|
||||
this.currentValue = void 0;
|
||||
// Dependency
|
||||
this.subs = void 0;
|
||||
this.subsTail = void 0;
|
||||
this.lastTrackedId = 0;
|
||||
// Subscriber
|
||||
this.deps = void 0;
|
||||
this.depsTail = void 0;
|
||||
this.flags = 16 /* Dirty */;
|
||||
}
|
||||
get() {
|
||||
const flags = this.flags;
|
||||
if (flags & 16 /* Dirty */) {
|
||||
if (this.update()) {
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
}
|
||||
} else if (flags & 8 /* ToCheckDirty */) {
|
||||
if (checkDirty(this.deps)) {
|
||||
if (this.update()) {
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.flags = flags & ~8 /* ToCheckDirty */;
|
||||
}
|
||||
}
|
||||
if (activeTrackId) {
|
||||
if (this.lastTrackedId !== activeTrackId) {
|
||||
this.lastTrackedId = activeTrackId;
|
||||
link(this, activeSub);
|
||||
}
|
||||
} else if (activeScopeTrackId) {
|
||||
if (this.lastTrackedId !== activeScopeTrackId) {
|
||||
this.lastTrackedId = activeScopeTrackId;
|
||||
link(this, activeEffectScope);
|
||||
}
|
||||
}
|
||||
return this.currentValue;
|
||||
}
|
||||
update() {
|
||||
const prevSub = activeSub;
|
||||
const prevTrackId = activeTrackId;
|
||||
setActiveSub(this, nextTrackId());
|
||||
startTrack(this);
|
||||
try {
|
||||
const oldValue = this.currentValue;
|
||||
const newValue = this.getter(oldValue);
|
||||
if (oldValue !== newValue) {
|
||||
this.currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
setActiveSub(prevSub, prevTrackId);
|
||||
endTrack(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// src/signal.ts
|
||||
function signal(oldValue) {
|
||||
return new Signal(oldValue);
|
||||
}
|
||||
var Signal = class {
|
||||
constructor(currentValue) {
|
||||
this.currentValue = currentValue;
|
||||
// Dependency
|
||||
this.subs = void 0;
|
||||
this.subsTail = void 0;
|
||||
this.lastTrackedId = 0;
|
||||
}
|
||||
get() {
|
||||
if (activeTrackId && this.lastTrackedId !== activeTrackId) {
|
||||
this.lastTrackedId = activeTrackId;
|
||||
link(this, activeSub);
|
||||
}
|
||||
return this.currentValue;
|
||||
}
|
||||
set(value) {
|
||||
if (this.currentValue !== value) {
|
||||
this.currentValue = value;
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
propagate(subs);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// src/unstable/asyncSystem.ts
|
||||
async function asyncCheckDirty(link2) {
|
||||
let stack = 0;
|
||||
let dirty;
|
||||
let nextDep;
|
||||
top: do {
|
||||
dirty = false;
|
||||
const dep = link2.dep;
|
||||
if ("update" in dep) {
|
||||
const depFlags = dep.flags;
|
||||
if (depFlags & 16 /* Dirty */) {
|
||||
if (await dep.update()) {
|
||||
const subs = dep.subs;
|
||||
if (subs.nextSub !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
} else if (depFlags & 8 /* ToCheckDirty */) {
|
||||
const depSubs = dep.subs;
|
||||
if (depSubs.nextSub !== void 0) {
|
||||
depSubs.prevSub = link2;
|
||||
}
|
||||
link2 = dep.deps;
|
||||
++stack;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (dirty || (nextDep = link2.nextDep) === void 0) {
|
||||
if (stack) {
|
||||
let sub = link2.sub;
|
||||
do {
|
||||
--stack;
|
||||
const subSubs = sub.subs;
|
||||
let prevLink = subSubs.prevSub;
|
||||
if (prevLink !== void 0) {
|
||||
subSubs.prevSub = void 0;
|
||||
if (dirty) {
|
||||
if (await sub.update()) {
|
||||
shallowPropagate(sub.subs);
|
||||
sub = prevLink.sub;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
sub.flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
} else {
|
||||
if (dirty) {
|
||||
if (await sub.update()) {
|
||||
sub = subSubs.sub;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
sub.flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
prevLink = subSubs;
|
||||
}
|
||||
link2 = prevLink.nextDep;
|
||||
if (link2 !== void 0) {
|
||||
continue top;
|
||||
}
|
||||
sub = prevLink.sub;
|
||||
dirty = false;
|
||||
} while (stack);
|
||||
}
|
||||
return dirty;
|
||||
}
|
||||
link2 = nextDep;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
// src/unstable/asyncComputed.ts
|
||||
function asyncComputed(getter) {
|
||||
return new AsyncComputed(getter);
|
||||
}
|
||||
var AsyncComputed = class extends Computed {
|
||||
async get() {
|
||||
const flags = this.flags;
|
||||
if (flags & 16 /* Dirty */) {
|
||||
if (await this.update()) {
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
}
|
||||
} else if (flags & 8 /* ToCheckDirty */) {
|
||||
if (await asyncCheckDirty(this.deps)) {
|
||||
if (await this.update()) {
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.flags = flags & ~8 /* ToCheckDirty */;
|
||||
}
|
||||
}
|
||||
return this.currentValue;
|
||||
}
|
||||
// @ts-expect-error
|
||||
async update() {
|
||||
try {
|
||||
startTrack(this);
|
||||
const trackId = nextTrackId();
|
||||
const oldValue = this.currentValue;
|
||||
const generator = this.getter(oldValue);
|
||||
let current = await generator.next();
|
||||
while (!current.done) {
|
||||
const dep = current.value;
|
||||
if (dep.lastTrackedId !== trackId) {
|
||||
dep.lastTrackedId = trackId;
|
||||
link(dep, this);
|
||||
}
|
||||
current = await generator.next();
|
||||
}
|
||||
const newValue = await current.value;
|
||||
if (oldValue !== newValue) {
|
||||
this.currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
endTrack(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// src/unstable/asyncEffect.ts
|
||||
function asyncEffect(fn) {
|
||||
const e = new AsyncEffect(fn);
|
||||
e.run();
|
||||
return e;
|
||||
}
|
||||
var AsyncEffect = class extends Effect {
|
||||
async notify() {
|
||||
let flags = this.flags;
|
||||
if (flags & 16 /* Dirty */) {
|
||||
this.run();
|
||||
return;
|
||||
}
|
||||
if (flags & 8 /* ToCheckDirty */) {
|
||||
if (await asyncCheckDirty(this.deps)) {
|
||||
this.run();
|
||||
return;
|
||||
} else {
|
||||
this.flags = flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
}
|
||||
if (flags & 4 /* InnerEffectsPending */) {
|
||||
this.flags = flags & ~4 /* InnerEffectsPending */;
|
||||
let link2 = this.deps;
|
||||
do {
|
||||
const dep = link2.dep;
|
||||
if ("notify" in dep) {
|
||||
dep.notify();
|
||||
}
|
||||
link2 = link2.nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
}
|
||||
async run() {
|
||||
try {
|
||||
startTrack(this);
|
||||
const trackId = nextTrackId();
|
||||
const generator = this.fn();
|
||||
let current = await generator.next();
|
||||
while (!current.done) {
|
||||
const dep = current.value;
|
||||
if (dep.lastTrackedId !== trackId) {
|
||||
dep.lastTrackedId = trackId;
|
||||
link(dep, this);
|
||||
}
|
||||
current = await generator.next();
|
||||
}
|
||||
return await current.value;
|
||||
} finally {
|
||||
endTrack(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// src/unstable/computedArray.ts
|
||||
function computedArray(arr, getGetter) {
|
||||
const length = computed(() => arr.get().length);
|
||||
const keys = computed(
|
||||
() => {
|
||||
const keys2 = [];
|
||||
for (let i = 0; i < length.get(); i++) {
|
||||
keys2.push(String(i));
|
||||
}
|
||||
return keys2;
|
||||
}
|
||||
);
|
||||
const items = computed(
|
||||
(array) => {
|
||||
array ??= [];
|
||||
while (array.length < length.get()) {
|
||||
const index = array.length;
|
||||
const item = computed(() => arr.get()[index]);
|
||||
array.push(computed(getGetter(item, index)));
|
||||
}
|
||||
if (array.length > length.get()) {
|
||||
array.length = length.get();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
);
|
||||
return new Proxy({}, {
|
||||
get(_, p, receiver) {
|
||||
if (p === "length") {
|
||||
return length.get();
|
||||
}
|
||||
if (typeof p === "string" && !isNaN(Number(p))) {
|
||||
return items.get()[Number(p)]?.get();
|
||||
}
|
||||
return Reflect.get(items.get(), p, receiver);
|
||||
},
|
||||
has(_, p) {
|
||||
return Reflect.has(items.get(), p);
|
||||
},
|
||||
ownKeys() {
|
||||
return keys.get();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// src/unstable/computedSet.ts
|
||||
function computedSet(source) {
|
||||
return computed(
|
||||
(oldValue) => {
|
||||
const newValue = source.get();
|
||||
if (oldValue?.size === newValue.size && [...oldValue].every((c) => newValue.has(c))) {
|
||||
return oldValue;
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// src/unstable/equalityComputed.ts
|
||||
function equalityComputed(getter) {
|
||||
return new EqualityComputed(getter);
|
||||
}
|
||||
var EqualityComputed = class extends Computed {
|
||||
constructor(getter) {
|
||||
super((oldValue) => {
|
||||
const newValue = getter();
|
||||
if (this.equals(oldValue, newValue)) {
|
||||
return oldValue;
|
||||
}
|
||||
return newValue;
|
||||
});
|
||||
}
|
||||
equals(a, b) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (a === null || b === null || typeof a !== typeof b) {
|
||||
return false;
|
||||
}
|
||||
if (typeof a === "object") {
|
||||
if (Array.isArray(a) && Array.isArray(b)) {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (!this.equals(a[i], b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!Array.isArray(a) && !Array.isArray(b)) {
|
||||
for (const key in a) {
|
||||
if (a.hasOwnProperty(key)) {
|
||||
if (!b.hasOwnProperty(key) || !this.equals(a[key], b[key])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const key in b) {
|
||||
if (b.hasOwnProperty(key) && !a.hasOwnProperty(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// src/unstable/index.ts
|
||||
var unstable = {
|
||||
AsyncComputed,
|
||||
asyncComputed,
|
||||
AsyncEffect,
|
||||
asyncEffect,
|
||||
asyncCheckDirty,
|
||||
computedArray,
|
||||
computedSet,
|
||||
EqualityComputed,
|
||||
equalityComputed
|
||||
};
|
||||
6
node_modules/alien-signals/cjs/index.d.ts
generated
vendored
Normal file
6
node_modules/alien-signals/cjs/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './computed.js';
|
||||
export * from './effect.js';
|
||||
export * from './effectScope.js';
|
||||
export * from './signal.js';
|
||||
export * from './system.js';
|
||||
export * as Unstable from './unstable/index.js';
|
||||
15
node_modules/alien-signals/cjs/signal.d.ts
generated
vendored
Normal file
15
node_modules/alien-signals/cjs/signal.d.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ISignal } from './computed.js';
|
||||
import { Dependency, Link } from './system.js';
|
||||
export interface IWritableSignal<T = any> extends ISignal<T> {
|
||||
set(value: T): void;
|
||||
}
|
||||
export declare function signal<T>(): Signal<T | undefined>;
|
||||
export declare function signal<T>(oldValue: T): Signal<T>;
|
||||
export declare class Signal<T = any> implements Dependency {
|
||||
currentValue: T;
|
||||
subs: Link | undefined;
|
||||
subsTail: Link | undefined;
|
||||
constructor(currentValue: T);
|
||||
get(): NonNullable<T>;
|
||||
set(value: T): void;
|
||||
}
|
||||
56
node_modules/alien-signals/cjs/system.d.ts
generated
vendored
Normal file
56
node_modules/alien-signals/cjs/system.d.ts
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
export interface IEffect extends Subscriber {
|
||||
nextNotify: IEffect | undefined;
|
||||
notify(): void;
|
||||
}
|
||||
export interface IComputed extends Dependency, Subscriber {
|
||||
update(): boolean;
|
||||
}
|
||||
export interface Dependency {
|
||||
subs: Link | undefined;
|
||||
subsTail: Link | undefined;
|
||||
}
|
||||
export interface Subscriber {
|
||||
trackId: number;
|
||||
canPropagate: boolean;
|
||||
dirtyLevel: DirtyLevels;
|
||||
deps: Link | undefined;
|
||||
depsTail: Link | undefined;
|
||||
}
|
||||
export interface Link {
|
||||
dep: Dependency | IComputed | (Dependency & IEffect);
|
||||
sub: Subscriber | IComputed | IEffect;
|
||||
trackId: number;
|
||||
prevSub: Link | undefined;
|
||||
nextSub: Link | undefined;
|
||||
nextDep: Link | undefined;
|
||||
}
|
||||
export declare const enum DirtyLevels {
|
||||
None = 0,
|
||||
SideEffectsOnly = 1,
|
||||
MaybeDirty = 2,
|
||||
Dirty = 3
|
||||
}
|
||||
export declare namespace System {
|
||||
let activeSub: Subscriber | undefined;
|
||||
let activeTrackId: number;
|
||||
let batchDepth: number;
|
||||
let lastTrackId: number;
|
||||
let queuedEffects: IEffect | undefined;
|
||||
let queuedEffectsTail: IEffect | undefined;
|
||||
}
|
||||
export declare function startBatch(): void;
|
||||
export declare function endBatch(): void;
|
||||
export declare namespace Link {
|
||||
function get(dep: Dependency, sub: Subscriber, nextDep: Link | undefined): Link;
|
||||
function release(link: Link): void;
|
||||
}
|
||||
export declare namespace Dependency {
|
||||
function link(dep: Dependency, sub: Subscriber): void;
|
||||
function propagate(subs: Link): void;
|
||||
}
|
||||
export declare namespace Subscriber {
|
||||
function checkDirty(link: Link, depth?: number): boolean;
|
||||
function startTrack(sub: Subscriber): Subscriber | undefined;
|
||||
function endTrack(sub: Subscriber, prevSub: Subscriber | undefined): void;
|
||||
function clearTrack(link: Link): void;
|
||||
}
|
||||
2
node_modules/alien-signals/cjs/unstable/computedArray.d.ts
generated
vendored
Normal file
2
node_modules/alien-signals/cjs/unstable/computedArray.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { ISignal } from '../index.js';
|
||||
export declare function computedArray<I, O>(arr: ISignal<I[]>, getGetter: (item: ISignal<I>, index: number) => () => O): readonly Readonly<O>[];
|
||||
2
node_modules/alien-signals/cjs/unstable/computedSet.d.ts
generated
vendored
Normal file
2
node_modules/alien-signals/cjs/unstable/computedSet.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { ISignal } from '../index.js';
|
||||
export declare function computedSet<T>(source: ISignal<Set<T>>): ISignal<Set<T>>;
|
||||
6
node_modules/alien-signals/cjs/unstable/equalityComputed.d.ts
generated
vendored
Normal file
6
node_modules/alien-signals/cjs/unstable/equalityComputed.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { Computed, ISignal } from '../index.js';
|
||||
export declare function equalityComputed<T>(getter: () => T): ISignal<T>;
|
||||
export declare class EqualityComputed<T = any> extends Computed<T> {
|
||||
constructor(getter: () => T);
|
||||
equals(a: any, b: any): boolean;
|
||||
}
|
||||
3
node_modules/alien-signals/cjs/unstable/index.d.ts
generated
vendored
Normal file
3
node_modules/alien-signals/cjs/unstable/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './computedArray.js';
|
||||
export * from './computedSet.js';
|
||||
export * from './equalityComputed.js';
|
||||
872
node_modules/alien-signals/esm/index.mjs
generated
vendored
Normal file
872
node_modules/alien-signals/esm/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,872 @@
|
||||
// src/system.ts
|
||||
var SubscriberFlags = /* @__PURE__ */ ((SubscriberFlags2) => {
|
||||
SubscriberFlags2[SubscriberFlags2["None"] = 0] = "None";
|
||||
SubscriberFlags2[SubscriberFlags2["Tracking"] = 1] = "Tracking";
|
||||
SubscriberFlags2[SubscriberFlags2["Recursed"] = 2] = "Recursed";
|
||||
SubscriberFlags2[SubscriberFlags2["InnerEffectsPending"] = 4] = "InnerEffectsPending";
|
||||
SubscriberFlags2[SubscriberFlags2["ToCheckDirty"] = 8] = "ToCheckDirty";
|
||||
SubscriberFlags2[SubscriberFlags2["Dirty"] = 16] = "Dirty";
|
||||
return SubscriberFlags2;
|
||||
})(SubscriberFlags || {});
|
||||
var batchDepth = 0;
|
||||
var queuedEffects;
|
||||
var queuedEffectsTail;
|
||||
var linkPool;
|
||||
function startBatch() {
|
||||
++batchDepth;
|
||||
}
|
||||
function endBatch() {
|
||||
if (!--batchDepth) {
|
||||
drainQueuedEffects();
|
||||
}
|
||||
}
|
||||
function drainQueuedEffects() {
|
||||
while (queuedEffects !== void 0) {
|
||||
const effect2 = queuedEffects;
|
||||
const queuedNext = effect2.nextNotify;
|
||||
if (queuedNext !== void 0) {
|
||||
effect2.nextNotify = void 0;
|
||||
queuedEffects = queuedNext;
|
||||
} else {
|
||||
queuedEffects = void 0;
|
||||
queuedEffectsTail = void 0;
|
||||
}
|
||||
effect2.notify();
|
||||
}
|
||||
}
|
||||
function link(dep, sub) {
|
||||
const currentDep = sub.depsTail;
|
||||
const nextDep = currentDep !== void 0 ? currentDep.nextDep : sub.deps;
|
||||
if (nextDep !== void 0 && nextDep.dep === dep) {
|
||||
sub.depsTail = nextDep;
|
||||
} else {
|
||||
linkNewDep(dep, sub, nextDep, currentDep);
|
||||
}
|
||||
}
|
||||
function linkNewDep(dep, sub, nextDep, depsTail) {
|
||||
let newLink;
|
||||
if (linkPool !== void 0) {
|
||||
newLink = linkPool;
|
||||
linkPool = newLink.nextDep;
|
||||
newLink.nextDep = nextDep;
|
||||
newLink.dep = dep;
|
||||
newLink.sub = sub;
|
||||
} else {
|
||||
newLink = {
|
||||
dep,
|
||||
sub,
|
||||
nextDep,
|
||||
prevSub: void 0,
|
||||
nextSub: void 0
|
||||
};
|
||||
}
|
||||
if (depsTail === void 0) {
|
||||
sub.deps = newLink;
|
||||
} else {
|
||||
depsTail.nextDep = newLink;
|
||||
}
|
||||
if (dep.subs === void 0) {
|
||||
dep.subs = newLink;
|
||||
} else {
|
||||
const oldTail = dep.subsTail;
|
||||
newLink.prevSub = oldTail;
|
||||
oldTail.nextSub = newLink;
|
||||
}
|
||||
sub.depsTail = newLink;
|
||||
dep.subsTail = newLink;
|
||||
}
|
||||
function propagate(link2) {
|
||||
let targetFlag = 16 /* Dirty */;
|
||||
let subs = link2;
|
||||
let stack = 0;
|
||||
top: do {
|
||||
const sub = link2.sub;
|
||||
const subFlags = sub.flags;
|
||||
if (!(subFlags & (1 /* Tracking */ | 2 /* Recursed */ | 4 /* InnerEffectsPending */ | 8 /* ToCheckDirty */ | 16 /* Dirty */)) && (sub.flags = subFlags | targetFlag, true) || (subFlags & (1 /* Tracking */ | 2 /* Recursed */)) === 2 /* Recursed */ && (sub.flags = subFlags & ~2 /* Recursed */ | targetFlag, true) || !(subFlags & (4 /* InnerEffectsPending */ | 8 /* ToCheckDirty */ | 16 /* Dirty */)) && isValidLink(link2, sub) && (sub.flags = subFlags | 2 /* Recursed */ | targetFlag, sub.subs !== void 0)) {
|
||||
const subSubs = sub.subs;
|
||||
if (subSubs !== void 0) {
|
||||
if (subSubs.nextSub !== void 0) {
|
||||
subSubs.prevSub = subs;
|
||||
link2 = subs = subSubs;
|
||||
targetFlag = 8 /* ToCheckDirty */;
|
||||
++stack;
|
||||
} else {
|
||||
link2 = subSubs;
|
||||
targetFlag = "notify" in sub ? 4 /* InnerEffectsPending */ : 8 /* ToCheckDirty */;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ("notify" in sub) {
|
||||
if (queuedEffectsTail !== void 0) {
|
||||
queuedEffectsTail.nextNotify = sub;
|
||||
} else {
|
||||
queuedEffects = sub;
|
||||
}
|
||||
queuedEffectsTail = sub;
|
||||
}
|
||||
} else if (!(subFlags & (1 /* Tracking */ | targetFlag)) || !(subFlags & targetFlag) && subFlags & (4 /* InnerEffectsPending */ | 8 /* ToCheckDirty */ | 16 /* Dirty */) && isValidLink(link2, sub)) {
|
||||
sub.flags = subFlags | targetFlag;
|
||||
}
|
||||
if ((link2 = subs.nextSub) !== void 0) {
|
||||
subs = link2;
|
||||
targetFlag = stack ? 8 /* ToCheckDirty */ : 16 /* Dirty */;
|
||||
continue;
|
||||
}
|
||||
while (stack) {
|
||||
--stack;
|
||||
const dep = subs.dep;
|
||||
const depSubs = dep.subs;
|
||||
subs = depSubs.prevSub;
|
||||
depSubs.prevSub = void 0;
|
||||
if ((link2 = subs.nextSub) !== void 0) {
|
||||
subs = link2;
|
||||
targetFlag = stack ? 8 /* ToCheckDirty */ : 16 /* Dirty */;
|
||||
continue top;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} while (true);
|
||||
if (!batchDepth) {
|
||||
drainQueuedEffects();
|
||||
}
|
||||
}
|
||||
function shallowPropagate(link2) {
|
||||
do {
|
||||
const updateSub = link2.sub;
|
||||
const updateSubFlags = updateSub.flags;
|
||||
if ((updateSubFlags & (8 /* ToCheckDirty */ | 16 /* Dirty */)) === 8 /* ToCheckDirty */) {
|
||||
updateSub.flags = updateSubFlags | 16 /* Dirty */;
|
||||
}
|
||||
link2 = link2.nextSub;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
function isValidLink(subLink, sub) {
|
||||
const depsTail = sub.depsTail;
|
||||
if (depsTail !== void 0) {
|
||||
let link2 = sub.deps;
|
||||
do {
|
||||
if (link2 === subLink) {
|
||||
return true;
|
||||
}
|
||||
if (link2 === depsTail) {
|
||||
break;
|
||||
}
|
||||
link2 = link2.nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function checkDirty(link2) {
|
||||
let stack = 0;
|
||||
let dirty;
|
||||
top: do {
|
||||
dirty = false;
|
||||
const dep = link2.dep;
|
||||
if ("update" in dep) {
|
||||
const depFlags = dep.flags;
|
||||
if (depFlags & 16 /* Dirty */) {
|
||||
if (dep.update()) {
|
||||
const subs = dep.subs;
|
||||
if (subs.nextSub !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
} else if (depFlags & 8 /* ToCheckDirty */) {
|
||||
const depSubs = dep.subs;
|
||||
if (depSubs.nextSub !== void 0) {
|
||||
depSubs.prevSub = link2;
|
||||
}
|
||||
link2 = dep.deps;
|
||||
++stack;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!dirty && link2.nextDep !== void 0) {
|
||||
link2 = link2.nextDep;
|
||||
continue;
|
||||
}
|
||||
if (stack) {
|
||||
let sub = link2.sub;
|
||||
do {
|
||||
--stack;
|
||||
const subSubs = sub.subs;
|
||||
if (dirty) {
|
||||
if (sub.update()) {
|
||||
if ((link2 = subSubs.prevSub) !== void 0) {
|
||||
subSubs.prevSub = void 0;
|
||||
shallowPropagate(sub.subs);
|
||||
sub = link2.sub;
|
||||
} else {
|
||||
sub = subSubs.sub;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
sub.flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
if ((link2 = subSubs.prevSub) !== void 0) {
|
||||
subSubs.prevSub = void 0;
|
||||
if (link2.nextDep !== void 0) {
|
||||
link2 = link2.nextDep;
|
||||
continue top;
|
||||
}
|
||||
sub = link2.sub;
|
||||
} else {
|
||||
if ((link2 = subSubs.nextDep) !== void 0) {
|
||||
continue top;
|
||||
}
|
||||
sub = subSubs.sub;
|
||||
}
|
||||
dirty = false;
|
||||
} while (stack);
|
||||
}
|
||||
return dirty;
|
||||
} while (true);
|
||||
}
|
||||
function startTrack(sub) {
|
||||
sub.depsTail = void 0;
|
||||
sub.flags = 1 /* Tracking */;
|
||||
}
|
||||
function endTrack(sub) {
|
||||
const depsTail = sub.depsTail;
|
||||
if (depsTail !== void 0) {
|
||||
const nextDep = depsTail.nextDep;
|
||||
if (nextDep !== void 0) {
|
||||
clearTrack(nextDep);
|
||||
depsTail.nextDep = void 0;
|
||||
}
|
||||
} else if (sub.deps !== void 0) {
|
||||
clearTrack(sub.deps);
|
||||
sub.deps = void 0;
|
||||
}
|
||||
sub.flags &= ~1 /* Tracking */;
|
||||
}
|
||||
function clearTrack(link2) {
|
||||
do {
|
||||
const dep = link2.dep;
|
||||
const nextDep = link2.nextDep;
|
||||
const nextSub = link2.nextSub;
|
||||
const prevSub = link2.prevSub;
|
||||
if (nextSub !== void 0) {
|
||||
nextSub.prevSub = prevSub;
|
||||
link2.nextSub = void 0;
|
||||
} else {
|
||||
dep.subsTail = prevSub;
|
||||
if ("lastTrackedId" in dep) {
|
||||
dep.lastTrackedId = 0;
|
||||
}
|
||||
}
|
||||
if (prevSub !== void 0) {
|
||||
prevSub.nextSub = nextSub;
|
||||
link2.prevSub = void 0;
|
||||
} else {
|
||||
dep.subs = nextSub;
|
||||
}
|
||||
link2.dep = void 0;
|
||||
link2.sub = void 0;
|
||||
link2.nextDep = linkPool;
|
||||
linkPool = link2;
|
||||
if (dep.subs === void 0 && "deps" in dep) {
|
||||
if ("notify" in dep) {
|
||||
dep.flags = 0 /* None */;
|
||||
} else {
|
||||
const depFlags = dep.flags;
|
||||
if (!(depFlags & 16 /* Dirty */)) {
|
||||
dep.flags = depFlags | 16 /* Dirty */;
|
||||
}
|
||||
}
|
||||
const depDeps = dep.deps;
|
||||
if (depDeps !== void 0) {
|
||||
link2 = depDeps;
|
||||
dep.depsTail.nextDep = nextDep;
|
||||
dep.deps = void 0;
|
||||
dep.depsTail = void 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
link2 = nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
|
||||
// src/effectScope.ts
|
||||
var activeEffectScope = void 0;
|
||||
var activeScopeTrackId = 0;
|
||||
function untrackScope(fn) {
|
||||
const prevSub = activeEffectScope;
|
||||
const prevTrackId = activeScopeTrackId;
|
||||
setActiveScope(void 0, 0);
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
setActiveScope(prevSub, prevTrackId);
|
||||
}
|
||||
}
|
||||
function setActiveScope(sub, trackId) {
|
||||
activeEffectScope = sub;
|
||||
activeScopeTrackId = trackId;
|
||||
}
|
||||
function effectScope() {
|
||||
return new EffectScope();
|
||||
}
|
||||
var EffectScope = class {
|
||||
constructor() {
|
||||
// Subscriber
|
||||
this.deps = void 0;
|
||||
this.depsTail = void 0;
|
||||
this.flags = 0 /* None */;
|
||||
this.trackId = nextTrackId();
|
||||
}
|
||||
notify() {
|
||||
const flags = this.flags;
|
||||
if (flags & 4 /* InnerEffectsPending */) {
|
||||
this.flags = flags & ~4 /* InnerEffectsPending */;
|
||||
let link2 = this.deps;
|
||||
do {
|
||||
const dep = link2.dep;
|
||||
if ("notify" in dep) {
|
||||
dep.notify();
|
||||
}
|
||||
link2 = link2.nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
}
|
||||
run(fn) {
|
||||
const prevSub = activeEffectScope;
|
||||
const prevTrackId = activeScopeTrackId;
|
||||
setActiveScope(this, this.trackId);
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
setActiveScope(prevSub, prevTrackId);
|
||||
}
|
||||
}
|
||||
stop() {
|
||||
startTrack(this);
|
||||
endTrack(this);
|
||||
}
|
||||
};
|
||||
|
||||
// src/effect.ts
|
||||
var activeSub;
|
||||
var activeTrackId = 0;
|
||||
var lastTrackId = 0;
|
||||
function untrack(fn) {
|
||||
const prevSub = activeSub;
|
||||
const prevTrackId = activeTrackId;
|
||||
setActiveSub(void 0, 0);
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
setActiveSub(prevSub, prevTrackId);
|
||||
}
|
||||
}
|
||||
function setActiveSub(sub, trackId) {
|
||||
activeSub = sub;
|
||||
activeTrackId = trackId;
|
||||
}
|
||||
function nextTrackId() {
|
||||
return ++lastTrackId;
|
||||
}
|
||||
function effect(fn) {
|
||||
const e = new Effect(fn);
|
||||
e.run();
|
||||
return e;
|
||||
}
|
||||
var Effect = class {
|
||||
constructor(fn) {
|
||||
this.fn = fn;
|
||||
this.nextNotify = void 0;
|
||||
// Dependency
|
||||
this.subs = void 0;
|
||||
this.subsTail = void 0;
|
||||
// Subscriber
|
||||
this.deps = void 0;
|
||||
this.depsTail = void 0;
|
||||
this.flags = 16 /* Dirty */;
|
||||
if (activeTrackId) {
|
||||
link(this, activeSub);
|
||||
} else if (activeScopeTrackId) {
|
||||
link(this, activeEffectScope);
|
||||
}
|
||||
}
|
||||
notify() {
|
||||
let flags = this.flags;
|
||||
if (flags & 16 /* Dirty */) {
|
||||
this.run();
|
||||
return;
|
||||
}
|
||||
if (flags & 8 /* ToCheckDirty */) {
|
||||
if (checkDirty(this.deps)) {
|
||||
this.run();
|
||||
return;
|
||||
} else {
|
||||
this.flags = flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
}
|
||||
if (flags & 4 /* InnerEffectsPending */) {
|
||||
this.flags = flags & ~4 /* InnerEffectsPending */;
|
||||
let link2 = this.deps;
|
||||
do {
|
||||
const dep = link2.dep;
|
||||
if ("notify" in dep) {
|
||||
dep.notify();
|
||||
}
|
||||
link2 = link2.nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
}
|
||||
run() {
|
||||
const prevSub = activeSub;
|
||||
const prevTrackId = activeTrackId;
|
||||
setActiveSub(this, nextTrackId());
|
||||
startTrack(this);
|
||||
try {
|
||||
return this.fn();
|
||||
} finally {
|
||||
setActiveSub(prevSub, prevTrackId);
|
||||
endTrack(this);
|
||||
}
|
||||
}
|
||||
stop() {
|
||||
startTrack(this);
|
||||
endTrack(this);
|
||||
}
|
||||
};
|
||||
|
||||
// src/computed.ts
|
||||
function computed(getter) {
|
||||
return new Computed(getter);
|
||||
}
|
||||
var Computed = class {
|
||||
constructor(getter) {
|
||||
this.getter = getter;
|
||||
this.currentValue = void 0;
|
||||
// Dependency
|
||||
this.subs = void 0;
|
||||
this.subsTail = void 0;
|
||||
this.lastTrackedId = 0;
|
||||
// Subscriber
|
||||
this.deps = void 0;
|
||||
this.depsTail = void 0;
|
||||
this.flags = 16 /* Dirty */;
|
||||
}
|
||||
get() {
|
||||
const flags = this.flags;
|
||||
if (flags & 16 /* Dirty */) {
|
||||
if (this.update()) {
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
}
|
||||
} else if (flags & 8 /* ToCheckDirty */) {
|
||||
if (checkDirty(this.deps)) {
|
||||
if (this.update()) {
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.flags = flags & ~8 /* ToCheckDirty */;
|
||||
}
|
||||
}
|
||||
if (activeTrackId) {
|
||||
if (this.lastTrackedId !== activeTrackId) {
|
||||
this.lastTrackedId = activeTrackId;
|
||||
link(this, activeSub);
|
||||
}
|
||||
} else if (activeScopeTrackId) {
|
||||
if (this.lastTrackedId !== activeScopeTrackId) {
|
||||
this.lastTrackedId = activeScopeTrackId;
|
||||
link(this, activeEffectScope);
|
||||
}
|
||||
}
|
||||
return this.currentValue;
|
||||
}
|
||||
update() {
|
||||
const prevSub = activeSub;
|
||||
const prevTrackId = activeTrackId;
|
||||
setActiveSub(this, nextTrackId());
|
||||
startTrack(this);
|
||||
try {
|
||||
const oldValue = this.currentValue;
|
||||
const newValue = this.getter(oldValue);
|
||||
if (oldValue !== newValue) {
|
||||
this.currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
setActiveSub(prevSub, prevTrackId);
|
||||
endTrack(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// src/signal.ts
|
||||
function signal(oldValue) {
|
||||
return new Signal(oldValue);
|
||||
}
|
||||
var Signal = class {
|
||||
constructor(currentValue) {
|
||||
this.currentValue = currentValue;
|
||||
// Dependency
|
||||
this.subs = void 0;
|
||||
this.subsTail = void 0;
|
||||
this.lastTrackedId = 0;
|
||||
}
|
||||
get() {
|
||||
if (activeTrackId && this.lastTrackedId !== activeTrackId) {
|
||||
this.lastTrackedId = activeTrackId;
|
||||
link(this, activeSub);
|
||||
}
|
||||
return this.currentValue;
|
||||
}
|
||||
set(value) {
|
||||
if (this.currentValue !== value) {
|
||||
this.currentValue = value;
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
propagate(subs);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// src/unstable/asyncSystem.ts
|
||||
async function asyncCheckDirty(link2) {
|
||||
let stack = 0;
|
||||
let dirty;
|
||||
let nextDep;
|
||||
top: do {
|
||||
dirty = false;
|
||||
const dep = link2.dep;
|
||||
if ("update" in dep) {
|
||||
const depFlags = dep.flags;
|
||||
if (depFlags & 16 /* Dirty */) {
|
||||
if (await dep.update()) {
|
||||
const subs = dep.subs;
|
||||
if (subs.nextSub !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
} else if (depFlags & 8 /* ToCheckDirty */) {
|
||||
const depSubs = dep.subs;
|
||||
if (depSubs.nextSub !== void 0) {
|
||||
depSubs.prevSub = link2;
|
||||
}
|
||||
link2 = dep.deps;
|
||||
++stack;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (dirty || (nextDep = link2.nextDep) === void 0) {
|
||||
if (stack) {
|
||||
let sub = link2.sub;
|
||||
do {
|
||||
--stack;
|
||||
const subSubs = sub.subs;
|
||||
let prevLink = subSubs.prevSub;
|
||||
if (prevLink !== void 0) {
|
||||
subSubs.prevSub = void 0;
|
||||
if (dirty) {
|
||||
if (await sub.update()) {
|
||||
shallowPropagate(sub.subs);
|
||||
sub = prevLink.sub;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
sub.flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
} else {
|
||||
if (dirty) {
|
||||
if (await sub.update()) {
|
||||
sub = subSubs.sub;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
sub.flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
prevLink = subSubs;
|
||||
}
|
||||
link2 = prevLink.nextDep;
|
||||
if (link2 !== void 0) {
|
||||
continue top;
|
||||
}
|
||||
sub = prevLink.sub;
|
||||
dirty = false;
|
||||
} while (stack);
|
||||
}
|
||||
return dirty;
|
||||
}
|
||||
link2 = nextDep;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
// src/unstable/asyncComputed.ts
|
||||
function asyncComputed(getter) {
|
||||
return new AsyncComputed(getter);
|
||||
}
|
||||
var AsyncComputed = class extends Computed {
|
||||
async get() {
|
||||
const flags = this.flags;
|
||||
if (flags & 16 /* Dirty */) {
|
||||
if (await this.update()) {
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
}
|
||||
} else if (flags & 8 /* ToCheckDirty */) {
|
||||
if (await asyncCheckDirty(this.deps)) {
|
||||
if (await this.update()) {
|
||||
const subs = this.subs;
|
||||
if (subs !== void 0) {
|
||||
shallowPropagate(subs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.flags = flags & ~8 /* ToCheckDirty */;
|
||||
}
|
||||
}
|
||||
return this.currentValue;
|
||||
}
|
||||
// @ts-expect-error
|
||||
async update() {
|
||||
try {
|
||||
startTrack(this);
|
||||
const trackId = nextTrackId();
|
||||
const oldValue = this.currentValue;
|
||||
const generator = this.getter(oldValue);
|
||||
let current = await generator.next();
|
||||
while (!current.done) {
|
||||
const dep = current.value;
|
||||
if (dep.lastTrackedId !== trackId) {
|
||||
dep.lastTrackedId = trackId;
|
||||
link(dep, this);
|
||||
}
|
||||
current = await generator.next();
|
||||
}
|
||||
const newValue = await current.value;
|
||||
if (oldValue !== newValue) {
|
||||
this.currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
endTrack(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// src/unstable/asyncEffect.ts
|
||||
function asyncEffect(fn) {
|
||||
const e = new AsyncEffect(fn);
|
||||
e.run();
|
||||
return e;
|
||||
}
|
||||
var AsyncEffect = class extends Effect {
|
||||
async notify() {
|
||||
let flags = this.flags;
|
||||
if (flags & 16 /* Dirty */) {
|
||||
this.run();
|
||||
return;
|
||||
}
|
||||
if (flags & 8 /* ToCheckDirty */) {
|
||||
if (await asyncCheckDirty(this.deps)) {
|
||||
this.run();
|
||||
return;
|
||||
} else {
|
||||
this.flags = flags &= ~8 /* ToCheckDirty */;
|
||||
}
|
||||
}
|
||||
if (flags & 4 /* InnerEffectsPending */) {
|
||||
this.flags = flags & ~4 /* InnerEffectsPending */;
|
||||
let link2 = this.deps;
|
||||
do {
|
||||
const dep = link2.dep;
|
||||
if ("notify" in dep) {
|
||||
dep.notify();
|
||||
}
|
||||
link2 = link2.nextDep;
|
||||
} while (link2 !== void 0);
|
||||
}
|
||||
}
|
||||
async run() {
|
||||
try {
|
||||
startTrack(this);
|
||||
const trackId = nextTrackId();
|
||||
const generator = this.fn();
|
||||
let current = await generator.next();
|
||||
while (!current.done) {
|
||||
const dep = current.value;
|
||||
if (dep.lastTrackedId !== trackId) {
|
||||
dep.lastTrackedId = trackId;
|
||||
link(dep, this);
|
||||
}
|
||||
current = await generator.next();
|
||||
}
|
||||
return await current.value;
|
||||
} finally {
|
||||
endTrack(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// src/unstable/computedArray.ts
|
||||
function computedArray(arr, getGetter) {
|
||||
const length = computed(() => arr.get().length);
|
||||
const keys = computed(
|
||||
() => {
|
||||
const keys2 = [];
|
||||
for (let i = 0; i < length.get(); i++) {
|
||||
keys2.push(String(i));
|
||||
}
|
||||
return keys2;
|
||||
}
|
||||
);
|
||||
const items = computed(
|
||||
(array) => {
|
||||
array ??= [];
|
||||
while (array.length < length.get()) {
|
||||
const index = array.length;
|
||||
const item = computed(() => arr.get()[index]);
|
||||
array.push(computed(getGetter(item, index)));
|
||||
}
|
||||
if (array.length > length.get()) {
|
||||
array.length = length.get();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
);
|
||||
return new Proxy({}, {
|
||||
get(_, p, receiver) {
|
||||
if (p === "length") {
|
||||
return length.get();
|
||||
}
|
||||
if (typeof p === "string" && !isNaN(Number(p))) {
|
||||
return items.get()[Number(p)]?.get();
|
||||
}
|
||||
return Reflect.get(items.get(), p, receiver);
|
||||
},
|
||||
has(_, p) {
|
||||
return Reflect.has(items.get(), p);
|
||||
},
|
||||
ownKeys() {
|
||||
return keys.get();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// src/unstable/computedSet.ts
|
||||
function computedSet(source) {
|
||||
return computed(
|
||||
(oldValue) => {
|
||||
const newValue = source.get();
|
||||
if (oldValue?.size === newValue.size && [...oldValue].every((c) => newValue.has(c))) {
|
||||
return oldValue;
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// src/unstable/equalityComputed.ts
|
||||
function equalityComputed(getter) {
|
||||
return new EqualityComputed(getter);
|
||||
}
|
||||
var EqualityComputed = class extends Computed {
|
||||
constructor(getter) {
|
||||
super((oldValue) => {
|
||||
const newValue = getter();
|
||||
if (this.equals(oldValue, newValue)) {
|
||||
return oldValue;
|
||||
}
|
||||
return newValue;
|
||||
});
|
||||
}
|
||||
equals(a, b) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (a === null || b === null || typeof a !== typeof b) {
|
||||
return false;
|
||||
}
|
||||
if (typeof a === "object") {
|
||||
if (Array.isArray(a) && Array.isArray(b)) {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (!this.equals(a[i], b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!Array.isArray(a) && !Array.isArray(b)) {
|
||||
for (const key in a) {
|
||||
if (a.hasOwnProperty(key)) {
|
||||
if (!b.hasOwnProperty(key) || !this.equals(a[key], b[key])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const key in b) {
|
||||
if (b.hasOwnProperty(key) && !a.hasOwnProperty(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// src/unstable/index.ts
|
||||
var unstable = {
|
||||
AsyncComputed,
|
||||
asyncComputed,
|
||||
AsyncEffect,
|
||||
asyncEffect,
|
||||
asyncCheckDirty,
|
||||
computedArray,
|
||||
computedSet,
|
||||
EqualityComputed,
|
||||
equalityComputed
|
||||
};
|
||||
export {
|
||||
Computed,
|
||||
Effect,
|
||||
EffectScope,
|
||||
Signal,
|
||||
SubscriberFlags,
|
||||
activeEffectScope,
|
||||
activeScopeTrackId,
|
||||
activeSub,
|
||||
activeTrackId,
|
||||
checkDirty,
|
||||
computed,
|
||||
effect,
|
||||
effectScope,
|
||||
endBatch,
|
||||
endTrack,
|
||||
lastTrackId,
|
||||
link,
|
||||
nextTrackId,
|
||||
propagate,
|
||||
setActiveScope,
|
||||
setActiveSub,
|
||||
shallowPropagate,
|
||||
signal,
|
||||
startBatch,
|
||||
startTrack,
|
||||
unstable,
|
||||
untrack,
|
||||
untrackScope
|
||||
};
|
||||
50
node_modules/alien-signals/package.json
generated
vendored
Normal file
50
node_modules/alien-signals/package.json
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "alien-signals",
|
||||
"version": "0.4.14",
|
||||
"sideEffects": false,
|
||||
"license": "MIT",
|
||||
"description": "The lightest signal library.",
|
||||
"packageManager": "pnpm@9.12.0",
|
||||
"types": "./types/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./types/index.d.ts",
|
||||
"import": "./esm/index.mjs",
|
||||
"require": "./cjs/index.cjs"
|
||||
},
|
||||
"./cjs": {
|
||||
"types": "./types/index.d.ts",
|
||||
"import": "./cjs/index.cjs",
|
||||
"require": "./cjs/index.cjs"
|
||||
},
|
||||
"./esm": {
|
||||
"types": "./types/index.d.ts",
|
||||
"import": "./esm/index.mjs",
|
||||
"require": "./esm/index.mjs"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"**/*.cjs",
|
||||
"**/*.mjs",
|
||||
"**/*.d.ts"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/johnsoncodehk/signals.git"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run build",
|
||||
"build": "tsc && npm run build:esm && npm run build:cjs",
|
||||
"build:esm": "esbuild src/index.ts --bundle --format=esm --outfile=esm/index.mjs",
|
||||
"build:cjs": "esbuild src/index.ts --bundle --format=cjs --outfile=cjs/index.cjs",
|
||||
"test": "vitest run",
|
||||
"bench": "npm run build:esm && node --jitless --expose-gc benchs/propagate.mjs && node --jitless --expose-gc benchs/complex.mjs",
|
||||
"bench:memory": "npm run build:esm && node --expose-gc benchs/memoryUsage.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "latest",
|
||||
"mitata": "latest",
|
||||
"typescript": "latest",
|
||||
"vitest": "latest"
|
||||
}
|
||||
}
|
||||
16
node_modules/alien-signals/types/computed.d.ts
generated
vendored
Normal file
16
node_modules/alien-signals/types/computed.d.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { IComputed, Link, SubscriberFlags } from './system.js';
|
||||
import type { ISignal } from './types.js';
|
||||
export declare function computed<T>(getter: (cachedValue?: T) => T): Computed<T>;
|
||||
export declare class Computed<T = any> implements IComputed, ISignal<T> {
|
||||
getter: (cachedValue?: T) => T;
|
||||
currentValue: T | undefined;
|
||||
subs: Link | undefined;
|
||||
subsTail: Link | undefined;
|
||||
lastTrackedId: number;
|
||||
deps: Link | undefined;
|
||||
depsTail: Link | undefined;
|
||||
flags: SubscriberFlags;
|
||||
constructor(getter: (cachedValue?: T) => T);
|
||||
get(): T;
|
||||
update(): boolean;
|
||||
}
|
||||
21
node_modules/alien-signals/types/effect.d.ts
generated
vendored
Normal file
21
node_modules/alien-signals/types/effect.d.ts
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Dependency, IEffect, Link, Subscriber, SubscriberFlags } from './system.js';
|
||||
export declare let activeSub: Subscriber | undefined;
|
||||
export declare let activeTrackId: number;
|
||||
export declare let lastTrackId: number;
|
||||
export declare function untrack<T>(fn: () => T): T;
|
||||
export declare function setActiveSub(sub: Subscriber | undefined, trackId: number): void;
|
||||
export declare function nextTrackId(): number;
|
||||
export declare function effect<T>(fn: () => T): Effect<T>;
|
||||
export declare class Effect<T = any> implements IEffect, Dependency {
|
||||
fn: () => T;
|
||||
nextNotify: IEffect | undefined;
|
||||
subs: Link | undefined;
|
||||
subsTail: Link | undefined;
|
||||
deps: Link | undefined;
|
||||
depsTail: Link | undefined;
|
||||
flags: SubscriberFlags;
|
||||
constructor(fn: () => T);
|
||||
notify(): void;
|
||||
run(): T;
|
||||
stop(): void;
|
||||
}
|
||||
15
node_modules/alien-signals/types/effectScope.d.ts
generated
vendored
Normal file
15
node_modules/alien-signals/types/effectScope.d.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Link, Subscriber, SubscriberFlags } from './system.js';
|
||||
export declare let activeEffectScope: EffectScope | undefined;
|
||||
export declare let activeScopeTrackId: number;
|
||||
export declare function untrackScope<T>(fn: () => T): T;
|
||||
export declare function setActiveScope(sub: EffectScope | undefined, trackId: number): void;
|
||||
export declare function effectScope(): EffectScope;
|
||||
export declare class EffectScope implements Subscriber {
|
||||
deps: Link | undefined;
|
||||
depsTail: Link | undefined;
|
||||
flags: SubscriberFlags;
|
||||
trackId: number;
|
||||
notify(): void;
|
||||
run<T>(fn: () => T): T;
|
||||
stop(): void;
|
||||
}
|
||||
7
node_modules/alien-signals/types/index.d.ts
generated
vendored
Normal file
7
node_modules/alien-signals/types/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export * from './computed.js';
|
||||
export * from './effect.js';
|
||||
export * from './effectScope.js';
|
||||
export * from './signal.js';
|
||||
export * from './system.js';
|
||||
export * from './types.js';
|
||||
export * from './unstable/index.js';
|
||||
13
node_modules/alien-signals/types/signal.d.ts
generated
vendored
Normal file
13
node_modules/alien-signals/types/signal.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Dependency, Link } from './system.js';
|
||||
import type { IWritableSignal } from './types.js';
|
||||
export declare function signal<T>(): Signal<T | undefined>;
|
||||
export declare function signal<T>(oldValue: T): Signal<T>;
|
||||
export declare class Signal<T = any> implements Dependency, IWritableSignal<T> {
|
||||
currentValue: T;
|
||||
subs: Link | undefined;
|
||||
subsTail: Link | undefined;
|
||||
lastTrackedId: number;
|
||||
constructor(currentValue: T);
|
||||
get(): T;
|
||||
set(value: T): void;
|
||||
}
|
||||
40
node_modules/alien-signals/types/system.d.ts
generated
vendored
Normal file
40
node_modules/alien-signals/types/system.d.ts
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
export interface IEffect extends Subscriber {
|
||||
nextNotify: IEffect | undefined;
|
||||
notify(): void;
|
||||
}
|
||||
export interface IComputed extends Dependency, Subscriber {
|
||||
update(): boolean;
|
||||
}
|
||||
export interface Dependency {
|
||||
subs: Link | undefined;
|
||||
subsTail: Link | undefined;
|
||||
lastTrackedId?: number;
|
||||
}
|
||||
export interface Subscriber {
|
||||
flags: SubscriberFlags;
|
||||
deps: Link | undefined;
|
||||
depsTail: Link | undefined;
|
||||
}
|
||||
export interface Link {
|
||||
dep: Dependency | IComputed | (Dependency & IEffect);
|
||||
sub: Subscriber | IComputed | (Dependency & IEffect) | IEffect;
|
||||
prevSub: Link | undefined;
|
||||
nextSub: Link | undefined;
|
||||
nextDep: Link | undefined;
|
||||
}
|
||||
export declare const enum SubscriberFlags {
|
||||
None = 0,
|
||||
Tracking = 1,
|
||||
Recursed = 2,
|
||||
InnerEffectsPending = 4,
|
||||
ToCheckDirty = 8,
|
||||
Dirty = 16
|
||||
}
|
||||
export declare function startBatch(): void;
|
||||
export declare function endBatch(): void;
|
||||
export declare function link(dep: Dependency, sub: Subscriber): void;
|
||||
export declare function propagate(link: Link): void;
|
||||
export declare function shallowPropagate(link: Link): void;
|
||||
export declare function checkDirty(link: Link): boolean;
|
||||
export declare function startTrack(sub: Subscriber): void;
|
||||
export declare function endTrack(sub: Subscriber): void;
|
||||
6
node_modules/alien-signals/types/types.d.ts
generated
vendored
Normal file
6
node_modules/alien-signals/types/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface ISignal<T = any> {
|
||||
get(): T;
|
||||
}
|
||||
export interface IWritableSignal<T = any> extends ISignal<T> {
|
||||
set(value: T): void;
|
||||
}
|
||||
7
node_modules/alien-signals/types/unstable/asyncComputed.d.ts
generated
vendored
Normal file
7
node_modules/alien-signals/types/unstable/asyncComputed.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Computed } from '../computed.js';
|
||||
import { Dependency } from '../system.js';
|
||||
export declare function asyncComputed<T>(getter: (cachedValue?: T) => AsyncGenerator<Dependency, T>): AsyncComputed<T>;
|
||||
export declare class AsyncComputed<T = any> extends Computed {
|
||||
get(): Promise<T>;
|
||||
update(): Promise<boolean>;
|
||||
}
|
||||
7
node_modules/alien-signals/types/unstable/asyncEffect.d.ts
generated
vendored
Normal file
7
node_modules/alien-signals/types/unstable/asyncEffect.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Effect } from '../effect.js';
|
||||
import { Dependency } from '../system.js';
|
||||
export declare function asyncEffect<T>(fn: () => AsyncGenerator<Dependency, T>): AsyncEffect<T>;
|
||||
export declare class AsyncEffect<T = any> extends Effect {
|
||||
notify(): Promise<void>;
|
||||
run(): Promise<T>;
|
||||
}
|
||||
2
node_modules/alien-signals/types/unstable/asyncSystem.d.ts
generated
vendored
Normal file
2
node_modules/alien-signals/types/unstable/asyncSystem.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { Link } from "../system";
|
||||
export declare function asyncCheckDirty(link: Link): Promise<boolean>;
|
||||
2
node_modules/alien-signals/types/unstable/computedArray.d.ts
generated
vendored
Normal file
2
node_modules/alien-signals/types/unstable/computedArray.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { ISignal } from '../index.js';
|
||||
export declare function computedArray<I, O>(arr: ISignal<I[]>, getGetter: (item: ISignal<I>, index: number) => () => O): readonly Readonly<O>[];
|
||||
2
node_modules/alien-signals/types/unstable/computedSet.d.ts
generated
vendored
Normal file
2
node_modules/alien-signals/types/unstable/computedSet.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { ISignal } from '../index.js';
|
||||
export declare function computedSet<T>(source: ISignal<Set<T>>): ISignal<Set<T>>;
|
||||
6
node_modules/alien-signals/types/unstable/equalityComputed.d.ts
generated
vendored
Normal file
6
node_modules/alien-signals/types/unstable/equalityComputed.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { Computed, ISignal } from '../index.js';
|
||||
export declare function equalityComputed<T>(getter: () => T): ISignal<T>;
|
||||
export declare class EqualityComputed<T = any> extends Computed<T> {
|
||||
constructor(getter: () => T);
|
||||
equals(a: any, b: any): boolean;
|
||||
}
|
||||
17
node_modules/alien-signals/types/unstable/index.d.ts
generated
vendored
Normal file
17
node_modules/alien-signals/types/unstable/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { AsyncComputed, asyncComputed } from './asyncComputed.js';
|
||||
import { AsyncEffect, asyncEffect } from './asyncEffect.js';
|
||||
import { asyncCheckDirty } from './asyncSystem.js';
|
||||
import { computedArray } from './computedArray.js';
|
||||
import { computedSet } from './computedSet.js';
|
||||
import { EqualityComputed, equalityComputed } from './equalityComputed.js';
|
||||
export declare const unstable: {
|
||||
AsyncComputed: typeof AsyncComputed;
|
||||
asyncComputed: typeof asyncComputed;
|
||||
AsyncEffect: typeof AsyncEffect;
|
||||
asyncEffect: typeof asyncEffect;
|
||||
asyncCheckDirty: typeof asyncCheckDirty;
|
||||
computedArray: typeof computedArray;
|
||||
computedSet: typeof computedSet;
|
||||
EqualityComputed: typeof EqualityComputed;
|
||||
equalityComputed: typeof equalityComputed;
|
||||
};
|
||||
Reference in New Issue
Block a user