From f18ef4e66eb97741e3d01f24cdc6774c701a90d7 Mon Sep 17 00:00:00 2001 From: Zalmoxisus Date: Thu, 27 Dec 2018 01:00:29 +0200 Subject: [PATCH 1/2] Create redux-devtools-core and include remotedev-utils --- packages/redux-devtools-core/.babelrc | 3 + packages/redux-devtools-core/.eslintrc | 36 +++++ packages/redux-devtools-core/LICENSE.txt | 21 +++ packages/redux-devtools-core/README.md | 5 + packages/redux-devtools-core/package.json | 56 ++++++++ packages/redux-devtools-core/src/index.js | 6 + .../src/utils/catchErrors.js | 35 +++++ .../redux-devtools-core/src/utils/filters.js | 124 +++++++++++++++++ .../src/utils/importState.js | 50 +++++++ .../redux-devtools-core/src/utils/index.js | 130 ++++++++++++++++++ yarn.lock | 103 ++++++++++++-- 11 files changed, 559 insertions(+), 10 deletions(-) create mode 100644 packages/redux-devtools-core/.babelrc create mode 100644 packages/redux-devtools-core/.eslintrc create mode 100644 packages/redux-devtools-core/LICENSE.txt create mode 100755 packages/redux-devtools-core/README.md create mode 100644 packages/redux-devtools-core/package.json create mode 100644 packages/redux-devtools-core/src/index.js create mode 100644 packages/redux-devtools-core/src/utils/catchErrors.js create mode 100644 packages/redux-devtools-core/src/utils/filters.js create mode 100644 packages/redux-devtools-core/src/utils/importState.js create mode 100644 packages/redux-devtools-core/src/utils/index.js diff --git a/packages/redux-devtools-core/.babelrc b/packages/redux-devtools-core/.babelrc new file mode 100644 index 00000000..65836a67 --- /dev/null +++ b/packages/redux-devtools-core/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015-loose", "stage-0", "react"] +} diff --git a/packages/redux-devtools-core/.eslintrc b/packages/redux-devtools-core/.eslintrc new file mode 100644 index 00000000..e5e85d39 --- /dev/null +++ b/packages/redux-devtools-core/.eslintrc @@ -0,0 +1,36 @@ +{ + "extends": "eslint-config-airbnb", + "env": { + "mocha": true, + "browser": true, + "node": true + }, + "parser": "babel-eslint", + "rules": { + "react/jsx-uses-react": 2, + "react/jsx-uses-vars": 2, + "react/react-in-jsx-scope": 2, + "react/jsx-quotes": 0, + "block-scoped-var": 0, + "padded-blocks": 0, + "quotes": [ 1, "single" ], + "comma-style": [ 2, "last" ], + "eol-last": 0, + "no-unused-vars": 0, + "no-console": 0, + "func-names": 0, + "prefer-const": 0, + "prefer-arrow-callback": 0, + "comma-dangle": 0, + "id-length": 0, + "indent": [2, 2, {"SwitchCase": 1}], + "default-case": 0, + "prefer-template": 0, + "prefer-rest-params": 0, + "no-proto": 0, + "no-underscore-dangle": 0 + }, + "plugins": [ + "react" + ] +} diff --git a/packages/redux-devtools-core/LICENSE.txt b/packages/redux-devtools-core/LICENSE.txt new file mode 100644 index 00000000..01698ebb --- /dev/null +++ b/packages/redux-devtools-core/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Mihail Diordiev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/redux-devtools-core/README.md b/packages/redux-devtools-core/README.md new file mode 100755 index 00000000..c799607a --- /dev/null +++ b/packages/redux-devtools-core/README.md @@ -0,0 +1,5 @@ +Common functions for [Redux DevTools Extension](https://github.com/zalmoxisus/redux-devtools-extension) and [Remote Redux DevTools](https://github.com/zalmoxisus/remote-redux-devtools). + +## LICENSE + +[MIT](LICENSE) diff --git a/packages/redux-devtools-core/package.json b/packages/redux-devtools-core/package.json new file mode 100644 index 00000000..41e6833c --- /dev/null +++ b/packages/redux-devtools-core/package.json @@ -0,0 +1,56 @@ +{ + "name": "redux-devtools-core", + "version": "0.2.0", + "description": "Reusable functions of Redux DevTools", + "main": "lib/index.js", + "files": [ + "src", + "lib" + ], + "scripts": { + "clean": "rimraf lib", + "build:lib": "babel src --out-dir lib", + "build": "npm run build:lib", + "lint": "eslint src test", + "lintfix": "eslint src --fix", + "prepare": "npm run build", + "prepublishOnly": "npm run lint && npm run clean && npm run build" + }, + "repository": { + "type": "git", + "url": "https://github.com/reduxjs/redux-devtools.git" + }, + "author": "Mihail Diordiev (https://github.com/zalmoxisus)", + "license": "MIT", + "bugs": { + "url": "https://github.com/reduxjs/redux-devtools/issues" + }, + "homepage": "https://github.com/reduxjs/redux-devtools", + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-core": "^6.26.3", + "babel-eslint": "^6.1.2", + "babel-loader": "^6.2.4", + "babel-plugin-transform-decorators-legacy": "^1.3.4", + "babel-preset-es2015": "^6.24.1", + "babel-preset-es2015-loose": "^7.0.0", + "babel-preset-react": "^6.5.0", + "babel-preset-stage-0": "^6.5.0", + "eslint": "^3.2.0", + "eslint-config-airbnb": "^9.0.1", + "eslint-plugin-import": "^1.12.0", + "eslint-plugin-jsx-a11y": "^2.0.1", + "eslint-plugin-react": "^5.2.2", + "rimraf": "^2.5.2" + }, + "dependencies": { + "get-params": "^0.1.2", + "jsan": "^3.1.13", + "lodash": "^4.17.11", + "nanoid": "^2.0.0", + "remotedev-serialize": "^0.1.8" + }, + "pre-commit": [ + "lint" + ] +} diff --git a/packages/redux-devtools-core/src/index.js b/packages/redux-devtools-core/src/index.js new file mode 100644 index 00000000..b130b0c9 --- /dev/null +++ b/packages/redux-devtools-core/src/index.js @@ -0,0 +1,6 @@ +function injectedScript() { + console.error('Not implemented yet. WIP. If you\'re looking for utils, ' + + 'import `redux-devtools-core/lib/utils`.'); +} + +export default injectedScript; diff --git a/packages/redux-devtools-core/src/utils/catchErrors.js b/packages/redux-devtools-core/src/utils/catchErrors.js new file mode 100644 index 00000000..d4b3f2c3 --- /dev/null +++ b/packages/redux-devtools-core/src/utils/catchErrors.js @@ -0,0 +1,35 @@ +const ERROR = '@@remotedev/ERROR'; + +export default function catchErrors(sendError) { + if (typeof window === 'object' && typeof window.onerror === 'object') { + window.onerror = function (message, url, lineNo, columnNo, error) { + const errorAction = { type: ERROR, message, url, lineNo, columnNo }; + if (error && error.stack) errorAction.stack = error.stack; + sendError(errorAction); + return false; + }; + } else if (typeof global !== 'undefined' && global.ErrorUtils) { + global.ErrorUtils.setGlobalHandler((error, isFatal) => { + sendError({ type: ERROR, error, isFatal }); + }); + } + + if ( + typeof console === 'object' && typeof console.error === 'function' && !console.beforeRemotedev + ) { + console.beforeRemotedev = console.error.bind(console); + console.error = function () { + let errorAction = { type: ERROR }; + const error = arguments[0]; + errorAction.message = error.message ? error.message : error; + if (error.sourceURL) { + errorAction = { + ...errorAction, sourceURL: error.sourceURL, line: error.line, column: error.column + }; + } + if (error.stack) errorAction.stack = error.stack; + sendError(errorAction); + console.beforeRemotedev.apply(null, arguments); + }; + } +} diff --git a/packages/redux-devtools-core/src/utils/filters.js b/packages/redux-devtools-core/src/utils/filters.js new file mode 100644 index 00000000..814cc9c7 --- /dev/null +++ b/packages/redux-devtools-core/src/utils/filters.js @@ -0,0 +1,124 @@ +import mapValues from 'lodash/mapValues'; + +export const FilterState = { + DO_NOT_FILTER: 'DO_NOT_FILTER', + BLACKLIST_SPECIFIC: 'BLACKLIST_SPECIFIC', + WHITELIST_SPECIFIC: 'WHITELIST_SPECIFIC' +}; + +export function arrToRegex(v) { + return typeof v === 'string' ? v : v.join('|'); +} + +function filterActions(actionsById, actionsFilter) { + if (!actionsFilter) return actionsById; + return mapValues(actionsById, (action, id) => ( + { ...action, action: actionsFilter(action.action, id) } + )); +} + +function filterStates(computedStates, statesFilter) { + if (!statesFilter) return computedStates; + return computedStates.map((state, idx) => ( + { ...state, state: statesFilter(state.state, idx) } + )); +} + +export function getLocalFilter(config) { + if (config.actionsBlacklist || config.actionsWhitelist) { + return { + whitelist: config.actionsWhitelist && config.actionsWhitelist.join('|'), + blacklist: config.actionsBlacklist && config.actionsBlacklist.join('|') + }; + } + return undefined; +} + +function getDevToolsOptions() { + return typeof window !== 'undefined' && window.devToolsOptions || {}; +} + +export function isFiltered(action, localFilter) { + const { type } = action.action || action; + const opts = getDevToolsOptions(); + if ( + !localFilter && (opts.filter && opts.filter === FilterState.DO_NOT_FILTER) || + type && typeof type.match !== 'function' + ) return false; + + const { whitelist, blacklist } = localFilter || opts; + return ( + whitelist && !type.match(whitelist) || + blacklist && type.match(blacklist) + ); +} + +export function filterStagedActions(state, filters) { + if (!filters) return state; + + const filteredStagedActionIds = []; + const filteredComputedStates = []; + + state.stagedActionIds.forEach((id, idx) => { + if (!isFiltered(state.actionsById[id], filters)) { + filteredStagedActionIds.push(id); + filteredComputedStates.push(state.computedStates[idx]); + } + }); + + return { ...state, + stagedActionIds: filteredStagedActionIds, + computedStates: filteredComputedStates + }; +} + +export function filterState( + state, type, localFilter, stateSanitizer, actionSanitizer, nextActionId, predicate +) { + if (type === 'ACTION') return !stateSanitizer ? state : stateSanitizer(state, nextActionId - 1); + else if (type !== 'STATE') return state; + + const { filter } = getDevToolsOptions(); + if (predicate || localFilter || (filter && filter !== FilterState.DO_NOT_FILTER)) { + const filteredStagedActionIds = []; + const filteredComputedStates = []; + const sanitizedActionsById = actionSanitizer && {}; + const { actionsById } = state; + const { computedStates } = state; + + state.stagedActionIds.forEach((id, idx) => { + const liftedAction = actionsById[id]; + const currAction = liftedAction.action; + const liftedState = computedStates[idx]; + const currState = liftedState.state; + if (idx) { + if (predicate && !predicate(currState, currAction)) return; + if (isFiltered(currAction, localFilter)) return; + } + + filteredStagedActionIds.push(id); + filteredComputedStates.push( + stateSanitizer ? { ...liftedState, state: stateSanitizer(currState, idx) } : liftedState + ); + if (actionSanitizer) { + sanitizedActionsById[id] = { + ...liftedAction, action: actionSanitizer(currAction, id) + }; + } + }); + + return { + ...state, + actionsById: sanitizedActionsById || actionsById, + stagedActionIds: filteredStagedActionIds, + computedStates: filteredComputedStates + }; + } + + if (!stateSanitizer && !actionSanitizer) return state; + return { + ...state, + actionsById: filterActions(state.actionsById, actionSanitizer), + computedStates: filterStates(state.computedStates, stateSanitizer) + }; +} diff --git a/packages/redux-devtools-core/src/utils/importState.js b/packages/redux-devtools-core/src/utils/importState.js new file mode 100644 index 00000000..54ece7c9 --- /dev/null +++ b/packages/redux-devtools-core/src/utils/importState.js @@ -0,0 +1,50 @@ +import mapValues from 'lodash/mapValues'; +import jsan from 'jsan'; +import seralizeImmutable from 'remotedev-serialize/immutable/serialize'; + +function deprecate(param) { + console.warn(`\`${param}\` parameter for Redux DevTools Extension is deprecated. Use \`serialize\` parameter instead: https://github.com/zalmoxisus/redux-devtools-extension/releases/tag/v2.12.1`); // eslint-disable-line +} + +export default function importState(state, { deserializeState, deserializeAction, serialize }) { + if (!state) return undefined; + let parse = jsan.parse; + if (serialize) { + if (serialize.immutable) { + parse = v => jsan.parse(v, seralizeImmutable(serialize.immutable, serialize.refs).reviver); + } else if (serialize.reviver) { + parse = v => jsan.parse(v, serialize.reviver); + } + } + + let preloadedState; + let nextLiftedState = parse(state); + if (nextLiftedState.payload) { + if (nextLiftedState.preloadedState) preloadedState = parse(nextLiftedState.preloadedState); + nextLiftedState = parse(nextLiftedState.payload); + } + if (deserializeState) { + deprecate('deserializeState'); + if (typeof nextLiftedState.computedStates !== 'undefined') { + nextLiftedState.computedStates = nextLiftedState.computedStates.map(computedState => ({ + ...computedState, + state: deserializeState(computedState.state) + })); + } + if (typeof nextLiftedState.committedState !== 'undefined') { + nextLiftedState.committedState = deserializeState(nextLiftedState.committedState); + } + if (typeof preloadedState !== 'undefined') { + preloadedState = deserializeState(preloadedState); + } + } + if (deserializeAction) { + deprecate('deserializeAction'); + nextLiftedState.actionsById = mapValues(nextLiftedState.actionsById, liftedAction => ({ + ...liftedAction, + action: deserializeAction(liftedAction.action) + })); + } + + return { nextLiftedState, preloadedState }; +} \ No newline at end of file diff --git a/packages/redux-devtools-core/src/utils/index.js b/packages/redux-devtools-core/src/utils/index.js new file mode 100644 index 00000000..d68ddd46 --- /dev/null +++ b/packages/redux-devtools-core/src/utils/index.js @@ -0,0 +1,130 @@ +import getParams from 'get-params'; +import jsan from 'jsan'; +import nanoid from 'nanoid'; +import seralizeImmutable from 'remotedev-serialize/immutable/serialize'; + +export function generateId(id) { + return id || nanoid(7); +} + +function flatTree(obj, namespace = '') { + let functions = []; + Object.keys(obj).forEach(key => { + const prop = obj[key]; + if (typeof prop === 'function') { + functions.push({ + name: namespace + (key || prop.name || 'anonymous'), + func: prop, + args: getParams(prop), + }); + } else if (typeof prop === 'object') { + functions = functions.concat(flatTree(prop, namespace + key + '.')); + } + }); + return functions; +} + +export function getMethods(obj) { + if (typeof obj !== 'object') return undefined; + let functions; + let m; + if (obj.__proto__) m = obj.__proto__.__proto__; + if (!m) m = obj; + + Object.getOwnPropertyNames(m).forEach(key => { + const propDescriptor = Object.getOwnPropertyDescriptor(m, key); + if (!propDescriptor || 'get' in propDescriptor || 'set' in propDescriptor) return; + const prop = m[key]; + if (typeof prop === 'function' && key !== 'constructor') { + if (!functions) functions = []; + functions.push({ + name: key || prop.name || 'anonymous', + args: getParams(prop), + }); + } + }); + return functions; +} + +export function getActionsArray(actionCreators) { + if (Array.isArray(actionCreators)) return actionCreators; + return flatTree(actionCreators); +} + +/* eslint-disable no-new-func */ +const interpretArg = (arg) => (new Function('return ' + arg))(); + +function evalArgs(inArgs, restArgs) { + const args = inArgs.map(interpretArg); + if (!restArgs) return args; + const rest = interpretArg(restArgs); + if (Array.isArray(rest)) return args.concat(...rest); + throw new Error('rest must be an array'); +} + +export function evalAction(action, actionCreators) { + if (typeof action === 'string') { + return (new Function('return ' + action))(); + } + + const actionCreator = actionCreators[action.selected].func; + const args = evalArgs(action.args, action.rest); + return actionCreator(...args); +} + +export function evalMethod(action, obj) { + if (typeof action === 'string') { + return (new Function('return ' + action)).call(obj); + } + + const args = evalArgs(action.args, action.rest); + return (new Function('args', `return this.${action.name}(args)`)).apply(obj, args); +} +/* eslint-enable */ + +function tryCatchStringify(obj) { + try { + return JSON.stringify(obj); + } catch (err) { + /* eslint-disable no-console */ + if (process.env.NODE_ENV !== 'production') console.log('Failed to stringify', err); + /* eslint-enable no-console */ + return jsan.stringify(obj, null, null, { circular: '[CIRCULAR]' }); + } +} + +export function stringify(obj, serialize) { + if (typeof serialize === 'undefined') { + return tryCatchStringify(obj); + } + if (serialize === true) { + return jsan.stringify(obj, function (key, value) { + if (value && typeof value.toJS === 'function') return value.toJS(); + return value; + }, null, true); + } + return jsan.stringify(obj, serialize.replacer, null, serialize.options); +} + +export function getSeralizeParameter(config, param) { + const serialize = config.serialize; + if (serialize) { + if (serialize === true) return { options: true }; + if (serialize.immutable) { + return { + replacer: seralizeImmutable(serialize.immutable, serialize.refs).replacer, + options: serialize.options || true + }; + } + if (!serialize.replacer) return { options: serialize.options }; + return { replacer: serialize.replacer, options: serialize.options || true }; + } + + const value = config[param]; + if (typeof value === 'undefined') return undefined; + console.warn(`\`${param}\` parameter for Redux DevTools Extension is deprecated. Use \`serialize\` parameter instead: https://github.com/zalmoxisus/redux-devtools-extension/releases/tag/v2.12.1`); // eslint-disable-line + + if (typeof serializeState === 'boolean') return { options: value }; + if (typeof serializeState === 'function') return { replacer: value }; + return value; +} diff --git a/yarn.lock b/yarn.lock index 6b0de4e1..e19d7ce3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1368,7 +1368,7 @@ babel-cli@^6.10.1, babel-cli@^6.24.1, babel-cli@^6.26.0, babel-cli@^6.3.15, babe optionalDependencies: chokidar "^1.6.1" -babel-code-frame@^6.11.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: +babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= @@ -1429,7 +1429,7 @@ babel-core@^5.1.8, babel-core@^5.8.25, babel-core@^5.8.33: trim-right "^1.0.0" try-resolve "^1.0.0" -babel-core@^6.0.0, babel-core@^6.1.20, babel-core@^6.1.4, babel-core@^6.10.4, babel-core@^6.24.1, babel-core@^6.26.0, babel-core@^6.3.17, babel-core@^6.4.5: +babel-core@^6.0.0, babel-core@^6.1.20, babel-core@^6.1.4, babel-core@^6.10.4, babel-core@^6.24.1, babel-core@^6.26.0, babel-core@^6.26.3, babel-core@^6.3.17, babel-core@^6.4.5: version "6.26.3" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== @@ -1496,7 +1496,7 @@ babel-eslint@^5.0.0-beta4: lodash.assign "^3.2.0" lodash.pick "^3.1.0" -babel-eslint@^6.0.5: +babel-eslint@^6.0.5, babel-eslint@^6.1.2: version "6.1.2" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-6.1.2.tgz#5293419fe3672d66598d327da9694567ba6a5f2f" integrity sha1-UpNBn+NnLWZZjTJ9qWlFZ7pqXy8= @@ -3571,7 +3571,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.6.0: +concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.5.2, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -5076,7 +5076,7 @@ eslint-plugin-import@2.14.0, eslint-plugin-import@^2.2.0, eslint-plugin-import@^ read-pkg-up "^2.0.0" resolve "^1.6.0" -eslint-plugin-import@^1.9.2: +eslint-plugin-import@^1.12.0, eslint-plugin-import@^1.9.2: version "1.16.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-1.16.0.tgz#b2fa07ebcc53504d0f2a4477582ec8bff1871b9f" integrity sha1-svoH68xTUE0PKkR3WC7Iv/GHG58= @@ -5121,6 +5121,15 @@ eslint-plugin-jsx-a11y@^1.5.3: jsx-ast-utils "^1.0.0" object-assign "^4.0.1" +eslint-plugin-jsx-a11y@^2.0.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-2.2.3.tgz#4e35cb71b8a7db702ac415c806eb8e8d9ea6c65d" + integrity sha1-TjXLcbin23AqxBXIBuuOjZ6mxl0= + dependencies: + damerau-levenshtein "^1.0.0" + jsx-ast-utils "^1.0.0" + object-assign "^4.0.1" + eslint-plugin-jsx-a11y@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-4.0.0.tgz#779bb0fe7b08da564a422624911de10061e048ee" @@ -5416,6 +5425,47 @@ eslint@^2.13.1: text-table "~0.2.0" user-home "^2.0.0" +eslint@^3.2.0: + version "3.19.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" + integrity sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw= + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.5.2" + debug "^2.1.1" + doctrine "^2.0.0" + escope "^3.6.0" + espree "^3.4.0" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.14.0" + ignore "^3.2.0" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~2.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + eslint@^4.0.0, eslint@^4.10: version "4.19.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" @@ -5508,7 +5558,7 @@ espree@^2.0.1, espree@^2.2.4: resolved "https://registry.yarnpkg.com/espree/-/espree-2.2.5.tgz#df691b9310889402aeb29cc066708c56690b854b" integrity sha1-32kbkxCIlAKuspzAZnCMVmkLhUs= -espree@^3.1.6, espree@^3.5.4: +espree@^3.1.6, espree@^3.4.0, espree@^3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== @@ -6293,6 +6343,11 @@ get-own-enumerable-property-symbols@^3.0.0: resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203" integrity sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg== +get-params@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/get-params/-/get-params-0.1.2.tgz#bae0dfaba588a0c60d7834c0d8dc2ff60eeef2fe" + integrity sha1-uuDfq6WIoMYNeDTA2Nwv9g7u8v4= + get-pkg-repo@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d" @@ -6436,7 +6491,7 @@ glob@^5.0.14, glob@^5.0.15, glob@~5.0.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== @@ -6471,7 +6526,7 @@ globals@^8.0.0, globals@^8.11.0: resolved "https://registry.yarnpkg.com/globals/-/globals-8.18.0.tgz#93d4a62bdcac38cfafafc47d6b034768cb0ffcb4" integrity sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ= -globals@^9.18.0, globals@^9.2.0: +globals@^9.14.0, globals@^9.18.0, globals@^9.2.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== @@ -6947,7 +7002,7 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.1.2, ignore@^3.3.3, ignore@^3.3.5, ignore@^3.3.6: +ignore@^3.1.2, ignore@^3.2.0, ignore@^3.3.3, ignore@^3.3.5, ignore@^3.3.6: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== @@ -8187,7 +8242,7 @@ js-yaml@~3.7.0: argparse "^1.0.7" esprima "^2.6.0" -jsan@^3.1.3: +jsan@^3.1.13, jsan@^3.1.3: version "3.1.13" resolved "https://registry.yarnpkg.com/jsan/-/jsan-3.1.13.tgz#4de8c7bf8d1cfcd020c313d438f930cec4b91d86" integrity sha512-9kGpCsGHifmw6oJet+y8HaCl14y7qgAsxVdV3pCHDySNR3BfDC30zgkssd7x5LRVAT22dnpbe9JdzzmXZnq9/g== @@ -9712,6 +9767,11 @@ nan@^2.9.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== +nanoid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.0.0.tgz#e1ab4a4b024a38d15531ba34a712a201540de639" + integrity sha512-SG2qscLE3iM4C0CNzGrsAojJHSVHMS1J8NnvJ31P1lH8P0hGHOiafmniNJz6w6q7vuoDlV7RdySlJgtqkFEVtQ== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -11983,6 +12043,13 @@ recast@^0.11.17: private "~0.1.5" source-map "~0.5.0" +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + redbox-react@^1.3.6: version "1.6.0" resolved "https://registry.yarnpkg.com/redbox-react/-/redbox-react-1.6.0.tgz#e753ac02595bc1bf695b3935889a4f5b1b5a21a1" @@ -12201,6 +12268,13 @@ remotedev-inspector-monitor@^0.11.0: react-pure-render "^1.0.2" redux-devtools-themes "^1.0.0" +remotedev-serialize@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/remotedev-serialize/-/remotedev-serialize-0.1.8.tgz#c99cb184e7f71a906162abc404be8ce33810205f" + integrity sha512-3YG/FDcOmiK22bl5oMRM8RRnbGrFEuPGjbcDG+z2xi5aQaNQNZ8lqoRnZTwXVfaZtutXuiAQOgPRrogzQk8edg== + dependencies: + jsan "^3.1.13" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -12682,6 +12756,15 @@ shelljs@^0.6.0: resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" integrity sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg= +shelljs@^0.7.5: + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + shellwords@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" From 04673cb03233b094c2ffb3240ac66711e7cd0bd1 Mon Sep 17 00:00:00 2001 From: Zalmoxisus Date: Thu, 27 Dec 2018 01:10:55 +0200 Subject: [PATCH 2/2] Add `getStackTrace` --- packages/redux-devtools-core/.eslintrc | 3 +- .../redux-devtools-core/src/utils/index.js | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/redux-devtools-core/.eslintrc b/packages/redux-devtools-core/.eslintrc index e5e85d39..90959cf7 100644 --- a/packages/redux-devtools-core/.eslintrc +++ b/packages/redux-devtools-core/.eslintrc @@ -28,7 +28,8 @@ "prefer-template": 0, "prefer-rest-params": 0, "no-proto": 0, - "no-underscore-dangle": 0 + "no-underscore-dangle": 0, + "max-len": ["error", { "code": 120 }] }, "plugins": [ "react" diff --git a/packages/redux-devtools-core/src/utils/index.js b/packages/redux-devtools-core/src/utils/index.js index d68ddd46..e7b9225d 100644 --- a/packages/redux-devtools-core/src/utils/index.js +++ b/packages/redux-devtools-core/src/utils/index.js @@ -128,3 +128,32 @@ export function getSeralizeParameter(config, param) { if (typeof serializeState === 'function') return { replacer: value }; return value; } + +export function getStackTrace(config, toExcludeFromTrace) { + if (!config.trace) return undefined; + if (typeof config.trace === 'function') return config.trace(); + + let stack; + let extraFrames = 0; + let prevStackTraceLimit; + const traceLimit = config.traceLimit; + const error = Error(); + if (Error.captureStackTrace) { + if (Error.stackTraceLimit < traceLimit) { + prevStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = traceLimit; + } + Error.captureStackTrace(error, toExcludeFromTrace); + } else { + extraFrames = 3; + } + stack = error.stack; + if (prevStackTraceLimit) Error.stackTraceLimit = prevStackTraceLimit; + if (extraFrames || typeof Error.stackTraceLimit !== 'number' || Error.stackTraceLimit > traceLimit) { + const frames = stack.split('\n'); + if (frames.length > traceLimit) { + stack = frames.slice(0, traceLimit + extraFrames + (frames[0] === 'Error' ? 1 : 0)).join('\n'); + } + } + return stack; +}