@doeixd/machine 0.0.23 → 1.0.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.
Files changed (50) hide show
  1. package/README.md +101 -65
  2. package/dist/cjs/development/core.js +19 -45
  3. package/dist/cjs/development/core.js.map +3 -3
  4. package/dist/cjs/development/index.js +51 -46
  5. package/dist/cjs/development/index.js.map +4 -4
  6. package/dist/cjs/development/react.js +19 -46
  7. package/dist/cjs/development/react.js.map +3 -3
  8. package/dist/cjs/production/core.js +1 -1
  9. package/dist/cjs/production/index.js +3 -3
  10. package/dist/cjs/production/react.js +1 -1
  11. package/dist/esm/development/core.js +19 -45
  12. package/dist/esm/development/core.js.map +3 -3
  13. package/dist/esm/development/index.js +51 -46
  14. package/dist/esm/development/index.js.map +4 -4
  15. package/dist/esm/development/react.js +19 -46
  16. package/dist/esm/development/react.js.map +3 -3
  17. package/dist/esm/production/core.js +1 -1
  18. package/dist/esm/production/index.js +3 -3
  19. package/dist/esm/production/react.js +1 -1
  20. package/dist/types/actor.d.ts +4 -4
  21. package/dist/types/actor.d.ts.map +1 -1
  22. package/dist/types/context-bound.d.ts +94 -0
  23. package/dist/types/context-bound.d.ts.map +1 -0
  24. package/dist/types/entry-react.d.ts +1 -1
  25. package/dist/types/entry-react.d.ts.map +1 -1
  26. package/dist/types/functional-combinators.d.ts +5 -5
  27. package/dist/types/generators.d.ts +2 -2
  28. package/dist/types/index.d.ts +14 -29
  29. package/dist/types/index.d.ts.map +1 -1
  30. package/dist/types/primitives.d.ts +25 -5
  31. package/dist/types/primitives.d.ts.map +1 -1
  32. package/dist/types/react.d.ts.map +1 -1
  33. package/dist/types/utils.d.ts +22 -22
  34. package/dist/types/utils.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/actor.ts +1 -1
  37. package/src/context-bound.ts +147 -0
  38. package/src/entry-react.ts +9 -2
  39. package/src/functional-combinators.ts +5 -5
  40. package/src/generators.ts +2 -2
  41. package/src/higher-order.ts +2 -2
  42. package/src/index.ts +31 -68
  43. package/src/middleware/time-travel.ts +2 -2
  44. package/src/middleware.ts +2 -2
  45. package/src/multi.ts +4 -4
  46. package/src/primitives.ts +34 -14
  47. package/src/prototype_functional.ts +2 -2
  48. package/src/react.ts +1 -2
  49. package/src/test.ts +7 -7
  50. package/src/utils.ts +31 -31
@@ -5,5 +5,12 @@
5
5
  // Re-export core functionality
6
6
  export * from './core';
7
7
 
8
- // Re-export React-specific functionality
9
- export * from './react';
8
+ // Re-export React-specific functionality (excluding duplicates like Runner)
9
+ export {
10
+ useMachine,
11
+ useMachineSelector,
12
+ useEnsemble,
13
+ createMachineContext,
14
+ useActor,
15
+ useActorSelector,
16
+ } from './react';
@@ -21,7 +21,7 @@ import { createMachine, Machine, BaseMachine, extendTransitions } from './index'
21
21
  * // Define your machine's transitions object
22
22
  * const counterTransitions = {
23
23
  * increment: function(amount: number) {
24
- * return createMachine({ count: this.count + amount }, counterTransitions);
24
+ * return createMachine({ count: this.context.count + amount }, counterTransitions);
25
25
  * }
26
26
  * };
27
27
  *
@@ -103,7 +103,7 @@ export function createTransitionFactory<C extends object>() {
103
103
  * // Start with a basic counter machine
104
104
  * const basicCounter = createMachine({ count: 0 }, {
105
105
  * increment: function() {
106
- * return createMachine({ count: this.count + 1 }, this);
106
+ * return createMachine({ count: this.context.count + 1 }, this);
107
107
  * }
108
108
  * });
109
109
  *
@@ -276,7 +276,7 @@ export function createFunctionalMachine<C extends object>(initialContext: C) {
276
276
  * 1. **Traditional Pattern** (with transitions object):
277
277
  * ```typescript
278
278
  * const machine = state({ count: 0 }, {
279
- * increment() { return createMachine({ count: this.count + 1 }, this); }
279
+ * increment() { return createMachine({ count: this.context.count + 1 }, this); }
280
280
  * });
281
281
  * ```
282
282
  *
@@ -308,8 +308,8 @@ export function createFunctionalMachine<C extends object>(initialContext: C) {
308
308
  * ```typescript
309
309
  * // Traditional pattern
310
310
  * const counter1 = state({ count: 0 }, {
311
- * increment() { return createMachine({ count: this.count + 1 }, this); },
312
- * decrement() { return createMachine({ count: this.count - 1 }, this); }
311
+ * increment() { return createMachine({ count: this.context.count + 1 }, this); },
312
+ * decrement() { return createMachine({ count: this.context.count - 1 }, this); }
313
313
  * });
314
314
  *
315
315
  * // Functional pattern
package/src/generators.ts CHANGED
@@ -58,10 +58,10 @@
58
58
  * ```typescript
59
59
  * const counter = createMachine({ count: 0 }, {
60
60
  * increment: function() {
61
- * return createMachine({ count: this.count + 1 }, this);
61
+ * return createMachine({ count: this.context.count + 1 }, this);
62
62
  * },
63
63
  * add: function(n: number) {
64
- * return createMachine({ count: this.count + n }, this);
64
+ * return createMachine({ count: this.context.count + n }, this);
65
65
  * }
66
66
  * });
67
67
  *
@@ -333,7 +333,7 @@ export function createParallelMachine<
333
333
  for (const key in transitions1) {
334
334
  const transitionFn = (transitions1 as any)[key];
335
335
  combinedTransitions[key] = (...args: any[]) => {
336
- const nextM1 = transitionFn.apply(m1.context, args);
336
+ const nextM1 = transitionFn.apply(m1, args);
337
337
  // Recursively create a new parallel machine with the new M1 state
338
338
  return createParallelMachine(nextM1, m2);
339
339
  };
@@ -343,7 +343,7 @@ export function createParallelMachine<
343
343
  for (const key in transitions2) {
344
344
  const transitionFn = (transitions2 as any)[key];
345
345
  combinedTransitions[key] = (...args: any[]) => {
346
- const nextM2 = transitionFn.apply(m2.context, args);
346
+ const nextM2 = transitionFn.apply(m2, args);
347
347
  // Recursively create a new parallel machine with the new M2 state
348
348
  return createParallelMachine(m1, nextM2);
349
349
  };
package/src/index.ts CHANGED
@@ -198,12 +198,12 @@ export type Event<M extends BaseMachine<any>> = {
198
198
  * const counterTransitions = {
199
199
  * increment() {
200
200
  * // `this` is now fully typed!
201
- * // IntelliSense knows `this.count` is a number and
201
+ * // IntelliSense knows `this.context.count` is a number and
202
202
  * // `this.transitions.add` is a function.
203
- * return createMachine({ count: this.count + 1 }, this.transitions);
203
+ * return createMachine({ count: this.context.count + 1 }, this.transitions);
204
204
  * },
205
205
  * add(n: number) {
206
- * return createMachine({ count: this.count + n }, this.transitions);
206
+ * return createMachine({ count: this.context.count + n }, this.transitions);
207
207
  * },
208
208
  * // ❌ TypeScript will immediately throw a compile error on the next line
209
209
  * // because the return type 'string' does not satisfy 'Machine<any>'.
@@ -220,7 +220,7 @@ export type Event<M extends BaseMachine<any>> = {
220
220
  * }
221
221
  */
222
222
  export type TransitionsFor<C extends object, T extends Record<string, any>> = {
223
- [K in keyof T]: (this: C & { transitions: T }, ...args: Parameters<T[K] extends (...a: infer A) => any ? (...a: A) => any : never>) => Machine<any, any>;
223
+ [K in keyof T]: (this: Machine<C, T>, ...args: Parameters<T[K] extends (...a: infer A) => any ? (...a: A) => any : never>) => Machine<any, any>;
224
224
  };
225
225
 
226
226
  /**
@@ -228,7 +228,7 @@ export type TransitionsFor<C extends object, T extends Record<string, any>> = {
228
228
  * type-checking for standalone asynchronous transition objects.
229
229
  */
230
230
  export type AsyncTransitionsFor<C extends object, T extends Record<string, any>> = {
231
- [K in keyof T]: (this: C & { transitions: T }, ...args: Parameters<T[K] extends (...a: infer A) => any ? (...a: A) => any : never>) => MaybePromise<AsyncMachine<any, any>>;
231
+ [K in keyof T]: (this: Machine<C, T>, ...args: Parameters<T[K] extends (...a: infer A) => any ? (...a: A) => any : never>) => MaybePromise<AsyncMachine<any, any>>;
232
232
  };
233
233
 
234
234
  /**
@@ -345,24 +345,26 @@ export type BindTransitions<T> = {
345
345
  * @param factory - A function that receives a `transition` helper and returns the transitions object.
346
346
  * @returns A new machine instance.
347
347
  */
348
- export function createMachine<C extends object, T extends Record<string, (this: C, ...args: any[]) => any> = Record<string, (this: C, ...args: any[]) => any>>(
348
+ export function createMachine<C extends object, T extends Record<string, (this: Machine<C, any>, ...args: any[]) => any> = Record<string, (this: Machine<C, any>, ...args: any[]) => any>>(
349
349
  context: C,
350
350
  factory: (transition: (newContext: C) => Machine<C, any>) => T
351
- ): Machine<C, BindTransitions<T>>;
351
+ ): Machine<C, T>;
352
352
 
353
353
  /**
354
354
  * Creates a synchronous state machine from a context and transition functions.
355
355
  * This is the core factory for the functional approach.
356
+ * Transitions receive the full machine as `this`, allowing them to access
357
+ * `this.context` and call other transitions via `this.otherTransition()`.
356
358
  *
357
359
  * @template C - The context object type.
358
360
  * @param context - The initial state context.
359
361
  * @param fns - An object containing transition function definitions.
360
362
  * @returns A new machine instance.
361
363
  */
362
- export function createMachine<C extends object, T extends Record<string, (this: { context: C } & T, ...args: any[]) => any> & { context?: any }>(
364
+ export function createMachine<C extends object, T extends Record<string, (this: Machine<C, T>, ...args: any[]) => any> & { context?: any }>(
363
365
  context: C,
364
366
  fns: T
365
- ): { context: C } & T;
367
+ ): Machine<C, T>;
366
368
 
367
369
  /**
368
370
  * Creates a synchronous state machine by copying context and transitions from an existing machine.
@@ -379,45 +381,15 @@ export function createMachine<C extends object, M extends BaseMachine<C>>(
379
381
  machine: M
380
382
  ): Machine<C, Transitions<M>>;
381
383
 
382
- /**
383
- * Creates a synchronous state machine from a context and transition functions that expect `this` to be the context object.
384
- * This is used internally by utilities that need to bind transitions to context objects.
385
- *
386
- * @template C - The context object type.
387
- * @param context - The initial state context.
388
- * @param fns - An object containing transition function definitions that expect `this` to be the context.
389
- * @returns A new machine instance.
390
- */
391
- export function createMachine<C extends object, T extends Record<string, (this: C, ...args: any[]) => any>>(
392
- context: C,
393
- fns: T
394
- ): Machine<C, T>;
395
-
396
384
  export function createMachine(context: any, fnsOrFactory: any): any {
397
385
  if (typeof fnsOrFactory === 'function') {
398
386
  let transitions: any;
399
387
  const transition = (newContext: any) => {
400
- const machine = createMachine(newContext, transitions);
401
- // Re-bind transitions to the new context
402
- const boundTransitions = Object.fromEntries(
403
- Object.entries(transitions).map(([key, fn]) => [
404
- key,
405
- (fn as Function).bind(newContext)
406
- ])
407
- );
408
- return Object.assign(machine, boundTransitions);
388
+ return createMachine(newContext, transitions);
409
389
  };
410
390
  transitions = fnsOrFactory(transition);
411
391
 
412
- // Bind transitions to initial context
413
- const boundTransitions = Object.fromEntries(
414
- Object.entries(transitions).map(([key, fn]) => [
415
- key,
416
- (fn as Function).bind(context)
417
- ])
418
- );
419
-
420
- return Object.assign({ context }, boundTransitions);
392
+ return Object.assign({ context }, transitions);
421
393
  }
422
394
 
423
395
  // If fns is a machine (has context property), extract just the transition functions
@@ -425,10 +397,6 @@ export function createMachine(context: any, fnsOrFactory: any): any {
425
397
  Object.entries(fnsOrFactory).filter(([key]) => key !== 'context')
426
398
  ) : fnsOrFactory;
427
399
 
428
- // For normal object transitions, we might also need binding if they use `this`
429
- // But existing code expects `this` to be the machine (context + transitions).
430
- // The new API expects `this` to be just context.
431
-
432
400
  const machine = Object.assign({ context }, transitions);
433
401
  return machine;
434
402
  }
@@ -481,27 +449,11 @@ export function createAsyncMachine(context: any, fnsOrFactory: any): any {
481
449
  if (typeof fnsOrFactory === 'function') {
482
450
  let transitions: any;
483
451
  const transition = (newContext: any) => {
484
- const machine = createAsyncMachine(newContext, transitions);
485
- // Re-bind transitions to the new context
486
- const boundTransitions = Object.fromEntries(
487
- Object.entries(transitions).map(([key, fn]) => [
488
- key,
489
- (fn as Function).bind(newContext)
490
- ])
491
- );
492
- return Object.assign(machine, boundTransitions);
452
+ return createAsyncMachine(newContext, transitions);
493
453
  };
494
454
  transitions = fnsOrFactory(transition);
495
455
 
496
- // Bind transitions to initial context
497
- const boundTransitions = Object.fromEntries(
498
- Object.entries(transitions).map(([key, fn]) => [
499
- key,
500
- (fn as Function).bind(context)
501
- ])
502
- );
503
-
504
- return Object.assign({ context }, boundTransitions);
456
+ return Object.assign({ context }, transitions);
505
457
  }
506
458
 
507
459
  // If fns is a machine (has context property), extract just the transition functions
@@ -682,14 +634,14 @@ export function extendTransitions<
682
634
  * // Define two independent machines
683
635
  * const createCounter = (initial: number) =>
684
636
  * createMachine({ count: initial }, {
685
- * increment: function() { return createMachine({ count: this.count + 1 }, this); },
686
- * decrement: function() { return createMachine({ count: this.count - 1 }, this); }
637
+ * increment: function() { return createMachine({ count: this.context.count + 1 }, this); },
638
+ * decrement: function() { return createMachine({ count: this.context.count - 1 }, this); }
687
639
  * });
688
640
  *
689
641
  * const createLogger = () =>
690
642
  * createMachine({ logs: [] as string[] }, {
691
643
  * log: function(message: string) {
692
- * return createMachine({ logs: [...this.logs, message] }, this);
644
+ * return createMachine({ logs: [...this.context.logs, message] }, this);
693
645
  * },
694
646
  * clear: function() {
695
647
  * return createMachine({ logs: [] }, this);
@@ -872,7 +824,7 @@ export function runMachine<M extends AsyncMachine<any>>(
872
824
 
873
825
  try {
874
826
  // 3. Pass the signal to the transition function.
875
- const nextStatePromise = fn.apply(current.context, [...event.args, { signal: controller.signal }]);
827
+ const nextStatePromise = fn.apply(current, [...event.args, { signal: controller.signal }]);
876
828
 
877
829
  const nextState = await nextStatePromise;
878
830
 
@@ -1164,4 +1116,15 @@ export {
1164
1116
  fromObservable,
1165
1117
  type ActorRef,
1166
1118
  type InspectionEvent
1167
- } from './actor';
1119
+ } from './actor';
1120
+
1121
+ // =============================================================================
1122
+ // SECTION: CONTEXT-BOUND UTILITIES
1123
+ // =============================================================================
1124
+
1125
+ export {
1126
+ createContextBoundMachine,
1127
+ callWithContext,
1128
+ isContextBound,
1129
+ type ContextBoundMachine
1130
+ } from './context-bound';
@@ -211,7 +211,7 @@ export function withTimeTravel<M extends BaseMachine<any>>(
211
211
  for (const entry of transitionsToReplay) {
212
212
  const transitionFn = replayedMachine[entry.transitionName as keyof M] as Function;
213
213
  if (transitionFn) {
214
- replayedMachine = transitionFn.apply(replayedMachine.context, entry.args);
214
+ replayedMachine = transitionFn.apply(replayedMachine, entry.args);
215
215
  }
216
216
  }
217
217
 
@@ -233,4 +233,4 @@ export function withTimeTravel<M extends BaseMachine<any>>(
233
233
  restoreSnapshot,
234
234
  replayFrom
235
235
  }) as WithTimeTravel<M>;
236
- }
236
+ }
package/src/middleware.ts CHANGED
@@ -976,7 +976,7 @@ export function withTimeTravel<M extends BaseMachine<any>>(
976
976
  for (const entry of transitionsToReplay) {
977
977
  const transitionFn = replayedMachine[entry.transitionName as keyof M] as Function;
978
978
  if (transitionFn) {
979
- replayedMachine = transitionFn.apply(replayedMachine.context, entry.args);
979
+ replayedMachine = transitionFn.apply(replayedMachine, entry.args);
980
980
  }
981
981
  }
982
982
 
@@ -1443,4 +1443,4 @@ export type WithDebugging<M extends BaseMachine<any>> = WithTimeTravel<WithSnaps
1443
1443
  */
1444
1444
  export function withDebugging<M extends BaseMachine<any>>(machine: M): WithDebugging<M> {
1445
1445
  return withTimeTravel(withSnapshot(withHistory(machine)));
1446
- }
1446
+ }
package/src/multi.ts CHANGED
@@ -211,7 +211,7 @@ export function createRunner<M extends Machine<any>>(
211
211
  }
212
212
 
213
213
  return (...args: any[]) => {
214
- const nextState = transition.apply(currentMachine.context, args);
214
+ const nextState = transition.apply(currentMachine, args);
215
215
  // Ensure the next state has all the original transitions
216
216
  // by reconstructing it with the original transition functions
217
217
  const nextStateWithTransitions = Object.assign(
@@ -498,7 +498,7 @@ export function createEnsemble<
498
498
  // Return a function that, when called, executes the transition.
499
499
  // The transition itself is responsible for calling `store.setContext`.
500
500
  return (...args: any[]) => {
501
- return action.apply(currentMachine.context, args);
501
+ return action.apply(currentMachine, args);
502
502
  };
503
503
  },
504
504
  });
@@ -1153,7 +1153,7 @@ export function createMutableMachine<
1153
1153
  if (typeof transition === 'function') {
1154
1154
  return (...args: any[]) => {
1155
1155
  // This pattern requires transitions to be pure functions that return the next context.
1156
- const nextContext = transition.apply(currentMachine.context, args);
1156
+ const nextContext = transition.apply(currentMachine, args);
1157
1157
  if (typeof nextContext !== 'object' || nextContext === null) {
1158
1158
  console.warn(`[MutableMachine] Transition "${String(prop)}" did not return a valid context object. State may be inconsistent.`);
1159
1159
  return;
@@ -1178,4 +1178,4 @@ export function createMutableMachine<
1178
1178
  return prop in target || typeof (currentMachine as any)[prop] === 'function';
1179
1179
  }
1180
1180
  }) as MutableMachine<C, ReturnType<F[keyof F]>>;
1181
- }
1181
+ }
package/src/primitives.ts CHANGED
@@ -354,6 +354,14 @@ export type GuardedTransition<
354
354
  * Creates a synchronous runtime guard that checks conditions before executing transitions.
355
355
  * This provides actual runtime protection with synchronous execution - use this for the majority of cases.
356
356
  *
357
+ * **IMPORTANT - Context-Bound Limitation:**
358
+ * Guards accept calls with either `this === machine` or `this === context`, but when called
359
+ * with context-only binding, the guard normalizes to `{ context }` before passing to the transition.
360
+ * This means:
361
+ * - ✅ Transitions can access `this.context`
362
+ * - ❌ Transitions CANNOT call `this.otherTransition()` (no transitions property)
363
+ * - Recommended: Use guards only with machine-bound transitions for full composition support
364
+ *
357
365
  * @template C - The context type
358
366
  * @template TSuccess - The transition return type when condition passes
359
367
  * @template TFailure - The fallback return type when condition fails (defaults to Machine<C>)
@@ -367,8 +375,10 @@ export type GuardedTransition<
367
375
  * const machine = createMachine({ balance: 100 }, {
368
376
  * withdraw: guard(
369
377
  * (ctx, amount) => ctx.balance >= amount,
370
- * function(amount: number) {
371
- * return createMachine({ balance: this.balance - amount }, this);
378
+ * function(this: Machine<{balance: number}>, amount: number) {
379
+ * // Can access this.context
380
+ * return createMachine({ balance: this.context.balance - amount }, this);
381
+ * // ❌ Cannot call this.otherTransition() if guard was called with context-only binding
372
382
  * },
373
383
  * { onFail: 'throw', errorMessage: 'Insufficient funds' }
374
384
  * )
@@ -403,9 +413,9 @@ export function guard<
403
413
 
404
414
  if (conditionResult) {
405
415
  // Condition passed, execute the transition
406
- // Transition functions expect 'this' to be the context
407
- const contextForTransition = isMachine ? (this as Machine<C>).context : (this as C);
408
- return transition.apply(contextForTransition, args);
416
+ // Transition functions expect 'this' to be the machine
417
+ const machineForTransition = isMachine ? (this as Machine<C>) : { context: this as C };
418
+ return transition.apply(machineForTransition, args);
409
419
  } else {
410
420
  // Condition failed, handle according to options
411
421
  if (onFail === 'throw') {
@@ -453,6 +463,14 @@ export function guard<
453
463
  * This provides actual runtime protection, unlike the `guarded` primitive which only adds metadata.
454
464
  * Use this when your condition or transition logic is asynchronous.
455
465
  *
466
+ * **IMPORTANT - Context-Bound Limitation:**
467
+ * Guards accept calls with either `this === machine` or `this === context`, but when called
468
+ * with context-only binding, the guard normalizes to `{ context }` before passing to the transition.
469
+ * This means:
470
+ * - ✅ Transitions can access `this.context`
471
+ * - ❌ Transitions CANNOT call `this.otherTransition()` (no transitions property)
472
+ * - Recommended: Use guards only with machine-bound transitions for full composition support
473
+ *
456
474
  * @template C - The context type
457
475
  * @template TSuccess - The transition return type when condition passes
458
476
  * @template TFailure - The fallback return type when condition fails (defaults to Machine<C>)
@@ -470,10 +488,12 @@ export function guard<
470
488
  * await new Promise(resolve => setTimeout(resolve, 100));
471
489
  * return ctx.balance >= amount;
472
490
  * },
473
- * async function(amount: number) {
491
+ * async function(this: Machine<{balance: number}>, amount: number) {
474
492
  * // Simulate API call to process withdrawal
475
493
  * await new Promise(resolve => setTimeout(resolve, 100));
476
- * return createMachine({ balance: this.balance - amount }, this);
494
+ * // Can access this.context
495
+ * return createMachine({ balance: this.context.balance - amount }, this);
496
+ * // ❌ Cannot call this.otherTransition() if guard was called with context-only binding
477
497
  * },
478
498
  * { onFail: 'throw', errorMessage: 'Insufficient funds' }
479
499
  * )
@@ -508,9 +528,9 @@ export function guardAsync<
508
528
 
509
529
  if (conditionResult) {
510
530
  // Condition passed, execute the transition
511
- // Transition functions expect 'this' to be the context
512
- const contextForTransition = isMachine ? (this as Machine<C>).context : (this as C);
513
- return transition.apply(contextForTransition, args);
531
+ // Transition functions expect 'this' to be the machine
532
+ const machineForTransition = isMachine ? (this as Machine<C>) : { context: this as C };
533
+ return transition.apply(machineForTransition, args);
514
534
  } else {
515
535
  // Condition failed, handle according to options
516
536
  if (onFail === 'throw') {
@@ -571,7 +591,7 @@ export function guardAsync<
571
591
  * withdraw: guardSync(
572
592
  * (ctx, amount) => ctx.balance >= amount,
573
593
  * function(amount: number) {
574
- * return createMachine({ balance: this.balance - amount }, this);
594
+ * return createMachine({ balance: this.context.balance - amount }, this);
575
595
  * },
576
596
  * { onFail: 'throw', errorMessage: 'Insufficient funds' }
577
597
  * )
@@ -606,9 +626,9 @@ export function guardSync<
606
626
 
607
627
  if (conditionResult) {
608
628
  // Condition passed, execute the transition
609
- // Transition functions expect 'this' to be the context
610
- const contextForTransition = isMachine ? (this as Machine<C>).context : (this as C);
611
- return transition.apply(contextForTransition, args);
629
+ // Transition functions expect 'this' to be the machine
630
+ const machineForTransition = isMachine ? (this as Machine<C>) : { context: this as C };
631
+ return transition.apply(machineForTransition, args);
612
632
  } else {
613
633
  // Condition failed, handle according to options
614
634
  if (onFail === 'throw') {
@@ -33,10 +33,10 @@ type Context = { count: number };
33
33
  const machine = createMachine({ count: 0 }, (transition) => ({
34
34
  inc() {
35
35
  // 'this' should be Context
36
- return transition({ count: this.count + 1 });
36
+ return transition({ count: this.context.count + 1 });
37
37
  },
38
38
  add(n: number) {
39
- return transition({ count: this.count + n });
39
+ return transition({ count: this.context.count + n });
40
40
  }
41
41
  }));
42
42
 
package/src/react.ts CHANGED
@@ -302,7 +302,6 @@ export function useActorSelector<M extends BaseMachine<any>, T>(
302
302
  selector: (state: M) => T,
303
303
  isEqual: (a: T, b: T) => boolean = Object.is
304
304
  ): T {
305
- const subscribe = useMemo(() => actor.subscribe.bind(actor), [actor]);
306
305
  const getSnapshot = useMemo(() => actor.getSnapshot.bind(actor), [actor]);
307
306
 
308
307
  const getSelection = () => selector(getSnapshot());
@@ -333,4 +332,4 @@ export function useActorSelector<M extends BaseMachine<any>, T>(
333
332
  }, [actor, selector, isEqual]);
334
333
 
335
334
  return selection;
336
- }
335
+ }
package/src/test.ts CHANGED
@@ -27,7 +27,7 @@ type AsyncFunctions<C extends object> =
27
27
  * const machine: Machine<{ count: number }> = {
28
28
  * context: { count: 0 },
29
29
  * increment: function() {
30
- * return createMachine({ count: this.count + 1 }, this)
30
+ * return createMachine({ count: this.context.count + 1 }, this)
31
31
  * }
32
32
  * }
33
33
  */
@@ -57,10 +57,10 @@ export type AsyncMachine<C extends object> = { context: C } & AsyncFunctions<C>
57
57
  * { count: 0 },
58
58
  * {
59
59
  * increment: function() {
60
- * return createMachine({ count: this.count + 1 }, this)
60
+ * return createMachine({ count: this.context.count + 1 }, this)
61
61
  * },
62
62
  * decrement: function() {
63
- * return createMachine({ count: this.count - 1 }, this)
63
+ * return createMachine({ count: this.context.count - 1 }, this)
64
64
  * }
65
65
  * }
66
66
  * )
@@ -147,7 +147,7 @@ export type Event<M> = {
147
147
  * { count: 0 },
148
148
  * {
149
149
  * increment: async function() {
150
- * return createAsyncMachine({ count: this.count + 1 }, this)
150
+ * return createAsyncMachine({ count: this.context.count + 1 }, this)
151
151
  * }
152
152
  * }
153
153
  * )
@@ -164,7 +164,7 @@ export function runMachine<C extends object>(
164
164
  async function dispatch<E extends Event<typeof current>>(event: E) {
165
165
  const fn = current[event.type] as any
166
166
  if (!fn) throw new Error(`Unknown event: ${event.type}`)
167
- const next = await fn.apply(current.context, event.args)
167
+ const next = await fn.apply(current as any, event.args)
168
168
  current = next
169
169
  onChange?.(current)
170
170
  return current
@@ -203,5 +203,5 @@ const counter = createMachine(
203
203
  );
204
204
 
205
205
  // Test by calling with proper context binding
206
- const result = counterFns.increment.call(counter.context);
207
- console.log('Result:', result.context.count);
206
+ const result = counterFns.increment.call(counter);
207
+ console.log('Result:', result.context.count);