From b3b1fe15e035f119d5e30bfe8819ee4df36dbf22 Mon Sep 17 00:00:00 2001
From: Umur Kontaci <umur@umur.io>
Date: Thu, 16 Jun 2016 23:41:13 -0700
Subject: [PATCH] Add console error for ES6 instance functions in development
 environments

---
 client/boot/index.js                        |  3 +
 client/lib/wrap-es6-functions/index.js      | 28 +++++++++
 client/lib/wrap-es6-functions/test/index.js | 70 +++++++++++++++++++++
 3 files changed, 101 insertions(+)
 create mode 100644 client/lib/wrap-es6-functions/index.js
 create mode 100644 client/lib/wrap-es6-functions/test/index.js

diff --git a/client/boot/index.js b/client/boot/index.js
index 4f6279301dbea..77d3db97d050b 100644
--- a/client/boot/index.js
+++ b/client/boot/index.js
@@ -1,5 +1,8 @@
 // Initialize localStorage polyfill before any dependencies are loaded
 require( 'lib/local-storage' )();
+if ( process.env.NODE_ENV === 'development' ) {
+	require( 'lib/wrap-es6-functions' )();
+}
 
 /**
  * External dependencies
diff --git a/client/lib/wrap-es6-functions/index.js b/client/lib/wrap-es6-functions/index.js
new file mode 100644
index 0000000000000..0026f4afafd77
--- /dev/null
+++ b/client/lib/wrap-es6-functions/index.js
@@ -0,0 +1,28 @@
+import partial from 'lodash/partial';
+import isFunction from 'lodash/isFunction';
+
+function wrapFnWithWarning( fn, name ) {
+	const consoleFn = ( console.error || console.log ).bind( console );
+	return function() {
+		const err = new Error( `${ name } is not supported on all browsers. You must use a replacement method from lodash.` );
+		consoleFn( err );
+		return fn.apply( this, arguments );
+	}
+}
+
+function wrapObjectFn( obj, objectName, key ) {
+	if ( isFunction( obj[ key ] ) ) {
+		Object.defineProperty( obj, key, { value: wrapFnWithWarning( obj[ key ], `${ objectName }${ key}` ) } );
+	}
+}
+
+export default function() {
+	[ 'keys', 'entries', 'values', 'findIndex', 'fill', 'find' ]
+		.map( partial( wrapObjectFn, Array.prototype, 'Array#' ) );
+
+	[ 'codePointAt', 'normalize', 'repeat', 'startsWith', 'endsWith', 'includes' ]
+		.map( partial( wrapObjectFn, String.prototype, 'String#' ) );
+
+	[ 'flags' ].map( partial( wrapObjectFn, RegExp.prototype, 'RegExp#' ) );
+
+}
diff --git a/client/lib/wrap-es6-functions/test/index.js b/client/lib/wrap-es6-functions/test/index.js
new file mode 100644
index 0000000000000..cc566a13572e0
--- /dev/null
+++ b/client/lib/wrap-es6-functions/test/index.js
@@ -0,0 +1,70 @@
+/**
+ * External Dependencies
+ */
+import partial from 'lodash/partial';
+import assert from 'assert';
+import isFunction from 'lodash/isFunction';
+
+/**
+ * Internal Dependencies
+ */
+import { useSandbox } from 'test/helpers/use-sinon';
+
+
+describe( 'wrapping', () => {
+	let sandbox,
+		arrayProps = [ 'keys', 'entries', 'values', 'findIndex', 'fill', 'find' ].filter( key => isFunction( Array.prototype[ key ] ) ),
+		stringProps = [ 'codePointAt', 'normalize', 'repeat', 'startsWith', 'endsWith', 'includes' ].filter( key => isFunction( String.prototype[ key ] ) ),
+		consoleSpy,
+		regExpProps = [ 'flags' ].filter( key => isFunction( RegExp.prototype[ key ] ) );
+
+	function installSpies( props, obj ) {
+		props.forEach( key => {
+			sandbox.spy( obj, key );
+		} );
+	}
+
+	function assertCall( obj, args, key ) {
+		it( key, () => {
+			if ( isFunction( obj[ key ] ) ) {
+				obj[ key ].apply( obj, args );
+				assert( consoleSpy.calledOnce );
+			}
+		} )
+	}
+
+	useSandbox( newSandbox => sandbox = newSandbox );
+	before( () => {
+		consoleSpy = sandbox.stub( console, 'error' );
+		installSpies( arrayProps, Array.prototype );
+		installSpies( stringProps, String.prototype );
+		installSpies( regExpProps, RegExp.prototype );
+
+		require( '../' )();
+	} );
+
+	after( () => {
+		sandbox.restore();
+	} );
+
+	beforeEach( () => {
+		consoleSpy.reset();
+	} );
+
+	describe( 'Array', () => {
+		[ 'keys', 'entries', 'values' ].forEach( partial( assertCall, Array.prototype, [] ) );
+		[ 'findIndex', 'find' ].forEach( partial( assertCall, Array.prototype, [ () => true ] ) );
+		[ 'fill' ].forEach( partial( assertCall, Array.prototype, [ 1 ] ) );
+	} );
+
+	describe( 'String', () => {
+		[ 'codePointAt', 'repeat' ].forEach( partial( assertCall, 'hello', [ 1 ] ) );
+		[ 'startsWith', 'endsWith', 'includes' ].forEach( partial( assertCall, 'hello', [ 'a' ] ) );
+		[ 'normalize' ].forEach( partial( assertCall, 'hello', [] ) );
+	} );
+
+	describe( 'RegExp', () => {
+		[ 'flags' ].forEach( partial( assertCall, /a/, 'flags', [ 'g' ] ) );
+	} );
+
+} );