From 761b877626e9f056464f3ef12923d0bb768c276b Mon Sep 17 00:00:00 2001 From: Pat O'Neill Date: Fri, 2 Dec 2016 15:51:41 -0500 Subject: [PATCH] feat: Eliminate lodash-compat as a dependency, rewrite mergeOptions (#3760) --- build/grunt.js | 2 +- build/options-customizer.js | 2 +- package.json | 2 +- .../progress-control/mouse-time-display.js | 3 +- src/js/utils/fn.js | 33 ++++++++- src/js/utils/merge-options.js | 73 +++++++------------ src/js/video.js | 9 ++- 7 files changed, 66 insertions(+), 58 deletions(-) diff --git a/build/grunt.js b/build/grunt.js index 698b6cffce..ebc4df725b 100644 --- a/build/grunt.js +++ b/build/grunt.js @@ -5,7 +5,7 @@ import npmRun from 'npm-run'; module.exports = function(grunt) { require('time-grunt')(grunt); - let _ = require('lodash-compat'); + let _ = require('lodash'); let pkg = grunt.file.readJSON('package.json'); let license = grunt.file.read('build/license-header.txt'); let bannerCommonData = _.pick(pkg, ['version', 'copyright']); diff --git a/build/options-customizer.js b/build/options-customizer.js index 5257e73d6f..a3db5cd3aa 100644 --- a/build/options-customizer.js +++ b/build/options-customizer.js @@ -1,4 +1,4 @@ -import _ from 'lodash-compat'; +import _ from 'lodash'; /** * Customizes _.merge behavior in `gruntOptions` to concatenate * arrays. This can be overridden on a per-call basis to diff --git a/package.json b/package.json index 6cc3b5fa11..54e5351d65 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "dependencies": { "babel-runtime": "^6.9.2", "global": "4.3.0", - "lodash-compat": "3.10.2", "safe-json-parse": "4.0.0", "tsml": "1.0.1", "videojs-font": "2.0.0", @@ -101,6 +100,7 @@ "karma-safari-launcher": "^1.0.0", "karma-sinon": "^1.0.5", "load-grunt-tasks": "^3.1.0", + "lodash": "^4.16.6", "markdown-table": "^1.0.0", "npm-run": "^4.1.0", "proxyquireify": "^3.0.0", diff --git a/src/js/control-bar/progress-control/mouse-time-display.js b/src/js/control-bar/progress-control/mouse-time-display.js index 158cbc300c..837f5c4244 100644 --- a/src/js/control-bar/progress-control/mouse-time-display.js +++ b/src/js/control-bar/progress-control/mouse-time-display.js @@ -5,7 +5,6 @@ import Component from '../../component.js'; import * as Dom from '../../utils/dom.js'; import * as Fn from '../../utils/fn.js'; import formatTime from '../../utils/format-time.js'; -import throttle from 'lodash-compat/function/throttle'; import computedStyle from '../../utils/computed-style.js'; /** @@ -44,7 +43,7 @@ class MouseTimeDisplay extends Component { this.update(0, 0); player.on('ready', () => { - this.on(player.controlBar.progressControl.el(), 'mousemove', throttle(Fn.bind(this, this.handleMouseMove), 25)); + this.on(player.controlBar.progressControl.el(), 'mousemove', Fn.throttle(Fn.bind(this, this.handleMouseMove), 25)); }); } diff --git a/src/js/utils/fn.js b/src/js/utils/fn.js index 0151419d93..4ad087be39 100644 --- a/src/js/utils/fn.js +++ b/src/js/utils/fn.js @@ -27,7 +27,7 @@ export const bind = function(context, fn, uid) { } // Create the new function that changes the context - const ret = function() { + const bound = function() { return fn.apply(context, arguments); }; @@ -37,7 +37,34 @@ export const bind = function(context, fn, uid) { // it will remove both because they both have the same guid. // when using this, you need to use the bind method when you remove the listener as well. // currently used in text tracks - ret.guid = (uid) ? uid + '_' + fn.guid : fn.guid; + bound.guid = (uid) ? uid + '_' + fn.guid : fn.guid; - return ret; + return bound; +}; + +/** + * Wraps the given function, `fn`, with a new function that only invokes `fn` + * at most once per every `wait` milliseconds. + * + * @param {Function} fn + * The function to be throttled. + * + * @param {Number} wait + * The number of milliseconds by which to throttle. + * + * @return {Function} + */ +export const throttle = function(fn, wait) { + let last; + + const throttled = function(...args) { + const now = Date.now(); + + if (now - last >= wait) { + fn(...args); + last = now; + } + }; + + return throttled; }; diff --git a/src/js/utils/merge-options.js b/src/js/utils/merge-options.js index 8ecd69a6cb..73a012bf14 100644 --- a/src/js/utils/merge-options.js +++ b/src/js/utils/merge-options.js @@ -2,62 +2,39 @@ * @file merge-options.js * @module merge-options */ -import merge from 'lodash-compat/object/merge'; -import {isPlain} from './obj'; +import {each, isPlain} from './obj'; /** - * Merge customizer. video.js simply overwrites non-simple objects - * (like arrays) instead of attempting to overlay them. + * Deep-merge one or more options objects, recursively merging **only** plain + * object properties. * - * @param {Mixed} destination - * The merge destination - * - * @param {Mixed} source - * A merge source. - * - * @retun {Mixed} - * The source and destination merged. - * - * @see https://lodash.com/docs#merge - */ -function customizer(destination, source) { - // If we're not working with a plain object, copy the value as is - // If source is an array, for instance, it will replace destination - if (!isPlain(source)) { - return source; - } - - // If the new value is a plain object but the first object value is not - // we need to create a new object for the first object to merge with. - // This makes it consistent with how merge() works by default - // and also protects from later changes the to first object affecting - // the second object's values. - if (!isPlain(destination)) { - return mergeOptions(source); - } -} - -/** - * Merge one or more options objects, recursively merging **only** - * plain object properties. Previously `deepMerge`. - * - * @param {Object[]} source - * One or more objects to merge + * @param {Object[]} sources + * One or more objects to merge into a new object. * * @returns {Object} - * a new object that is the union of all + * A new object that is the merged result of all sources. */ -export default function mergeOptions(...objects) { +export default function mergeOptions(...sources) { + const result = {}; + + sources.forEach(source => { + if (!source) { + return; + } - // unshift an empty object into the front of the call as the target - // of the merge - objects.unshift({}); + each(source, (value, key) => { + if (!isPlain(value)) { + result[key] = value; + return; + } - // customize conflict resolution to match our historical merge behavior - objects.push(customizer); + if (!isPlain(result[key])) { + result[key] = {}; + } - merge.apply(null, objects); + result[key] = mergeOptions(result[key], value); + }); + }); - // return the mutated result object - return objects[0]; + return result; } diff --git a/src/js/video.js b/src/js/video.js index 48ae816dfd..0e8d981e77 100644 --- a/src/js/video.js +++ b/src/js/video.js @@ -29,7 +29,6 @@ import * as Url from './utils/url.js'; import {isObject} from './utils/obj'; import computedStyle from './utils/computed-style.js'; import extendFn from './extend.js'; -import merge from 'lodash-compat/object/merge'; import xhr from 'xhr'; // Include the built-in techs @@ -498,7 +497,13 @@ videojs.plugin = plugin; */ videojs.addLanguage = function(code, data) { code = ('' + code).toLowerCase(); - return merge(videojs.options.languages, { [code]: data })[code]; + + videojs.options.languages = mergeOptions( + videojs.options.languages, + {[code]: data} + ); + + return videojs.options.languages[code]; }; /**