mirror of
				https://github.com/reduxjs/redux-devtools.git
				synced 2025-10-30 23:47:35 +03:00 
			
		
		
		
	Get stack trace using an outside trace function
				
					
				
			This commit is contained in:
		
							parent
							
								
									6fbb2ab7c6
								
							
						
					
					
						commit
						ee439fac9f
					
				|  | @ -50,7 +50,7 @@ export default function configureStore(initialState) { | |||
|     - **pauseActionType** *string* - if specified, whenever `pauseRecording(false)` lifted action is dispatched and there are actions in the history log, will add this action type. If not specified, will commit when paused. | ||||
|     - **shouldStartLocked** *boolean* - if specified as `true`, it will not allow any non-monitor actions to be dispatched till `lockChanges(false)` is dispatched. Default is `false`. | ||||
|     - **shouldHotReload** *boolean* - if set to `false`, will not recompute the states on hot reloading (or on replacing the reducers). Default to `true`. | ||||
|     - **shouldIncludeCallstack** *boolean* - if set to `true`, will include callstack for every dispatched action. Default to `false`. | ||||
|     - **trace** *boolean* or *function* - if set to `true`, will include stack trace for every dispatched action. You can use a function (with action object as argument) which should return `new Error().stack` string, getting the stack outside of reducers. Default to `false`. | ||||
| 
 | ||||
| ### License | ||||
| 
 | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ export const ActionTypes = { | |||
|  * Action creators to change the History state. | ||||
|  */ | ||||
| export const ActionCreators = { | ||||
|   performAction(action, shouldIncludeCallstack) { | ||||
|   performAction(action, trace) { | ||||
|     if (!isPlainObject(action)) { | ||||
|       throw new Error( | ||||
|         'Actions must be plain objects. ' + | ||||
|  | @ -38,10 +38,13 @@ export const ActionCreators = { | |||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       type: ActionTypes.PERFORM_ACTION, action, timestamp: Date.now(), | ||||
|       stack: shouldIncludeCallstack ? Error().stack : undefined | ||||
|     }; | ||||
|     let stack; | ||||
|     if (trace) { | ||||
|       if (typeof trace === 'function') stack = trace(action); | ||||
|       else stack = Error().stack; | ||||
|     } | ||||
| 
 | ||||
|     return { type: ActionTypes.PERFORM_ACTION, action, timestamp: Date.now(), stack }; | ||||
|   }, | ||||
| 
 | ||||
|   reset() { | ||||
|  | @ -188,8 +191,8 @@ function recomputeStates( | |||
| /** | ||||
|  * Lifts an app's action into an action on the lifted store. | ||||
|  */ | ||||
| export function liftAction(action, shouldIncludeCallstack) { | ||||
|   return ActionCreators.performAction(action, shouldIncludeCallstack); | ||||
| export function liftAction(action, trace) { | ||||
|   return ActionCreators.performAction(action, trace); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | @ -502,7 +505,7 @@ export function liftReducerWith(reducer, initialCommittedState, monitorReducer, | |||
|             minInvalidatedStateIndex = 0; | ||||
|             // iterate through actions
 | ||||
|             liftedAction.nextLiftedState.forEach(action => { | ||||
|               actionsById[nextActionId] = liftAction(action, options.shouldIncludeCallstack); | ||||
|               actionsById[nextActionId] = liftAction(action, options.trace || options.shouldIncludeCallstack); | ||||
|               stagedActionIds.push(nextActionId); | ||||
|               nextActionId++; | ||||
|             }); | ||||
|  | @ -595,7 +598,7 @@ export function unliftState(liftedState) { | |||
|  */ | ||||
| export function unliftStore(liftedStore, liftReducer, options) { | ||||
|   let lastDefinedState; | ||||
|   const { shouldIncludeCallstack } = options; | ||||
|   const trace = options.trace || options.shouldIncludeCallstack; | ||||
| 
 | ||||
|   function getState() { | ||||
|     const state = unliftState(liftedStore.getState()); | ||||
|  | @ -611,7 +614,7 @@ export function unliftStore(liftedStore, liftReducer, options) { | |||
|     liftedStore, | ||||
| 
 | ||||
|     dispatch(action) { | ||||
|       liftedStore.dispatch(liftAction(action, shouldIncludeCallstack)); | ||||
|       liftedStore.dispatch(liftAction(action, trace)); | ||||
|       return action; | ||||
|     }, | ||||
| 
 | ||||
|  |  | |||
|  | @ -686,6 +686,71 @@ describe('instrument', () => { | |||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('trace option', () => { | ||||
|     let monitoredStore; | ||||
|     let monitoredLiftedStore; | ||||
|     let exportedState; | ||||
| 
 | ||||
|     it('should not include stack trace', () => { | ||||
|       monitoredStore = createStore(counter, instrument()); | ||||
|       monitoredLiftedStore = monitoredStore.liftedStore; | ||||
|       monitoredStore.dispatch({ type: 'INCREMENT' }); | ||||
| 
 | ||||
|       exportedState = monitoredLiftedStore.getState(); | ||||
|       expect(exportedState.actionsById[0].stack).toBe(undefined); | ||||
|       expect(exportedState.actionsById[1].stack).toBe(undefined); | ||||
|     }); | ||||
| 
 | ||||
|     it('should include stack trace', () => { | ||||
|       monitoredStore = createStore(counter, instrument(undefined, { trace: true })); | ||||
|       monitoredLiftedStore = monitoredStore.liftedStore; | ||||
|       monitoredStore.dispatch({ type: 'INCREMENT' }); | ||||
| 
 | ||||
|       exportedState = monitoredLiftedStore.getState(); | ||||
|       expect(exportedState.actionsById[0].stack).toBe(undefined); | ||||
|       expect(exportedState.actionsById[1].stack).toBeA('string'); | ||||
|       expect(exportedState.actionsById[1].stack).toMatch(/^Error/); | ||||
|       expect(exportedState.actionsById[1].stack).toContain('at Object.performAction'); | ||||
|       expect(exportedState.actionsById[1].stack).toContain('instrument.js'); | ||||
|       expect(exportedState.actionsById[1].stack).toContain('instrument.spec.js'); | ||||
|       expect(exportedState.actionsById[1].stack).toContain('/mocha/'); | ||||
|     }); | ||||
| 
 | ||||
|     it('should get stack trace from a function', () => { | ||||
|       const traceFn = () => new Error().stack; | ||||
|       monitoredStore = createStore(counter, instrument(undefined, { trace: traceFn })); | ||||
|       monitoredLiftedStore = monitoredStore.liftedStore; | ||||
|       monitoredStore.dispatch({ type: 'INCREMENT' }); | ||||
| 
 | ||||
|       exportedState = monitoredLiftedStore.getState(); | ||||
|       expect(exportedState.actionsById[0].stack).toBe(undefined); | ||||
|       expect(exportedState.actionsById[1].stack).toBeA('string'); | ||||
|       expect(exportedState.actionsById[1].stack).toContain('at Object.performAction'); | ||||
|       expect(exportedState.actionsById[1].stack).toContain('instrument.js'); | ||||
|       expect(exportedState.actionsById[1].stack).toContain('instrument.spec.js'); | ||||
|       expect(exportedState.actionsById[1].stack).toContain('/mocha/'); | ||||
|     }); | ||||
| 
 | ||||
|     it('should get stack trace inside setTimeout using a function', (done) => { | ||||
|       const stack = new Error().stack; | ||||
|       setTimeout(() => { | ||||
|         const traceFn = () => stack + new Error().stack; | ||||
|         monitoredStore = createStore(counter, instrument(undefined, { trace: traceFn })); | ||||
|         monitoredLiftedStore = monitoredStore.liftedStore; | ||||
|         monitoredStore.dispatch({ type: 'INCREMENT' }); | ||||
| 
 | ||||
|         exportedState = monitoredLiftedStore.getState(); | ||||
|         expect(exportedState.actionsById[0].stack).toBe(undefined); | ||||
|         expect(exportedState.actionsById[1].stack).toBeA('string'); | ||||
|         expect(exportedState.actionsById[1].stack).toContain('at Object.performAction'); | ||||
|         expect(exportedState.actionsById[1].stack).toContain('instrument.js'); | ||||
|         expect(exportedState.actionsById[1].stack).toContain('instrument.spec.js'); | ||||
|         expect(exportedState.actionsById[1].stack).toContain('/mocha/'); | ||||
|         done(); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('Import State', () => { | ||||
|     let monitoredStore; | ||||
|     let monitoredLiftedStore; | ||||
|  | @ -736,8 +801,8 @@ describe('instrument', () => { | |||
|       expect(importMonitoredLiftedStore.getState()).toEqual(expectedImportedState); | ||||
|     }); | ||||
| 
 | ||||
|     it('should include callstack', () => { | ||||
|       let importMonitoredStore = createStore(counter, instrument(undefined, { shouldIncludeCallstack: true })); | ||||
|     it('should include stack trace', () => { | ||||
|       let importMonitoredStore = createStore(counter, instrument(undefined, { trace: true })); | ||||
|       let importMonitoredLiftedStore = importMonitoredStore.liftedStore; | ||||
| 
 | ||||
|       importMonitoredStore.dispatch({ type: 'DECREMENT' }); | ||||
|  | @ -801,8 +866,8 @@ describe('instrument', () => { | |||
|       expect(filterStackAndTimestamps(importMonitoredLiftedStore.getState())).toEqual(exportedState); | ||||
|     }); | ||||
| 
 | ||||
|     it('should include callstack', () => { | ||||
|       let importMonitoredStore = createStore(counter, instrument(undefined, { shouldIncludeCallstack: true })); | ||||
|     it('should include stack trace', () => { | ||||
|       let importMonitoredStore = createStore(counter, instrument(undefined, { trace: true })); | ||||
|       let importMonitoredLiftedStore = importMonitoredStore.liftedStore; | ||||
| 
 | ||||
|       importMonitoredStore.dispatch({ type: 'DECREMENT' }); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user