mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-25 11:03:57 +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