From cd147a9ba6d5427431dc86511aa60f441d10f49b Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Sun, 2 Apr 2017 15:25:34 +0300 Subject: [PATCH 1/3] refactor: random changes --- background.js | 22 +++--- devtoolsBackground.js | 73 ++++++++----------- inject.js | 13 ++-- panel/app.css | 5 +- panel/app.html | 2 +- panel/components/code/code.js | 4 +- .../components/inspected-app/inspected-app.js | 54 ++++++++------ 7 files changed, 84 insertions(+), 89 deletions(-) diff --git a/background.js b/background.js index 4125ebd..da778d9 100644 --- a/background.js +++ b/background.js @@ -20,6 +20,7 @@ function brokerMessage(message, sender) { transformMessage(tabId, message); bufferData(tabId, message); } + if (devToolsPort) { devToolsPort.postMessage(message); } @@ -47,8 +48,8 @@ function transformMessage(tabId, message) { } if (message.event === 'model:change') { - message.data.value = (typeof message.data.value === 'undefined') ? - undefined : JSON.parse(message.data.value) + message.data.value = (message.data.value === undefined) ? + undefined : JSON.parse(message.data.value); } } @@ -71,13 +72,18 @@ function bufferData(tabId, message) { } if (message.event === 'scope:new') { - tabData.scopes[message.data.child] = { - parent: message.data.parent, + var childId = message.data.child; + var parentId = message.data.parent; + var parentScopeData = tabData.scopes[parentId]; + + tabData.scopes[childId] = { + parent: parentId, children: [], models: {} }; - if (tabData.scopes[message.data.parent]) { - tabData.scopes[message.data.parent].children.push(message.data.child); + + if (parentScopeData) { + parentScopeData.children.push(childId); } } else if (message.data.id && (scope = tabData.scopes[message.data.id])) { if (message.event === 'scope:destroy') { @@ -101,8 +107,7 @@ function bufferData(tabId, message) { // context script –> background chrome.runtime.onMessage.addListener(brokerMessage); -chrome.runtime.onConnect.addListener(function(devToolsPort) { - +chrome.runtime.onConnect.addListener(function (devToolsPort) { devToolsPort.onMessage.addListener(registerInspectedTabId); function registerInspectedTabId(inspectedTabId) { @@ -122,7 +127,6 @@ chrome.runtime.onConnect.addListener(function(devToolsPort) { //devToolsPort.onMessage.removeListener(registerInspectedTabId); } - }); chrome.tabs.onRemoved.addListener(function (tabId) { diff --git a/devtoolsBackground.js b/devtoolsBackground.js index 2244621..724e0b8 100644 --- a/devtoolsBackground.js +++ b/devtoolsBackground.js @@ -1,58 +1,47 @@ var panels = chrome && chrome.devtools && chrome.devtools.panels; +var elementsPanel = panels && panels.elements; + +if (elementsPanel) { + elementsPanel.createSidebarPane('$scope', function onSidebarCreated(sidebar) { + elementsPanel.onSelectionChanged.addListener(function updateElementProperties() { + sidebar.setExpression('(' + getPanelContents.toString() + ')()'); + }); + + // AngularJS panel + panels.create('AngularJS', 'img/angular.png', 'panel/app.html'); + }); +} // The function below is executed in the context of the inspected page. +function getPanelContents() { + var angular = window.angular; + var panelContents = {}; -var getPanelContents = function () { - if (window.angular && $0) { - //TODO: can we move this scope export into updateElementProperties + if (angular && $0) { var scope = getScope($0); // Export $scope to the console window.$scope = scope; - return (function (scope) { - var panelContents = { - __private__: {} - }; - - for (prop in scope) { - if (scope.hasOwnProperty(prop)) { - if (prop.substr(0, 2) === '$$') { - panelContents.__private__[prop] = scope[prop]; - } else { - panelContents[prop] = scope[prop]; - } - } - } - return panelContents; - }(scope)); - } else { - return {}; + + // Get sidebar contents + panelContents.__private__ = {}; + Object.keys(scope).forEach(function (prop) { + var dest = (prop.substr(0, 2) === '$$') ? panelContents.__private__ : panelContents; + dest[prop] = scope[prop]; + }); } + return panelContents; + + // Helpers function getScope(node) { - var scope = window.angular.element(node).scope(); + var scope = angular.element(node).scope(); if (!scope) { // Might be a child of a DocumentFragment... - while (node && node.nodeType === 1) node = node.parentNode; - if (node && node.nodeType === 11) node = (node.parentNode || node.host); - return getScope(node); + while (node && node.nodeType === Node.ELEMENT_NODE) node = node.parentNode; + if (node && node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) node = node.parentNode || node.host; + return node && getScope(node); } return scope; } -}; - -panels && panels.elements.createSidebarPane( - "$scope", - function (sidebar) { - panels.elements.onSelectionChanged.addListener(function updateElementProperties() { - sidebar.setExpression("(" + getPanelContents.toString() + ")()"); - }); - - // Angular panel - var angularPanel = panels.create( - "AngularJS", - "img/angular.png", - "panel/app.html" - ); -}); - +} diff --git a/inject.js b/inject.js index 479f25e..54957d0 100644 --- a/inject.js +++ b/inject.js @@ -1,15 +1,15 @@ -if (document.cookie.indexOf('__ngDebug=true') != -1) { +if (document.cookie.indexOf('__ngDebug=true') !== -1) { bootstrapHint(); } function bootstrapHint () { chrome.runtime.sendMessage('refresh'); - var html = document.getElementsByTagName('html')[0]; + var html = document.documentElement; // inject into the application context from the content script context - var script = window.document.createElement('script'); - script.src = chrome.extension.getURL('dist/hint.js'); + var script = document.createElement('script'); + script.src = chrome.runtime.getURL('dist/hint.js'); window.addEventListener('message', function (evt) { // There's no good way to verify the provenance of the message. @@ -21,14 +21,13 @@ function bootstrapHint () { // we would send, cross our fingers, and send it on. // Thus, we check for one of the properties known to be on *all* of our // messages (__fromBatarang === true). + var eventData = evt.data; - // NOTE: Check for null before checking for the property, since typeof null === 'object'. - if (typeof eventData === 'object' && eventData !== null && eventData.hasOwnProperty('__fromBatarang') && eventData.__fromBatarang) { + if (eventData && typeof eventData === 'object' && eventData.__fromBatarang) { chrome.runtime.sendMessage(eventData); } }); html.setAttribute('ng-hint', ''); - html.appendChild(script); } diff --git a/panel/app.css b/panel/app.css index b3ea676..1a30955 100644 --- a/panel/app.css +++ b/panel/app.css @@ -238,8 +238,7 @@ body:focus .sidebar-tree-item.selected { .profile-launcher-view-tree-item > .icon { padding: 15px; - background-image: url(../img/toolbarIcons.png); - background-position-x: -160px; + visibility: hidden; } li .status { @@ -387,4 +386,4 @@ li .status:empty { width: 80%; z-index: 9999; text-align: right; -} \ No newline at end of file +} diff --git a/panel/app.html b/panel/app.html index a59d395..4356219 100644 --- a/panel/app.html +++ b/panel/app.html @@ -29,7 +29,7 @@ - + diff --git a/panel/components/code/code.js b/panel/components/code/code.js index dcc0512..b3606b0 100644 --- a/panel/components/code/code.js +++ b/panel/components/code/code.js @@ -22,7 +22,5 @@ directive('batCode', function() { // super lite version of markdown var CODE_RE = /\`(.+?)\`/g; function replaceCodeInString(str) { - return str.replace(CODE_RE, function (match, contents) { - return ['', contents, ''].join(''); - }); + return str.replace(CODE_RE, '$1'); } diff --git a/panel/components/inspected-app/inspected-app.js b/panel/components/inspected-app/inspected-app.js index dc38d7f..043067e 100644 --- a/panel/components/inspected-app/inspected-app.js +++ b/panel/components/inspected-app/inspected-app.js @@ -1,9 +1,9 @@ 'use strict'; angular.module('batarang.inspected-app', []). - service('inspectedApp', ['$rootScope', '$q', inspectedAppService]); + service('inspectedApp', ['$rootScope', '$q', InspectedAppService]); -function inspectedAppService($rootScope, $q) { +function InspectedAppService($rootScope, $q) { var scopes = this.scopes = {}, hints = this.hints = [], @@ -27,23 +27,21 @@ function inspectedAppService($rootScope, $q) { "(function () {" + "var prev = document.cookie.indexOf('__ngDebug=true') !== -1;" + "if (prev !== " + setting + ") {" + - "window.document.cookie = '__ngDebug=" + setting + ";';" + - "window.document.location.reload();" + + "document.cookie = '__ngDebug=" + setting + ";';" + + "document.location.reload();" + "}" + "}())" ); }; this.getInstrumentationStatus = function () { - return $q(function(resolve, reject) { + return $q(function (resolve) { chrome.devtools.inspectedWindow.eval( "document.cookie.indexOf('__ngDebug=true') !== -1", resolve); }); }; - /* - * sets window.$scope to the scope of the given id - */ + // Sets window.$scope to the scope of the given id this.inspectScope = function (scopeId) { return invokeAngularHintMethod('inspectScope', scopeId); }; @@ -59,21 +57,21 @@ function inspectedAppService($rootScope, $q) { var port = chrome.runtime.connect(); port.postMessage(chrome.devtools.inspectedWindow.tabId); - port.onMessage.addListener(function(msg) { + port.onMessage.addListener(function (msg) { $rootScope.$applyAsync(function () { if (msg === 'refresh') { onRefreshMessage(); $rootScope.$broadcast('refresh'); - } else if (typeof msg === 'string') { - var hint = JSON.parse(msg); - onHintMessage(hint); - } else if (typeof msg === 'object') { + } else { + if (typeof msg === 'string') { + msg = JSON.parse(msg); + } onHintMessage(msg); } }); }); - port.onDisconnect.addListener(function (a) { - console.log(a); + port.onDisconnect.addListener(function () { + console.log('Disconnected from tab ' + chrome.devtools.inspectedWindow.tabId + '.'); }); function onHintMessage(message) { @@ -90,13 +88,16 @@ function inspectedAppService($rootScope, $q) { } else if (message.event === 'scope:new') { addNewScope(message); } else if (message.data.id && scopes[message.data.id]) { - var scope = scopes[message.data.id]; + var scopeId = message.data.id; + var scope = scopes[scopeId]; + if (message.event === 'scope:destroy') { - if (scope.parent) { - var parentScope = scopes[scope.parent]; - parentScope.children.splice(parentScope.children.indexOf(message.data.id), 1); + var parentScope = scopes[scope.parent]; + if (parentScope) { + parentScope.children.splice(parentScope.children.indexOf(scopeId), 1); } - for (var i = 0; i < message.data.subTree.length; i++){ + + for (var i = 0; i < message.data.subTree.length; i++) { delete scopes[message.data.subTree[i]]; } } else if (message.event === 'model:change') { @@ -108,6 +109,7 @@ function inspectedAppService($rootScope, $q) { perf[0] = message.data; } } + $rootScope.$broadcast(message.event, message.data); } } @@ -118,13 +120,17 @@ function inspectedAppService($rootScope, $q) { } function addNewScope (message) { - scopes[message.data.child] = { - parent: message.data.parent, + var childId = message.data.child; + var parentId = message.data.parent; + + scopes[childId] = { + parent: parentId, children: [], models: {} }; - if (scopes[message.data.parent]) { - scopes[message.data.parent].children.push(message.data.child); + + if (scopes[parentId]) { + scopes[parentId].children.push(childId); } } From a8336d4d8e3b5e0048ad69bd402caf11c2405d5a Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Sun, 2 Apr 2017 15:45:57 +0300 Subject: [PATCH 2/3] fix(hint): do not crash Somewhere between v0.14.4 and v4.0.0, `EventEmitter2` started being inconsistent wrt to the arguments passed to the `onAny()` listener; sometimes the `eventType` is passed as the first argument, sometimes it isn't. This caused batarang to crash. This commit fixes it, by accounting for the fact that `eventType` might or might not be passed as a first argument. Fixes #310 --- dist/hint.js | 14 +++++++++++--- hint.js | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) mode change 100755 => 100644 dist/hint.js diff --git a/dist/hint.js b/dist/hint.js old mode 100755 new mode 100644 index 22ec548..98b87f0 --- a/dist/hint.js +++ b/dist/hint.js @@ -7,11 +7,19 @@ require('./loader.js'); require('angular-hint'); -angular.hint.onAny(function (data, severity) { +angular.hint.onAny(function (event, data, severity) { + // EventEmitter2 usually omits the event type for the argument list (assigning it to `this.event` + // instead), but under certain circumstances it may include it. + if (this.event !== event) { + severity = data; + data = event; + event = this.event; + } + window.postMessage({ __fromBatarang: true, - module: this.event.split(':')[0], - event: this.event, + module: event.split(':')[0], + event: event, data: data, severity: severity }, '*'); diff --git a/hint.js b/hint.js index a37eb0a..5501f88 100644 --- a/hint.js +++ b/hint.js @@ -5,12 +5,20 @@ */ require('./loader.js'); require('angular-hint'); + +angular.hint.onAny(function (event, data, severity) { + // EventEmitter2 usually omits the event type for the argument list (assigning it to `this.event` + // instead), but under certain circumstances it may include it. + if (this.event !== event) { + severity = data; + data = event; + event = this.event; + } -angular.hint.onAny(function (data, severity) { window.postMessage({ - __fromBatarang: true, - module: this.event.split(':')[0], - event: this.event, + __fromBatarang: true, + module: event.split(':')[0], + event: event, data: data, severity: severity }, '*'); From 1e5bd106f6add6449baf15938667d8bc0db40b86 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Sun, 2 Apr 2017 20:14:36 +0300 Subject: [PATCH 3/3] fix(loader): use the latest version with fewer modifications and fixed `minErr` This commit updates `loader.js` based on `angular-loader.js` from angular/angular.js#15881, which is essentially the latest loader plus some `minErr` fixes (see angular/angular.js#15881 for more info). Additionally, the loader does a better job staying closer to the original `angular-loader` behavior for versions 1.3+ and it only modifies its behavior to support 1.2 apps. This change also fixes previously broken usecases that rely on private `angular.Module` APIs (see #88 for more info). Fixes #88 --- dist/hint.js | 165 ++++++++++++++++++++++++++++++++++++--------- hint.js | 24 +++---- loader.js | 161 ++++++++++++++++++++++++++++++++++++-------- package.json | 4 +- yarn.lock | 186 ++++++++++++++++++++++++++------------------------- 5 files changed, 376 insertions(+), 164 deletions(-) diff --git a/dist/hint.js b/dist/hint.js index 98b87f0..9e43d7d 100644 --- a/dist/hint.js +++ b/dist/hint.js @@ -4,7 +4,7 @@ * * This gets loaded into the context of the app you are inspecting */ -require('./loader.js'); +require('./loader'); require('angular-hint'); angular.hint.onAny(function (event, data, severity) { @@ -25,19 +25,131 @@ angular.hint.onAny(function (event, data, severity) { }, '*'); }); -},{"./loader.js":2,"angular-hint":3}],2:[function(require,module,exports){ +},{"./loader":2,"angular-hint":3}],2:[function(require,module,exports){ +// BATARANG +// Loader file based on `angular-loader.js` v1.6.5-local+sha.59dbff0c7 +// (https://github.com/angular/angular.js/pull/15881). +// Modified regions should be marked with `// BATARANG` comments. /** - * @license AngularJS v1.6.4-build.5322+sha.d96e58f + * @license AngularJS v1.6.5-local+sha.59dbff0c7 * (c) 2010-2017 Google, Inc. http://angularjs.org * License: MIT */ (function() {'use strict'; + function isFunction(value) {return typeof value === 'function';} + function isDefined(value) {return typeof value !== 'undefined';} + function isNumber(value) {return typeof value === 'number';} + function isObject(value) {return value !== null && typeof value === 'object';} + function isScope(obj) {return obj && obj.$evalAsync && obj.$watch;} + function isWindow(obj) {return obj && obj.window === obj;} + function sliceArgs(args, startIndex) {return Array.prototype.slice.call(args, startIndex || 0);} + function toJsonReplacer(key, value) { + var val = value; + + if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { + val = undefined; + } else if (isWindow(value)) { + val = '$WINDOW'; + } else if (value && window.document === value) { + val = '$DOCUMENT'; + } else if (isScope(value)) { + val = '$SCOPE'; + } + + return val; + } + +/* exported toDebugString */ + +// This file is also included in `angular-loader`, so `copy()` might not always be available in the +// closure. In such cases, it is lazily retrieved as `angular.copy()` when needed. +var copyFn; + +function serializeObject(obj, maxDepth) { + var seen = []; + + // There is no direct way to stringify object until reaching a specific depth + // and a very deep object can cause a performance issue, so we copy the object + // based on this specific depth and then stringify it. + if (isValidObjectMaxDepth(maxDepth)) { + if (!copyFn) { + copyFn = copy || angular.copy; + } + obj = copyFn(obj, null, maxDepth); + } + return JSON.stringify(obj, function(key, val) { + val = toJsonReplacer(key, val); + if (isObject(val)) { + + if (seen.indexOf(val) >= 0) return '...'; + + seen.push(val); + } + return val; + }); +} + +function toDebugString(obj, maxDepth) { + if (typeof obj === 'function') { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (isUndefined(obj)) { + return 'undefined'; + } else if (typeof obj !== 'string') { + return serializeObject(obj, maxDepth); + } + return obj; +} + +/* exported + minErrConfig, + errorHandlingConfig, + isValidObjectMaxDepth +*/ + +var minErrConfig = { + objectMaxDepth: 5 +}; +/** + * @ngdoc function + * @name angular.errorHandlingConfig + * @module ng + * @kind function + * + * @description + * Configure several aspects of error handling in AngularJS if used as a setter or return the + * current configuration if used as a getter. The following options are supported: + * + * - **objectMaxDepth**: The maximum depth to which objects are traversed when stringified for error messages. + * + * Omitted or undefined options will leave the corresponding configuration values unchanged. + * + * @param {Object=} config - The configuration object. May only contain the options that need to be + * updated. Supported keys: + * + * * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a + * non-positive or non-numeric value, removes the max depth limit. + * Default: 5 + */ +function errorHandlingConfig(config) { + if (isObject(config)) { + if (isDefined(config.objectMaxDepth)) { + minErrConfig.objectMaxDepth = isValidObjectMaxDepth(config.objectMaxDepth) ? config.objectMaxDepth : NaN; + } + } else { + return minErrConfig; + } +} -function isFunction(value) { return typeof value === 'function'; } -function isDefined(value) { return typeof value !== 'undefined'; } -function isObject(value) { return value !== null && typeof value === 'object'; } +/** + * @private + * @param {Number} maxDepth + * @return {boolean} + */ +function isValidObjectMaxDepth(maxDepth) { + return isNumber(maxDepth) && maxDepth > 0; +} /** * @description @@ -69,25 +181,15 @@ function isObject(value) { return value !== null && typeof value === 'object'; } * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance */ -function toDebugString(obj) { - if (typeof obj === 'function') { - return obj.toString().replace(/ ?\{[\s\S]*$/, ''); - } else if (typeof obj === 'undefined') { - return 'undefined'; - } else if (typeof obj !== 'string') { - return JSON.stringify(obj); - } - return obj; -} - function minErr(module, ErrorConstructor) { ErrorConstructor = ErrorConstructor || Error; return function() { var code = arguments[0], template = arguments[1], - version = (angular.version && angular.version.full) || 'snapshot', message = '[' + (module ? module + ':' : '') + code + '] ', - templateArgs = Array.prototype.slice.call(arguments, 2).map(toDebugString), + templateArgs = sliceArgs(arguments, 2).map(function(arg) { + return toDebugString(arg, minErrConfig.objectMaxDepth); + }), paramPrefix, i; message += template.replace(/\{\d+\}/g, function(match) { @@ -96,9 +198,13 @@ function minErr(module, ErrorConstructor) { if (index < templateArgs.length) { return templateArgs[index]; } + return match; }); + // BATARANG + // Use the app's version in error URLs instead of the version this file was based on. + var version = (angular.version && angular.version.full) || 'snapshot'; message += '\nhttp://errors.angularjs.org/' + version + '/' + (module ? module + '/' : '') + code; @@ -223,9 +329,11 @@ function setupModuleLoader(window) { /** @type {angular.Module} */ var moduleInstance = { // Private state - // ANGULAR HINT ALTERATION - // See the definition of `_invokeQueue` below for more info. - _configBlocks: [], + // BATARANG + // `_invokeQueue` needs to be handled in a special way in order to support both v1.2 and + // v1.3+ apps. See its definition below for more details. + //_invokeQueue: invokeQueue, + _configBlocks: configBlocks, _runBlocks: runBlocks, /** @@ -477,16 +585,13 @@ function setupModuleLoader(window) { } }; - /** - * ANGULAR HINT ALTERATION - * To make this loader compatible with apps that are running both Angular 1.2 and 1.3+, the - * loader must handle 1.3+ applications that expect to initialize their config blocks after - * all providers are registered. Hence, an empty `_configBlocks` array is exposed on - * `moduleInstance` and the actual `configBlocks` are added to the end of the `invokeQueue`. - */ + // BATARANG + // To make this loader compatible with both AngularJS v1.2 and v1.3+ apps, it must handle + // v1.2 apps that do not know about `_configBlocks` and expect everything to be on the + // `_invokeQueue`. Object.defineProperty(moduleInstance, '_invokeQueue', { get: function() { - return invokeQueue.concat(configBlocks); + return (angular.version.minor <= 2) ? invokeQueue.concat(configBlocks) : invokeQueue; } }); diff --git a/hint.js b/hint.js index 5501f88..0dbe63d 100644 --- a/hint.js +++ b/hint.js @@ -3,21 +3,21 @@ * * This gets loaded into the context of the app you are inspecting */ -require('./loader.js'); +require('./loader'); require('angular-hint'); - -angular.hint.onAny(function (event, data, severity) { - // EventEmitter2 usually omits the event type for the argument list (assigning it to `this.event` - // instead), but under certain circumstances it may include it. - if (this.event !== event) { - severity = data; - data = event; - event = this.event; - } + +angular.hint.onAny(function (event, data, severity) { + // EventEmitter2 usually omits the event type for the argument list (assigning it to `this.event` + // instead), but under certain circumstances it may include it. + if (this.event !== event) { + severity = data; + data = event; + event = this.event; + } window.postMessage({ - __fromBatarang: true, - module: event.split(':')[0], + __fromBatarang: true, + module: event.split(':')[0], event: event, data: data, severity: severity diff --git a/loader.js b/loader.js index ee694ce..4377a3c 100644 --- a/loader.js +++ b/loader.js @@ -1,15 +1,127 @@ +// BATARANG +// Loader file based on `angular-loader.js` v1.6.5-local+sha.59dbff0c7 +// (https://github.com/angular/angular.js/pull/15881). +// Modified regions should be marked with `// BATARANG` comments. /** - * @license AngularJS v1.6.4-build.5322+sha.d96e58f + * @license AngularJS v1.6.5-local+sha.59dbff0c7 * (c) 2010-2017 Google, Inc. http://angularjs.org * License: MIT */ (function() {'use strict'; + function isFunction(value) {return typeof value === 'function';} + function isDefined(value) {return typeof value !== 'undefined';} + function isNumber(value) {return typeof value === 'number';} + function isObject(value) {return value !== null && typeof value === 'object';} + function isScope(obj) {return obj && obj.$evalAsync && obj.$watch;} + function isWindow(obj) {return obj && obj.window === obj;} + function sliceArgs(args, startIndex) {return Array.prototype.slice.call(args, startIndex || 0);} + function toJsonReplacer(key, value) { + var val = value; + + if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { + val = undefined; + } else if (isWindow(value)) { + val = '$WINDOW'; + } else if (value && window.document === value) { + val = '$DOCUMENT'; + } else if (isScope(value)) { + val = '$SCOPE'; + } + + return val; + } + +/* exported toDebugString */ + +// This file is also included in `angular-loader`, so `copy()` might not always be available in the +// closure. In such cases, it is lazily retrieved as `angular.copy()` when needed. +var copyFn; + +function serializeObject(obj, maxDepth) { + var seen = []; + + // There is no direct way to stringify object until reaching a specific depth + // and a very deep object can cause a performance issue, so we copy the object + // based on this specific depth and then stringify it. + if (isValidObjectMaxDepth(maxDepth)) { + if (!copyFn) { + copyFn = copy || angular.copy; + } + obj = copyFn(obj, null, maxDepth); + } + return JSON.stringify(obj, function(key, val) { + val = toJsonReplacer(key, val); + if (isObject(val)) { + + if (seen.indexOf(val) >= 0) return '...'; + + seen.push(val); + } + return val; + }); +} + +function toDebugString(obj, maxDepth) { + if (typeof obj === 'function') { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (isUndefined(obj)) { + return 'undefined'; + } else if (typeof obj !== 'string') { + return serializeObject(obj, maxDepth); + } + return obj; +} +/* exported + minErrConfig, + errorHandlingConfig, + isValidObjectMaxDepth +*/ -function isFunction(value) { return typeof value === 'function'; } -function isDefined(value) { return typeof value !== 'undefined'; } -function isObject(value) { return value !== null && typeof value === 'object'; } +var minErrConfig = { + objectMaxDepth: 5 +}; + +/** + * @ngdoc function + * @name angular.errorHandlingConfig + * @module ng + * @kind function + * + * @description + * Configure several aspects of error handling in AngularJS if used as a setter or return the + * current configuration if used as a getter. The following options are supported: + * + * - **objectMaxDepth**: The maximum depth to which objects are traversed when stringified for error messages. + * + * Omitted or undefined options will leave the corresponding configuration values unchanged. + * + * @param {Object=} config - The configuration object. May only contain the options that need to be + * updated. Supported keys: + * + * * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a + * non-positive or non-numeric value, removes the max depth limit. + * Default: 5 + */ +function errorHandlingConfig(config) { + if (isObject(config)) { + if (isDefined(config.objectMaxDepth)) { + minErrConfig.objectMaxDepth = isValidObjectMaxDepth(config.objectMaxDepth) ? config.objectMaxDepth : NaN; + } + } else { + return minErrConfig; + } +} + +/** + * @private + * @param {Number} maxDepth + * @return {boolean} + */ +function isValidObjectMaxDepth(maxDepth) { + return isNumber(maxDepth) && maxDepth > 0; +} /** * @description @@ -41,25 +153,15 @@ function isObject(value) { return value !== null && typeof value === 'object'; } * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance */ -function toDebugString(obj) { - if (typeof obj === 'function') { - return obj.toString().replace(/ ?\{[\s\S]*$/, ''); - } else if (typeof obj === 'undefined') { - return 'undefined'; - } else if (typeof obj !== 'string') { - return JSON.stringify(obj); - } - return obj; -} - function minErr(module, ErrorConstructor) { ErrorConstructor = ErrorConstructor || Error; return function() { var code = arguments[0], template = arguments[1], - version = (angular.version && angular.version.full) || 'snapshot', message = '[' + (module ? module + ':' : '') + code + '] ', - templateArgs = Array.prototype.slice.call(arguments, 2).map(toDebugString), + templateArgs = sliceArgs(arguments, 2).map(function(arg) { + return toDebugString(arg, minErrConfig.objectMaxDepth); + }), paramPrefix, i; message += template.replace(/\{\d+\}/g, function(match) { @@ -68,9 +170,13 @@ function minErr(module, ErrorConstructor) { if (index < templateArgs.length) { return templateArgs[index]; } + return match; }); + // BATARANG + // Use the app's version in error URLs instead of the version this file was based on. + var version = (angular.version && angular.version.full) || 'snapshot'; message += '\nhttp://errors.angularjs.org/' + version + '/' + (module ? module + '/' : '') + code; @@ -195,9 +301,11 @@ function setupModuleLoader(window) { /** @type {angular.Module} */ var moduleInstance = { // Private state - // ANGULAR HINT ALTERATION - // See the definition of `_invokeQueue` below for more info. - _configBlocks: [], + // BATARANG + // `_invokeQueue` needs to be handled in a special way in order to support both v1.2 and + // v1.3+ apps. See its definition below for more details. + //_invokeQueue: invokeQueue, + _configBlocks: configBlocks, _runBlocks: runBlocks, /** @@ -449,16 +557,13 @@ function setupModuleLoader(window) { } }; - /** - * ANGULAR HINT ALTERATION - * To make this loader compatible with apps that are running both Angular 1.2 and 1.3+, the - * loader must handle 1.3+ applications that expect to initialize their config blocks after - * all providers are registered. Hence, an empty `_configBlocks` array is exposed on - * `moduleInstance` and the actual `configBlocks` are added to the end of the `invokeQueue`. - */ + // BATARANG + // To make this loader compatible with both AngularJS v1.2 and v1.3+ apps, it must handle + // v1.2 apps that do not know about `_configBlocks` and expect everything to be on the + // `_invokeQueue`. Object.defineProperty(moduleInstance, '_invokeQueue', { get: function() { - return invokeQueue.concat(configBlocks); + return (angular.version.minor <= 2) ? invokeQueue.concat(configBlocks) : invokeQueue; } }); diff --git a/package.json b/package.json index 40ec300..1129a97 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "chrome extension for inspecting angular apps", "main": "hint.js", "devDependencies": { - "angular-mocks": "^1.6.3", + "angular-mocks": "^1.6.4", "browserify": "^14.1.0", "gulp": "^3.9.1", "gulp-zip": "^4.0.0", @@ -18,7 +18,7 @@ "watchify": "^3.9.0" }, "dependencies": { - "angular": "^1.6.3", + "angular": "^1.6.4", "angular-hint": "https://github.com/angular/angular-hint#v0.3.9", "browserify-eep": "^0.3.1" }, diff --git a/yarn.lock b/yarn.lock index bf41ffd..fc1a6d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -66,13 +66,13 @@ amdefine@>=0.0.4: eventemitter2 "^4.0.0" suggest-it "^0.0.1" -angular-mocks@^1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.6.3.tgz#12fafc0f1e0903f16864004ba375bf3fb9101ef1" +angular-mocks@^1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.6.4.tgz#47fdf50921cf24fb489f100a8cf2ad99d0538f40" -angular@^1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.6.3.tgz#5d34b799234e8fa17c6a3a14e0258733935f43e7" +angular@^1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/angular/-/angular-1.6.4.tgz#03b7b15c01a0802d7e2cf593240e604054dc77fb" ansi-regex@^2.0.0: version "2.1.1" @@ -223,7 +223,7 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" -async@1.4.0: +async@1.4.0, async@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/async/-/async-1.4.0.tgz#35f86f83c59e0421d099cd9a91d8278fb578c00d" @@ -233,10 +233,6 @@ async@2.0.1, async@^2.0.0: dependencies: lodash "^4.8.0" -async@^1.4.0, async@^1.4.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -492,8 +488,8 @@ browserify-rsa@^4.0.0: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.0.tgz#10773910c3c206d5420a46aad8694f820b85968f" + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" dependencies: bn.js "^4.1.1" browserify-rsa "^4.0.0" @@ -810,8 +806,8 @@ content-type@~1.0.2: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" convert-source-map@^1.1.3, convert-source-map@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.4.0.tgz#e3dad195bf61bfe13a7a3c73e9876ec14a0268f3" + version "1.5.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" convert-source-map@~1.1.0: version "1.1.3" @@ -830,8 +826,8 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" coveralls@^2.11.2: - version "2.12.0" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.12.0.tgz#b3d064108e29728385b56e42fc2d119f43e0e517" + version "2.13.0" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.0.tgz#df933876e8c6f478efb04f4d3ab70dc96b7e5a8e" dependencies: js-yaml "3.6.1" lcov-parse "0.0.10" @@ -1541,8 +1537,8 @@ global-prefix@^0.1.4: which "^1.2.12" globals@^9.0.0: - version "9.16.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.16.0.tgz#63e903658171ec2d9f51b1d31de5e2b8dc01fb80" + version "9.17.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" globule@~0.1.0: version "0.1.0" @@ -1838,8 +1834,8 @@ insert-module-globals@^7.0.0: xtend "^4.0.0" interpret@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" + version "1.0.2" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.2.tgz#f4f623f0bb7122f15f5717c8e254b8161b5c5b2d" invariant@^2.2.0: version "2.2.2" @@ -1999,51 +1995,49 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -istanbul-lib-coverage@^1.0.0, istanbul-lib-coverage@^1.0.0-alpha, istanbul-lib-coverage@^1.0.0-alpha.0, istanbul-lib-coverage@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.1.tgz#f263efb519c051c5f1f3343034fc40e7b43ff212" +istanbul-lib-coverage@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.2.tgz#87a0c015b6910651cb3b184814dfb339337e25e1" -istanbul-lib-hook@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.4.tgz#1919debbc195807880041971caf9c7e2be2144d6" +istanbul-lib-hook@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.5.tgz#6ca3d16d60c5f4082da39f7c5cd38ea8a772b88e" dependencies: append-transform "^0.4.0" -istanbul-lib-instrument@^1.4.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.6.2.tgz#dac644f358f51efd6113536d7070959a0111f73b" +istanbul-lib-instrument@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.0.tgz#b8e0dc25709bb44e17336ab47b7bb5c97c23f659" dependencies: babel-generator "^6.18.0" babel-template "^6.16.0" babel-traverse "^6.18.0" babel-types "^6.18.0" babylon "^6.13.0" - istanbul-lib-coverage "^1.0.0" + istanbul-lib-coverage "^1.0.2" semver "^5.3.0" -istanbul-lib-report@^1.0.0-alpha.3: - version "1.0.0-alpha.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.0.0-alpha.3.tgz#32d5f6ec7f33ca3a602209e278b2e6ff143498af" +istanbul-lib-report@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.0.0.tgz#d83dac7f26566b521585569367fe84ccfc7aaecb" dependencies: - async "^1.4.2" - istanbul-lib-coverage "^1.0.0-alpha" + istanbul-lib-coverage "^1.0.2" mkdirp "^0.5.1" path-parse "^1.0.5" - rimraf "^2.4.3" supports-color "^3.1.2" -istanbul-lib-source-maps@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.1.0.tgz#9d429218f35b823560ea300a96ff0c3bbdab785f" +istanbul-lib-source-maps@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.1.1.tgz#f8c8c2e8f2160d1d91526d97e5bd63b2079af71c" dependencies: - istanbul-lib-coverage "^1.0.0-alpha.0" + istanbul-lib-coverage "^1.0.2" mkdirp "^0.5.1" rimraf "^2.4.4" source-map "^0.5.3" -istanbul-reports@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.0.1.tgz#9a17176bc4a6cbebdae52b2f15961d52fa623fbc" +istanbul-reports@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.0.2.tgz#4e8366abe6fa746cc1cd6633f108de12cc6ac6fa" dependencies: handlebars "^4.0.3" @@ -2374,14 +2368,10 @@ lodash@3.10.1, lodash@^3.10.1, lodash@^3.8.0: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@4.16.2: +lodash@4.16.2, lodash@^4.2.0, lodash@^4.5.0, lodash@^4.8.0: version "4.16.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" -lodash@^4.2.0, lodash@^4.5.0, lodash@^4.8.0: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - lodash@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" @@ -2467,15 +2457,15 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.26.0: - version "1.26.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.26.0.tgz#eaffcd0e4fc6935cf8134da246e2e6c35305adff" +mime-db@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" -mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.13, mime-types@~2.1.7: - version "2.1.14" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.14.tgz#f7ef7d97583fcaf3b7d282b6f8b5679dab1e94ee" +mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7: + version "2.1.15" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" dependencies: - mime-db "~1.26.0" + mime-db "~1.27.0" mime@^1.3.4: version "1.3.4" @@ -2605,8 +2595,10 @@ normalize-package-data@^2.3.2: validate-npm-package-license "^3.0.1" normalize-path@^2.0.0, normalize-path@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" npmlog@^4.0.2: version "4.0.2" @@ -2626,8 +2618,8 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" nyc@^10.0.0: - version "10.1.2" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-10.1.2.tgz#ea7acaa20a235210101604f4e7d56d28453b0274" + version "10.2.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-10.2.0.tgz#facd90240600c9aa4dd81ea99c2fb6a85c53de0c" dependencies: archy "^1.0.0" arrify "^1.0.1" @@ -2639,12 +2631,12 @@ nyc@^10.0.0: find-up "^1.1.2" foreground-child "^1.5.3" glob "^7.0.6" - istanbul-lib-coverage "^1.0.1" - istanbul-lib-hook "^1.0.0" - istanbul-lib-instrument "^1.4.2" - istanbul-lib-report "^1.0.0-alpha.3" - istanbul-lib-source-maps "^1.1.0" - istanbul-reports "^1.0.0" + istanbul-lib-coverage "^1.0.2" + istanbul-lib-hook "^1.0.5" + istanbul-lib-instrument "^1.7.0" + istanbul-lib-report "^1.0.0" + istanbul-lib-source-maps "^1.1.1" + istanbul-reports "^1.0.2" md5-hex "^1.2.0" merge-source-map "^1.0.2" micromatch "^2.3.11" @@ -2653,8 +2645,8 @@ nyc@^10.0.0: rimraf "^2.5.4" signal-exit "^3.0.1" spawn-wrap "1.2.4" - test-exclude "^3.3.0" - yargs "^6.6.0" + test-exclude "^4.0.0" + yargs "^7.0.2" yargs-parser "^4.0.2" oauth-sign@~0.8.1: @@ -3001,8 +2993,8 @@ raw-body@~2.2.0: unpipe "1.0.0" rc@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.7.tgz#c5ea564bb07aff9fd3a5b32e906c1d3a65940fea" + version "1.2.0" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.0.tgz#c7de973b7b46297c041366b2fd3d2363b1697c66" dependencies: deep-extend "~0.4.0" ini "~1.3.0" @@ -3097,6 +3089,10 @@ regex-cache@^0.4.2: is-equal-shallow "^0.1.3" is-primitive "^2.0.0" +remove-trailing-separator@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz#615ebb96af559552d4bf4057c8436d486ab63cc4" + repeat-element@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" @@ -3210,7 +3206,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.3.3, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1: +rimraf@2, rimraf@^2.3.3, rimraf@^2.4.4, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" dependencies: @@ -3559,8 +3555,8 @@ tap-parser@^5.1.0, tap-parser@^5.3.1: readable-stream "^2" tap@>=0.2.3: - version "10.3.0" - resolved "https://registry.yarnpkg.com/tap/-/tap-10.3.0.tgz#7454c3ab3da89e5450ff0b90d0d9bacc2ee25a9a" + version "10.3.1" + resolved "https://registry.yarnpkg.com/tap/-/tap-10.3.1.tgz#3262fe43b6123cce7eab362420a2f3e70cee8b1c" dependencies: bind-obj-methods "^1.0.0" bluebird "^3.3.1" @@ -3620,9 +3616,9 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" -test-exclude@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-3.3.0.tgz#7a17ca1239988c98367b0621456dbb7d4bc38977" +test-exclude@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.0.3.tgz#86a13ce3effcc60e6c90403cf31a27a60ac6c4e7" dependencies: arrify "^1.0.1" micromatch "^2.3.11" @@ -3719,19 +3715,19 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" type-is@~1.6.14: - version "1.6.14" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.14.tgz#e219639c17ded1ca0789092dd54a03826b817cb2" + version "1.6.15" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" dependencies: media-typer "0.3.0" - mime-types "~2.1.13" + mime-types "~2.1.15" typedarray@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" uglify-js@^2.6: - version "2.8.15" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.15.tgz#835dd4cd5872554756e6874508d0d0561704d94d" + version "2.8.21" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.21.tgz#1733f669ae6f82fc90c7b25ec0f5c783ee375314" dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -3792,8 +3788,8 @@ user-home@^1.1.1: resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" useragent@^2.1.12: - version "2.1.12" - resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.1.12.tgz#aa7da6cdc48bdc37ba86790871a7321d64edbaa2" + version "2.1.13" + resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.1.13.tgz#bba43e8aa24d5ceb83c2937473e102e21df74c10" dependencies: lru-cache "2.2.x" tmp "0.0.x" @@ -3817,8 +3813,8 @@ uuid@^3.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" v8flags@^2.0.2: - version "2.0.11" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.11.tgz#bca8f30f0d6d60612cc2c00641e6962d42ae6881" + version "2.0.12" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.12.tgz#73235d9f7176f8e8833fb286795445f7938d84e5" dependencies: user-home "^1.1.1" @@ -3901,8 +3897,8 @@ watchify@^3.9.0: xtend "^4.0.0" wd@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wd/-/wd-1.1.3.tgz#4a09c89047abcd1326ab15f384590f18a9de0e0e" + version "1.2.0" + resolved "https://registry.yarnpkg.com/wd/-/wd-1.2.0.tgz#4112c4657eca5af593ebc060d54b80caeea04807" dependencies: archiver "1.3.0" async "2.0.1" @@ -3991,15 +3987,21 @@ yapool@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/yapool/-/yapool-1.0.0.tgz#f693f29a315b50d9a9da2646a7a6645c96985b6a" -yargs-parser@^4.0.2, yargs-parser@^4.2.0: +yargs-parser@^4.0.2: version "4.2.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" dependencies: camelcase "^3.0.0" -yargs@^6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + dependencies: + camelcase "^3.0.0" + +yargs@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.0.2.tgz#115b97df1321823e8b8648e8968c782521221f67" dependencies: camelcase "^3.0.0" cliui "^3.2.0" @@ -4013,7 +4015,7 @@ yargs@^6.6.0: string-width "^1.0.2" which-module "^1.0.0" y18n "^3.2.1" - yargs-parser "^4.2.0" + yargs-parser "^5.0.0" yargs@~3.10.0: version "3.10.0"