Socket
Book a DemoInstallSign in
Socket

alien-signals

Package Overview
Dependencies
Maintainers
1
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

alien-signals - npm Package Compare versions

Comparing version

to
2.0.0-alpha.1

15

package.json
{
"name": "alien-signals",
"version": "2.0.0-alpha.0",
"version": "2.0.0-alpha.1",
"sideEffects": false,

@@ -27,5 +27,5 @@ "license": "MIT",

"files": [
"**/*.cjs",
"**/*.mjs",
"**/*.d.ts"
"cjs/index.cjs",
"esm/index.mjs",
"types/*.d.ts"
],

@@ -39,5 +39,6 @@ "repository": {

"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",
"build:esm": "esbuild src/index.ts --bundle --minify-whitespace --format=esm --outfile=esm/index.mjs",
"build:cjs": "esbuild src/index.ts --bundle --minify-whitespace --format=cjs --outfile=cjs/index.cjs",
"test": "vitest run",
"lint": "tsslint --project tsconfig.json",
"bench": "npm run build:esm && node --jitless --expose-gc benchs/propagate.mjs",

@@ -47,2 +48,4 @@ "bench:memory": "npm run build:esm && node --expose-gc benchs/memoryUsage.mjs"

"devDependencies": {
"@tsslint/cli": "latest",
"@tsslint/config": "latest",
"esbuild": "latest",

@@ -49,0 +52,0 @@ "mitata": "latest",

63

README.md

@@ -33,6 +33,9 @@ <p align="center">

- [YanqingXu/alien-signals-in-lua](https://github.com/YanqingXu/alien-signals-in-lua): Lua implementation of alien-signals
- [medz/alien-signals-dart](https://github.com/medz/alien-signals-dart): alien-signals Dart implementation of alien-signals
- [medz/alien-signals-dart](https://github.com/medz/alien-signals-dart): Dart implementation of alien-signals
- [delaneyj/alien-signals-go](https://github.com/delaneyj/alien-signals-go): Go implementation of alien-signals
- [Rajaniraiyn/react-alien-signals](https://github.com/Rajaniraiyn/react-alien-signals): React bindings for the alien-signals API
- [CCherry07/alien-deepsignals](https://github.com/CCherry07/alien-deepsignals): Use alien-signals with the interface of a plain JavaScript object
- [hunghg255/reactjs-signal](https://github.com/hunghg255/reactjs-signal): Share Store State with Signal Pattern
- [gn8-ai/universe-alien-signals](https://github.com/gn8-ai/universe-alien-signals): Enables simple use of the Alien Signals state management system in modern frontend frameworks
- [Nicell/alien-signals-luau](https://github.com/Nicell/alien-signals-luau): Luau implementation of alien-signals

@@ -68,3 +71,3 @@ ## Adoption

```ts
import { signal, effectScope } from 'alien-signals';
import { signal, effect, effectScope } from 'alien-signals';

@@ -77,6 +80,6 @@ const count = signal(1);

}); // Console: Count in scope: 1
count(2); // Console: Count in scope: 2
});
count(2); // Console: Count in scope: 2
stopScope();

@@ -87,3 +90,3 @@

#### Creating Your Own Public API
#### Creating Your Own Surface API

@@ -111,21 +114,16 @@ You can reuse alien-signals’ core algorithm via `createReactiveSystem()` to build your own signal API. For implementation examples, see:

if (
(
!(subFlags & (SubscriberFlags.Tracking | SubscriberFlags.Recursed | SubscriberFlags.Propagated))
&& (sub.flags = subFlags | targetFlag | SubscriberFlags.Notified, true)
)
|| (
(subFlags & SubscriberFlags.Recursed)
&& !(subFlags & SubscriberFlags.Tracking)
&& (sub.flags = (subFlags & ~SubscriberFlags.Recursed) | targetFlag | SubscriberFlags.Notified, true)
)
|| (
!(subFlags & SubscriberFlags.Propagated)
&& isValidLink(link, sub)
&& (
sub.flags = subFlags | SubscriberFlags.Recursed | targetFlag | SubscriberFlags.Notified,
(sub as Dependency).subs !== undefined
)
)
) {
let shouldNotify = false;
if (!(subFlags & (SubscriberFlags.Tracking | SubscriberFlags.Recursed | SubscriberFlags.Propagated))) {
sub.flags = subFlags | targetFlag | SubscriberFlags.Notified;
shouldNotify = true;
} else if ((subFlags & SubscriberFlags.Recursed) && !(subFlags & SubscriberFlags.Tracking)) {
sub.flags = (subFlags & ~SubscriberFlags.Recursed) | targetFlag | SubscriberFlags.Notified;
shouldNotify = true;
} else if (!(subFlags & SubscriberFlags.Propagated) && isValidLink(current, sub)) {
sub.flags = subFlags | SubscriberFlags.Recursed | targetFlag | SubscriberFlags.Notified;
shouldNotify = (sub as Dependency).subs !== undefined;
}
if (shouldNotify) {
const subSubs = (sub as Dependency).subs;

@@ -139,9 +137,9 @@ if (subSubs !== undefined) {

);
} else if (subFlags & SubscriberFlags.Effect) {
}
if (subFlags & SubscriberFlags.Effect) {
if (queuedEffectsTail !== undefined) {
queuedEffectsTail.depsTail!.nextDep = sub.deps;
queuedEffectsTail = queuedEffectsTail.linked = { target: sub, linked: undefined };
} else {
queuedEffects = sub;
queuedEffectsTail = queuedEffects = { target: sub, linked: undefined };
}
queuedEffectsTail = sub;
}

@@ -152,7 +150,6 @@ } else if (!(subFlags & (SubscriberFlags.Tracking | targetFlag))) {

if (queuedEffectsTail !== undefined) {
queuedEffectsTail.depsTail!.nextDep = sub.deps;
queuedEffectsTail = queuedEffectsTail.linked = { target: sub, linked: undefined };
} else {
queuedEffects = sub;
queuedEffectsTail = queuedEffects = { target: sub, linked: undefined };
}
queuedEffectsTail = sub;
}

@@ -181,3 +178,3 @@ } else if (

if ((depFlags & (SubscriberFlags.Computed | SubscriberFlags.Dirty)) === (SubscriberFlags.Computed | SubscriberFlags.Dirty)) {
if (updateComputed(dep)) {
if (update(dep)) {
const subs = dep.subs!;

@@ -191,3 +188,3 @@ if (subs.nextSub !== undefined) {

if (checkDirty(dep.deps!)) {
if (updateComputed(dep)) {
if (update(dep)) {
const subs = dep.subs!;

@@ -194,0 +191,0 @@ if (subs.nextSub !== undefined) {

export * from './system.js';
interface WriteableSignal<T> {
(): T;
(value: T): void;
}
export declare let batchDepth: number;
export declare function startBatch(): void;

@@ -10,6 +7,12 @@ export declare function endBatch(): void;

export declare function resumeTracking(): void;
export declare function signal<T>(): WriteableSignal<T | undefined>;
export declare function signal<T>(oldValue: T): WriteableSignal<T>;
export declare function computed<T>(getter: (cachedValue?: T) => T): () => T;
export declare function signal<T>(): {
(): T | undefined;
(value: T | undefined): void;
};
export declare function signal<T>(initialValue: T): {
(): T;
(value: T): void;
};
export declare function computed<T>(getter: (previousValue?: T) => T): () => T;
export declare function effect<T>(fn: () => T): () => void;
export declare function effectScope<T>(fn: () => T): () => void;
export interface Dependency {
version?: number;
subs: Link | undefined;

@@ -12,3 +11,2 @@ subsTail: Link | undefined;

export interface Link {
version: number | undefined;
dep: Dependency | (Dependency & Subscriber);

@@ -18,114 +16,35 @@ sub: Subscriber | (Dependency & Subscriber);

nextSub: Link | undefined;
prevDep: Link | undefined;
nextDep: Link | undefined;
}
export declare const enum SubscriberFlags {
None = 0,
Computed = 1,
Effect = 2,
Tracking = 4,
Recursed = 8,
Mutable = 1,
Watching = 2,
BlockPropagation = 4,
IsPropagationBlocked = 8,
Dirty = 16,
Pending = 32,
Cold = 64,
Propagated = 48
Pending = 32
}
export declare function createReactiveSystem({ computed: { update: updateComputed, onUnwatched: onUnwatchedComputed, }, effect: { notify: notifyEffect, }, }: {
computed: {
/**
* Updates the computed subscriber's value and returns whether it changed.
*
* This function should be called when a computed subscriber is marked as Dirty.
* The computed subscriber's getter function is invoked, and its value is updated.
* If the value changes, the new value is stored, and the function returns `true`.
*
* @param computed - The computed subscriber to update.
* @returns `true` if the computed subscriber's value changed; otherwise `false`.
*/
update(computed: Dependency & Subscriber): boolean;
onUnwatched?: (computed: Dependency & Subscriber) => void;
};
effect: {
/**
* Handles effect notifications by processing the specified `effect`.
*
* When an `effect` first receives any of the following flags:
* - `Dirty`
* - `PendingComputed`
* - `PendingEffect`
* this method will process them and return `true` if the flags are successfully handled.
* If not fully handled, future changes to these flags will trigger additional calls
* until the method eventually returns `true`.
*/
notify(effect: Subscriber): void;
};
}): {
export declare function createReactiveSystem({ update, notify, unwatched, }: {
/**
* Links a given dependency and subscriber if they are not already linked.
* Updates the computed subscriber's value and returns whether it changed.
*
* @param dep - The dependency to be linked.
* @param sub - The subscriber that depends on this dependency.
* @returns The newly created link object if the two are not already linked; otherwise `undefined`.
*/
link(dep: Dependency, sub: Subscriber): Link | undefined;
/**
* Traverses and marks subscribers starting from the provided link.
* This function should be called when a computed subscriber is marked as Dirty.
* The computed subscriber's getter function is invoked, and its value is updated.
* If the value changes, the new value is stored, and the function returns `true`.
*
* It sets flags (e.g., Dirty, PendingComputed, PendingEffect) on each subscriber
* to indicate which ones require re-computation or effect processing.
* This function should be called after a signal's value changes.
*
* @param link - The starting link from which propagation begins.
* @param sub - The computed subscriber to update.
* @returns `true` if the computed subscriber's value changed; otherwise `false`.
*/
propagate(link: Link): void;
/**
* Prepares the given subscriber to track new dependencies.
*
* It resets the subscriber's internal pointers (e.g., depsTail) and
* sets its flags to indicate it is now tracking dependency links.
*
* @param sub - The subscriber to start tracking.
*/
startTracking(sub: Subscriber): void;
/**
* Concludes tracking of dependencies for the specified subscriber.
*
* It clears or unlinks any tracked dependency information, then
* updates the subscriber's flags to indicate tracking is complete.
*
* @param sub - The subscriber whose tracking is ending.
*/
endTracking(sub: Subscriber): void;
/**
* Recursively checks and updates all computed subscribers marked as pending.
*
* It traverses the linked structure using a stack mechanism. For each computed
* subscriber in a pending state, updateComputed is called and shallowPropagate
* is triggered if a value changes. Returns whether any updates occurred.
*
* @param link - The starting link representing a sequence of pending computeds.
* @returns `true` if a computed was updated, otherwise `false`.
*/
checkDirty(link: Link): boolean;
/**
* Ensures all pending internal effects for the given subscriber are processed.
*
* This should be called after an effect decides not to re-run itself but may still
* have dependencies flagged with PendingEffect. If the subscriber is flagged with
* PendingEffect, this function clears that flag and invokes `notifyEffect` on any
* related dependencies marked as Effect and Propagated, processing pending effects.
*
* @param sub - The subscriber which may have pending effects.
* @param flags - The current flags on the subscriber to check.
*/
processPendingInnerEffects(sub: Subscriber): void;
/**
* Processes queued effect notifications after a batch operation finishes.
*
* Iterates through all queued effects, calling notifyEffect on each.
* If an effect remains partially handled, its flags are updated, and future
* notifications may be triggered until fully handled.
*/
processEffectNotifications(): void;
warming: (sub: Subscriber & Dependency) => void;
cooling: (sub: Subscriber & Dependency) => void;
update(sub: Dependency & Subscriber): boolean;
notify(sub: Subscriber, nextSub: Link | undefined): void;
unwatched(sub: Dependency): void;
}): {
link: (dep: Dependency, sub: Subscriber) => Link | undefined;
unlink: (link: Link, sub?: Subscriber) => Link | undefined;
propagate: (current: Link) => void;
shallowPropagate: (link: Link) => void;
checkDirty: (current: Link) => boolean;
startTracking: (sub: Subscriber) => void;
endTracking: (sub: Subscriber) => void;
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.