Repository: yargs/yargs (js)

Issue:
Using `hasOwnProperty` breaks for config objects with null prototype
I'm loading a config object from a third-party library, then passing it to yargs.  This library happens to return an object with a null prototype.  yargs breaks because it's trying to call `config.hasOwnProperty`.

https://github.com/yargs/yargs/blob/master/lib/apply-extends.js#L22

Pull request description:
fix: tolerate null prototype for config objects with `extends`
Fixes #1372

Patch:
diff --git a/lib/apply-extends.js b/lib/apply-extends.js
index 1436b65..864567a 100644
--- a/lib/apply-extends.js
+++ b/lib/apply-extends.js
@@ -19,7 +19,7 @@ function getPathToDefaultConfig (cwd, pathToExtend) {
 function applyExtends (config, cwd) {
   let defaultConfig = {}
 
-  if (config.hasOwnProperty('extends')) {
+  if (Object.prototype.hasOwnProperty.call(config, 'extends')) {
     if (typeof config.extends !== 'string') return defaultConfig
     const isPath = /\.json|\..*rc$/.test(config.extends)
     let pathToDefault = null
diff --git a/lib/decamelize.js b/lib/decamelize.js
deleted file mode 100644
index c3a4151..0000000
--- a/lib/decamelize.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-MIT License
-
-Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
-
-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.
-*/
-'use strict'
-
-module.exports = (text, separator) => {
-  separator = typeof separator === 'undefined' ? '_' : separator
-
-  return text
-    .replace(/([a-z\d])([A-Z])/g, `$1${separator}$2`)
-    .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, `$1${separator}$2`)
-    .toLowerCase()
-}
diff --git a/lib/usage.js b/lib/usage.js
index 8c3b068..cbcb176 100644
--- a/lib/usage.js
+++ b/lib/usage.js
@@ -1,7 +1,7 @@
 'use strict'
 // this file handles outputting usage instructions,
 // failures, etc. keeps logging in one place.
-const decamelize = require('./decamelize')
+const decamelize = require('decamelize')
 const stringWidth = require('string-width')
 const objFilter = require('./obj-filter')
 const path = require('path')
diff --git a/package.json b/package.json
index 436c04b..f8f06cf 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
   ],
   "dependencies": {
     "cliui": "^5.0.0",
+    "decamelize": "^1.2.0",
     "find-up": "^3.0.0",
     "get-caller-file": "^2.0.1",
     "require-directory": "^2.1.1",


Test patch:
diff --git a/test/yargs.js b/test/yargs.js
index 66c5bf8..e64802e 100644
--- a/test/yargs.js
+++ b/test/yargs.js
@@ -1292,6 +1292,20 @@ describe('yargs dsl tests', () => {
         argv.z.should.equal(15)
       })
 
+      it('tolerates null prototype config objects', () => {
+        const argv = yargs
+          .config({
+            __proto__: null,
+            a: 2,
+            extends: './test/fixtures/extends/config_1.json'
+          })
+          .parse()
+
+        argv.a.should.equal(2)
+        argv.b.should.equal(22)
+        argv.z.should.equal(15)
+      })
+
       // see: https://www.npmjs.com/package/yargs-test-extends
       it('allows a module to be extended, rather than a JSON file', () => {
         const argv = yargs()