@@ -18,6 +18,7 @@ import { handleEvent } from "./handleEvent"
1818import { HandleActionsOptions , TestOptions } from "./types"
1919import { deepClone , findNamedChild , set } from "./utils"
2020import { handleArrayLogic } from "./arrayHandling"
21+ import { create } from "mutative"
2122
2223/**
2324 * Recursively evaluate a value or object.
@@ -333,33 +334,52 @@ export function handleActions<Context>(
333334 return context
334335 }
335336
337+ return create ( context , ( draft ) => {
338+ handleActionsOnDraft ( input , draft , context , options )
339+ } )
340+ }
341+
342+ /**
343+ * Internal function that applies actions directly to a draft object.
344+ * This is used both by handleActions and handleEvent to avoid code duplication.
345+ */
346+ export function handleActionsOnDraft < Context > (
347+ input : any ,
348+ draft : any ,
349+ originalContext : Context ,
350+ options ?: HandleActionsOptions ,
351+ ) : void {
352+ if ( ! input || typeof input !== "object" ) {
353+ return
354+ }
355+
336356 const addOrDec = ( op : string ) => {
337357 if ( typeof input [ op ] === "string" ) {
338358 let reference = input [ op ]
339359
340- const variableValue = findNamedChild ( input [ op ] , context , true )
360+ const variableValue = findNamedChild ( input [ op ] , originalContext , true )
341361
342362 if ( typeof variableValue !== "number" ) {
343363 return
344364 }
345365
346366 set (
347- context ,
367+ draft ,
348368 reference ,
349369 op === "$inc" ? variableValue + 1 : variableValue - 1 ,
350370 )
351371 } else {
352372 let reference = input [ op ] [ 0 ]
353373
354- const variableValue = findNamedChild ( reference , context , true )
355- const incrementBy = findNamedChild ( input [ op ] [ 1 ] , context , false )
374+ const variableValue = findNamedChild ( reference , originalContext , true )
375+ const incrementBy = findNamedChild ( input [ op ] [ 1 ] , originalContext , false )
356376
357377 if ( typeof variableValue !== "number" ) {
358378 return
359379 }
360380
361381 set (
362- context ,
382+ draft ,
363383 reference ,
364384 op === "$inc"
365385 ? variableValue + incrementBy
@@ -376,10 +396,10 @@ export function handleActions<Context>(
376396 reference = reference . substring ( 1 )
377397 }
378398
379- const value = findNamedChild ( input [ op ] [ 1 ] , context , false )
399+ const value = findNamedChild ( input [ op ] [ 1 ] , originalContext , false )
380400
381401 // clone the thing
382- const array = deepClone ( findNamedChild ( reference , context , true ) )
402+ const array = deepClone ( findNamedChild ( reference , originalContext , true ) )
383403
384404 if ( ! Array . isArray ( array ) ) {
385405 return
@@ -395,7 +415,7 @@ export function handleActions<Context>(
395415 array . push ( value )
396416 }
397417
398- set ( context , reference , array )
418+ set ( draft , reference , array )
399419 }
400420
401421 for ( const key of Object . keys ( input ) ) {
@@ -416,12 +436,12 @@ export function handleActions<Context>(
416436 // Therefore the 1st operand might get written to, but the 2nd one is purely a read.
417437 const variableValue1 = findNamedChild (
418438 input [ "$mul" ] [ 0 ] ,
419- context ,
439+ originalContext ,
420440 true ,
421441 )
422442 const variableValue2 = findNamedChild (
423443 input [ "$mul" ] [ 1 ] ,
424- context ,
444+ originalContext ,
425445 false ,
426446 )
427447
@@ -432,15 +452,15 @@ export function handleActions<Context>(
432452 break
433453 }
434454
435- set ( context , reference , variableValue1 * variableValue2 )
455+ set ( draft , reference , variableValue1 * variableValue2 )
436456 break
437457 }
438458 case "$set" : {
439459 let reference = input . $set [ 0 ]
440460
441- const value = findNamedChild ( input . $set [ 1 ] , context , false )
461+ const value = findNamedChild ( input . $set [ 1 ] , originalContext , false )
442462
443- set ( context , reference , value )
463+ set ( draft , reference , value )
444464 break
445465 }
446466 case "$push" : {
@@ -458,11 +478,11 @@ export function handleActions<Context>(
458478 reference = reference . substring ( 1 )
459479 }
460480
461- const value = findNamedChild ( input . $remove [ 1 ] , context , false )
481+ const value = findNamedChild ( input . $remove [ 1 ] , originalContext , false )
462482
463483 // clone the thing
464484 let array : unknown [ ] = deepClone (
465- findNamedChild ( reference , context , true ) ,
485+ findNamedChild ( reference , originalContext , true ) ,
466486 )
467487
468488 if ( ! Array . isArray ( array ) ) {
@@ -471,24 +491,22 @@ export function handleActions<Context>(
471491
472492 array = array . filter ( ( item ) => item !== value )
473493
474- set ( context , reference , array )
494+ set ( draft , reference , array )
475495 break
476496 }
477497 case "$reset" : {
478498 let reference = input . $reset
479499 const value = findNamedChild (
480500 reference ,
481- options . originalContext ,
501+ options ? .originalContext ,
482502 true ,
483503 )
484504
485- set ( context , reference , value )
505+ set ( draft , reference , value )
486506 break
487507 }
488508 }
489509 }
490-
491- return context
492510}
493511
494512export { handleEvent }
0 commit comments