Socket
Socket
Sign inDemoInstall

mini-signals

Package Overview
Dependencies
0
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0-0 to 2.0.0-1

dist/mini-signals.test-d.d.ts

3

dist/index.d.ts

@@ -1,2 +0,1 @@

export { MiniSignalBinding } from './mini-signals-binding';
export { MiniSignal } from './mini-signals';
export * from './mini-signals';
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MiniSignal = exports.MiniSignalBinding = void 0;
var mini_signals_binding_1 = require("./mini-signals-binding");
Object.defineProperty(exports, "MiniSignalBinding", { enumerable: true, get: function () { return mini_signals_binding_1.MiniSignalBinding; } });
var mini_signals_1 = require("./mini-signals");
Object.defineProperty(exports, "MiniSignal", { enumerable: true, get: function () { return mini_signals_1.MiniSignal; } });
__exportStar(require("./mini-signals"), exports);

@@ -1,15 +0,19 @@

import { type BoundFunction, MiniSignalBinding } from './mini-signals-binding';
export declare class MiniSignal<T extends any[] = any[], A extends any | undefined = any | undefined> {
type CallBack<T extends any[]> = (...x: T) => void;
declare const MiniSignalSymbol: unique symbol;
type MiniSignalNode<T extends any[]> = {
fn: CallBack<T>;
next?: MiniSignalNode<T>;
prev?: MiniSignalNode<T>;
[MiniSignalSymbol]?: symbol;
};
type MiniSignalRef<T extends any[], S extends any> = WeakRef<MiniSignalNode<T>> & S;
export declare class MiniSignal<T extends any[] = any[], S extends any = {
[MiniSignalSymbol]: true;
}> {
private _head?;
private _tail?;
hasHandlers(): boolean;
private readonly symbol;
private dispatching;
hasListeners(): boolean;
/**
* Return an array of attached MiniSignalBinding.
*/
handlers(): Array<MiniSignalBinding<T, A>>;
/**
* Return true if node is a MiniSignalBinding attached to this MiniSignal
*/
has(node: MiniSignalBinding<T, A>): boolean;
/**
* Dispatches a signal to all registered listeners.

@@ -21,11 +25,7 @@ */

*/
add(fn: BoundFunction<T>, thisArg?: A): MiniSignalBinding<T, A>;
add(fn: CallBack<T>): MiniSignalRef<T, S>;
/**
* Register a new listener that will be executed only once.
*/
once(fn: BoundFunction<T>, thisArg?: A): MiniSignalBinding;
/**
* Remove binding object.
*/
detach(node: MiniSignalBinding<T, A>): this;
detach(ref: MiniSignalRef<T, S>): this;
/**

@@ -35,3 +35,6 @@ * Detach all listeners.

detachAll(): this;
private _addMiniSignalBinding;
private _destroyNode;
private _disconnectNode;
private _addNode;
}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MiniSignal = void 0;
const mini_signals_binding_1 = require("./mini-signals-binding");
const MiniSignalSymbol = Symbol('MiniSignalSymbol');
class MiniSignal {

@@ -9,40 +9,24 @@ constructor() {

this._tail = undefined;
this.symbol = Symbol('MiniSignal');
this.dispatching = false;
}
hasHandlers() {
hasListeners() {
return !(this._head == null);
}
/**
* Return an array of attached MiniSignalBinding.
*/
handlers() {
let node = this._head;
const ee = [];
while (node != null) {
ee.push(node);
node = node._next;
}
return ee;
}
/**
* Return true if node is a MiniSignalBinding attached to this MiniSignal
*/
has(node) {
if (!(node instanceof mini_signals_binding_1.MiniSignalBinding)) {
throw new Error('MiniSignal#has(): First arg must be a MiniSignalBinding object.');
}
return node._owner === this;
}
/**
* Dispatches a signal to all registered listeners.
*/
dispatch(...args) {
if (this.dispatching) {
throw new Error('MiniSignal#dispatch(): Signal already dispatching.');
}
let node = this._head;
if (node == null)
return false;
this.dispatching = true;
while (node != null) {
if (node._once)
this.detach(node);
node._fn.apply(node._thisArg, args);
node = node._next;
node.fn(...args);
node = node.next;
}
this.dispatching = false;
return true;

@@ -53,34 +37,51 @@ }

*/
add(fn, thisArg) {
add(fn) {
if (typeof fn !== 'function') {
throw new Error('MiniSignal#add(): First arg must be a Function.');
}
return this._addMiniSignalBinding(new mini_signals_binding_1.MiniSignalBinding(fn, false, thisArg));
return this._addNode({
fn,
[MiniSignalSymbol]: this.symbol
});
}
/**
* Register a new listener that will be executed only once.
* Remove binding object.
*/
once(fn, thisArg) {
if (typeof fn !== 'function') {
throw new Error('MiniSignal#once(): First arg must be a Function.');
detach(ref) {
if (!(ref instanceof WeakRef)) {
throw new Error('MiniSignal#detach(): First arg must be a MiniSignalNode object.');
}
return this._addMiniSignalBinding(new mini_signals_binding_1.MiniSignalBinding(fn, true, thisArg));
const node = ref.deref();
if (!node || !node[MiniSignalSymbol])
return this;
if (node[MiniSignalSymbol] !== this.symbol)
return this; // Error?
this._disconnectNode(node);
this._destroyNode(node);
return this;
}
/**
* Remove binding object.
* Detach all listeners.
*/
detach(node) {
if (!(node instanceof mini_signals_binding_1.MiniSignalBinding)) {
throw new Error('MiniSignal#detach(): First arg must be a MiniSignalBinding object.');
detachAll() {
let n = this._head;
if (n == null)
return this;
this._head = this._tail = undefined;
while (n != null) {
this._destroyNode(n);
n = n.next;
}
if (node._owner !== this)
return this; // todo: or error?
if (node._prev !== undefined && node._prev !== null)
node._prev._next = node._next;
if (node._next !== undefined && node._next !== null)
node._next._prev = node._prev;
return this;
}
_destroyNode(node) {
node.fn = undefined;
node.prev = undefined;
node[MiniSignalSymbol] = undefined;
}
_disconnectNode(node) {
if (node === this._head) {
// first node
this._head = node._next;
if (node._next === null) {
this._head = node.next;
if (node.next == null) {
this._tail = undefined;

@@ -91,24 +92,16 @@ }

// last node
this._tail = node._prev;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this._tail._next = undefined;
this._tail = node.prev;
if (this._tail != null) {
this._tail.next = undefined;
}
}
node._owner = null;
return this;
}
/**
* Detach all listeners.
*/
detachAll() {
let node = this._head;
if (node == null)
return this;
this._head = this._tail = undefined;
while (node != null) {
node._owner = null;
node = node._next;
if (node.prev != null) {
node.prev.next = node.next;
}
return this;
if (node.next != null) {
node.next.prev = node.prev;
}
node[MiniSignalSymbol] = undefined;
}
_addMiniSignalBinding(node) {
_addNode(node) {
if (this._head == null) {

@@ -120,10 +113,9 @@ this._head = node;

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this._tail._next = node;
node._prev = this._tail;
this._tail.next = node;
node.prev = this._tail;
this._tail = node;
}
node._owner = this;
return node;
return new WeakRef(node);
}
}
exports.MiniSignal = MiniSignal;
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const mini_signals_1 = require("../src/mini-signals");
const mini_signals_binding_1 = require("../src/mini-signals-binding");
const node_util_1 = require("node:util");
const chai_1 = require("chai");
const node_assert_1 = require("node:assert");
describe('MiniSignal', () => {
it('inherits when used with require(util).inherits', () => {
function Beast() {
/* rawr, i'm a beast */
}
(0, node_util_1.inherits)(Beast, mini_signals_1.MiniSignal);
const moop = new Beast();
const meap = new Beast();
(0, chai_1.expect)(moop).is.instanceOf(Beast);
(0, chai_1.expect)(moop).is.instanceOf(mini_signals_1.MiniSignal);
moop.handlers();
meap.handlers();
/* istanbul ignore next */
moop.add(() => {
throw new Error('I should not dispatch');
});
meap.dispatch('rawr');
meap.detachAll();
const pattern = [];
const writer = (a) => {
pattern.push(a);
};
beforeEach(() => {
pattern.length = 0;
});
it('quick test', () => {
const pattern = [];
const e = new mini_signals_1.MiniSignal();
const foo = e.add(writer, 'foo');
e.add(writer, 'baz');
const bar = e.add(writer, 'bar');
const foo = e.add(writer);
e.add(writer);
const bar = e.add(writer);
(0, chai_1.expect)(e instanceof mini_signals_1.MiniSignal);
(0, chai_1.expect)(foo instanceof mini_signals_binding_1.MiniSignalBinding);
e.dispatch('banana');
e.dispatch('apple');
foo.detach();
bar.detach();
e.detach(foo);
e.detach(bar);
e.dispatch('pear');
e.detachAll();
e.dispatch('raspberry');
(0, chai_1.expect)(pattern.join(';') ===
'foo:banana;baz:banana;bar:banana;foo:apple;baz:apple;bar:apple;baz:pear');
function writer(a) {
pattern.push(String(this) + ':' + a);
}
(0, chai_1.expect)(pattern.join(';')).to.equal('banana;banana;banana;apple;apple;apple;pear');
});
describe('MiniSignal#once', () => {
let e;
let context;
beforeEach(() => {
e = new mini_signals_1.MiniSignal();
context = { bar: 'baz' };
describe('Readme Examples', () => {
it('Example Usage', () => {
const mySignal = new mini_signals_1.MiniSignal();
const binding = mySignal.add(onSignal); // add listener
mySignal.dispatch('foo', 'bar'); // dispatch signal passing custom parameters
mySignal.detach(binding); // remove a single listener
function onSignal(foo, bar) {
(0, chai_1.expect)(foo).to.equal('foo');
(0, chai_1.expect)(bar).to.equal('bar');
}
});
it('should throw error for incorrect types', () => {
(0, chai_1.expect)(() => {
// @ts-expect-error testing error
e.once();
}).throws('MiniSignal#once(): First arg must be a Function.');
(0, chai_1.expect)(() => {
// @ts-expect-error testing error
e.once(123);
}).throws('MiniSignal#once(): First arg must be a Function.');
(0, chai_1.expect)(() => {
// @ts-expect-error testing error
e.once(true);
}).throws('MiniSignal#once(): First arg must be a Function.');
(0, chai_1.expect)(e.handlers().length).equals(0);
});
it('should not invoke twice', () => {
it('Function#bind example', () => {
const mySignal = new mini_signals_1.MiniSignal();
const context = {};
const cb = function (bar) {
(0, chai_1.expect)(arguments).has.length(1);
(0, chai_1.expect)(bar).equals('bar');
(0, chai_1.expect)(this).equals(context);
(0, chai_1.expect)(arguments).has.length(1);
e.dispatch('bar');
}.bind(context);
e.once(cb);
e.dispatch('bar');
mySignal.add(cb);
mySignal.dispatch('bar');
});
it('Function#bind example with parameters', () => {
const mySignal = new mini_signals_1.MiniSignal();
const context = {};
const cb = function (bar) {
(0, chai_1.expect)(arguments).has.length(1);
(0, chai_1.expect)(bar).equals('bar');
(0, chai_1.expect)(this).equals(context);
}.bind(context, 'bar');
mySignal.add(cb);
mySignal.dispatch();
});
});

@@ -99,16 +89,22 @@ describe('MiniSignal#add', () => {

}).throws('MiniSignal#add(): First arg must be a Function.');
(0, chai_1.expect)(e.handlers().length).equals(0);
(0, chai_1.expect)(!e.hasListeners);
});
// Note: once is deprecated
// These tests use the add method instead
it('should not invoke twice', () => {
const l = e.add(function (arg) {
writer(arg);
(0, chai_1.expect)(arg).equals('foo');
e.detach(l);
});
e.dispatch('foo');
e.dispatch('bar');
e.dispatch('baz');
(0, chai_1.expect)(pattern.join(';')).equals('foo');
});
});
describe('MiniSignal#dispatch', () => {
function writer() {
pattern += String(this);
}
let e;
let context = { bar: 'baz' };
let pattern = '';
beforeEach(() => {
e = new mini_signals_1.MiniSignal();
context = { bar: 'baz' };
pattern = '';
});

@@ -128,10 +124,2 @@ it('should return false when there are not events to dispatch', () => {

});
it('emits with context when context is specified', () => {
e.add(function (bar) {
(0, chai_1.expect)(bar).equals('bar');
(0, chai_1.expect)(this).equals(context);
(0, chai_1.expect)(arguments).has.length(1);
}, context);
e.dispatch('bar');
});
it('can dispatch the function with multiple arguments', () => {

@@ -188,21 +176,2 @@ for (let i = 0; i < 100; i++) {

});
it('emits with context, multiple listeners (force loop)', () => {
e.add(function (bar) {
(0, chai_1.expect)(this).deep.equals({ foo: 'bar' });
(0, chai_1.expect)(bar).equals('bar');
}, { foo: 'bar' });
e.add(function (bar) {
(0, chai_1.expect)(this).deep.equals({ bar: 'baz' });
(0, chai_1.expect)(bar).equals('bar');
}, { bar: 'baz' });
e.dispatch('bar');
});
it('emits with different contexts', () => {
e.add(writer, 'foo');
e.add(writer, 'baz');
e.add(writer, 'bar');
e.add(writer, 'banana');
e.dispatch();
(0, chai_1.expect)(pattern).equals('foobazbarbanana');
});
it('should return true when there are events to dispatch', function (done) {

@@ -219,3 +188,3 @@ e.add(() => {

const e = new mini_signals_1.MiniSignal();
e.add(function (a, b, c, d, undef) {
e.add(function (a, b, c, undef) {
(0, chai_1.expect)(a).equals('foo');

@@ -244,3 +213,2 @@ (0, chai_1.expect)(b).equals(e);

const e = new mini_signals_1.MiniSignal();
const pattern = [];
function foo1() {

@@ -263,15 +231,12 @@ pattern.push('foo1');

const e = new mini_signals_1.MiniSignal();
const pattern = [];
function foo1() {
e.add(() => {
pattern.push('foo1');
}
function foo2() {
});
const l = e.add(() => {
pattern.push('foo2');
}
function foo3() {
e.detach(l);
});
e.add(() => {
pattern.push('foo3');
}
e.add(foo1);
e.once(foo2);
e.add(foo3);
});
e.dispatch();

@@ -281,44 +246,13 @@ e.dispatch();

});
});
describe('MiniSignal#handlers', () => {
/* istanbul ignore next */
function foo() { }
it('returns an empty array if no handlers are added', () => {
const e = new mini_signals_1.MiniSignal();
(0, chai_1.expect)(e.handlers()).is.a('array');
(0, chai_1.expect)(e.handlers().length).equals(0);
it('cannot dispatch while dispatching', () => {
const cb = function (bar) {
(0, chai_1.expect)(bar).equals('bar');
(0, chai_1.expect)(arguments).has.length(1);
e.dispatch('bar');
};
e.add(cb);
(0, chai_1.expect)(() => {
e.dispatch('bar');
}).throws('MiniSignal#dispatch(): Signal already dispatching.');
});
it('returns an array of MiniSignalBinding', () => {
const e = new mini_signals_1.MiniSignal();
e.add(foo);
e.add(foo);
(0, chai_1.expect)(e.handlers()).is.a('array');
(0, chai_1.expect)(e.handlers().length).equals(2);
e.handlers().forEach(function (h) {
(0, chai_1.expect)(h).instanceOf(mini_signals_binding_1.MiniSignalBinding);
});
});
it('is not vulnerable to modifications', () => {
const e = new mini_signals_1.MiniSignal();
e.add(foo);
e.add(foo);
(0, chai_1.expect)(e.handlers().length).equals(2);
e.handlers().length = 0;
(0, chai_1.expect)(e.handlers().length).equals(2);
e.handlers().forEach(function (h) {
(0, chai_1.expect)(h).instanceOf(mini_signals_binding_1.MiniSignalBinding);
});
});
it('can return a boolean as indication if handlers exist', () => {
const e = new mini_signals_1.MiniSignal();
e.add(foo);
e.add(foo);
e.add(foo);
e.add(foo);
e.add(foo);
e.add(foo);
(0, chai_1.expect)(e.hasHandlers()).equals(true);
e.detachAll();
(0, chai_1.expect)(e.hasHandlers()).equals(false);
});
});

@@ -352,11 +286,11 @@ describe('MiniSignal#detach', () => {

e.detach();
}).throws('MiniSignal#detach(): First arg must be a MiniSignalBinding object.');
}).throws('MiniSignal#detach(): First arg must be a MiniSignalNode object.');
(0, chai_1.expect)(() => {
// @ts-expect-error testing error
e.detach(1);
}).throws('MiniSignal#detach(): First arg must be a MiniSignalBinding object.');
}).throws('MiniSignal#detach(): First arg must be a MiniSignalNode object.');
(0, chai_1.expect)(() => {
// @ts-expect-error testing error
e.detach(bar);
}).throws('MiniSignal#detach(): First arg must be a MiniSignalBinding object.');
}).throws('MiniSignal#detach(): First arg must be a MiniSignalNode object.');
});

@@ -367,7 +301,7 @@ it('should only remove the event with the specified node', () => {

const _bar = e.add(bar);
(0, chai_1.expect)(e.handlers().length).equals(3);
(0, chai_1.expect)(e.hasListeners()).equals(true);
e.dispatch();
(0, chai_1.expect)(pattern.join(';')).equals('a;b;bar');
e.detach(_bar);
(0, chai_1.expect)(e.handlers().length).equals(2);
(0, chai_1.expect)(e.hasListeners()).equals(true);
e.dispatch();

@@ -380,7 +314,7 @@ (0, chai_1.expect)(pattern.join(';')).equals('a;b;bar;a;b');

e.add(b);
(0, chai_1.expect)(e.handlers().length).equals(3);
(0, chai_1.expect)(e.hasListeners()).equals(true);
e.dispatch();
(0, chai_1.expect)(pattern.join(';')).equals('bar;a;b');
e.detach(_bar);
(0, chai_1.expect)(e.handlers().length).equals(2);
(0, chai_1.expect)(e.hasListeners()).equals(true);
e.dispatch();

@@ -393,7 +327,7 @@ (0, chai_1.expect)(pattern.join(';')).equals('bar;a;b;a;b');

e.add(b);
(0, chai_1.expect)(e.handlers().length).equals(3);
(0, chai_1.expect)(e.hasListeners()).equals(true);
e.dispatch();
(0, chai_1.expect)(pattern.join(';')).equals('a;bar;b');
e.detach(_bar);
(0, chai_1.expect)(e.handlers().length).equals(2);
(0, chai_1.expect)(e.hasListeners()).equals(true);
e.dispatch();

@@ -462,10 +396,7 @@ (0, chai_1.expect)(pattern.join(';')).equals('a;bar;b;a;b');

e2.detach(binding);
(0, chai_1.expect)(binding._owner === e);
(0, chai_1.expect)(e.hasHandlers());
(0, chai_1.expect)(e.hasListeners());
});
it('can be called multiple times', () => {
const binding = e.add(foo);
(0, chai_1.expect)(binding._owner === e);
e.detach(binding);
(0, chai_1.expect)(binding._owner === null);
e.detach(binding);

@@ -489,5 +420,5 @@ e.detach(binding);

e.add(oops);
(0, chai_1.expect)(e.handlers().length).equals(4);
(0, chai_1.expect)(e.hasListeners()).equals(true);
(0, chai_1.expect)(e.detachAll()).equals(e);
(0, chai_1.expect)(e.handlers().length).equals(0);
(0, chai_1.expect)(e.hasListeners()).equals(false);
(0, chai_1.expect)(e.dispatch()).equals(false);

@@ -497,3 +428,3 @@ });

(0, chai_1.expect)(e.detachAll()).equals(e);
(0, chai_1.expect)(e.handlers().length).equals(0);
(0, chai_1.expect)(e.hasListeners()).equals(false);
(0, chai_1.expect)(e.dispatch()).equals(false);

@@ -507,85 +438,31 @@ });

});
describe('MiniSignal#has', () => {
/* istanbul ignore next */
function oops() {
throw new Error('oops');
}
let e;
beforeEach(() => {
e = new mini_signals_1.MiniSignal();
});
it('has returns true if bound', () => {
const binding = e.add(oops);
(0, node_assert_1.strict)(e.has(binding));
});
it('has returns false if bound to another signal', () => {
const e2 = new mini_signals_1.MiniSignal();
const binding = e2.add(oops);
(0, node_assert_1.strict)(e.has(binding) === false);
});
it('has returns false if detached', () => {
const binding = e.add(oops);
(0, node_assert_1.strict)(e.has(binding));
binding.detach();
(0, node_assert_1.strict)(e.has(binding) === false);
});
it('has returns false after detachAll', () => {
const binding = e.add(oops);
(0, node_assert_1.strict)(e.has(binding));
e.detachAll();
(0, node_assert_1.strict)(e.has(binding) === false);
});
it('should throw error for incorrect types', () => {
(0, chai_1.expect)(() => {
e.has({});
}).throws('MiniSignal#has(): First arg must be a MiniSignalBinding object.');
});
describe('Garbage Collection', () => {
it('should not leak memory', () => __awaiter(void 0, void 0, void 0, function* () {
const e = new mini_signals_1.MiniSignal();
const w = e.add(() => {
/* */
});
(0, chai_1.expect)(w.deref()).to.exist;
e.dispatch();
(0, chai_1.expect)(w.deref()).to.exist;
e.detach(w);
yield new Promise(resolve => setTimeout(resolve, 0));
global.gc();
(0, chai_1.expect)(w.deref()).to.be.undefined;
// should not throw an error when detaching gc ref
e.detach(w);
}));
it('can clean up after itself when using add', () => __awaiter(void 0, void 0, void 0, function* () {
const e = new mini_signals_1.MiniSignal();
const w = e.add(() => {
e.detach(w);
});
(0, chai_1.expect)(w.deref()).to.exist;
e.dispatch();
(0, chai_1.expect)(w.deref()).to.exist;
yield new Promise(resolve => setTimeout(resolve, 0));
global.gc();
(0, chai_1.expect)(w.deref()).to.be.undefined;
}));
});
describe('Readme Examples', () => {
it('Example Usage', () => {
const mySignal = new mini_signals_1.MiniSignal();
const binding = mySignal.add(onSignal); // add listener
mySignal.dispatch('foo', 'bar'); // dispatch signal passing custom parameters
binding.detach(); // remove a single listener
function onSignal(foo, bar) {
(0, node_assert_1.strict)(foo === 'foo');
(0, node_assert_1.strict)(bar === 'bar');
}
});
it('Another Example', () => {
const myObject = {
foo: 'bar',
updated: new mini_signals_1.MiniSignal(),
};
myObject.updated.add(onUpdated, myObject); // add listener with context
myObject.foo = 'baz';
myObject.updated.dispatch(); // dispatch signal
function onUpdated() {
(0, node_assert_1.strict)(this === myObject);
(0, node_assert_1.strict)(this.foo === 'baz');
}
});
it('Function#bind example', () => {
const mySignal = new mini_signals_1.MiniSignal();
const context = {};
const cb = function (bar) {
(0, chai_1.expect)(arguments).has.length(1);
(0, chai_1.expect)(bar).equals('bar');
(0, chai_1.expect)(this).equals(context);
}.bind(context);
mySignal.add(cb);
mySignal.dispatch('bar');
});
it('Function#bind example with parameters', () => {
const mySignal = new mini_signals_1.MiniSignal();
const context = {};
const cb = function (bar) {
(0, chai_1.expect)(arguments).has.length(1);
(0, chai_1.expect)(bar).equals('bar');
(0, chai_1.expect)(this).equals(context);
}.bind(context, 'bar');
mySignal.add(cb);
mySignal.dispatch();
});
});
});
{
"name": "mini-signals",
"version": "2.0.0-0",
"version": "2.0.0-1",
"description": "signals, in TypeScript, fast",

@@ -8,12 +8,14 @@ "main": "dist/index.js",

"files": [
"/dist"
"/dist",
"/docs"
],
"scripts": {
"test": "npm-run-all test:*",
"test:unit": "mocha --reporter spec --compilers ts:ts-node/register src/**/*.spec.ts",
"test:unit": "mocha --reporter spec --require ts-node/register src/**/*.spec.ts -n expose-gc",
"test:deopt": "node --trace_opt --trace_deopt ./bench/test-deopt.js | grep \"disabled optimization\" || true",
"test:types": "tsd -f ./src/mini-signals.test-d.ts",
"build": "npm-run-all build:*",
"build:tsc": "tsc",
"xxx-build:jsdoc2md": "jsdoc-parse ./src/mini-signals.ts | dmd > API.md",
"coverage": "istanbul cover -- ./node_modules/mocha/bin/_mocha --compilers js:babel/register ./test/mini-signals-*.js",
"xxx-build:doc": "typedoc --plugin typedoc-plugin-markdown --out docs src/index.ts",
"coverage": "nyc --reporter=html --reporter=text --timeout=3000 npm run test:unit",
"bench": "ts-node ./bench/index.js | tee ./bench/latest.md",

@@ -52,3 +54,2 @@ "bench:emit": "ts-node ./bench/emit.js",

"chg": "^0.4.0",
"dmd": "^1.2.0",
"eslint": "^8.36.0",

@@ -60,13 +61,16 @@ "eslint-config-prettier": "^8.8.0",

"eslint-plugin-promise": "^6.1.1",
"eventemitter3": "^1.1.1",
"istanbul": "^0.3.19",
"jsdoc-parse": "^1.1.0",
"mocha": "^2.2.5",
"np": "^2.20.1",
"eventemitter3": "^5.0.0",
"mocha": "^10.2.0",
"np": "^7.6.4",
"npm-check": "^6.0.1",
"npm-run-all": "^4.1.5",
"nyc": "^15.1.0",
"prettier": "2.8.7",
"signals": "^1.0.0",
"ts-node": "^10.9.1",
"tsd": "^0.28.0",
"typedoc": "^0.23.28",
"typedoc-plugin-markdown": "^3.14.0",
"typescript": "^5.0.2"
}
}

@@ -15,2 +15,18 @@ # mini-signals

## mini-signals 2.0.0
MiniSignals v2.0.0 has been rewritten in TypeScript and had it's API changed to improve performance and add type safety.
New features:
- `.add` now returns a weak node reference which can be used to remove the listener directly from the signal. Reduces memory leaks.
- `.add` is now type safe. The type of the listener is checked against the type variable in the constructor.
Breaking changes:
- `.add` now returns a node reference instead of a object, which had a `detach` method. The node reference can be used to remove the listener directly from the signal.
- `.once` has been removed. Use `.add` instead with a call to `.detach` in the listener.
- The `thisArg` parameter has been removed from `.add`. Use `.add` with a call to `.bind` or use an arrow function with a closure.
- `.dispatch` now throws an error if the signal is already dispatching.
## Install

@@ -27,15 +43,14 @@

```ts
import { MiniSignal } from "mini-signals";
import { MiniSignal } from 'mini-signals';
const mySignal = new MiniSignal<[string, string]>();
const mySignal = new MiniSignal<[string, string]>(); // the type variable is optional and defines the parameters to be dispatched
const binding = mySignal.add(onSignal); //add listener
const binding = mySignal.add((foo: string, bar: string) => { // add listener, note the parameter types match the type variable in the constructor
console.log('signal dispatched');
assert(foo === 'foo');
assert(bar === 'bar');
});
mySignal.dispatch("foo", "bar"); // dispatch signal passing custom parameters
mySignal.dispatch('foo', 'bar'); // dispatch signal passing custom parameters
binding.detach(); // remove a single listener
function onSignal(foo: string, bar: string) {
assert(foo === "foo");
assert(bar === "bar");
}
```

@@ -48,14 +63,13 @@

foo: "bar",
updated: new MiniSignal<never>(),
updated: new MiniSignal<never, typeof myObject>() // in this case the type variable is never, since we are not passing any parameters
};
myObject.updated.add(onUpdated, myObject); //add listener with context
myObject.updated.add(() => {
console.log('signal dispatched');
assert(this === myObject);
assert(this.foo === 'baz');
}, myObject); // add listener with context
myObject.foo = "baz";
myObject.updated.dispatch(); //dispatch signal
function onUpdated() {
assert(this === myObject);
assert(this.foo === "baz");
}
myObject.foo = 'baz';
myObject.updated.dispatch(); // dispatch signal
```

@@ -62,0 +76,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc