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

Merge branch 'v3-beta' of github.com:zeit/next.js into v3-beta

This commit is contained in:
Arunoda Susiripala 2017-07-20 23:48:58 +05:30
commit d4eb9455b8
15 changed files with 320 additions and 115 deletions

View file

@ -8,7 +8,6 @@ addons:
- google-chrome-stable - google-chrome-stable
language: node_js language: node_js
node_js: node_js:
- "4"
- "6" - "6"
cache: cache:
directories: directories:

View file

@ -1,6 +1,5 @@
environment: environment:
matrix: matrix:
- nodejs_version: "4"
- nodejs_version: "6" - nodejs_version: "6"
# Install scripts. (runs after repo cloning) # Install scripts. (runs after repo cloning)

View file

@ -54,7 +54,8 @@ export default function dynamicComponent (p, o) {
} }
loadComponent () { loadComponent () {
promise.then((AsyncComponent) => { promise.then((m) => {
const AsyncComponent = m.default || m
// Set a readable displayName for the wrapper component // Set a readable displayName for the wrapper component
const asyncCompName = getDisplayName(AsyncComponent) const asyncCompName = getDisplayName(AsyncComponent)
if (asyncCompName) { if (asyncCompName) {
@ -65,7 +66,7 @@ export default function dynamicComponent (p, o) {
this.setState({ AsyncComponent }) this.setState({ AsyncComponent })
} else { } else {
if (this.isServer) { if (this.isServer) {
registerChunk(AsyncComponent.__webpackChunkName) registerChunk(m.__webpackChunkName)
} }
this.state.AsyncComponent = AsyncComponent this.state.AsyncComponent = AsyncComponent
} }
@ -100,9 +101,10 @@ export default function dynamicComponent (p, o) {
const loadModule = (name) => { const loadModule = (name) => {
const promise = modulePromiseMap[name] const promise = modulePromiseMap[name]
promise.then((Component) => { promise.then((m) => {
const Component = m.default || m
if (this.isServer) { if (this.isServer) {
registerChunk(Component.__webpackChunkName) registerChunk(m.__webpackChunkName)
} }
moduleMap[name] = Component moduleMap[name] = Component
remainingPromises-- remainingPromises--

View file

@ -15,9 +15,12 @@ export default class Link extends Component {
} }
static propTypes = exact({ static propTypes = exact({
href: PropTypes.string, href: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
as: PropTypes.string, as: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
prefetch: PropTypes.bool, prefetch: PropTypes.bool,
replace: PropTypes.bool,
shallow: PropTypes.bool,
passHref: PropTypes.bool,
children: PropTypes.oneOfType([ children: PropTypes.oneOfType([
PropTypes.element, PropTypes.element,
(props, propName) => { (props, propName) => {
@ -29,9 +32,7 @@ export default class Link extends Component {
return null return null
} }
]).isRequired, ]).isRequired
shallow: PropTypes.bool,
passHref: PropTypes.bool
}) })
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {

View file

@ -118,12 +118,14 @@
"coveralls": "2.13.1", "coveralls": "2.13.1",
"cross-env": "5.0.1", "cross-env": "5.0.1",
"express": "4.15.2", "express": "4.15.2",
"fkill": "^5.0.0",
"husky": "0.14.3", "husky": "0.14.3",
"jest-cli": "20.0.4", "jest-cli": "20.0.4",
"lint-staged": "^4.0.0", "lint-staged": "^4.0.0",
"node-fetch": "1.7.1", "node-fetch": "1.7.1",
"node-notifier": "5.1.2", "node-notifier": "5.1.2",
"nyc": "11.0.3", "nyc": "11.0.3",
"portfinder": "^1.0.13",
"react": "15.5.4", "react": "15.5.4",
"react-dom": "15.5.4", "react-dom": "15.5.4",
"standard": "9.0.2", "standard": "9.0.2",

View file

@ -13,7 +13,6 @@ const buildImport = (args) => (template(`
eval('require.ensure = function (deps, callback) { callback(require) }') eval('require.ensure = function (deps, callback) { callback(require) }')
require.ensure([], (require) => { require.ensure([], (require) => {
let m = require(SOURCE) let m = require(SOURCE)
m = m.default || m
m.__webpackChunkName = '${args.name}.js' m.__webpackChunkName = '${args.name}.js'
resolve(m); resolve(m);
}, 'chunks/${args.name}.js'); }, 'chunks/${args.name}.js');
@ -23,13 +22,12 @@ const buildImport = (args) => (template(`
const weakId = require.resolveWeak(SOURCE) const weakId = require.resolveWeak(SOURCE)
try { try {
const weakModule = __webpack_require__(weakId) const weakModule = __webpack_require__(weakId)
return resolve(weakModule.default || weakModule) return resolve(weakModule)
} catch (err) {} } catch (err) {}
require.ensure([], (require) => { require.ensure([], (require) => {
try { try {
let m = require(SOURCE) let m = require(SOURCE)
m = m.default || m
resolve(m) resolve(m)
} catch(error) { } catch(error) {
reject(error) reject(error)

View file

@ -0,0 +1,19 @@
import React from 'react'
export default class Counter extends React.Component {
state = { count: 0 }
incr () {
const { count } = this.state
this.setState({ count: count + 1 })
}
render () {
return (
<div>
<p>COUNT: {this.state.count}</p>
<button onClick={() => this.incr()}>Increment</button>
</div>
)
}
}

View file

@ -4,6 +4,16 @@ import { readFileSync, writeFileSync, renameSync } from 'fs'
import { join } from 'path' import { join } from 'path'
import { waitFor } from 'next-test-utils' import { waitFor } from 'next-test-utils'
async function check (contentFn, regex) {
while (true) {
try {
const newContent = await contentFn()
if (regex.test(newContent)) break
await waitFor(1000)
} catch (ex) {}
}
}
export default (context, render) => { export default (context, render) => {
describe('Hot Module Reloading', () => { describe('Hot Module Reloading', () => {
describe('syntax error', () => { describe('syntax error', () => {
@ -21,18 +31,45 @@ export default (context, render) => {
// change the content // change the content
writeFileSync(aboutPagePath, erroredContent, 'utf8') writeFileSync(aboutPagePath, erroredContent, 'utf8')
const errorMessage = await browser await check(
.waitForElementByCss('pre') () => browser.elementByCss('body').text(),
.elementByCss('pre').text() /Unterminated JSX contents/
expect(errorMessage.includes('Unterminated JSX contents')).toBeTruthy() )
// add the original content // add the original content
writeFileSync(aboutPagePath, originalContent, 'utf8') writeFileSync(aboutPagePath, originalContent, 'utf8')
const newContent = await browser await check(
.waitForElementByCss('.hmr-about-page') () => browser.elementByCss('body').text(),
.elementByCss('p').text() /This is the about page/
expect(newContent).toBe('This is the about page.') )
browser.close()
})
it('should show the error on all pages', async () => {
const aboutPagePath = join(__dirname, '../', 'pages', 'hmr', 'about.js')
const originalContent = readFileSync(aboutPagePath, 'utf8')
const erroredContent = originalContent.replace('</div>', 'div')
// change the content
writeFileSync(aboutPagePath, erroredContent, 'utf8')
const browser = await webdriver(context.appPort, '/hmr/contact')
await check(
() => browser.elementByCss('body').text(),
/Unterminated JSX contents/
)
// add the original content
writeFileSync(aboutPagePath, originalContent, 'utf8')
await check(
() => browser.elementByCss('body').text(),
/This is the contact page/
)
browser.close() browser.close()
}) })
@ -52,27 +89,81 @@ export default (context, render) => {
renameSync(contactPagePath, newContactPagePath) renameSync(contactPagePath, newContactPagePath)
// wait until the 404 page comes // wait until the 404 page comes
while (true) { await check(
try { () => browser.elementByCss('body').text(),
const pageContent = await browser.elementByCss('body').text() /This page could not be found/
if (/This page could not be found/.test(pageContent)) break )
} catch (ex) {}
await waitFor(1000)
}
// Rename the file back to the original filename // Rename the file back to the original filename
renameSync(newContactPagePath, contactPagePath) renameSync(newContactPagePath, contactPagePath)
// wait until the page comes back // wait until the page comes back
while (true) { await check(
try { () => browser.elementByCss('body').text(),
const pageContent = await browser.elementByCss('body').text() /This is the contact page/
if (/This is the contact page/.test(pageContent)) break )
} catch (ex) {}
await waitFor(1000) browser.close()
} })
})
describe('editing a page', () => {
it('should detect the changes and display it', async () => {
const browser = await webdriver(context.appPort, '/hmr/about')
const text = await browser
.elementByCss('p').text()
expect(text).toBe('This is the about page.')
const aboutPagePath = join(__dirname, '../', 'pages', 'hmr', 'about.js')
const originalContent = readFileSync(aboutPagePath, 'utf8')
const editedContent = originalContent.replace('This is the about page', 'COOL page')
// change the content
writeFileSync(aboutPagePath, editedContent, 'utf8')
await check(
() => browser.elementByCss('body').text(),
/COOL page/
)
// add the original content
writeFileSync(aboutPagePath, originalContent, 'utf8')
await check(
() => browser.elementByCss('body').text(),
/This is the about page/
)
browser.close()
})
it('should not reload unrelated pages', async () => {
const browser = await webdriver(context.appPort, '/hmr/counter')
const text = await browser
.elementByCss('button').click()
.elementByCss('button').click()
.elementByCss('p').text()
expect(text).toBe('COUNT: 2')
const aboutPagePath = join(__dirname, '../', 'pages', 'hmr', 'about.js')
const originalContent = readFileSync(aboutPagePath, 'utf8')
const editedContent = originalContent.replace('This is the about page', 'COOL page')
// Change the about.js page
writeFileSync(aboutPagePath, editedContent, 'utf8')
// wait for 5 seconds
await waitFor(5000)
// Check whether the this page has reloaded or not.
const newText = await browser
.elementByCss('p').text()
expect(newText).toBe('COUNT: 2')
// restore the about page content.
writeFileSync(aboutPagePath, originalContent, 'utf8')
browser.close() browser.close()
}) })

View file

@ -2,34 +2,25 @@
import { join } from 'path' import { join } from 'path'
import { import {
nextServer,
renderViaAPI,
renderViaHTTP, renderViaHTTP,
startApp, findPort,
stopApp launchApp,
killApp
} from 'next-test-utils' } from 'next-test-utils'
// test suits // test suits
import xPoweredBy from './xpowered-by'
import rendering from './rendering' import rendering from './rendering'
import misc from './misc'
import clientNavigation from './client-navigation' import clientNavigation from './client-navigation'
import hmr from './hmr' import hmr from './hmr'
import dynamic from './dynamic' import dynamic from './dynamic'
const context = {} const context = {}
context.app = nextServer({
dir: join(__dirname, '../'),
dev: true,
quiet: true
})
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2 jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2
describe('Basic Features', () => { describe('Basic Features', () => {
beforeAll(async () => { beforeAll(async () => {
context.server = await startApp(context.app) context.appPort = await findPort()
context.appPort = context.server.address().port context.server = await launchApp(join(__dirname, '../'), context.appPort, true)
// pre-build all pages at the start // pre-build all pages at the start
await Promise.all([ await Promise.all([
@ -55,15 +46,16 @@ describe('Basic Features', () => {
renderViaHTTP(context.appPort, '/nav/as-path'), renderViaHTTP(context.appPort, '/nav/as-path'),
renderViaHTTP(context.appPort, '/nav/as-path-using-router'), renderViaHTTP(context.appPort, '/nav/as-path-using-router'),
renderViaHTTP(context.appPort, '/nested-cdm/index') renderViaHTTP(context.appPort, '/nested-cdm/index'),
renderViaHTTP(context.appPort, '/hmr/about'),
renderViaHTTP(context.appPort, '/hmr/contact'),
renderViaHTTP(context.appPort, '/hmr/counter')
]) ])
}) })
afterAll(() => stopApp(context.server)) afterAll(() => killApp(context.server))
rendering(context, 'Rendering via API', (p, q) => renderViaAPI(context.app, p, q))
rendering(context, 'Rendering via HTTP', (p, q) => renderViaHTTP(context.appPort, p, q)) rendering(context, 'Rendering via HTTP', (p, q) => renderViaHTTP(context.appPort, p, q))
xPoweredBy(context)
misc(context)
clientNavigation(context, (p, q) => renderViaHTTP(context.appPort, p, q)) clientNavigation(context, (p, q) => renderViaHTTP(context.appPort, p, q))
dynamic(context, (p, q) => renderViaHTTP(context.appPort, p, q)) dynamic(context, (p, q) => renderViaHTTP(context.appPort, p, q))
hmr(context, (p, q) => renderViaHTTP(context.appPort, p, q)) hmr(context, (p, q) => renderViaHTTP(context.appPort, p, q))

View file

@ -1,16 +0,0 @@
/* global describe, test, expect */
export default function (context) {
describe('Misc', () => {
test('finishes response', async () => {
const res = {
finished: false,
end () {
this.finished = true
}
}
const html = await context.app.renderToHTML({}, res, '/finish-response', {})
expect(html).toBeFalsy()
})
})
}

View file

@ -1,37 +0,0 @@
/* global describe, test, expect */
import { pkg } from 'next-test-utils'
export default function ({ app }) {
describe('X-Powered-By header', () => {
test('set it by default', async () => {
const req = { url: '/stateless', headers: {} }
const headers = {}
const res = {
setHeader (key, value) {
headers[key] = value
},
end () {}
}
await app.render(req, res, req.url)
expect(headers['X-Powered-By']).toEqual(`Next.js ${pkg.version}`)
})
test('do not set it when poweredByHeader==false', async () => {
const req = { url: '/stateless', headers: {} }
const originalConfigValue = app.config.poweredByHeader
app.config.poweredByHeader = false
const res = {
setHeader (key, value) {
if (key === 'X-Powered-By') {
throw new Error('Should not set the X-Powered-By header')
}
},
end () {}
}
await app.render(req, res, req.url)
app.config.poweredByHeader = originalConfigValue
})
})
}

View file

@ -2,6 +2,7 @@
import { join } from 'path' import { join } from 'path'
import { import {
pkg,
nextServer, nextServer,
nextBuild, nextBuild,
startApp, startApp,
@ -89,5 +90,51 @@ describe('Production Usage', () => {
}) })
}) })
describe('Misc', () => {
it('should handle already finished responses', async () => {
const res = {
finished: false,
end () {
this.finished = true
}
}
const html = await app.renderToHTML({}, res, '/finish-response', {})
expect(html).toBeFalsy()
})
})
describe('X-Powered-By header', () => {
it('should set it by default', async () => {
const req = { url: '/stateless', headers: {} }
const headers = {}
const res = {
setHeader (key, value) {
headers[key] = value
},
end () {}
}
await app.render(req, res, req.url)
expect(headers['X-Powered-By']).toEqual(`Next.js ${pkg.version}`)
})
it('should not set it when poweredByHeader==false', async () => {
const req = { url: '/stateless', headers: {} }
const originalConfigValue = app.config.poweredByHeader
app.config.poweredByHeader = false
const res = {
setHeader (key, value) {
if (key === 'X-Powered-By') {
throw new Error('Should not set the X-Powered-By header')
}
},
end () {}
}
await app.render(req, res, req.url)
app.config.poweredByHeader = originalConfigValue
})
})
dynamicImportTests(context, (p, q) => renderViaHTTP(context.appPort, p, q)) dynamicImportTests(context, (p, q) => renderViaHTTP(context.appPort, p, q))
}) })

View file

@ -2,6 +2,10 @@ import fetch from 'node-fetch'
import qs from 'querystring' import qs from 'querystring'
import http from 'http' import http from 'http'
import express from 'express' import express from 'express'
import path from 'path'
import portfinder from 'portfinder'
import { spawn } from 'child_process'
import fkill from 'fkill'
import server from '../../dist/server/next' import server from '../../dist/server/next'
import build from '../../dist/server/build' import build from '../../dist/server/build'
@ -23,6 +27,48 @@ export function renderViaHTTP (appPort, pathname, query = {}) {
return fetch(url).then((res) => res.text()) return fetch(url).then((res) => res.text())
} }
export function findPort () {
portfinder.basePort = 20000 + Math.ceil(Math.random() * 10000)
return portfinder.getPortPromise()
}
// Launch the app in dev mode.
export function launchApp (dir, port) {
const cwd = path.resolve(__dirname, '../../')
return new Promise((resolve, reject) => {
const instance = spawn('node', ['dist/bin/next', dir, '-p', port], { cwd })
function handleStdout (data) {
const message = data.toString()
if (/> Ready on/.test(message)) {
resolve(instance)
}
process.stdout.write(message)
}
function handleStderr (data) {
process.stderr.write(data.toString())
}
instance.stdout.on('data', handleStdout)
instance.stderr.on('data', handleStderr)
instance.on('close', () => {
instance.stdout.removeListener('data', handleStdout)
instance.stderr.removeListener('data', handleStderr)
})
instance.on('error', (err) => {
reject(err)
})
})
}
// Kill a launched app
export async function killApp (instance) {
await fkill(instance.pid)
}
export async function startApp (app) { export async function startApp (app) {
await app.prepare() await app.prepare()
const handler = app.getRequestHandler() const handler = app.getRequestHandler()

View file

@ -74,6 +74,13 @@ acorn@^5.0.0, acorn@^5.0.1:
version "5.1.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.0.tgz#e468bf609b0672700e02f878ae2f1b360fe24b4f" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.0.tgz#e468bf609b0672700e02f878ae2f1b360fe24b4f"
aggregate-error@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-1.0.0.tgz#888344dad0220a72e3af50906117f48771925fac"
dependencies:
clean-stack "^1.0.0"
indent-string "^3.0.0"
ajv-keywords@^1.0.0: ajv-keywords@^1.0.0:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
@ -290,7 +297,7 @@ async@2.0.1:
dependencies: dependencies:
lodash "^4.8.0" lodash "^4.8.0"
async@^1.4.0: async@^1.4.0, async@^1.5.2:
version "1.5.2" version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
@ -1298,6 +1305,10 @@ circular-json@^0.3.1:
version "0.3.1" version "0.3.1"
resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d"
clean-stack@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31"
cli-cursor@^1.0.1, cli-cursor@^1.0.2: cli-cursor@^1.0.1, cli-cursor@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
@ -1514,6 +1525,13 @@ cross-env@5.0.1:
cross-spawn "^5.1.0" cross-spawn "^5.1.0"
is-windows "^1.0.0" is-windows "^1.0.0"
cross-spawn-async@^2.1.1:
version "2.2.5"
resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc"
dependencies:
lru-cache "^4.0.0"
which "^1.2.8"
cross-spawn@5.1.0, cross-spawn@^5.0.1, cross-spawn@^5.1.0: cross-spawn@5.1.0, cross-spawn@^5.0.1, cross-spawn@^5.1.0:
version "5.1.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
@ -2096,6 +2114,14 @@ exec-sh@^0.2.0:
dependencies: dependencies:
merge "^1.1.3" merge "^1.1.3"
execa@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.1.1.tgz#b09c2a9309bc0ef0501479472db3180f8d4c3edd"
dependencies:
cross-spawn-async "^2.1.1"
object-assign "^4.0.1"
strip-eof "^1.0.0"
execa@^0.5.0: execa@^0.5.0:
version "0.5.1" version "0.5.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.5.1.tgz#de3fb85cb8d6e91c85bcbceb164581785cb57b36" resolved "https://registry.yarnpkg.com/execa/-/execa-0.5.1.tgz#de3fb85cb8d6e91c85bcbceb164581785cb57b36"
@ -2108,6 +2134,18 @@ execa@^0.5.0:
signal-exit "^3.0.0" signal-exit "^3.0.0"
strip-eof "^1.0.0" strip-eof "^1.0.0"
execa@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.6.3.tgz#57b69a594f081759c69e5370f0d17b9cb11658fe"
dependencies:
cross-spawn "^5.0.1"
get-stream "^3.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
execa@^0.7.0: execa@^0.7.0:
version "0.7.0" version "0.7.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
@ -2321,6 +2359,15 @@ find-up@^2.0.0, find-up@^2.1.0:
dependencies: dependencies:
locate-path "^2.0.0" locate-path "^2.0.0"
fkill@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/fkill/-/fkill-5.0.0.tgz#642f746aa631c965afc76c0d56dcc492a1ee504f"
dependencies:
aggregate-error "^1.0.0"
arrify "^1.0.0"
execa "^0.6.3"
taskkill "^2.0.0"
flat-cache@^1.2.1: flat-cache@^1.2.1:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96"
@ -3599,7 +3646,7 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
dependencies: dependencies:
js-tokens "^3.0.0" js-tokens "^3.0.0"
lru-cache@^4.0.1: lru-cache@^4.0.0, lru-cache@^4.0.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
dependencies: dependencies:
@ -3764,7 +3811,7 @@ mkdirp@0.5.0:
dependencies: dependencies:
minimist "0.0.8" minimist "0.0.8"
"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
version "0.5.1" version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies: dependencies:
@ -4291,6 +4338,14 @@ pluralize@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
portfinder@^1.0.13:
version "1.0.13"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
dependencies:
async "^1.5.2"
debug "^2.2.0"
mkdirp "0.5.x"
prelude-ls@~1.1.2: prelude-ls@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@ -4371,11 +4426,11 @@ public-encrypt@^4.0.0:
parse-asn1 "^5.0.0" parse-asn1 "^5.0.0"
randombytes "^2.0.1" randombytes "^2.0.1"
punycode@1.3.2: punycode@1.3.2, punycode@^1.2.4:
version "1.3.2" version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
punycode@^1.2.4, punycode@^1.4.1: punycode@^1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
@ -5181,6 +5236,13 @@ tar@^2.2.1:
fstream "^1.0.2" fstream "^1.0.2"
inherits "2" inherits "2"
taskkill@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/taskkill/-/taskkill-2.0.0.tgz#a354305702a964357033027aa949eaed5331b784"
dependencies:
arrify "^1.0.0"
execa "^0.1.1"
taskr@1.0.6: taskr@1.0.6:
version "1.0.6" version "1.0.6"
resolved "https://registry.yarnpkg.com/taskr/-/taskr-1.0.6.tgz#6ba5b671f51703f780fb6335d3dc792cfcf9c192" resolved "https://registry.yarnpkg.com/taskr/-/taskr-1.0.6.tgz#6ba5b671f51703f780fb6335d3dc792cfcf9c192"
@ -5539,7 +5601,7 @@ which-module@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
which@^1.2.10, which@^1.2.12, which@^1.2.4, which@^1.2.9: which@^1.2.10, which@^1.2.12, which@^1.2.4, which@^1.2.8, which@^1.2.9:
version "1.2.14" version "1.2.14"
resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
dependencies: dependencies: