1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Open editor from error-overlay (minor) (#4979)

This PR adds links to the [react-error-overlay](https://www.npmjs.com/package/react-error-overlay).
This allows a developer to open a stack trace in its own editor.

![codelinking](https://user-images.githubusercontent.com/1265681/44278860-a63e0a80-a24f-11e8-9c69-c5365c026c58.gif)

Closes #4813
This commit is contained in:
HaNdTriX 2018-08-24 16:30:41 +02:00 committed by Tim Neutkens
parent 0dd2b2aa74
commit 11816537c3
7 changed files with 87 additions and 3 deletions

View file

@ -6,9 +6,9 @@
import {getEventSourceWrapper} from './eventsource'
import formatWebpackMessages from './format-webpack-messages'
import * as ErrorOverlay from 'react-error-overlay'
// import url from 'url'
import stripAnsi from 'strip-ansi'
import {rewriteStacktrace} from '../source-map-support'
import fetch from 'unfetch'
const {
distDir
@ -30,6 +30,16 @@ const {
let hadRuntimeError = false
let customHmrEventHandler
export default function connect (options) {
// Open stack traces in an editor.
ErrorOverlay.setEditorHandler(function editorHandler ({ fileName, lineNumber, colNumber }) {
fetch(
'/_next/development/open-stack-frame-in-editor' +
`?fileName=${window.encodeURIComponent(fileName)}` +
`&lineNumber=${lineNumber || 1}` +
`&colNumber=${colNumber || 1}`
)
})
// We need to keep track of if there has been a runtime error.
// Essentially, we cannot guarantee application state was not corrupted by the
// runtime error. To prevent confusing behavior, we forcibly reload the entire

View file

@ -87,6 +87,7 @@
"htmlescape": "1.1.1",
"http-errors": "1.6.2",
"http-status": "1.0.1",
"launch-editor": "2.2.1",
"loader-utils": "1.1.0",
"minimist": "1.2.0",
"mkdirp-then": "1.2.0",

View file

@ -1,6 +1,7 @@
import { join, relative, sep, normalize } from 'path'
import WebpackDevMiddleware from 'webpack-dev-middleware'
import WebpackHotMiddleware from 'webpack-hot-middleware'
import errorOverlayMiddleware from './lib/error-overlay-middleware'
import del from 'del'
import onDemandEntryHandler, {normalizePage} from './on-demand-entry-handler'
import webpack from 'webpack'
@ -186,6 +187,7 @@ export default class HotReloader {
this.middlewares = [
webpackDevMiddleware,
webpackHotMiddleware,
errorOverlayMiddleware,
onDemandEntries.middleware()
]
}

View file

@ -0,0 +1,14 @@
import url from 'url'
import launchEditor from 'launch-editor'
export default function errorOverlayMiddleware (req, res, next) {
if (req.url.startsWith('/_next/development/open-stack-frame-in-editor')) {
const query = url.parse(req.url, true).query
const lineNumber = parseInt(query.lineNumber, 10) || 1
const colNumber = parseInt(query.colNumber, 10) || 1
launchEditor(`${query.fileName}:${lineNumber}:${colNumber}`)
res.end()
} else {
next()
}
}

View file

@ -5,6 +5,35 @@ import { check, File, waitFor, getReactErrorOverlayContent } from 'next-test-uti
export default (context, render) => {
describe('Error Recovery', () => {
it('should have installed the react-overlay-editor editor handler', async () => {
let browser
const aboutPage = new File(join(__dirname, '../', 'pages', 'hmr', 'about.js'))
aboutPage.replace('</div>', 'div')
try {
browser = await webdriver(context.appPort, '/hmr/about')
// Wait for react-error-overlay
await browser.waitForElementByCss('iframe', 2000)
// react-error-overlay uses the following inline style if an editorHandler is installed
expect(await getReactErrorOverlayContent(browser)).toMatch(/style="cursor: pointer;"/)
aboutPage.restore()
await check(
() => browser.elementByCss('body').text(),
/This is the about page/
)
} finally {
aboutPage.restore()
if (browser) {
browser.close()
}
}
})
it('should detect syntax errors and recover', async () => {
let browser
const aboutPage = new File(join(__dirname, '../', 'pages', 'hmr', 'about.js'))

View file

@ -7,7 +7,7 @@ describe('loadGetInitialProps', () => {
getInitialProps () {}
}
const rejectPromise = loadGetInitialProps(TestComponent, {})
const error = new Error('"TestComponent.getInitialProps()" is defined as an instance method - visit https://err.sh/zeit/next.js/get-inital-props-as-an-instance-method for more information.')
const error = new Error('"TestComponent.getInitialProps()" is defined as an instance method - visit https://err.sh/zeit/next.js/get-initial-props-as-an-instance-method for more information.')
return expect(rejectPromise).rejects.toEqual(error)
})

View file

@ -1074,6 +1074,10 @@ array-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
array-filter@~0.0.0:
version "0.0.1"
resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec"
array-find-index@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
@ -1089,6 +1093,14 @@ array-includes@^3.0.3:
define-properties "^1.1.2"
es-abstract "^1.7.0"
array-map@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662"
array-reduce@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b"
array-union@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
@ -1778,7 +1790,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.0, chalk@^2.4.1:
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.0, chalk@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
dependencies:
@ -4693,6 +4705,13 @@ kind-of@^6.0.0, kind-of@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
launch-editor@2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.2.1.tgz#871b5a3ee39d6680fcc26d37930b6eeda89db0ca"
dependencies:
chalk "^2.3.0"
shell-quote "^1.6.1"
lazy-cache@^0.2.3:
version "0.2.7"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65"
@ -7058,6 +7077,15 @@ shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
shell-quote@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767"
dependencies:
array-filter "~0.0.0"
array-map "~0.0.0"
array-reduce "~0.0.0"
jsonify "~0.0.0"
shellwords@^0.1.0, shellwords@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"