mirror of
				https://github.com/reduxjs/redux-devtools.git
				synced 2025-11-04 01:47:25 +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.
 | 
					    - **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`.
 | 
					    - **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`.
 | 
					    - **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
 | 
					### License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ export const ActionTypes = {
 | 
				
			||||||
 * Action creators to change the History state.
 | 
					 * Action creators to change the History state.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const ActionCreators = {
 | 
					export const ActionCreators = {
 | 
				
			||||||
  performAction(action, shouldIncludeCallstack) {
 | 
					  performAction(action, trace) {
 | 
				
			||||||
    if (!isPlainObject(action)) {
 | 
					    if (!isPlainObject(action)) {
 | 
				
			||||||
      throw new Error(
 | 
					      throw new Error(
 | 
				
			||||||
        'Actions must be plain objects. ' +
 | 
					        'Actions must be plain objects. ' +
 | 
				
			||||||
| 
						 | 
					@ -38,10 +38,13 @@ export const ActionCreators = {
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    let stack;
 | 
				
			||||||
      type: ActionTypes.PERFORM_ACTION, action, timestamp: Date.now(),
 | 
					    if (trace) {
 | 
				
			||||||
      stack: shouldIncludeCallstack ? Error().stack : undefined
 | 
					      if (typeof trace === 'function') stack = trace(action);
 | 
				
			||||||
    };
 | 
					      else stack = Error().stack;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return { type: ActionTypes.PERFORM_ACTION, action, timestamp: Date.now(), stack };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  reset() {
 | 
					  reset() {
 | 
				
			||||||
| 
						 | 
					@ -188,8 +191,8 @@ function recomputeStates(
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Lifts an app's action into an action on the lifted store.
 | 
					 * Lifts an app's action into an action on the lifted store.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function liftAction(action, shouldIncludeCallstack) {
 | 
					export function liftAction(action, trace) {
 | 
				
			||||||
  return ActionCreators.performAction(action, shouldIncludeCallstack);
 | 
					  return ActionCreators.performAction(action, trace);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -502,7 +505,7 @@ export function liftReducerWith(reducer, initialCommittedState, monitorReducer,
 | 
				
			||||||
            minInvalidatedStateIndex = 0;
 | 
					            minInvalidatedStateIndex = 0;
 | 
				
			||||||
            // iterate through actions
 | 
					            // iterate through actions
 | 
				
			||||||
            liftedAction.nextLiftedState.forEach(action => {
 | 
					            liftedAction.nextLiftedState.forEach(action => {
 | 
				
			||||||
              actionsById[nextActionId] = liftAction(action, options.shouldIncludeCallstack);
 | 
					              actionsById[nextActionId] = liftAction(action, options.trace || options.shouldIncludeCallstack);
 | 
				
			||||||
              stagedActionIds.push(nextActionId);
 | 
					              stagedActionIds.push(nextActionId);
 | 
				
			||||||
              nextActionId++;
 | 
					              nextActionId++;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
| 
						 | 
					@ -595,7 +598,7 @@ export function unliftState(liftedState) {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function unliftStore(liftedStore, liftReducer, options) {
 | 
					export function unliftStore(liftedStore, liftReducer, options) {
 | 
				
			||||||
  let lastDefinedState;
 | 
					  let lastDefinedState;
 | 
				
			||||||
  const { shouldIncludeCallstack } = options;
 | 
					  const trace = options.trace || options.shouldIncludeCallstack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function getState() {
 | 
					  function getState() {
 | 
				
			||||||
    const state = unliftState(liftedStore.getState());
 | 
					    const state = unliftState(liftedStore.getState());
 | 
				
			||||||
| 
						 | 
					@ -611,7 +614,7 @@ export function unliftStore(liftedStore, liftReducer, options) {
 | 
				
			||||||
    liftedStore,
 | 
					    liftedStore,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dispatch(action) {
 | 
					    dispatch(action) {
 | 
				
			||||||
      liftedStore.dispatch(liftAction(action, shouldIncludeCallstack));
 | 
					      liftedStore.dispatch(liftAction(action, trace));
 | 
				
			||||||
      return action;
 | 
					      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', () => {
 | 
					  describe('Import State', () => {
 | 
				
			||||||
    let monitoredStore;
 | 
					    let monitoredStore;
 | 
				
			||||||
    let monitoredLiftedStore;
 | 
					    let monitoredLiftedStore;
 | 
				
			||||||
| 
						 | 
					@ -736,8 +801,8 @@ describe('instrument', () => {
 | 
				
			||||||
      expect(importMonitoredLiftedStore.getState()).toEqual(expectedImportedState);
 | 
					      expect(importMonitoredLiftedStore.getState()).toEqual(expectedImportedState);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it('should include callstack', () => {
 | 
					    it('should include stack trace', () => {
 | 
				
			||||||
      let importMonitoredStore = createStore(counter, instrument(undefined, { shouldIncludeCallstack: true }));
 | 
					      let importMonitoredStore = createStore(counter, instrument(undefined, { trace: true }));
 | 
				
			||||||
      let importMonitoredLiftedStore = importMonitoredStore.liftedStore;
 | 
					      let importMonitoredLiftedStore = importMonitoredStore.liftedStore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      importMonitoredStore.dispatch({ type: 'DECREMENT' });
 | 
					      importMonitoredStore.dispatch({ type: 'DECREMENT' });
 | 
				
			||||||
| 
						 | 
					@ -801,8 +866,8 @@ describe('instrument', () => {
 | 
				
			||||||
      expect(filterStackAndTimestamps(importMonitoredLiftedStore.getState())).toEqual(exportedState);
 | 
					      expect(filterStackAndTimestamps(importMonitoredLiftedStore.getState())).toEqual(exportedState);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it('should include callstack', () => {
 | 
					    it('should include stack trace', () => {
 | 
				
			||||||
      let importMonitoredStore = createStore(counter, instrument(undefined, { shouldIncludeCallstack: true }));
 | 
					      let importMonitoredStore = createStore(counter, instrument(undefined, { trace: true }));
 | 
				
			||||||
      let importMonitoredLiftedStore = importMonitoredStore.liftedStore;
 | 
					      let importMonitoredLiftedStore = importMonitoredStore.liftedStore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      importMonitoredStore.dispatch({ type: 'DECREMENT' });
 | 
					      importMonitoredStore.dispatch({ type: 'DECREMENT' });
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user