Socket
Socket
Sign inDemoInstall

@wixc3/patterns

Package Overview
Dependencies
Maintainers
67
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wixc3/patterns - npm Package Compare versions

Comparing version 15.3.1 to 16.0.0

5

dist/cjs/event-emitter.d.ts

@@ -28,3 +28,2 @@ import { Signal } from './signal';

protected events: Map<EventId, Signal<any>>;
protected emitOnce: Map<EventId, Signal<any>>;
/**

@@ -37,2 +36,3 @@ * Check if an event has subscribers

* Subscribe a handler for event
*
* @returns unsubscribe fn

@@ -46,3 +46,4 @@ */

/**
* Adds a handler that will be called at most once
* Adds a handler that will be called at most once.
*
* @returns unsubscribe fn

@@ -49,0 +50,0 @@ */

34

dist/cjs/event-emitter.js

@@ -32,3 +32,2 @@ "use strict";

this.events = new Map();
this.emitOnce = new Map();
/**

@@ -41,2 +40,3 @@ * Check if an event has subscribers

* Subscribe a handler for event
*
* @returns unsubscribe fn

@@ -46,3 +46,3 @@ */

const bucket = this.events.get(event);
bucket ? bucket.add(handler) : this.events.set(event, new signal_1.Signal([handler]));
bucket ? bucket.subscribe(handler) : this.events.set(event, new signal_1.Signal([handler]));
return () => this.unsubscribe(event, handler);

@@ -55,9 +55,13 @@ };

/**
* Adds a handler that will be called at most once
* Adds a handler that will be called at most once.
*
* @returns unsubscribe fn
*/
this.once = (event, handler) => {
this.off(event, handler);
const bucket = this.emitOnce.get(event);
bucket ? bucket.add(handler) : this.emitOnce.set(event, new signal_1.Signal([handler]));
let bucket = this.events.get(event);
if (!bucket) {
bucket = new signal_1.Signal();
this.events.set(event, bucket);
}
bucket.once(handler);
return () => this.unsubscribe(event, handler);

@@ -69,8 +73,7 @@ };

this.unsubscribe = (event, handler) => {
let bucket = this.events.get(event);
bucket === null || bucket === void 0 ? void 0 : bucket.delete(handler);
(bucket === null || bucket === void 0 ? void 0 : bucket.size) === 0 && this.events.delete(event);
bucket = this.emitOnce.get(event);
bucket === null || bucket === void 0 ? void 0 : bucket.delete(handler);
(bucket === null || bucket === void 0 ? void 0 : bucket.size) === 0 && this.events.delete(event);
const bucket = this.events.get(event);
bucket === null || bucket === void 0 ? void 0 : bucket.unsubscribe(handler);
if ((bucket === null || bucket === void 0 ? void 0 : bucket.size) === 0) {
this.events.delete(event);
}
};

@@ -87,3 +90,2 @@ /**

this.events.delete(event);
this.emitOnce.delete(event);
};

@@ -94,4 +96,4 @@ /**

this.clear = () => {
this.events.forEach((bucket) => bucket.clear());
this.events = new Map();
this.emitOnce = new Map();
};

@@ -104,6 +106,4 @@ /**

this.notify = (event, data) => {
var _a, _b;
var _a;
(_a = this.events.get(event)) === null || _a === void 0 ? void 0 : _a.notify(data);
(_b = this.emitOnce.get(event)) === null || _b === void 0 ? void 0 : _b.notify(data);
this.emitOnce.delete(event);
};

@@ -110,0 +110,0 @@ /**

@@ -33,14 +33,26 @@ export type Listener<T> = (data: T) => void;

*/
export declare class Signal<T> extends Set<Listener<T>> {
private onceHandlers;
export declare class Signal<T> {
private handlers;
constructor(handlers?: Listener<T>[]);
/**
* Subscribe a notification callback
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
subscribe: (handler: Listener<T>) => void;
/**
* Subscribe to only the next notification
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
once: (handler: Listener<T>) => void;
/**
* @returns true if a listener is subscribed
*/
has(value: Listener<T>): boolean;
/**
* Unsubscribe an existing callback
*/
unsubscribe: (handler: Listener<T>) => void;
get size(): number;
/**

@@ -47,0 +59,0 @@ * Notify all subscribers with arg data

@@ -35,15 +35,30 @@ "use strict";

*/
class Signal extends Set {
constructor() {
super(...arguments);
this.onceHandlers = new Set();
class Signal {
constructor(handlers) {
this.handlers = new Map();
/**
* Subscribe a notification callback
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
this.subscribe = (handler) => {
this.add(handler);
if (this.handlers.get(handler) !== true) {
this.handlers.set(handler, false);
}
else {
throw new Error(`handler already exists as "once" listener`);
}
};
/**
* Subscribe to only the next notification
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
this.once = (handler) => {
this.onceHandlers.add(handler);
if (this.handlers.get(handler) !== false) {
this.handlers.set(handler, true);
}
else {
throw new Error(`handler already exists as persistent listener`);
}
};

@@ -54,4 +69,3 @@ /**

this.unsubscribe = (handler) => {
this.onceHandlers.delete(handler);
this.delete(handler);
this.handlers.delete(handler);
};

@@ -62,14 +76,22 @@ /**

this.notify = (data) => {
for (const handler of this) {
for (const [handler, isOnce] of this.handlers) {
handler(data);
if (isOnce) {
this.handlers.delete(handler);
}
}
for (const handler of this.onceHandlers) {
handler(data);
this.onceHandlers.delete(handler);
}
};
handlers === null || handlers === void 0 ? void 0 : handlers.forEach((handler) => this.subscribe(handler));
}
/**
* @returns true if a listener is subscribed
*/
has(value) {
return this.handlers.has(value);
}
get size() {
return this.handlers.size;
}
clear() {
super.clear();
this.onceHandlers.clear();
this.handlers.clear();
}

@@ -76,0 +98,0 @@ }

@@ -28,3 +28,2 @@ import { Signal } from './signal';

protected events: Map<EventId, Signal<any>>;
protected emitOnce: Map<EventId, Signal<any>>;
/**

@@ -37,2 +36,3 @@ * Check if an event has subscribers

* Subscribe a handler for event
*
* @returns unsubscribe fn

@@ -46,3 +46,4 @@ */

/**
* Adds a handler that will be called at most once
* Adds a handler that will be called at most once.
*
* @returns unsubscribe fn

@@ -49,0 +50,0 @@ */

@@ -29,3 +29,2 @@ import { Signal } from './signal';

this.events = new Map();
this.emitOnce = new Map();
/**

@@ -38,2 +37,3 @@ * Check if an event has subscribers

* Subscribe a handler for event
*
* @returns unsubscribe fn

@@ -43,3 +43,3 @@ */

const bucket = this.events.get(event);
bucket ? bucket.add(handler) : this.events.set(event, new Signal([handler]));
bucket ? bucket.subscribe(handler) : this.events.set(event, new Signal([handler]));
return () => this.unsubscribe(event, handler);

@@ -52,9 +52,13 @@ };

/**
* Adds a handler that will be called at most once
* Adds a handler that will be called at most once.
*
* @returns unsubscribe fn
*/
this.once = (event, handler) => {
this.off(event, handler);
const bucket = this.emitOnce.get(event);
bucket ? bucket.add(handler) : this.emitOnce.set(event, new Signal([handler]));
let bucket = this.events.get(event);
if (!bucket) {
bucket = new Signal();
this.events.set(event, bucket);
}
bucket.once(handler);
return () => this.unsubscribe(event, handler);

@@ -66,8 +70,7 @@ };

this.unsubscribe = (event, handler) => {
let bucket = this.events.get(event);
bucket === null || bucket === void 0 ? void 0 : bucket.delete(handler);
(bucket === null || bucket === void 0 ? void 0 : bucket.size) === 0 && this.events.delete(event);
bucket = this.emitOnce.get(event);
bucket === null || bucket === void 0 ? void 0 : bucket.delete(handler);
(bucket === null || bucket === void 0 ? void 0 : bucket.size) === 0 && this.events.delete(event);
const bucket = this.events.get(event);
bucket === null || bucket === void 0 ? void 0 : bucket.unsubscribe(handler);
if ((bucket === null || bucket === void 0 ? void 0 : bucket.size) === 0) {
this.events.delete(event);
}
};

@@ -84,3 +87,2 @@ /**

this.events.delete(event);
this.emitOnce.delete(event);
};

@@ -91,4 +93,4 @@ /**

this.clear = () => {
this.events.forEach((bucket) => bucket.clear());
this.events = new Map();
this.emitOnce = new Map();
};

@@ -101,6 +103,4 @@ /**

this.notify = (event, data) => {
var _a, _b;
var _a;
(_a = this.events.get(event)) === null || _a === void 0 ? void 0 : _a.notify(data);
(_b = this.emitOnce.get(event)) === null || _b === void 0 ? void 0 : _b.notify(data);
this.emitOnce.delete(event);
};

@@ -107,0 +107,0 @@ /**

@@ -33,14 +33,26 @@ export type Listener<T> = (data: T) => void;

*/
export declare class Signal<T> extends Set<Listener<T>> {
private onceHandlers;
export declare class Signal<T> {
private handlers;
constructor(handlers?: Listener<T>[]);
/**
* Subscribe a notification callback
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
subscribe: (handler: Listener<T>) => void;
/**
* Subscribe to only the next notification
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
once: (handler: Listener<T>) => void;
/**
* @returns true if a listener is subscribed
*/
has(value: Listener<T>): boolean;
/**
* Unsubscribe an existing callback
*/
unsubscribe: (handler: Listener<T>) => void;
get size(): number;
/**

@@ -47,0 +59,0 @@ * Notify all subscribers with arg data

@@ -32,15 +32,30 @@ /**

*/
export class Signal extends Set {
constructor() {
super(...arguments);
this.onceHandlers = new Set();
export class Signal {
constructor(handlers) {
this.handlers = new Map();
/**
* Subscribe a notification callback
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
this.subscribe = (handler) => {
this.add(handler);
if (this.handlers.get(handler) !== true) {
this.handlers.set(handler, false);
}
else {
throw new Error(`handler already exists as "once" listener`);
}
};
/**
* Subscribe to only the next notification
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
this.once = (handler) => {
this.onceHandlers.add(handler);
if (this.handlers.get(handler) !== false) {
this.handlers.set(handler, true);
}
else {
throw new Error(`handler already exists as persistent listener`);
}
};

@@ -51,4 +66,3 @@ /**

this.unsubscribe = (handler) => {
this.onceHandlers.delete(handler);
this.delete(handler);
this.handlers.delete(handler);
};

@@ -59,16 +73,24 @@ /**

this.notify = (data) => {
for (const handler of this) {
for (const [handler, isOnce] of this.handlers) {
handler(data);
if (isOnce) {
this.handlers.delete(handler);
}
}
for (const handler of this.onceHandlers) {
handler(data);
this.onceHandlers.delete(handler);
}
};
handlers === null || handlers === void 0 ? void 0 : handlers.forEach((handler) => this.subscribe(handler));
}
/**
* @returns true if a listener is subscribed
*/
has(value) {
return this.handlers.has(value);
}
get size() {
return this.handlers.size;
}
clear() {
super.clear();
this.onceHandlers.clear();
this.handlers.clear();
}
}
//# sourceMappingURL=signal.js.map
{
"name": "@wixc3/patterns",
"version": "15.3.1",
"version": "16.0.0",
"description": "A utility for saving objects to be disposed",

@@ -21,5 +21,5 @@ "main": "dist/cjs/index.js",

"dependencies": {
"@wixc3/common": "^15.1.1",
"@wixc3/common": "^16.0.0",
"promise-assist": "^2.0.1"
}
}

@@ -29,3 +29,2 @@ import { Signal } from './signal';

protected events = new Map<EventId, Signal<any>>();
protected emitOnce = new Map<EventId, Signal<any>>();

@@ -40,2 +39,3 @@ /**

* Subscribe a handler for event
*
* @returns unsubscribe fn

@@ -45,3 +45,3 @@ */

const bucket = this.events.get(event);
bucket ? bucket.add(handler) : this.events.set(event, new Signal([handler]));
bucket ? bucket.subscribe(handler) : this.events.set(event, new Signal([handler]));
return () => this.unsubscribe(event, handler);

@@ -56,9 +56,14 @@ };

/**
* Adds a handler that will be called at most once
* Adds a handler that will be called at most once.
*
* @returns unsubscribe fn
*/
once = <Event extends EventId>(event: Event, handler: (data: Events[Event]) => void) => {
this.off(event, handler);
const bucket = this.emitOnce.get(event);
bucket ? bucket.add(handler) : this.emitOnce.set(event, new Signal([handler]));
let bucket = this.events.get(event);
if (!bucket) {
bucket = new Signal();
this.events.set(event, bucket);
}
bucket.once(handler);
return () => this.unsubscribe(event, handler);

@@ -71,8 +76,7 @@ };

unsubscribe = <Event extends EventId>(event: Event, handler: (data: Events[Event]) => void) => {
let bucket = this.events.get(event);
bucket?.delete(handler);
bucket?.size === 0 && this.events.delete(event);
bucket = this.emitOnce.get(event);
bucket?.delete(handler);
bucket?.size === 0 && this.events.delete(event);
const bucket = this.events.get(event);
bucket?.unsubscribe(handler);
if (bucket?.size === 0) {
this.events.delete(event);
}
};

@@ -91,3 +95,2 @@

this.events.delete(event);
this.emitOnce.delete(event);
};

@@ -99,4 +102,4 @@

clear = () => {
this.events.forEach((bucket) => bucket.clear());
this.events = new Map<EventId, Signal<any>>();
this.emitOnce = new Map<EventId, Signal<any>>();
};

@@ -111,4 +114,2 @@

this.events.get(event)?.notify(data);
this.emitOnce.get(event)?.notify(data);
this.emitOnce.delete(event);
};

@@ -115,0 +116,0 @@

export type Listener<T> = (data: T) => void;
type IS_ONCE = boolean;

@@ -34,22 +35,52 @@ /**

*/
export class Signal<T> extends Set<Listener<T>> {
private onceHandlers = new Set<Listener<T>>();
export class Signal<T> {
private handlers = new Map<Listener<T>, IS_ONCE>();
constructor(handlers?: Listener<T>[]) {
handlers?.forEach((handler) => this.subscribe(handler));
}
/**
* Subscribe a notification callback
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
subscribe = (handler: Listener<T>) => {
this.add(handler);
if (this.handlers.get(handler) !== true) {
this.handlers.set(handler, false);
} else {
throw new Error(`handler already exists as "once" listener`);
}
};
/**
* Subscribe to only the next notification
*
* @param handler - Will be executed with a data arg when a notification occurs
*/
once = (handler: Listener<T>) => {
this.onceHandlers.add(handler);
if (this.handlers.get(handler) !== false) {
this.handlers.set(handler, true);
} else {
throw new Error(`handler already exists as persistent listener`);
}
};
/**
* @returns true if a listener is subscribed
*/
has(value: Listener<T>): boolean {
return this.handlers.has(value);
}
/**
* Unsubscribe an existing callback
*/
unsubscribe = (handler: Listener<T>) => {
this.onceHandlers.delete(handler);
this.delete(handler);
this.handlers.delete(handler);
};
get size(): number {
return this.handlers.size;
}
/**

@@ -59,15 +90,13 @@ * Notify all subscribers with arg data

notify = (data: T) => {
for (const handler of this) {
for (const [handler, isOnce] of this.handlers) {
handler(data);
if (isOnce) {
this.handlers.delete(handler);
}
}
for (const handler of this.onceHandlers) {
handler(data);
this.onceHandlers.delete(handler);
}
};
override clear(): void {
super.clear();
this.onceHandlers.clear();
clear(): void {
this.handlers.clear();
}
}

@@ -39,2 +39,15 @@ import chai, { expect } from 'chai';

});
it('notifies handlers in the order they were subscribed', () => {
const listener1 = stub();
const listener2 = stub();
const listener3 = stub();
signal.subscribe(listener1);
signal.once(listener2);
signal.subscribe(listener3);
signal.subscribe(listener1); // should have no effect
signal.notify({ a: 'value', b: 5 });
expect(listener1.calledBefore(listener2), 'listener1 called before listener2').to.eql(true);
expect(listener2.calledBefore(listener3), 'listener2 called before listener3').to.eql(true);
});
describe('once', () => {

@@ -64,2 +77,10 @@ it('calls "once" listeners only one time', () => {

});
it('throws when a handler changes from "once" to persistent', () => {
signal.once(listener);
expect(() => signal.subscribe(listener)).to.throw(`handler already exists as "once" listener`);
});
it('throws when a handler changes from persistent to "once"', () => {
signal.subscribe(listener);
expect(() => signal.once(listener)).to.throw(`handler already exists as persistent listener`);
});
});

@@ -66,0 +87,0 @@ it(`doesn't call listeners after "unsubscribe"`, () => {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc