@alwatr/signal 9.32.0 → 9.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,7 +47,7 @@ export class DerivedSignal<S, T> implements IReadonlySignal<T> {
47
47
  }
48
48
 
49
49
  untilNext(): Promise<T> {
50
- this.logger_.logMethod?.('untilNext');
50
+ DEV_MODE && this.logger_.logMethod?.('untilNext');
51
51
  this.checkDestroyed__();
52
52
  return new Promise<T>((resolve) => {
53
53
  this.subscribe(
@@ -68,7 +68,7 @@ export class DerivedSignal<S, T> implements IReadonlySignal<T> {
68
68
  * @returns The current projected value.
69
69
  */
70
70
  public get(): T {
71
- this.logger_.logMethod?.('get');
71
+ DEV_MODE && this.logger_.logMethod?.('get');
72
72
  this.checkDestroyed__();
73
73
  if (this.activeConsumerCount__ === 0) {
74
74
  return this.config_.projector(this.config_.source.get());
@@ -94,13 +94,13 @@ export class DerivedSignal<S, T> implements IReadonlySignal<T> {
94
94
  * @returns Unsubscribe handle object.
95
95
  */
96
96
  public subscribe(callback: ListenerCallback<T>, options?: SubscribeOptions): SubscribeResult {
97
- this.logger_.logMethod?.('subscribe');
97
+ DEV_MODE && this.logger_.logMethod?.('subscribe');
98
98
  this.checkDestroyed__();
99
99
  this.activeConsumerCount__++;
100
100
 
101
101
  // Wake-up phase: if this is the first active consumer, dynamically clamp to the upstream core source
102
102
  if (this.activeConsumerCount__ === 1) {
103
- this.logger_.logMethod?.('wakeUp_');
103
+ DEV_MODE && this.logger_.logMethod?.('wakeUp_');
104
104
  this.internalSignal_ = new StateSignal<T>({
105
105
  name: `derived-internal:${this.name}`,
106
106
  initialValue: this.config_.projector(this.config_.source.get()),
@@ -117,14 +117,14 @@ export class DerivedSignal<S, T> implements IReadonlySignal<T> {
117
117
 
118
118
  return {
119
119
  unsubscribe: () => {
120
- this.logger_.logMethod?.('unsubscribe');
120
+ DEV_MODE && this.logger_.logMethod?.('unsubscribe');
121
121
 
122
122
  sub.unsubscribe();
123
123
  this.activeConsumerCount__--;
124
124
 
125
125
  // Hibernation phase: unlink tracking dependencies when view elements clear out to preserve processing cycles
126
126
  if (this.activeConsumerCount__ === 0 && this.sourceSubscription__) {
127
- this.logger_.logMethod?.('sleepCleanup_');
127
+ DEV_MODE && this.logger_.logMethod?.('sleepCleanup_');
128
128
  this.sourceSubscription__.unsubscribe();
129
129
  this.sourceSubscription__ = undefined;
130
130
  this.internalSignal_?.destroy();
@@ -138,7 +138,7 @@ export class DerivedSignal<S, T> implements IReadonlySignal<T> {
138
138
  * Destroys the derived signal and unsubscribes from the source signal if currently awake.
139
139
  */
140
140
  public destroy(): void {
141
- this.logger_.logMethod?.('destroy');
141
+ DEV_MODE && this.logger_.logMethod?.('destroy');
142
142
  if (this.isDestroyed) return;
143
143
 
144
144
  if (this.sourceSubscription__) {
@@ -158,7 +158,7 @@ export class DerivedSignal<S, T> implements IReadonlySignal<T> {
158
158
  * @throws {Error} If destroyed.
159
159
  */
160
160
  private checkDestroyed__(): void {
161
- this.logger_.logMethod?.('checkDestroyed__');
161
+ DEV_MODE && this.logger_.logMethod?.('checkDestroyed__');
162
162
  if (this.isDestroyed) {
163
163
  throw new Error(`Cannot interact with a destroyed signal (id: ${this.name})`);
164
164
  }
@@ -98,18 +98,18 @@ export class EffectSignal implements IEffectSignal {
98
98
  this.logger_ = createLogger(`effect-signal:${this.name}`);
99
99
  this.scheduleExecution_ = this.scheduleExecution_.bind(this);
100
100
 
101
- this.logger_.logMethod?.('constructor');
101
+ DEV_MODE && this.logger_.logMethod?.('constructor');
102
102
 
103
103
  // Subscribe to all dependencies. We don't need the previous value,
104
104
  // as the `runImmediately` option controls the initial execution.
105
105
  for (const signal of config_.deps) {
106
- this.logger_.logStep?.('constructor', 'subscribing_to_dependency', {signal: signal.name});
106
+ DEV_MODE && this.logger_.logStep?.('constructor', 'subscribing_to_dependency', {signal: signal.name});
107
107
  this.dependencySubscriptions__.push(signal.subscribe(this.scheduleExecution_, {receivePrevious: false}));
108
108
  }
109
109
 
110
110
  // Run the effect immediately if requested.
111
111
  if (config_.runImmediately === true) {
112
- this.logger_.logStep?.('constructor', 'scheduling_initial_execution');
112
+ DEV_MODE && this.logger_.logStep?.('constructor', 'scheduling_initial_execution');
113
113
  // We don't need to await this, let it run in the background.
114
114
  void this.scheduleExecution_();
115
115
  }
@@ -126,15 +126,15 @@ export class EffectSignal implements IEffectSignal {
126
126
  * @returns A promise that resolves when the execution schedules or runs.
127
127
  */
128
128
  protected async scheduleExecution_(): Promise<void> {
129
- this.logger_.logMethod?.('scheduleExecution_');
129
+ DEV_MODE && this.logger_.logMethod?.('scheduleExecution_');
130
130
 
131
131
  if (this.isDestroyed__) {
132
- this.logger_.incident?.('scheduleExecution_', 'schedule_execution_on_destroyed_signal');
132
+ DEV_MODE && this.logger_.incident?.('scheduleExecution_', 'schedule_execution_on_destroyed_signal');
133
133
  return;
134
134
  }
135
135
  if (this.isRunning__) {
136
136
  // If an execution is already scheduled, do nothing.
137
- this.logger_.logStep?.('scheduleExecution_', 'skipped_because_already_running');
137
+ DEV_MODE && this.logger_.logStep?.('scheduleExecution_', 'skipped_because_already_running');
138
138
  return;
139
139
  }
140
140
 
@@ -144,12 +144,12 @@ export class EffectSignal implements IEffectSignal {
144
144
  // Wait for the next macrotask to batch simultaneous updates.
145
145
  await delay.nextMicrotask();
146
146
  if (this.isDestroyed__) {
147
- this.logger_.incident?.('scheduleExecution_', 'destroyed_during_delay');
147
+ DEV_MODE && this.logger_.incident?.('scheduleExecution_', 'destroyed_during_delay');
148
148
  this.isRunning__ = false;
149
149
  return;
150
150
  }
151
151
 
152
- this.logger_.logStep?.('scheduleExecution_', 'executing_effect');
152
+ DEV_MODE && this.logger_.logStep?.('scheduleExecution_', 'executing_effect');
153
153
  this.config_.run();
154
154
  } catch (err) {
155
155
  this.logger_.error('scheduleExecution_', 'effect_failed', err);
@@ -167,10 +167,10 @@ export class EffectSignal implements IEffectSignal {
167
167
  * Failure to call `destroy()` will result in memory leaks and potentially unwanted side effects.
168
168
  */
169
169
  public destroy(): void {
170
- this.logger_.logMethod?.('destroy');
170
+ DEV_MODE && this.logger_.logMethod?.('destroy');
171
171
 
172
172
  if (this.isDestroyed__) {
173
- this.logger_.incident?.('destroy', 'already_destroyed');
173
+ DEV_MODE && this.logger_.incident?.('destroy', 'already_destroyed');
174
174
  return;
175
175
  }
176
176
 
@@ -46,7 +46,7 @@ export class EventSignal<T = void> extends SignalBase<T> implements IBaseSignal<
46
46
  constructor(config: SignalConfig) {
47
47
  super(config);
48
48
  this.logger_ = createLogger(`event_signal:${this.name}`);
49
- this.logger_.logMethod?.('constructor');
49
+ DEV_MODE && this.logger_.logMethod?.('constructor');
50
50
  }
51
51
 
52
52
  /**
@@ -58,7 +58,7 @@ export class EventSignal<T = void> extends SignalBase<T> implements IBaseSignal<
58
58
  * @param payload The data payload to send with the event.
59
59
  */
60
60
  public dispatch(payload: T): void {
61
- this.logger_.logMethodArgs?.('dispatch', {payload});
61
+ DEV_MODE && this.logger_.logMethodArgs?.('dispatch', {payload});
62
62
  this.checkDestroyed_();
63
63
  // Dispatch as a microtask to ensure consistent, non-blocking behavior.
64
64
  queueMicrotask(() => this.notify_(payload));
@@ -89,7 +89,7 @@ export class PersistentStateSignal<T> extends StateSignal<T> {
89
89
  */
90
90
  private readonly windowPageShowListener_ = (event: PageTransitionEvent): void => {
91
91
  if (event.persisted) {
92
- this.logger_.logMethod?.('windowPageShowListener_//restored_from_bfcache');
92
+ DEV_MODE && this.logger_.logMethod?.('windowPageShowListener_//restored_from_bfcache');
93
93
  const value = this.storageProvider__.read();
94
94
  if (value !== null) {
95
95
  this.set(value);
@@ -129,7 +129,7 @@ export class PersistentStateSignal<T> extends StateSignal<T> {
129
129
  onDestroy,
130
130
  });
131
131
 
132
- this.logger_.logMethodArgs?.('constructor', config);
132
+ DEV_MODE && this.logger_.logMethodArgs?.('constructor', config);
133
133
 
134
134
  this.storageProvider__ = storageProvider;
135
135
 
@@ -157,7 +157,7 @@ export class PersistentStateSignal<T> extends StateSignal<T> {
157
157
  * @private
158
158
  */
159
159
  private syncStorage__(newValue: T): void {
160
- this.logger_.logMethodArgs?.('syncStorage__', newValue);
160
+ DEV_MODE && this.logger_.logMethodArgs?.('syncStorage__', newValue);
161
161
  this.storageProvider__.write(newValue);
162
162
  }
163
163
 
@@ -167,7 +167,7 @@ export class PersistentStateSignal<T> extends StateSignal<T> {
167
167
  */
168
168
  public remove(): void {
169
169
  this.checkDestroyed_();
170
- this.logger_.logMethod?.('remove');
170
+ DEV_MODE && this.logger_.logMethod?.('remove');
171
171
  // Remove from storage.
172
172
  this.storageProvider__.remove();
173
173
  }
@@ -176,7 +176,7 @@ export class PersistentStateSignal<T> extends StateSignal<T> {
176
176
  * Overrides the destroy method to also clean up the storage sync subscription and event listeners.
177
177
  */
178
178
  public override destroy(): void {
179
- this.logger_.logMethod?.('destroy');
179
+ DEV_MODE && this.logger_.logMethod?.('destroy');
180
180
  if (typeof globalThis.removeEventListener === 'function') {
181
181
  globalThis.removeEventListener('pagehide', this.windowPageHideListener_);
182
182
  globalThis.removeEventListener('pageshow', this.windowPageShowListener_);
@@ -99,7 +99,7 @@ export class SessionStateSignal<T> extends StateSignal<T> {
99
99
  */
100
100
  private readonly windowPageShowListener__ = (event: PageTransitionEvent): void => {
101
101
  if (event.persisted) {
102
- this.logger_.logMethod?.('windowPageShowListener__//restored_from_bfcache');
102
+ DEV_MODE && this.logger_.logMethod?.('windowPageShowListener__//restored_from_bfcache');
103
103
  const value = this.storageProvider__.read();
104
104
  if (value !== null) {
105
105
  this.set(value);
@@ -129,7 +129,7 @@ export class SessionStateSignal<T> extends StateSignal<T> {
129
129
  onDestroy,
130
130
  });
131
131
 
132
- this.logger_.logMethodArgs?.('constructor', config);
132
+ DEV_MODE && this.logger_.logMethodArgs?.('constructor', config);
133
133
 
134
134
  this.storageProvider__ = storageProvider;
135
135
 
@@ -157,7 +157,7 @@ export class SessionStateSignal<T> extends StateSignal<T> {
157
157
  * @private
158
158
  */
159
159
  private syncStorage__(newValue: T): void {
160
- this.logger_.logMethodArgs?.('syncStorage__', newValue);
160
+ DEV_MODE && this.logger_.logMethodArgs?.('syncStorage__', newValue);
161
161
  this.storageProvider__.write(newValue);
162
162
  }
163
163
 
@@ -175,7 +175,7 @@ export class SessionStateSignal<T> extends StateSignal<T> {
175
175
  */
176
176
  public remove(): void {
177
177
  this.checkDestroyed_();
178
- this.logger_.logMethod?.('remove');
178
+ DEV_MODE && this.logger_.logMethod?.('remove');
179
179
  this.storageProvider__.remove();
180
180
  }
181
181
 
@@ -192,7 +192,7 @@ export class SessionStateSignal<T> extends StateSignal<T> {
192
192
  * ```
193
193
  */
194
194
  public override destroy(): void {
195
- this.logger_.logMethod?.('destroy');
195
+ DEV_MODE && this.logger_.logMethod?.('destroy');
196
196
  if (typeof globalThis.removeEventListener === 'function') {
197
197
  globalThis.removeEventListener('pagehide', this.windowPageHideListener__);
198
198
  globalThis.removeEventListener('pageshow', this.windowPageShowListener__);
@@ -74,10 +74,10 @@ export abstract class SignalBase<T> {
74
74
  * @protected
75
75
  */
76
76
  protected removeObserver_(observer: Observer_<T>): void {
77
- this.logger_.logMethod?.('removeObserver_');
77
+ DEV_MODE && this.logger_.logMethod?.('removeObserver_');
78
78
 
79
79
  if (this.isDestroyed__) {
80
- this.logger_.incident?.('removeObserver_', 'remove_observer_on_destroyed_signal');
80
+ DEV_MODE && this.logger_.incident?.('removeObserver_', 'remove_observer_on_destroyed_signal');
81
81
  return;
82
82
  }
83
83
 
@@ -104,7 +104,7 @@ export abstract class SignalBase<T> {
104
104
  * @returns An object with an `unsubscribe` method to remove the subscription.
105
105
  */
106
106
  public subscribe(callback: ListenerCallback<T>, options?: SubscribeOptions): SubscribeResult {
107
- this.logger_.logMethodArgs?.('subscribe.base', options);
107
+ DEV_MODE && this.logger_.logMethodArgs?.('subscribe.base', options);
108
108
  this.checkDestroyed_();
109
109
 
110
110
  const observer: Observer_<T> = {callback, options};
@@ -131,10 +131,10 @@ export abstract class SignalBase<T> {
131
131
  * @protected
132
132
  */
133
133
  protected notify_(value: T): void {
134
- this.logger_.logMethodArgs?.('notify_', value);
134
+ DEV_MODE && this.logger_.logMethodArgs?.('notify_', value);
135
135
 
136
136
  if (this.isDestroyed__) {
137
- this.logger_.incident?.('notify_', 'notify_on_destroyed_signal');
137
+ DEV_MODE && this.logger_.incident?.('notify_', 'notify_on_destroyed_signal');
138
138
  return;
139
139
  }
140
140
 
@@ -187,7 +187,7 @@ export abstract class SignalBase<T> {
187
187
  * @returns A Promise that resolves with the next value dispatched by the signal.
188
188
  */
189
189
  public untilNext(): Promise<T> {
190
- this.logger_.logMethod?.('untilNext');
190
+ DEV_MODE && this.logger_.logMethod?.('untilNext');
191
191
  this.checkDestroyed_();
192
192
  return new Promise((resolve, reject) => {
193
193
  this.pendingRejects__ ??= new Set();
@@ -212,9 +212,9 @@ export abstract class SignalBase<T> {
212
212
  * invokes the optional `onDestroy` config hook, and breaks internal references to facilitate GC.
213
213
  */
214
214
  public destroy(): void {
215
- this.logger_.logMethod?.('destroy');
215
+ DEV_MODE && this.logger_.logMethod?.('destroy');
216
216
  if (this.isDestroyed__) {
217
- this.logger_.incident?.('destroy_', 'double_destroy_attempt');
217
+ DEV_MODE && this.logger_.incident?.('destroy_', 'double_destroy_attempt');
218
218
  return;
219
219
  }
220
220
  this.isDestroyed__ = true;
@@ -79,7 +79,7 @@ export class StateSignal<T> extends SignalBase<T> implements IReadonlySignal<T>
79
79
  });
80
80
  this.logger_ = createLogger(`state_signal:${this.name}`);
81
81
  this.value__ = config.initialValue;
82
- this.logger_.logMethodArgs?.('constructor', {initialValue: this.value__});
82
+ DEV_MODE && this.logger_.logMethodArgs?.('constructor', {initialValue: this.value__});
83
83
  }
84
84
 
85
85
  /**
@@ -113,7 +113,7 @@ export class StateSignal<T> extends SignalBase<T> implements IReadonlySignal<T>
113
113
  * mySignal.set({ ...mySignal.get(), property: 'new-value' });
114
114
  */
115
115
  public set(newValue: T): void {
116
- this.logger_.logMethodArgs?.('set', {newValue});
116
+ DEV_MODE && this.logger_.logMethodArgs?.('set', {newValue});
117
117
 
118
118
  // For primitives (including null), do not notify if the value is the same.
119
119
  if (Object.is(this.value__, newValue) && (typeof newValue !== 'object' || newValue === null)) {
@@ -132,7 +132,7 @@ export class StateSignal<T> extends SignalBase<T> implements IReadonlySignal<T>
132
132
  * Notification is queued as a microtask for batching.
133
133
  */
134
134
  public notifyChange(): void {
135
- this.logger_.logMethod?.('notifyChange');
135
+ DEV_MODE && this.logger_.logMethod?.('notifyChange');
136
136
  this.checkDestroyed_();
137
137
 
138
138
  this.notifyVersion__++;
@@ -163,7 +163,7 @@ export class StateSignal<T> extends SignalBase<T> implements IReadonlySignal<T>
163
163
  public update(updater: (previousValue: T) => T): void {
164
164
  this.checkDestroyed_();
165
165
  const newValue = updater(this.value__);
166
- this.logger_.logMethodFull?.('update', this.value__, newValue);
166
+ DEV_MODE && this.logger_.logMethodFull?.('update', this.value__, newValue);
167
167
  this.set(newValue);
168
168
  }
169
169
 
@@ -178,7 +178,7 @@ export class StateSignal<T> extends SignalBase<T> implements IReadonlySignal<T>
178
178
  * @returns An object with an `unsubscribe` method to remove the listener.
179
179
  */
180
180
  public override subscribe(callback: ListenerCallback<T>, options: SubscribeOptions = {}): SubscribeResult {
181
- this.logger_.logMethodArgs?.('subscribe', options);
181
+ DEV_MODE && this.logger_.logMethodArgs?.('subscribe', options);
182
182
  this.checkDestroyed_();
183
183
 
184
184
  const result = super.subscribe(callback, options);
@@ -189,7 +189,7 @@ export class StateSignal<T> extends SignalBase<T> implements IReadonlySignal<T>
189
189
  const subscribeVersion = this.notifyVersion__;
190
190
 
191
191
  queueMicrotask((): void => {
192
- this.logger_.logStep?.('subscribe', 'immediate_callback');
192
+ DEV_MODE && this.logger_.logStep?.('subscribe', 'immediate_callback');
193
193
  if (this.notifyVersion__ !== subscribeVersion) return; // A notification occurred after subscribing, so skip the immediate callback.
194
194
  if (options.once) {
195
195
  result.unsubscribe();