Repository: eslint/eslint (js)

Issue:
Switch browserify to webpack or other bundler
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).

    This template is for requesting a change that is not a bug fix, rule change, or new rule. If you are here for another reason, please see below:

    1. To report a bug: https://eslint.org/docs/developer-guide/contributing/reporting-bugs
    2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
    3. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
    4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint

    Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->

**The problem you want to solve.**
Browserify isn't under active development. Should we consider switching to webpack or other bundler?

This not only relates browserify only, but also other build tool. For example, we can use `babel-loader` or `rollup-plugin-babel` instead of `babelify`.

**Your take on the correct solution to problem.**
1. Remove browserify from the build steps of ESLint.
2. Add webpack or other bundler.
3. Update the Karma config, and use some preprocessors if necessary.

**Are you willing to submit a pull request to implement this change?**
Yes.

Pull request description:
Build: switch from browserify to webpack (fixes #11366)
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[x] Other, please explain: Changes related to build

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**
Removed browserify, and added webpack, which brought smaller bundle size (not too much). And, build time should be reduced.

**Is there anything you'd like reviewers to focus on?**
Maybe the `Makefile.js` and `webpack.config.js`.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index acbd83a2d..89eb84613 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,46 @@
+v5.14.1 - February 18, 2019
+
+* [`1d6e639`](https://github.com/eslint/eslint/commit/1d6e63930073e79e52890f552cc6e9a0646b7fb4) Fix: sort-keys throws Error at SpreadElement (fixes #11402) (#11403) (Krist Wongsuphasawat)
+
+v5.14.0 - February 15, 2019
+
+* [`85a04b3`](https://github.com/eslint/eslint/commit/85a04b319e6dfde1458174cd1d8c9e7d33da0871) Fix: adds conditional for separateRequires in one-var (fixes #10179) (#10980) (Scott Stern)
+* [`0c02932`](https://github.com/eslint/eslint/commit/0c02932f1b2e2a85809e84617efa1b8836c19cfb) Upgrade: espree@5.0.1 (#11401) (Ilya Volodin)
+* [`104ae88`](https://github.com/eslint/eslint/commit/104ae881d0b21e9c64e006b2a2c21535cef0ad28) Docs: Update governance doc with reviewers status (#11399) (Nicholas C. Zakas)
+* [`ab8ac6a`](https://github.com/eslint/eslint/commit/ab8ac6adaaf7a88e160899e7f438a4cfd655eb6e) Fix: Support boundary spread elements in sort-keys (#11158) (Jakub Rożek)
+* [`a23d197`](https://github.com/eslint/eslint/commit/a23d1975d48841eafdead1a1357e2af842f688bc) New: add allowSingleLineBlocks opt. to padded-blocks rule (fixes #7145) (#11243) (richie3366)
+* [`e25e7aa`](https://github.com/eslint/eslint/commit/e25e7aa3ea1e8c9b3cd3242acda6d4a5572c2c6a) Fix: comma-spacing ignore comma before closing paren (fixes #11295) (#11374) (Pig Fang)
+* [`a1f7c44`](https://github.com/eslint/eslint/commit/a1f7c44ea9efbd9393889c1cc91b74260e0a8e02) Docs: fix space-before-blocks correct code for "classes": "never" (#11391) (PoziWorld)
+* [`14f58a2`](https://github.com/eslint/eslint/commit/14f58a2bec4d6aade0de22771c378b86b1e51959) Docs: fix grammar in object-curly-spacing docs (#11389) (PoziWorld)
+* [`d3e9a27`](https://github.com/eslint/eslint/commit/d3e9a27bbba30008a610df59e82b7192f0ecc3a3) Docs: fix grammar in “those who says” (#11390) (PoziWorld)
+* [`ea8e804`](https://github.com/eslint/eslint/commit/ea8e8045ba0e6c1e1015104346af962f3e16fd81) Docs: Add note about support for object spread (fixes #11136) (#11395) (Steven Thomas)
+* [`95aa3fd`](https://github.com/eslint/eslint/commit/95aa3fdb392d265e6c3d813d54076458e88e7ad8) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`51c4972`](https://github.com/eslint/eslint/commit/51c497298a15ad296a2b1f8fc397df687976b836) Update: Behavior of --init (fixes #11105) (#11332) (Nicholas C. Zakas)
+* [`ad7a380`](https://github.com/eslint/eslint/commit/ad7a38097c32a91e5a831ef1bc8933601532576c) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`550de1e`](https://github.com/eslint/eslint/commit/550de1e611a1e9af873bcb18d74cf2056e8d2e1b) Update: use `default` keyword in JSON schema (fixes #9929) (#11288) (Pig Fang)
+* [`983c520`](https://github.com/eslint/eslint/commit/983c5201210d7a4ffab0b3d05ab9919c0754e5ca) Update: Use 'readonly' and 'writable' for globals (fixes #11359) (#11384) (Nicholas C. Zakas)
+* [`f1d3a7e`](https://github.com/eslint/eslint/commit/f1d3a7ee7c82365989e219b1dae379f08f6dd526) Upgrade: some deps (fixes #11372) (#11373) (薛定谔的猫)
+* [`3e0c417`](https://github.com/eslint/eslint/commit/3e0c4176eff085498b813f8ba1732d7ed6ee44f8) Docs: Fix grammar in “there’s nothing prevent you” (#11385) (PoziWorld)
+* [`de988bc`](https://github.com/eslint/eslint/commit/de988bc909b491366ad0cd9bc83f4d6de42d041a) Docs: Fix grammar: Spacing improve -> Spacing improves (#11386) (PoziWorld)
+* [`1309dfd`](https://github.com/eslint/eslint/commit/1309dfdebb5595460b79dcac20df6a1f109e7566) Revert "Build: fix test failure on Node 11 (#11100)" (#11375) (薛定谔的猫)
+* [`1e56897`](https://github.com/eslint/eslint/commit/1e56897db3e254e0aef6d2fe3274157fc379c79e) Docs: “the function actually use”: use -> uses (#11380) (PoziWorld)
+* [`5a71bc9`](https://github.com/eslint/eslint/commit/5a71bc95a7e961b1b1b77022645e0bd9cdd08dc0) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`82a58ce`](https://github.com/eslint/eslint/commit/82a58ce26b282fd80335b3ac4fc88f21266c3ba1) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`546d355`](https://github.com/eslint/eslint/commit/546d355ace65631e27de859baea3ffcc50e0ad2c) Docs: Update README with latest sponsors/team data (#11378) (Nicholas C. Zakas)
+* [`c0df9fe`](https://github.com/eslint/eslint/commit/c0df9febb7c7e045ababc10b88dbcbb3f28c724c) Docs: `...` is not an operator (#11232) (Felix Kling)
+* [`7ecfdef`](https://github.com/eslint/eslint/commit/7ecfdefaeadb772f8b96ffe37c4a2c97fde0da16) Docs: update typescript parser (refs #11368) (#11369) (薛定谔的猫)
+* [`3c90dd7`](https://github.com/eslint/eslint/commit/3c90dd7e25cf97833deddb11cfbc107a5663ac08) Update: remove prefer-spread autofix (fixes #11330) (#11365) (薛定谔的猫)
+* [`5eb3121`](https://github.com/eslint/eslint/commit/5eb3121b82c1837da0c3021b7d9384bb30832e36) Update: add fixer for `prefer-destructuring` (fixes #11151) (#11301) (golopot)
+* [`173eb38`](https://github.com/eslint/eslint/commit/173eb38cdb3e4673cba947521f27158828186d77) Docs: Clarify ecmaVersion doesn't imply globals (refs #9812) (#11364) (Keith Maxwell)
+* [`84ce72f`](https://github.com/eslint/eslint/commit/84ce72fdeba082b7b132e4ac6b714fb1a93831b7) Fix: Remove extraneous linefeeds in `one-var` fixer (fixes #10741) (#10955) (st-sloth)
+* [`389362a`](https://github.com/eslint/eslint/commit/389362a06ac6601512b872d3e843c7371f2a1bcc) Docs: clarify motivation for no-prototype-builtins (#11356) (Teddy Katz)
+* [`533d240`](https://github.com/eslint/eslint/commit/533d240b0811f663494cb213b06cc9e51e1ff2d0) Update: no-shadow-restricted-names lets unassigned vars shadow undefined (#11341) (Teddy Katz)
+* [`d0e823a`](https://github.com/eslint/eslint/commit/d0e823aef196a6564c87a78b72c1ef980ce67af9) Update: Make --init run js config files through linter (fixes #9947) (#11337) (Brian Kurek)
+* [`92fc2f4`](https://github.com/eslint/eslint/commit/92fc2f4f3faf8aeaae8a8e71db0de405404fb6c3) Fix: CircularJSON dependency warning (fixes #11052) (#11314) (Terry)
+* [`4dd19a3`](https://github.com/eslint/eslint/commit/4dd19a3c4c037adc860a65e96f2ba3eeccace1de) Docs: mention 'prefer-spread' in docs of 'no-useless-call' (#11348) (Klaus Meinhardt)
+* [`4fd83d5`](https://github.com/eslint/eslint/commit/4fd83d5ec47a6a7b81cd8801c3bd63d27ea1c7c4) Docs: fix a misleading example in one-var (#11350) (薛定谔的猫)
+* [`9441ce7`](https://github.com/eslint/eslint/commit/9441ce77b7228f2c4562e158a10905afe11f31f2) Chore: update incorrect tests to fix build failing (#11354) (薛定谔的猫)
+
 v5.13.0 - February 1, 2019
 
 * [`91c8884`](https://github.com/eslint/eslint/commit/91c8884971f5e57f5f7490d8daf92c4a9a489836) Chore: use local function to append "s" instead of a package (#11293) (Timo Tijhof)
diff --git a/Makefile.js b/Makefile.js
index fa9227a5b..99d005268 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -595,7 +595,7 @@ target.test = function() {
         errors++;
     }
 
-    target.browserify();
+    target.webpack();
 
     lastReturn = exec(`${getBinFile("karma")} start karma.conf.js`);
     if (lastReturn.code !== 0) {
@@ -796,7 +796,7 @@ target.gensite = function(prereleaseVersion) {
     // 13. Update demos, but only for non-prereleases
     if (!prereleaseVersion) {
         echo("> Updating the demos (Step 13)");
-        target.browserify();
+        target.webpack("production");
         cp("-f", "build/eslint.js", `${SITE_DIR}js/app/eslint.js`);
     } else {
         echo("> Skipped updating the demos (Step 13)");
@@ -809,28 +809,8 @@ target.gensite = function(prereleaseVersion) {
     echo("Done generating eslint.org");
 };
 
-target.browserify = function() {
-
-    // 1. create temp and build directory
-    if (!test("-d", TEMP_DIR)) {
-        mkdir(TEMP_DIR);
-    }
-
-    if (!test("-d", BUILD_DIR)) {
-        mkdir(BUILD_DIR);
-    }
-
-    // 2. browserify the temp directory
-    exec(`${getBinFile("browserify")} -x espree lib/linter.js -o ${BUILD_DIR}eslint.js -s eslint --global-transform [ babelify --presets [ @babel/preset-env ] ]`);
-
-    // 3. Browserify espree
-    exec(`${getBinFile("browserify")} -r espree -o ${TEMP_DIR}espree.js --global-transform [ babelify --presets [ @babel/preset-env ] ]`);
-
-    // 4. Concatenate Babel polyfill, Espree, and ESLint files together
-    cat("./node_modules/@babel/polyfill/dist/polyfill.js", `${TEMP_DIR}espree.js`, `${BUILD_DIR}eslint.js`).to(`${BUILD_DIR}eslint.js`);
-
-    // 5. remove temp directory
-    rm("-rf", TEMP_DIR);
+target.webpack = function(mode = "none") {
+    exec(`${getBinFile("webpack")} --mode=${mode} --output-path=${path.resolve(__dirname, BUILD_DIR)}`);
 };
 
 target.checkRuleFiles = function() {
diff --git a/docs/developer-guide/development-environment.md b/docs/developer-guide/development-environment.md
index 3b3a12fb2..a93e1efbc 100644
--- a/docs/developer-guide/development-environment.md
+++ b/docs/developer-guide/development-environment.md
@@ -83,7 +83,7 @@ Be sure to run this after making changes and before sending a pull request with
 
 Runs just the JavaScript and JSON linting on the repository
 
-#### npm run browserify
+#### npm run webpack
 
 Generates `build/eslint.js`, a version of ESLint for use in the browser
 
diff --git a/docs/maintainer-guide/governance.md b/docs/maintainer-guide/governance.md
index a9852d512..ed110fe65 100644
--- a/docs/maintainer-guide/governance.md
+++ b/docs/maintainer-guide/governance.md
@@ -41,17 +41,39 @@ New Committers can be nominated by any existing Committer. Once they have been n
 
 It is important to recognize that committership is a privilege, not a right. That privilege must be earned and once earned it can be removed by the TSC members by a standard TSC motion. However, under normal circumstances committership exists for as long as the Committer wishes to continue engaging with the project.
 
-A Committer who shows an above-average level of contribution to the project, particularly with respect to its strategic direction and long-term health, may be nominated to become a TSC member, described below.
+A Committer who shows an above-average level of contribution to the project, particularly with respect to its strategic direction and long-term health, may be nominated to become a reviewer, described below.
 
 #### Process for Adding Committers
 
 1. Send email congratulating the new committer and confirming that they would like to accept. This should also outline the responsibilities of a committer with a link to the maintainer guide.
 1. Add the GitHub user to the "ESLint Team" team
 1. Add committer email to the ESLint team mailing list
-1. Add committer to the README
 1. Invite to Gitter team chatroom
 1. Tweet congratulations to the new committer from the ESLint Twitter account
 
+### Reviewers
+
+Reviewers are community members who have contributed a significant amount of time to the project through triaging of issues, fixing bugs, implementing enhancements/features, and are trusted community leaders.
+
+Reviewers may perform all of the duties of Committers, and also:
+
+* May merge external pull requests for accepted issues upon reviewing and approving the changes.
+* May merge their own pull requests once they have collected the feedback they deem necessary. (No pull request should be merged without at least one Committer/Reviewer/TSC member comment stating they've looked at the code.)
+
+To become a Reviewer:
+
+* Work in a helpful and collaborative way with the community.
+* Have given good feedback on others' submissions and displayed an overall understanding of the code quality standards for the project.
+* Commit to being a part of the community for the long-term.
+* Have submitted a minimum of 50 qualifying pull requests.
+
+A Committer is invited to become a Reviewer by existing Reviewers and TSC members. A nomination will result in discussion and then a decision by the TSC.
+
+#### Process for Adding Reviewers
+
+1. Add the GitHub user to the "ESLint Reviewers" GitHub team
+1. Tweet congratulations to the new Reviewer from the ESLint Twitter account
+
 ### Technical Steering Committee (TSC)
 
 The ESLint project is jointly governed by a Technical Steering Committee (TSC) which is responsible for high-level guidance of the project.
@@ -75,26 +97,22 @@ No more than 1/3 of the TSC members may be affiliated with the same employer. If
 
 TSC members have additional responsibilities over and above those of a Committer. These responsibilities ensure the smooth running of the project. TSC members are expected to review code contributions, approve changes to this document, manage the copyrights within the project outputs, and attend regular TSC meetings.
 
-TSC members fulfill all requirements of Committers, and also:
-
-* May merge external pull requests for accepted issues upon reviewing and approving the changes.
-* May merge their own pull requests once they have collected the feedback they deem necessary. (No pull request should be merged without at least one Committer/TSC member comment stating they've looked at the code.)
+TSC members may perform all of the duties of Reviewers, and also:
 
-To become a TSC member:
+* May release new versions of all ESLint projects.
+* May participate in TSC meetings.
+* May propose budget items.
+* May propose new ESLint projects.
 
-* Work in a helpful and collaborative way with the community.
-* Have given good feedback on others' submissions and displayed an overall understanding of the code quality standards for the project.
-* Commit to being a part of the community for the long-term.
-* Have submitted a minimum of 50 qualifying pull requests.
+There is no specific set of requirements or qualifications for TSC members beyond those that are expected of Reviewers.
 
-A Committer is invited to become a TSC member by existing TSC members. A nomination will result in discussion and then a decision by the TSC.
+A Reviewer is invited to become a TSC member by existing TSC members. A nomination will result in discussion and then a decision by the TSC.
 
 #### Process for Adding TSC Members
 
 1. Add the GitHub user to the "ESLint TSC" GitHub team
 1. Set the GitHub user to be have the "Owner" role for the ESLint organization
 1. Send a welcome email with a link to the [maintainer guide](./) and the [npm 2FA guide](./npm-2fa).
-1. Add the TSC member to the README
 1. Invite to the Gitter TSC chatroom
 1. Make the TSC member an admin on the ESLint team mailing list
 1. Add the TSC member to the recurring TSC meeting event on Google Calendar
@@ -115,7 +133,7 @@ The intention of the agenda is not to approve or review all patches.
 That should happen continuously on GitHub and be handled by the larger
 group of Committers.
 
-Any community member or committer can ask that something be added to
+Any community member, Committer, or Reviewer can ask that something be added to
 the next meeting's agenda by logging a GitHub Issue. Anyone can add the item to the agenda by adding
 the "tsc agenda" tag to the issue.
 
diff --git a/docs/rules/object-curly-spacing.md b/docs/rules/object-curly-spacing.md
index 8f88fc260..e7b054cdd 100644
--- a/docs/rules/object-curly-spacing.md
+++ b/docs/rules/object-curly-spacing.md
@@ -20,7 +20,7 @@ export { foo };
 
 ## Rule Details
 
-This rule enforce consistent spacing inside braces of object literals, destructuring assignments, and import/export specifiers.
+This rule enforces consistent spacing inside braces of object literals, destructuring assignments, and import/export specifiers.
 
 ## Options
 
diff --git a/docs/rules/padded-blocks.md b/docs/rules/padded-blocks.md
index 5c7908cff..d8b855ed3 100644
--- a/docs/rules/padded-blocks.md
+++ b/docs/rules/padded-blocks.md
@@ -20,7 +20,10 @@ This rule enforces consistent empty line padding within blocks.
 
 ## Options
 
-This rule has one option, which can be a string option or an object option.
+This rule has two options, the first one can be a string option or an object option.
+The second one is an object option, it can allow exceptions.
+
+### First option
 
 String option:
 
@@ -33,6 +36,10 @@ Object option:
 * `"classes"` require or disallow padding within classes
 * `"switches"` require or disallow padding within `switch` statements
 
+### Second option
+
+* `"allowSingleLineBlocks": true` allows single-line blocks
+
 ### always
 
 Examples of **incorrect** code for this rule with the default `"always"` option:
@@ -346,6 +353,42 @@ if (a) {
 }
 ```
 
+### always + allowSingleLineBlocks
+
+Examples of **incorrect** code for this rule with the `"always", {"allowSingleLineBlocks": true}` options:
+
+```js
+/*eslint padded-blocks: ["error", "always", { allowSingleLineBlocks: true }]*/
+
+if (a) {
+    b();
+}
+
+if (a) {
+
+    b();
+}
+
+if (a) {
+    b();
+
+}
+```
+
+Examples of **correct** code for this rule with the `"always", {"allowSingleLineBlocks": true}` options:
+
+```js
+/*eslint padded-blocks: ["error", "always", { allowSingleLineBlocks: true }]*/
+
+if (a) { b(); }
+
+if (a) {
+
+    b();
+
+}
+```
+
 ## When Not To Use It
 
 You can turn this rule off if you are not concerned with the consistency of padding within blocks.
diff --git a/docs/rules/prefer-object-spread.md b/docs/rules/prefer-object-spread.md
index b50e39716..95a646068 100644
--- a/docs/rules/prefer-object-spread.md
+++ b/docs/rules/prefer-object-spread.md
@@ -2,7 +2,7 @@
 
 When Object.assign is called using an object literal as the first argument, this rule requires using the object spread syntax instead. This rule also warns on cases where an `Object.assign` call is made using a single argument that is an object literal, in this case, the `Object.assign` call is not needed.
 
-Object spread is a declarative alternative which may perform better than the more dynamic, imperative `Object.assign`.
+Introduced in ES2018, object spread is a declarative alternative which may perform better than the more dynamic, imperative `Object.assign`.
 
 ## Rule Details
 
@@ -46,4 +46,4 @@ Object.assign(foo, { ...baz });
 
 ## When Not To Use It
 
-When object spread is not available in your codebase.
+This rule should not be used unless ES2018 is supported in your codebase.
diff --git a/docs/rules/semi.md b/docs/rules/semi.md
index c49b08faa..e345b0006 100644
--- a/docs/rules/semi.md
+++ b/docs/rules/semi.md
@@ -31,7 +31,7 @@ return;
 
 Effectively, a semicolon is inserted after the `return` statement, causing the code below it (a labeled literal inside a block) to be unreachable. This rule and the [no-unreachable](no-unreachable.md) rule will protect your code from such cases.
 
-On the other side of the argument are those who says that since semicolons are inserted automatically, they are optional and do not need to be inserted manually. However, the ASI mechanism can also be tricky to people who don't use semicolons. For example, consider this code:
+On the other side of the argument are those who say that since semicolons are inserted automatically, they are optional and do not need to be inserted manually. However, the ASI mechanism can also be tricky to people who don't use semicolons. For example, consider this code:
 
 ```js
 var globalCounter = { }
diff --git a/docs/rules/sort-keys.md b/docs/rules/sort-keys.md
index cd4b78983..e6c515568 100644
--- a/docs/rules/sort-keys.md
+++ b/docs/rules/sort-keys.md
@@ -53,7 +53,7 @@ let obj = {a: 1, ["c" + "d"]: 3, b: 2};
 let obj = {a: 1, [`${c}`]: 3, b: 2};
 let obj = {a: 1, [tag`c`]: 3, b: 2};
 
-// This rule ignores objects that have a spread operator in them.
+// This rule does not report unsorted properties that are separated by a spread property.
 let obj = {b: 1, ...c, a: 2};
 ```
 
diff --git a/docs/rules/space-before-blocks.md b/docs/rules/space-before-blocks.md
index ab4c2a2b4..0b188f260 100644
--- a/docs/rules/space-before-blocks.md
+++ b/docs/rules/space-before-blocks.md
@@ -143,7 +143,7 @@ describe(function(){
   // ...
 });
 
-class Foo {
+class Foo{
   constructor(){}
 }
 ```
diff --git a/karma.conf.js b/karma.conf.js
index 9b26395e9..595ba0c59 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -16,9 +16,6 @@ module.exports = function(config) {
 
         // list of files / patterns to load in the browser
         files: [
-            "node_modules/mocha/mocha.js",
-            "node_modules/chai/chai.js",
-            "node_modules/sinon/pkg/sinon.js",
             "build/eslint.js",
             "tests/lib/linter.js"
         ],
@@ -32,12 +29,14 @@ module.exports = function(config) {
         // preprocess matching files before serving them to the browser
         // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
         preprocessors: {
-            "tests/lib/linter.js": ["babel"]
+            "tests/lib/linter.js": ["webpack"]
         },
-        babelPreprocessor: {
-            options: {
-                presets: ["@babel/preset-env"]
-            }
+        webpack: {
+            mode: "none",
+            stats: "errors-only"
+        },
+        webpackMiddleware: {
+            logLevel: "error"
         },
 
 
diff --git a/lib/linter.js b/lib/linter.js
index 29505e9ac..2abd2d3ff 100644
--- a/lib/linter.js
+++ b/lib/linter.js
@@ -11,6 +11,7 @@
 
 const eslintScope = require("eslint-scope"),
     evk = require("eslint-visitor-keys"),
+    espree = require("espree"),
     lodash = require("lodash"),
     CodePathAnalyzer = require("./code-path-analysis/code-path-analyzer"),
     ConfigOps = require("./config/config-ops"),
@@ -776,6 +777,8 @@ module.exports = class Linter {
         ruleMaps.set(this, new Rules());
         this.version = pkg.version;
         this.environments = new Environments();
+
+        this.defineParser("espree", espree);
     }
 
     /**
diff --git a/lib/rules/comma-spacing.js b/lib/rules/comma-spacing.js
index 789de7843..a9f89676a 100644
--- a/lib/rules/comma-spacing.js
+++ b/lib/rules/comma-spacing.js
@@ -120,6 +120,10 @@ module.exports = {
                 report(reportItem, "before", tokens.left);
             }
 
+            if (tokens.right && astUtils.isClosingParenToken(tokens.right)) {
+                return;
+            }
+
             if (tokens.right && !options.after && tokens.right.type === "Line") {
                 return;
             }
diff --git a/lib/rules/one-var.js b/lib/rules/one-var.js
index 95b809fae..5a5c71b18 100644
--- a/lib/rules/one-var.js
+++ b/lib/rules/one-var.js
@@ -235,7 +235,9 @@ module.exports = {
 
             if (currentOptions.uninitialized === MODE_ALWAYS && currentOptions.initialized === MODE_ALWAYS) {
                 if (currentScope.uninitialized || currentScope.initialized) {
-                    return false;
+                    if (!hasRequires) {
+                        return false;
+                    }
                 }
             }
 
@@ -246,7 +248,9 @@ module.exports = {
             }
             if (declarationCounts.initialized > 0) {
                 if (currentOptions.initialized === MODE_ALWAYS && currentScope.initialized) {
-                    return false;
+                    if (!hasRequires) {
+                        return false;
+                    }
                 }
             }
             if (currentScope.required && hasRequires) {
diff --git a/lib/rules/padded-blocks.js b/lib/rules/padded-blocks.js
index 7c0b56ba7..e4dd37f4c 100644
--- a/lib/rules/padded-blocks.js
+++ b/lib/rules/padded-blocks.js
@@ -5,6 +5,12 @@
 
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../util/ast-utils");
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -45,32 +51,45 @@ module.exports = {
                         minProperties: 1
                     }
                 ]
+            },
+            {
+                type: "object",
+                properties: {
+                    allowSingleLineBlocks: {
+                        type: "boolean"
+                    }
+                }
             }
         ]
     },
 
     create(context) {
         const options = {};
-        const config = context.options[0] || "always";
+        const typeOptions = context.options[0] || "always";
+        const exceptOptions = context.options[1] || {};
 
-        if (typeof config === "string") {
-            const shouldHavePadding = config === "always";
+        if (typeof typeOptions === "string") {
+            const shouldHavePadding = typeOptions === "always";
 
             options.blocks = shouldHavePadding;
             options.switches = shouldHavePadding;
             options.classes = shouldHavePadding;
         } else {
-            if (Object.prototype.hasOwnProperty.call(config, "blocks")) {
-                options.blocks = config.blocks === "always";
+            if (Object.prototype.hasOwnProperty.call(typeOptions, "blocks")) {
+                options.blocks = typeOptions.blocks === "always";
             }
-            if (Object.prototype.hasOwnProperty.call(config, "switches")) {
-                options.switches = config.switches === "always";
+            if (Object.prototype.hasOwnProperty.call(typeOptions, "switches")) {
+                options.switches = typeOptions.switches === "always";
             }
-            if (Object.prototype.hasOwnProperty.call(config, "classes")) {
-                options.classes = config.classes === "always";
+            if (Object.prototype.hasOwnProperty.call(typeOptions, "classes")) {
+                options.classes = typeOptions.classes === "always";
             }
         }
 
+        if (Object.prototype.hasOwnProperty.call(exceptOptions, "allowSingleLineBlocks")) {
+            options.allowSingleLineBlocks = exceptOptions.allowSingleLineBlocks === true;
+        }
+
         const ALWAYS_MESSAGE = "Block must be padded by blank lines.",
             NEVER_MESSAGE = "Block must not be padded by blank lines.";
 
@@ -177,6 +196,10 @@ module.exports = {
                 blockHasTopPadding = isPaddingBetweenTokens(tokenBeforeFirst, firstBlockToken),
                 blockHasBottomPadding = isPaddingBetweenTokens(lastBlockToken, tokenAfterLast);
 
+            if (options.allowSingleLineBlocks && astUtils.isTokenOnSameLine(tokenBeforeFirst, tokenAfterLast)) {
+                return;
+            }
+
             if (requirePaddingFor(node)) {
                 if (!blockHasTopPadding) {
                     context.report({
diff --git a/lib/rules/sort-keys.js b/lib/rules/sort-keys.js
index 1e8a85e3d..fd5dd8a13 100644
--- a/lib/rules/sort-keys.js
+++ b/lib/rules/sort-keys.js
@@ -129,8 +129,14 @@ module.exports = {
                 stack = stack.upper;
             },
 
+            SpreadElement(node) {
+                if (node.parent.type === "ObjectExpression") {
+                    stack.prevName = null;
+                }
+            },
+
             Property(node) {
-                if (node.parent.type === "ObjectPattern" || node.parent.properties.some(n => n.type === "SpreadElement")) {
+                if (node.parent.type === "ObjectPattern") {
                     return;
                 }
 
diff --git a/package.json b/package.json
index cd25a4013..5fea28537 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "5.13.0",
+  "version": "5.14.1",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
@@ -18,7 +18,7 @@
     "publish-release": "node Makefile.js publishRelease",
     "docs": "node Makefile.js docs",
     "gensite": "node Makefile.js gensite",
-    "browserify": "node Makefile.js browserify",
+    "webpack": "node Makefile.js webpack",
     "perf": "node Makefile.js perf",
     "profile": "beefy tests/bench/bench.js --open -- -t brfs -t ./tests/bench/xform-rules.js -r espree",
     "coveralls": "cat ./coverage/lcov.info | coveralls"
@@ -44,7 +44,7 @@
     "eslint-scope": "^4.0.0",
     "eslint-utils": "^1.3.1",
     "eslint-visitor-keys": "^1.0.0",
-    "espree": "^5.0.0",
+    "espree": "^5.0.1",
     "esquery": "^1.0.1",
     "esutils": "^2.0.2",
     "file-entry-cache": "^5.0.1",
@@ -76,10 +76,9 @@
     "@babel/core": "^7.2.2",
     "@babel/polyfill": "^7.2.5",
     "@babel/preset-env": "^7.3.1",
-    "babelify": "^10.0.0",
+    "babel-loader": "^8.0.5",
     "beefy": "^2.1.8",
     "brfs": "^2.0.0",
-    "browserify": "^16.2.2",
     "chai": "^4.0.1",
     "cheerio": "^0.22.0",
     "common-tags": "^1.8.0",
@@ -96,10 +95,10 @@
     "istanbul": "^0.4.5",
     "jsdoc": "^3.5.5",
     "karma": "^3.1.4",
-    "karma-babel-preprocessor": "^8.0.0",
     "karma-chrome-launcher": "^2.2.0",
     "karma-mocha": "^1.3.0",
     "karma-mocha-reporter": "^2.2.3",
+    "karma-webpack": "^4.0.0-rc.6",
     "leche": "^2.2.3",
     "load-perf": "^0.2.0",
     "markdownlint": "^0.12.0",
@@ -111,7 +110,9 @@
     "shelljs": "^0.8.2",
     "sinon": "^3.3.0",
     "temp": "^0.9.0",
-    "through": "^2.3.8"
+    "through": "^2.3.8",
+    "webpack": "^4.29.3",
+    "webpack-cli": "^3.2.3"
   },
   "keywords": [
     "ast",
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 000000000..209c75a9e
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,23 @@
+module.exports = {
+    mode: "none",
+    entry: ["@babel/polyfill", "./lib/linter.js"],
+    output: {
+        filename: "eslint.js",
+        library: "eslint",
+        libraryTarget: "umd",
+        globalObject: "this"
+    },
+    module: {
+        rules: [
+            {
+                test: /\.js$/,
+                loader: "babel-loader",
+                options: {
+                    presets: ["@babel/preset-env"]
+                },
+                exclude: /node_modules/
+            }
+        ]
+    },
+    stats: "errors-only"
+};


Test patch:
diff --git a/tests/lib/linter.js b/tests/lib/linter.js
index 564bcee6b..78a31380e 100644
--- a/tests/lib/linter.js
+++ b/tests/lib/linter.js
@@ -32,10 +32,11 @@ function compatRequire(name, windowName) {
 // Requirements
 //------------------------------------------------------------------------------
 
-const assert = compatRequire("chai").assert,
-    sinon = compatRequire("sinon"),
-    path = compatRequire("path"),
-    Linter = compatRequire("../../lib/linter", "eslint");
+const assert = require("chai").assert,
+    sinon = require("sinon"),
+    path = require("path");
+
+const Linter = compatRequire("../../lib/linter", "eslint");
 
 //------------------------------------------------------------------------------
 // Constants
diff --git a/tests/lib/rules/comma-spacing.js b/tests/lib/rules/comma-spacing.js
index d5c8ff0ec..2df7c71fa 100644
--- a/tests/lib/rules/comma-spacing.js
+++ b/tests/lib/rules/comma-spacing.js
@@ -61,6 +61,10 @@ ruleTester.run("comma-spacing", rule, {
         "['  ,  ']",
         { code: "[`  ,  `]", parserOptions: { ecmaVersion: 6 } },
         { code: "`${[1, 2]}`", parserOptions: { ecmaVersion: 6 } },
+        { code: "fn(a, b,)", parserOptions: { ecmaVersion: 2018 } }, // #11295
+        { code: "const fn = (a, b,) => {}", parserOptions: { ecmaVersion: 2018 } }, // #11295
+        { code: "const fn = function (a, b,) {}", parserOptions: { ecmaVersion: 2018 } }, // #11295
+        { code: "function fn(a, b,) {}", parserOptions: { ecmaVersion: 2018 } }, // #11295
         "foo(/,/, 'a')",
         "var x = ',,,,,';",
         "var code = 'var foo = 1, bar = 3;'",
diff --git a/tests/lib/rules/one-var.js b/tests/lib/rules/one-var.js
index 3ab9d7473..ec7aa9338 100644
--- a/tests/lib/rules/one-var.js
+++ b/tests/lib/rules/one-var.js
@@ -209,6 +209,14 @@ ruleTester.run("one-var", rule, {
             options: [{ separateRequires: true, var: "always" }],
             parserOptions: { env: { node: true } }
         },
+        {
+            code: "var bar = 'bar'; var foo = require('foo');",
+            options: [{ separateRequires: true, var: "always" }]
+        },
+        {
+            code: "var foo = require('foo'); var bar = 'bar';",
+            options: [{ separateRequires: true, var: "always" }]
+        },
         {
             code: "var foo = require('foo'); var bar = 'bar';",
             options: [{ separateRequires: true, var: "always" }],
@@ -1092,6 +1100,17 @@ ruleTester.run("one-var", rule, {
                 column: 25
             }]
         },
+        {
+            code: "var a = true; var b = false;",
+            output: "var a = true,  b = false;",
+            options: [{ separateRequires: true, var: "always" }],
+            errors: [{
+                message: "Combine this with the previous 'var' statement.",
+                type: "VariableDeclaration",
+                line: 1,
+                column: 15
+            }]
+        },
         {
             code: "const a = 0; let b = 1; let c = 2; const d = 3;",
             output: "const a = 0; let b = 1,  c = 2; const d = 3;",
diff --git a/tests/lib/rules/padded-blocks.js b/tests/lib/rules/padded-blocks.js
index fb363cdf3..08ed2856c 100644
--- a/tests/lib/rules/padded-blocks.js
+++ b/tests/lib/rules/padded-blocks.js
@@ -54,6 +54,8 @@ ruleTester.run("padded-blocks", rule, {
         { code: "{\na();}", options: ["never"] },
         { code: "{a();\n}", options: ["never"] },
         { code: "{a();}", options: ["never"] },
+        { code: "{a();}", options: ["always", { allowSingleLineBlocks: true }] },
+        { code: "{\n\na();\n\n}", options: ["always", { allowSingleLineBlocks: true }] },
         { code: "{//comment\na();}", options: ["never"] },
         { code: "{\n//comment\na()\n}", options: ["never"] },
         { code: "{a();//comment\n}", options: ["never"] },
diff --git a/tests/lib/rules/sort-keys.js b/tests/lib/rules/sort-keys.js
index 5a3a0a057..1ae091fad 100644
--- a/tests/lib/rules/sort-keys.js
+++ b/tests/lib/rules/sort-keys.js
@@ -33,9 +33,22 @@ ruleTester.run("sort-keys", rule, {
         // ignore non-simple computed properties.
         { code: "var obj = {a:1, b:3, [a + b]: -1, c:2}", options: [], parserOptions: { ecmaVersion: 6 } },
 
-        // ignore spread properties.
+        // ignore properties separated by spread properties
         { code: "var obj = {a:1, ...z, b:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
         { code: "var obj = {b:1, ...z, a:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
+        { code: "var obj = {...a, b:1, ...c, d:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
+        { code: "var obj = {...a, b:1, ...d, ...c, e:2, z:5}", options: [], parserOptions: { ecmaVersion: 2018 } },
+        { code: "var obj = {b:1, ...c, ...d, e:2}", options: [], parserOptions: { ecmaVersion: 2018 } },
+
+        // not ignore properties not separated by spread properties
+        { code: "var obj = {...z, a:1, b:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
+        { code: "var obj = {...z, ...c, a:1, b:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
+        { code: "var obj = {a:1, b:1, ...z}", options: [], parserOptions: { ecmaVersion: 2018 } },
+        { code: "var obj = {...z, ...x, a:1, ...c, ...d, f:5, e:4}", options: ["desc"], parserOptions: { ecmaVersion: 2018 } },
+
+        // works when spread occurs somewhere other than an object literal
+        { code: "function fn(...args) { return [...args].length; }", options: [], parserOptions: { ecmaVersion: 2018 } },
+        { code: "function g() {}; function f(...args) { return g(...args); }", options: [], parserOptions: { ecmaVersion: 2018 } },
 
         // ignore destructuring patterns.
         { code: "let {a, b} = {}", options: [], parserOptions: { ecmaVersion: 6 } },
@@ -151,6 +164,53 @@ ruleTester.run("sort-keys", rule, {
             errors: ["Expected object keys to be in ascending order. 'Z' should be before 'À'."]
         },
 
+        // not ignore properties not separated by spread properties
+        {
+            code: "var obj = {...z, c:1, b:1}",
+            options: [],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: ["Expected object keys to be in ascending order. 'b' should be before 'c'."]
+        },
+        {
+            code: "var obj = {...z, ...c, d:4, b:1, ...y, ...f, e:2, a:1}",
+            options: [],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: [
+                "Expected object keys to be in ascending order. 'b' should be before 'd'.",
+                "Expected object keys to be in ascending order. 'a' should be before 'e'."
+            ]
+        },
+        {
+            code: "var obj = {c:1, b:1, ...a}",
+            options: [],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: ["Expected object keys to be in ascending order. 'b' should be before 'c'."]
+        },
+        {
+            code: "var obj = {...z, ...a, c:1, b:1}",
+            options: [],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: ["Expected object keys to be in ascending order. 'b' should be before 'c'."]
+        },
+        {
+            code: "var obj = {...z, b:1, a:1, ...d, ...c}",
+            options: [],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: ["Expected object keys to be in ascending order. 'a' should be before 'b'."]
+        },
+        {
+            code: "var obj = {...z, a:2, b:0, ...x, ...c}",
+            options: ["desc"],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: ["Expected object keys to be in descending order. 'b' should be before 'a'."]
+        },
+        {
+            code: "var obj = {...z, a:2, b:0, ...x}",
+            options: ["desc"],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: ["Expected object keys to be in descending order. 'b' should be before 'a'."]
+        },
+
         // not ignore simple computed properties.
         {
             code: "var obj = {a:1, b:3, [a]: -1, c:2}",