Don't depend on console object

Fixes #1311
This commit is contained in:
Dan Abramov
2016-01-29 17:13:48 +00:00
parent 80c7643969
commit b1bcee2746
4 changed files with 65 additions and 11 deletions

View File

@@ -2,8 +2,7 @@ import { ActionTypes } from './createStore'
import isPlainObject from './utils/isPlainObject'
import mapValues from './utils/mapValues'
import pick from './utils/pick'
/* eslint-disable no-console */
import warning from './utils/warning'
function getUndefinedStateErrorMessage(key, action) {
var actionType = action && action.type
@@ -112,7 +111,7 @@ export default function combineReducers(reducers) {
if (process.env.NODE_ENV !== 'production') {
var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action)
if (warningMessage) {
console.error(warningMessage)
warning(warningMessage)
}
}

View File

@@ -3,6 +3,7 @@ import combineReducers from './combineReducers'
import bindActionCreators from './bindActionCreators'
import applyMiddleware from './applyMiddleware'
import compose from './compose'
import warning from './utils/warning'
/*
* This is a dummy function to check if the function name has been altered by minification.
@@ -11,15 +12,13 @@ import compose from './compose'
function isCrushed() {}
if (isCrushed.name !== 'isCrushed' && process.env.NODE_ENV !== 'production') {
/*eslint-disable no-console */
console.error(
'You are currently using minified code outside of NODE_ENV === \'production\'. ' +
'This means that you are running a slower development build of Redux. ' +
'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' +
'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' +
warning(
'You are currently using minified code outside of NODE_ENV === \'production\'. ' +
'This means that you are running a slower development build of Redux. ' +
'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' +
'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' +
'to ensure you have the correct code for your production build.'
)
/*eslint-enable */
)
}
export {

20
src/utils/warning.js Normal file
View File

@@ -0,0 +1,20 @@
/**
* Prints a warning in the console if it exists.
*
* @param {String} message The warning message.
* @returns {void}
*/
export default function warning(message) {
/* eslint-disable no-console */
if (typeof console !== 'undefined' && typeof console.error === 'function') {
console.error(message)
}
/* eslint-enable no-console */
try {
// This error was thrown as a convenience so that you can use this stack
// to find the callsite that caused this warning to fire.
throw new Error(message)
/* eslint-disable no-empty */
} catch (e) { }
/* eslint-enable no-empty */
}

View File

@@ -0,0 +1,36 @@
import expect from 'expect'
import warning from '../../src/utils/warning'
describe('Utils', () => {
describe('warning', () => {
it('calls console.error when available', () => {
const spy = expect.spyOn(console, 'error')
try {
warning('Test')
expect(spy.calls[0].arguments[0]).toBe('Test')
} finally {
spy.restore()
}
})
it('does not throw when console.error is not available', () => {
const realConsole = global.console
Object.defineProperty(global, 'console', { value: {} })
try {
expect(() => warning('Test')).toNotThrow()
} finally {
Object.defineProperty(global, 'console', { value: realConsole })
}
})
it('does not throw when console is not available', () => {
const realConsole = global.console
Object.defineProperty(global, 'console', { value: undefined })
try {
expect(() => warning('Test')).toNotThrow()
} finally {
Object.defineProperty(global, 'console', { value: realConsole })
}
})
})
})