From e22c5d3dba67fb4e4de3b687a9ec285f3ee12b83 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 23 May 2018 19:20:29 +0100 Subject: [PATCH 001/217] chore(package.json): update dist-tag for master branch --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b610384fccae..0d62777e5d36 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "license": "MIT", "branchVersion": "^1.7.0", "branchPattern": "1.7.*", - "distTag": "latest", + "distTag": "next", "repository": { "type": "git", "url": "https://github.com/angular/angular.js.git" From 9fe596422fbb83ffbef0ece8c23d445ff0070355 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Wed, 23 May 2018 22:39:53 +0200 Subject: [PATCH 002/217] chore: add platform to ios saucelabs --- karma-shared.conf.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/karma-shared.conf.js b/karma-shared.conf.js index ec06ed40a369..23b3972d33b1 100644 --- a/karma-shared.conf.js +++ b/karma-shared.conf.js @@ -107,11 +107,13 @@ module.exports = function(config, specificOptions) { 'SL_iOS_10': { base: 'SauceLabs', browserName: 'iphone', + platform: 'OS X 10.12', version: '10.3' }, 'SL_iOS_11': { base: 'SauceLabs', browserName: 'iphone', + platform: 'OS X 10.12', version: '11' }, From 96c4cb6694d6775ef4892ed39556b7927b0897a7 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Wed, 23 May 2018 23:36:48 +0200 Subject: [PATCH 003/217] chore: set ios 11 in saucelabs to 11.3 --- karma-shared.conf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/karma-shared.conf.js b/karma-shared.conf.js index 23b3972d33b1..672576e83277 100644 --- a/karma-shared.conf.js +++ b/karma-shared.conf.js @@ -114,7 +114,7 @@ module.exports = function(config, specificOptions) { base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.12', - version: '11' + version: '11.3' }, 'BS_Chrome': { From 52620390966d6b796d36a8b294b7e90e5276b61e Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Wed, 23 May 2018 22:06:50 +0300 Subject: [PATCH 004/217] refactor(ngModelOptions): fix `ng-closure-runner` warning Without this fix `grunt minall` emits the following warning: > WARNING - Parse error. Non-JSDoc comment has annotations. > Did you mean to start it with '/**'? Closes #16575 --- src/ng/directive/ngModelOptions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/directive/ngModelOptions.js b/src/ng/directive/ngModelOptions.js index 62408d2ea84a..aefc7355c9c0 100644 --- a/src/ng/directive/ngModelOptions.js +++ b/src/ng/directive/ngModelOptions.js @@ -41,7 +41,7 @@ ModelOptions.prototype = { options = extend({}, options); // Inherit options from the parent if specified by the value `"$inherit"` - forEach(options, /* @this */ function(option, key) { + forEach(options, /** @this */ function(option, key) { if (option === '$inherit') { if (key === '*') { inheritAll = true; From 6a1d7dd7dce767b78411528de318e419a16769b1 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 25 May 2018 20:16:39 +0200 Subject: [PATCH 005/217] chore(saucelabs): remove platform for ios11 --- karma-shared.conf.js | 1 - 1 file changed, 1 deletion(-) diff --git a/karma-shared.conf.js b/karma-shared.conf.js index 672576e83277..aa42dee1d554 100644 --- a/karma-shared.conf.js +++ b/karma-shared.conf.js @@ -113,7 +113,6 @@ module.exports = function(config, specificOptions) { 'SL_iOS_11': { base: 'SauceLabs', browserName: 'iphone', - platform: 'OS X 10.12', version: '11.3' }, From 0b1adbb2e7bd47845aab92fd77d02c8e37cba091 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 25 May 2018 21:17:55 +0200 Subject: [PATCH 006/217] chore: try ios 11.2 --- karma-shared.conf.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/karma-shared.conf.js b/karma-shared.conf.js index aa42dee1d554..1e519d71cf26 100644 --- a/karma-shared.conf.js +++ b/karma-shared.conf.js @@ -113,7 +113,8 @@ module.exports = function(config, specificOptions) { 'SL_iOS_11': { base: 'SauceLabs', browserName: 'iphone', - version: '11.3' + platform: 'OS X 10.12', + version: '11.2' }, 'BS_Chrome': { From b9f19ad0d4907a1b33e1557f713b2351944f5ba9 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Sat, 26 May 2018 16:05:51 +0200 Subject: [PATCH 007/217] docs(ngMockE2E): add docs for $httpBackend.matchLatestDefinitionEnabled() Closes #16577 --- src/ngMock/angular-mocks.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index fd3041d3ac8d..136f70187d0f 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -2756,6 +2756,39 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) { * control how a matched request is handled. You can save this object for later use and invoke * `respond` or `passThrough` again in order to change how a matched request is handled. */ +/** + * @ngdoc method + * @name $httpBackend#matchLatestDefinition + * @module ngMockE2E + * @description + * This method can be used to change which mocked responses `$httpBackend` returns, when defining + * them with {@link ngMock.$httpBackend#when $httpBackend.when()} (and shortcut methods). + * By default, `$httpBackend` returns the first definition that matches. When setting + * `$http.matchLatestDefinition(true)`, it will use the last response that matches, i.e. the + * one that was added last. + * + * ```js + * hb.when('GET', '/url1').respond(200, 'content', {}); + * hb.when('GET', '/url1').respond(201, 'another', {}); + * hb('GET', '/url1'); // receives "content" + * + * $http.matchLatestDefinition(true) + * hb('GET', '/url1'); // receives "another" + * + * hb.when('GET', '/url1').respond(201, 'onemore', {}); + * hb('GET', '/url1'); // receives "onemore" + * ``` + * + * This is useful if a you have a default response that is overriden inside specific tests. + * + * Note that different from config methods on providers, `matchLatestDefinition()` can be changed + * even when the application is already running. + * + * @param {Boolean=} value value to set, either `true` or `false`. Default is `false`. + * If omitted, it will return the current value. + * @return {$httpBackend|Boolean} self when used as a setter, and the current value when used + * as a getter + */ angular.mock.e2e = {}; angular.mock.e2e.$httpBackendDecorator = ['$rootScope', '$timeout', '$delegate', '$browser', createHttpBackendMock]; From 78b9f61366faa1fd4460412771a65f8f01406ed0 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Sat, 26 May 2018 17:11:09 +0300 Subject: [PATCH 008/217] fix($compile): support transcluding multi-element directives Previously, transcluding multi-element directives (e.g. `foo-start`/`foo-end`) was not supported on elements with multi-slot transclusion (a `uterdir` error was thrown). This commit fixes it by putting the transcluded nodes into a DocumentFragment, where they can be traversed via `.nextSibling`. Fixes #15554 Closes #15555 --- src/ng/compile.js | 12 +++++++----- test/ng/compileSpec.js | 44 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index e8bd8ca01668..a257c0b5f096 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -2575,7 +2575,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // We have transclusion slots, // collect them up, compile them and store their transclusion functions - $template = []; + $template = window.document.createDocumentFragment(); var slotMap = createMap(); var filledSlots = createMap(); @@ -2603,10 +2603,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var slotName = slotMap[directiveNormalize(nodeName_(node))]; if (slotName) { filledSlots[slotName] = true; - slots[slotName] = slots[slotName] || []; - slots[slotName].push(node); + slots[slotName] = slots[slotName] || window.document.createDocumentFragment(); + slots[slotName].appendChild(node); } else { - $template.push(node); + $template.appendChild(node); } }); @@ -2620,9 +2620,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { for (var slotName in slots) { if (slots[slotName]) { // Only define a transclusion function if the slot was filled - slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName], transcludeFn); + slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName].childNodes, transcludeFn); } } + + $template = $template.childNodes; } $compileNode.empty(); // clear contents diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index d24a90f9744c..a0b8b7204439 100644 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -8843,6 +8843,50 @@ describe('$compile', function() { }); }); + + it('should correctly handle multi-element directives', function() { + module(function() { + directive('foo', valueFn({ + template: '[
]', + transclude: true + })); + directive('bar', valueFn({ + template: '[
|
]', + transclude: { + header: 'header', + footer: 'footer' + } + })); + }); + + inject(function($compile, $rootScope) { + var tmplWithFoo = + '' + + '
Hello,
' + + '
world!
' + + '
'; + var tmplWithBar = + '' + + '
This is a
' + + '
header!
' + + '
This is a
' + + '
footer!
' + + '
'; + + var elem1 = $compile(tmplWithFoo)($rootScope); + var elem2 = $compile(tmplWithBar)($rootScope); + + $rootScope.$digest(); + + expect(elem1.text()).toBe('[Hello, world!]'); + expect(elem2.text()).toBe('[This is a header!|This is a footer!]'); + + dealoc(elem1); + dealoc(elem2); + }); + }); + + //see issue https://github.com/angular/angular.js/issues/12936 it('should use the proper scope when it is on the root element of a replaced directive template', function() { module(function() { From 8e104ee508418bc2ebb65e5b4ac73d22285cc224 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Sat, 26 May 2018 14:13:00 +0300 Subject: [PATCH 009/217] refactor($compile): remove preAssignBindingsEnabled leftovers Now that we don't need to support `preAssignBindingsEnabled` (removed in #15782), complexity introduced in `$controller` by #7645 can be removed. One difference with the previous implementation is that all non-ES2015-class controller instances were available on the element before calling their constructors. Now it depends on the relative order of controllers. Controller constructors shouldn't be used to access other controllers (e.g. via `$element.controller(directiveName)`). The recommended way is to use the `require` property of the directive definition object and the life cycle hooks `$onChanges` or `$onInit`. See https://docs.angularjs.org/api/ng/service/$compile#-require- https://docs.angularjs.org/api/ng/service/$compile#life-cycle-hooks Closes #16580 --- src/auto/injector.js | 30 ++------- src/ng/compile.js | 130 ++++++++++++++++-------------------- src/ng/controller.js | 42 +----------- src/ngMock/angular-mocks.js | 13 ++-- test/auto/injectorSpec.js | 19 ------ 5 files changed, 67 insertions(+), 167 deletions(-) diff --git a/src/auto/injector.js b/src/auto/injector.js index b4995af8f6f6..c1cea832acde 100644 --- a/src/auto/injector.js +++ b/src/auto/injector.js @@ -70,12 +70,8 @@ var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; var $injectorMinErr = minErr('$injector'); -function stringifyFn(fn) { - return Function.prototype.toString.call(fn); -} - function extractArgs(fn) { - var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''), + var fnText = Function.prototype.toString.call(fn).replace(STRIP_COMMENTS, ''), args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS); return args; } @@ -914,19 +910,6 @@ function createInjector(modulesToLoad, strictDi) { return args; } - function isClass(func) { - // Support: IE 9-11 only - // IE 9-11 do not support classes and IE9 leaks with the code below. - if (msie || typeof func !== 'function') { - return false; - } - var result = func.$$ngIsClass; - if (!isBoolean(result)) { - result = func.$$ngIsClass = /^class\b/.test(stringifyFn(func)); - } - return result; - } - function invoke(fn, self, locals, serviceName) { if (typeof locals === 'string') { serviceName = locals; @@ -938,14 +921,9 @@ function createInjector(modulesToLoad, strictDi) { fn = fn[fn.length - 1]; } - if (!isClass(fn)) { - // http://jsperf.com/angularjs-invoke-apply-vs-switch - // #5388 - return fn.apply(self, args); - } else { - args.unshift(null); - return new (Function.prototype.bind.apply(fn, args))(); - } + // http://jsperf.com/angularjs-invoke-apply-vs-switch + // #5388 + return fn.apply(self, args); } diff --git a/src/ng/compile.js b/src/ng/compile.js index a257c0b5f096..470640d2d329 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -2790,10 +2790,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { }; } - if (controllerDirectives) { - elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective); - } - if (newIsolateScopeDirective) { // Initialize isolate scope bindings for new isolate scope directive. compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || @@ -2809,53 +2805,69 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } } - // Initialize bindToController bindings - for (var name in elementControllers) { - var controllerDirective = controllerDirectives[name]; - var controller = elementControllers[name]; - var bindings = controllerDirective.$$bindings.bindToController; + if (controllerDirectives) { + elementControllers = createMap(); + for (var name in controllerDirectives) { + var directive = controllerDirectives[name]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; - controller.instance = controller(); - $element.data('$' + controllerDirective.name + 'Controller', controller.instance); - controller.bindingInfo = - initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective); - } + var controllerConstructor = directive.controller; + if (controllerConstructor === '@') { + controllerConstructor = attrs[name]; + } - // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy - forEach(controllerDirectives, function(controllerDirective, name) { - var require = controllerDirective.require; - if (controllerDirective.bindToController && !isArray(require) && isObject(require)) { - extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers)); + var instance = $controller(controllerConstructor, locals, directive.controllerAs); + + $element.data('$' + name + 'Controller', instance); + + // Initialize bindToController bindings + var bindings = directive.$$bindings.bindToController; + var bindingInfo = initializeDirectiveBindings(controllerScope, attrs, instance, bindings, directive); + + elementControllers[name] = { instance: instance, bindingInfo: bindingInfo }; } - }); - // Handle the init and destroy lifecycle hooks on all controllers that have them - forEach(elementControllers, function(controller) { - var controllerInstance = controller.instance; - if (isFunction(controllerInstance.$onChanges)) { - try { - controllerInstance.$onChanges(controller.bindingInfo.initialChanges); - } catch (e) { - $exceptionHandler(e); + // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy + forEach(controllerDirectives, function(controllerDirective, name) { + var require = controllerDirective.require; + if (controllerDirective.bindToController && !isArray(require) && isObject(require)) { + extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers)); } - } - if (isFunction(controllerInstance.$onInit)) { - try { - controllerInstance.$onInit(); - } catch (e) { - $exceptionHandler(e); + }); + + // Handle the init and destroy lifecycle hooks on all controllers that have them + forEach(elementControllers, function(controller) { + var controllerInstance = controller.instance; + if (isFunction(controllerInstance.$onChanges)) { + try { + controllerInstance.$onChanges(controller.bindingInfo.initialChanges); + } catch (e) { + $exceptionHandler(e); + } } - } - if (isFunction(controllerInstance.$doCheck)) { - controllerScope.$watch(function() { controllerInstance.$doCheck(); }); - controllerInstance.$doCheck(); - } - if (isFunction(controllerInstance.$onDestroy)) { - controllerScope.$on('$destroy', function callOnDestroyHook() { - controllerInstance.$onDestroy(); - }); - } - }); + if (isFunction(controllerInstance.$onInit)) { + try { + controllerInstance.$onInit(); + } catch (e) { + $exceptionHandler(e); + } + } + if (isFunction(controllerInstance.$doCheck)) { + controllerScope.$watch(function() { controllerInstance.$doCheck(); }); + controllerInstance.$doCheck(); + } + if (isFunction(controllerInstance.$onDestroy)) { + controllerScope.$on('$destroy', function callOnDestroyHook() { + controllerInstance.$onDestroy(); + }); + } + }); + } // PRELINKING for (i = 0, ii = preLinkFns.length; i < ii; i++) { @@ -2983,34 +2995,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return value || null; } - function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective) { - var elementControllers = createMap(); - for (var controllerKey in controllerDirectives) { - var directive = controllerDirectives[controllerKey]; - var locals = { - $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, - $element: $element, - $attrs: attrs, - $transclude: transcludeFn - }; - - var controller = directive.controller; - if (controller === '@') { - controller = attrs[directive.name]; - } - - var controllerInstance = $controller(controller, locals, true, directive.controllerAs); - - // For directives with element transclusion the element is a comment. - // In this case .data will not attach any data. - // Instead, we save the controllers for the element in a local hash and attach to .data - // later, once we have the actual element. - elementControllers[directive.name] = controllerInstance; - $element.data('$' + directive.name + 'Controller', controllerInstance.instance); - } - return elementControllers; - } - // Depending upon the context in which a directive finds itself it might need to have a new isolated // or child scope created. For instance: // * if the directive has been pulled into a template because another directive with a higher priority diff --git a/src/ng/controller.js b/src/ng/controller.js index 3b8d6196449b..8148307bd431 100644 --- a/src/ng/controller.js +++ b/src/ng/controller.js @@ -81,16 +81,11 @@ function $ControllerProvider() { * It's just a simple call to {@link auto.$injector $injector}, but extracted into * a service, so that one can override this service with [BC version](https://gist.github.com/1649788). */ - return function $controller(expression, locals, later, ident) { + return function $controller(expression, locals, ident) { // PRIVATE API: - // param `later` --- indicates that the controller's constructor is invoked at a later time. - // If true, $controller will allocate the object with the correct - // prototype chain, but will not invoke the controller until a returned - // callback is invoked. // param `ident` --- An optional label which overrides the label parsed from the controller // expression, if any. var instance, match, constructor, identifier; - later = later === true; if (ident && isString(ident)) { identifier = ident; } @@ -116,41 +111,6 @@ function $ControllerProvider() { assertArgFn(expression, constructor, true); } - if (later) { - // Instantiate controller later: - // This machinery is used to create an instance of the object before calling the - // controller's constructor itself. - // - // This allows properties to be added to the controller before the constructor is - // invoked. Primarily, this is used for isolate scope bindings in $compile. - // - // This feature is not intended for use by applications, and is thus not documented - // publicly. - // Object creation: http://jsperf.com/create-constructor/2 - var controllerPrototype = (isArray(expression) ? - expression[expression.length - 1] : expression).prototype; - instance = Object.create(controllerPrototype || null); - - if (identifier) { - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - - return extend(function $controllerInit() { - var result = $injector.invoke(expression, instance, locals, constructor); - if (result !== instance && (isObject(result) || isFunction(result))) { - instance = result; - if (identifier) { - // If result changed, re-assign controllerAs value to scope. - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - } - return instance; - }, { - instance: instance, - identifier: identifier - }); - } - instance = $injector.instantiate(expression, locals, constructor); if (identifier) { diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 136f70187d0f..a03b5de79307 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -2332,14 +2332,11 @@ angular.mock.$RootElementProvider = function() { */ function createControllerDecorator() { angular.mock.$ControllerDecorator = ['$delegate', function($delegate) { - return function(expression, locals, later, ident) { - if (later && typeof later === 'object') { - var instantiate = $delegate(expression, locals, true, ident); - var instance = instantiate(); - angular.extend(instance, later); - return instance; - } - return $delegate(expression, locals, later, ident); + return function(expression, locals, bindings, ident) { + if (angular.isString(bindings)) ident = bindings; + var instance = $delegate(expression, locals, ident); + angular.extend(instance, bindings); + return instance; }; }]; diff --git a/test/auto/injectorSpec.js b/test/auto/injectorSpec.js index 7f5254e201e6..7189c95de5f7 100644 --- a/test/auto/injectorSpec.js +++ b/test/auto/injectorSpec.js @@ -482,25 +482,6 @@ describe('injector', function() { expect(instance).toEqual(new Clazz('a-value')); expect(instance.aVal()).toEqual('a-value'); }); - - they('should detect ES6 classes regardless of whitespace/comments ($prop)', [ - 'class Test {}', - 'class Test{}', - 'class //<--ES6 stuff\nTest {}', - 'class//<--ES6 stuff\nTest {}', - 'class {}', - 'class{}', - 'class //<--ES6 stuff\n {}', - 'class//<--ES6 stuff\n {}', - 'class/* Test */{}', - 'class /* Test */ {}' - ], function(classDefinition) { - // eslint-disable-next-line no-eval - var Clazz = eval('(' + classDefinition + ')'); - var instance = injector.invoke(Clazz); - - expect(instance).toEqual(jasmine.any(Clazz)); - }); } }); From 459997b482ef9597ce3505d16f7ebc3b9a14b9cb Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Wed, 30 May 2018 22:55:26 +0300 Subject: [PATCH 010/217] fix(ngModel): do not throw if view value changes on destroyed scope This could for example happen if updating the value is debounced (either by asynchronously calling `$setViewValue()` or via `ngModelOptions`). Fixes #16583 Closes #16585 --- src/ng/directive/ngModel.js | 3 ++- test/ng/directive/ngModelSpec.js | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ng/directive/ngModel.js b/src/ng/directive/ngModel.js index b9aa13ce13ea..5d73c33ceb28 100644 --- a/src/ng/directive/ngModel.js +++ b/src/ng/directive/ngModel.js @@ -287,6 +287,7 @@ function NgModelController($scope, $exceptionHandler, $attr, $element, $parse, $ this.$$currentValidationRunId = 0; this.$$scope = $scope; + this.$$rootScope = $scope.$root; this.$$attr = $attr; this.$$element = $element; this.$$animate = $animate; @@ -864,7 +865,7 @@ NgModelController.prototype = { this.$$pendingDebounce = this.$$timeout(function() { that.$commitViewValue(); }, debounceDelay); - } else if (this.$$scope.$root.$$phase) { + } else if (this.$$rootScope.$$phase) { this.$commitViewValue(); } else { this.$$scope.$apply(function() { diff --git a/test/ng/directive/ngModelSpec.js b/test/ng/directive/ngModelSpec.js index bc14959ce890..825973bdcf2f 100644 --- a/test/ng/directive/ngModelSpec.js +++ b/test/ng/directive/ngModelSpec.js @@ -6,7 +6,7 @@ describe('ngModel', function() { describe('NgModelController', function() { /* global NgModelController: false */ - var ctrl, scope, ngModelAccessor, element, parentFormCtrl; + var ctrl, scope, element, parentFormCtrl; beforeEach(inject(function($rootScope, $controller) { var attrs = {name: 'testAlias', ngModel: 'value'}; @@ -21,7 +21,6 @@ describe('ngModel', function() { element = jqLite('
'); scope = $rootScope; - ngModelAccessor = jasmine.createSpy('ngModel accessor'); ctrl = $controller(NgModelController, { $scope: scope, $element: element.find('input'), @@ -438,6 +437,13 @@ describe('ngModel', function() { expect(ctrl.$modelValue).toBe('c'); expect(scope.value).toBe('c'); })); + + + it('should not throw an error if the scope has been destroyed', function() { + scope.$destroy(); + ctrl.$setViewValue('some-val'); + expect(ctrl.$viewValue).toBe('some-val'); + }); }); From 586b6e8b73804e7ab1f80d6a628ec18cf8510719 Mon Sep 17 00:00:00 2001 From: Jakub Freisler Date: Sun, 27 May 2018 23:22:52 +0200 Subject: [PATCH 011/217] docs(ngAnimate): refactor of ngAnimate docs - Synced "animation aware" directives tables in API docs and "Animation" guide. - Sorted tables alphabetically. - Added info about `ngAnimateSwap` directive. References #16561 Closes #16581 --- docs/content/guide/animations.ngdoc | 23 ++++++++++-------- src/ngAnimate/module.js | 36 ++++++++++++++++++----------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/docs/content/guide/animations.ngdoc b/docs/content/guide/animations.ngdoc index 22e4df094839..5807db4cd42e 100644 --- a/docs/content/guide/animations.ngdoc +++ b/docs/content/guide/animations.ngdoc @@ -222,23 +222,26 @@ triggered: | Directive | Supported Animations | |-------------------------------------------------------------------------------|---------------------------------------------------------------------------| -| {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave, and move | -| {@link ng.directive:ngIf#animations ngIf} | enter and leave | -| {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | -| {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | -| {@link ngRoute.directive:ngView#animations ngView} | enter and leave | -| {@link module:ngMessages#animations ngMessage / ngMessageExp} | enter and leave | +| {@link ng.directive:form#animations form / ngForm} | add and remove ({@link ng.directive:form#css-classes various classes}) | +| {@link ngAnimate.directive:ngAnimateSwap#animations ngAnimateSwap} | enter and leave | | {@link ng.directive:ngClass#animations ngClass / {{class}​}} | add and remove | | {@link ng.directive:ngClassEven#animations ngClassEven} | add and remove | | {@link ng.directive:ngClassOdd#animations ngClassOdd} | add and remove | | {@link ng.directive:ngHide#animations ngHide} | add and remove (the `ng-hide` class) | -| {@link ng.directive:ngShow#animations ngShow} | add and remove (the `ng-hide` class) | -| {@link ng.directive:ngModel#animations ngModel} | add and remove ({@link ng.directive:ngModel#css-classes various classes}) | -| {@link ng.directive:form#animations form / ngForm} | add and remove ({@link ng.directive:form#css-classes various classes}) | +| {@link ng.directive:ngIf#animations ngIf} | enter and leave | +| {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | +| {@link module:ngMessages#animations ngMessage / ngMessageExp} | enter and leave | | {@link module:ngMessages#animations ngMessages} | add and remove (the `ng-active`/`ng-inactive` classes) | +| {@link ng.directive:ngModel#animations ngModel} | add and remove ({@link ng.directive:ngModel#css-classes various classes}) | +| {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave, and move | +| {@link ng.directive:ngShow#animations ngShow} | add and remove (the `ng-hide` class) | +| {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | +| {@link ngRoute.directive:ngView#animations ngView} | enter and leave | + +(More information can be found by visiting the documentation associated with each directive.) For a full breakdown of the steps involved during each animation event, refer to the -{@link ng.$animate API docs}. +{@link ng.$animate `$animate` API docs}. ## How do I use animations in my own directives? diff --git a/src/ngAnimate/module.js b/src/ngAnimate/module.js index f37c404f7d7f..0f929f3b0018 100644 --- a/src/ngAnimate/module.js +++ b/src/ngAnimate/module.js @@ -17,20 +17,28 @@ * ## Directive Support * The following directives are "animation aware": * - * | Directive | Supported Animations | - * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------| - * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move | - * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | - * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | - * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | - * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | - * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) | - * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) | - * | {@link ng.directive:form#animations form} & {@link ng.directive:ngModel#animations ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) | - * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) | - * | {@link module:ngMessages#animations ngMessage} | enter and leave | - * - * (More information can be found by visiting each the documentation associated with each directive.) + * | Directive | Supported Animations | + * |-------------------------------------------------------------------------------|---------------------------------------------------------------------------| + * | {@link ng.directive:form#animations form / ngForm} | add and remove ({@link ng.directive:form#css-classes various classes}) | + * | {@link ngAnimate.directive:ngAnimateSwap#animations ngAnimateSwap} | enter and leave | + * | {@link ng.directive:ngClass#animations ngClass / {{class}​}} | add and remove | + * | {@link ng.directive:ngClassEven#animations ngClassEven} | add and remove | + * | {@link ng.directive:ngClassOdd#animations ngClassOdd} | add and remove | + * | {@link ng.directive:ngHide#animations ngHide} | add and remove (the `ng-hide` class) | + * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | + * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | + * | {@link module:ngMessages#animations ngMessage / ngMessageExp} | enter and leave | + * | {@link module:ngMessages#animations ngMessages} | add and remove (the `ng-active`/`ng-inactive` classes) | + * | {@link ng.directive:ngModel#animations ngModel} | add and remove ({@link ng.directive:ngModel#css-classes various classes}) | + * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave, and move | + * | {@link ng.directive:ngShow#animations ngShow} | add and remove (the `ng-hide` class) | + * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | + * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | + * + * (More information can be found by visiting the documentation associated with each directive.) + * + * For a full breakdown of the steps involved during each animation event, refer to the + * {@link ng.$animate `$animate` API docs}. * * ## CSS-based Animations * From 1bb9aa05236a9c8649e7cbe48d25cf3be507984a Mon Sep 17 00:00:00 2001 From: Christian Oliff Date: Mon, 4 Jun 2018 17:13:43 +0900 Subject: [PATCH 012/217] docs(.editorconfig): change link to use https --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index f6a54e4dd2c5..a6bc2855214e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -# http://editorconfig.org +# https://editorconfig.org root = true From a7de87d3e8600ce1cdcb77f83a558fcfd2b8aef8 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Mon, 4 Jun 2018 00:21:25 +0300 Subject: [PATCH 013/217] docs($httpBackend): headers param of expect* can be function Closes #16588 --- src/ngMock/angular-mocks.js | 53 +++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index a03b5de79307..d051ab18a7ef 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -1558,7 +1558,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url * and returns true if the url matches the current definition. - * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1573,7 +1574,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url * and returns true if the url matches the current definition. - * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1588,7 +1590,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url * and returns true if the url matches the current definition. - * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1605,7 +1608,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * and returns true if the url matches the current definition. * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives * data string and returns true if the data is as expected. - * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1622,7 +1626,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * and returns true if the url matches the current definition. * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives * data string and returns true if the data is as expected. - * @param {(Object|function(Object))=} headers HTTP headers. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1654,7 +1659,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * @param {string} url HTTP url string that supports colon param matching. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in - * order to change how a matched request is handled. See #when for more info. + * order to change how a matched request is handled. + * See {@link ngMock.$httpBackend#when `when`} for more info. */ $httpBackend.whenRoute = function(method, url) { var pathObj = parseRoute(url); @@ -1743,8 +1749,9 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * Creates a new request expectation for GET requests. For more info see `expect()`. * * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url - * and returns true if the url matches the current definition. - * @param {Object=} headers HTTP headers. + * and returns true if the url matches the current expectation. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1758,8 +1765,9 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * Creates a new request expectation for HEAD requests. For more info see `expect()`. * * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url - * and returns true if the url matches the current definition. - * @param {Object=} headers HTTP headers. + * and returns true if the url matches the current expectation. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1773,8 +1781,9 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * Creates a new request expectation for DELETE requests. For more info see `expect()`. * * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url - * and returns true if the url matches the current definition. - * @param {Object=} headers HTTP headers. + * and returns true if the url matches the current expectation. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1788,11 +1797,12 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * Creates a new request expectation for POST requests. For more info see `expect()`. * * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url - * and returns true if the url matches the current definition. + * and returns true if the url matches the current expectation. * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that * receives data string and returns true if the data is as expected, or Object if request body * is in JSON format. - * @param {Object=} headers HTTP headers. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1806,11 +1816,12 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * Creates a new request expectation for PUT requests. For more info see `expect()`. * * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url - * and returns true if the url matches the current definition. + * and returns true if the url matches the current expectation. * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that * receives data string and returns true if the data is as expected, or Object if request body * is in JSON format. - * @param {Object=} headers HTTP headers. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1824,11 +1835,12 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * Creates a new request expectation for PATCH requests. For more info see `expect()`. * * @param {string|RegExp|function(string)=} url HTTP url or function that receives a url - * and returns true if the url matches the current definition. + * and returns true if the url matches the current expectation. * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that * receives data string and returns true if the data is as expected, or Object if request body * is in JSON format. - * @param {Object=} headers HTTP headers. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1842,7 +1854,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * Creates a new request expectation for JSONP requests. For more info see `expect()`. * * @param {string|RegExp|function(string)=} url HTTP url or function that receives an url - * and returns true if the url matches the current definition. + * and returns true if the url matches the current expectation. * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in @@ -1860,7 +1872,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * @param {string} url HTTP url string that supports colon param matching. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched * request is handled. You can save this object for later use and invoke `respond` again in - * order to change how a matched request is handled. See #expect for more info. + * order to change how a matched request is handled. + * See {@link ngMock.$httpBackend#expect `expect`} for more info. */ $httpBackend.expectRoute = function(method, url) { var pathObj = parseRoute(url); From aa6adc77aef68f555928a385ecd1e0049cd9b6d9 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Tue, 5 Jun 2018 15:00:12 +0200 Subject: [PATCH 014/217] feat(ngRef): add directive to publish controller, or element into scope Thanks to @drpicox for the original implementation: PR #14080 Closes #16511 --- angularFiles.js | 1 + docs/content/error/ngRef/noctrl.ngdoc | 17 + docs/content/error/ngRef/nonassign.ngdoc | 27 ++ src/AngularPublic.js | 2 + src/ng/directive/ngRef.js | 296 ++++++++++++ test/helpers/matchers.js | 1 + test/ng/directive/ngRefSpec.js | 561 +++++++++++++++++++++++ 7 files changed, 905 insertions(+) create mode 100644 docs/content/error/ngRef/noctrl.ngdoc create mode 100644 docs/content/error/ngRef/nonassign.ngdoc create mode 100644 src/ng/directive/ngRef.js create mode 100644 test/ng/directive/ngRefSpec.js diff --git a/angularFiles.js b/angularFiles.js index 0233722adfc4..01d9dfd3f0f3 100644 --- a/angularFiles.js +++ b/angularFiles.js @@ -74,6 +74,7 @@ var angularFiles = { 'src/ng/directive/ngNonBindable.js', 'src/ng/directive/ngOptions.js', 'src/ng/directive/ngPluralize.js', + 'src/ng/directive/ngRef.js', 'src/ng/directive/ngRepeat.js', 'src/ng/directive/ngShowHide.js', 'src/ng/directive/ngStyle.js', diff --git a/docs/content/error/ngRef/noctrl.ngdoc b/docs/content/error/ngRef/noctrl.ngdoc new file mode 100644 index 000000000000..29d19a9ae134 --- /dev/null +++ b/docs/content/error/ngRef/noctrl.ngdoc @@ -0,0 +1,17 @@ +@ngdoc error +@name ngRef:noctrl +@fullName A controller for the value of `ngRefRead` could not be found on the element. +@description + +This error occurs when the {@link ng.ngRef ngRef directive} specifies +a value in `ngRefRead` that cannot be resolved to a directive / component controller. + +Causes for this error can be: + +1. Your `ngRefRead` value has a typo. +2. You have a typo in the *registered* directive / component name. +3. The directive / component does not have a controller. + +Note that `ngRefRead` takes the name of the component / directive, not the name of controller, and +also not the combination of directive and 'Controller'. For example, for a directive called 'myDirective', +the correct declaration is `
`. diff --git a/docs/content/error/ngRef/nonassign.ngdoc b/docs/content/error/ngRef/nonassign.ngdoc new file mode 100644 index 000000000000..9c1c52ee35b7 --- /dev/null +++ b/docs/content/error/ngRef/nonassign.ngdoc @@ -0,0 +1,27 @@ +@ngdoc error +@name ngRef:nonassign +@fullName Non-Assignable Expression +@description + +This error occurs when ngRef defines an expression that is not-assignable. + +In order for ngRef to work, it must be possible to write the reference into the path defined with the expression. + +For example, the following expressions are non-assignable: + +``` + + + + + + + +``` + +To resolve this error, use a path expression that is assignable: + +``` + + +``` diff --git a/src/AngularPublic.js b/src/AngularPublic.js index c18889911a50..dca14bdd6ffd 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -28,6 +28,7 @@ ngInitDirective, ngNonBindableDirective, ngPluralizeDirective, + ngRefDirective, ngRepeatDirective, ngShowDirective, ngStyleDirective, @@ -194,6 +195,7 @@ function publishExternalAPI(angular) { ngInit: ngInitDirective, ngNonBindable: ngNonBindableDirective, ngPluralize: ngPluralizeDirective, + ngRef: ngRefDirective, ngRepeat: ngRepeatDirective, ngShow: ngShowDirective, ngStyle: ngStyleDirective, diff --git a/src/ng/directive/ngRef.js b/src/ng/directive/ngRef.js new file mode 100644 index 000000000000..4b3c7a746ba4 --- /dev/null +++ b/src/ng/directive/ngRef.js @@ -0,0 +1,296 @@ +'use strict'; + +/** + * @ngdoc directive + * @name ngRef + * @restrict A + * + * @description + * The `ngRef` attribute tells AngularJS to assign the controller of a component (or a directive) + * to the given property in the current scope. It is also possible to add the jqlite-wrapped DOM + * element to the scope. + * + * If the element with `ngRef` is destroyed `null` is assigned to the property. + * + * Note that if you want to assign from a child into the parent scope, you must initialize the + * target property on the parent scope, otherwise `ngRef` will assign on the child scope. + * This commonly happens when assigning elements or components wrapped in {@link ngIf} or + * {@link ngRepeat}. See the second example below. + * + * + * @element ANY + * @param {string} ngRef property name - A valid AngularJS expression identifier to which the + * controller or jqlite-wrapped DOM element will be bound. + * @param {string=} ngRefRead read value - The name of a directive (or component) on this element, + * or the special string `$element`. If a name is provided, `ngRef` will + * assign the matching controller. If `$element` is provided, the element + * itself is assigned (even if a controller is available). + * + * + * @example + * ### Simple toggle + * This example shows how the controller of the component toggle + * is reused in the template through the scope to use its logic. + * + * + * + * + *
+ * You are using a component in the same template to show it. + *
+ *
+ * + * angular.module('myApp', []) + * .component('myToggle', { + * controller: function ToggleController() { + * var opened = false; + * this.isOpen = function() { return opened; }; + * this.toggle = function() { opened = !opened; }; + * } + * }); + * + * + * it('should publish the toggle into the scope', function() { + * var toggle = element(by.buttonText('Toggle')); + * expect(toggle.evaluate('myToggle.isOpen()')).toEqual(false); + * toggle.click(); + * expect(toggle.evaluate('myToggle.isOpen()')).toEqual(true); + * }); + * + *
+ * + * @example + * ### ngRef inside scopes + * This example shows how `ngRef` works with child scopes. The `ngRepeat`-ed `myWrapper` components + * are assigned to the scope of `myRoot`, because the `toggles` property has been initialized. + * The repeated `myToggle` components are published to the child scopes created by `ngRepeat`. + * `ngIf` behaves similarly - the assignment of `myToggle` happens in the `ngIf` child scope, + * because the target property has not been initialized on the `myRoot` component controller. + * + * + * + * + * + * + * angular.module('myApp', []) + * .component('myRoot', { + * templateUrl: 'root.html', + * controller: function() { + * this.wrappers = []; // initialize the array so that the wrappers are assigned into the parent scope + * } + * }) + * .component('myToggle', { + * template: 'myToggle', + * transclude: true, + * controller: function ToggleController() { + * var opened = false; + * this.isOpen = function() { return opened; }; + * this.toggle = function() { opened = !opened; }; + * } + * }) + * .component('myWrapper', { + * transclude: true, + * template: 'myWrapper' + + * '
ngRepeatToggle.isOpen(): {{$ctrl.ngRepeatToggle.isOpen() | json}}
' + + * '' + * }); + *
+ * + * myRoot + * Outer Toggle + *
outerToggle.isOpen(): {{$ctrl.outerToggle.isOpen() | json}}
+ *
wrappers assigned to root
+ *
+ * wrapper.ngRepeatToggle.isOpen(): {{wrapper.ngRepeatToggle.isOpen() | json}} + *
+ * + *
    + *
  • + * ngRepeat + *
    outerToggle.isOpen(): {{$ctrl.outerToggle.isOpen() | json}}
    + * ngRepeat Toggle {{$index + 1}} + *
  • + *
+ * + *
ngIfToggle.isOpen(): {{ngIfToggle.isOpen()}} // This is always undefined because it's + * assigned to the child scope created by ngIf. + *
+ *
+ ngIf + * ngIf Toggle + *
ngIfToggle.isOpen(): {{ngIfToggle.isOpen() | json}}
+ *
outerToggle.isOpen(): {{$ctrl.outerToggle.isOpen() | json}}
+ *
+ * + * + * ul { + * list-style: none; + * padding-left: 0; + * } + * + * li[ng-repeat] { + * background: lightgreen; + * padding: 8px; + * margin: 8px; + * } + * + * [ng-if] { + * background: lightgrey; + * padding: 8px; + * } + * + * my-root { + * background: lightgoldenrodyellow; + * padding: 8px; + * display: block; + * } + * + * my-wrapper { + * background: lightsalmon; + * padding: 8px; + * display: block; + * } + * + * my-toggle { + * background: lightblue; + * padding: 8px; + * display: block; + * } + * + * + * var OuterToggle = function() { + * this.toggle = function() { + * element(by.buttonText('Outer Toggle')).click(); + * }; + * this.isOpen = function() { + * return element.all(by.binding('outerToggle.isOpen()')).first().getText(); + * }; + * }; + * var NgRepeatToggle = function(i) { + * var parent = element.all(by.repeater('(index, value) in [1,2,3]')).get(i - 1); + * this.toggle = function() { + * element(by.buttonText('ngRepeat Toggle ' + i)).click(); + * }; + * this.isOpen = function() { + * return parent.element(by.binding('ngRepeatToggle.isOpen() | json')).getText(); + * }; + * this.isOuterOpen = function() { + * return parent.element(by.binding('outerToggle.isOpen() | json')).getText(); + * }; + * }; + * var NgRepeatToggles = function() { + * var toggles = [1,2,3].map(function(i) { return new NgRepeatToggle(i); }); + * this.forEach = function(fn) { + * toggles.forEach(fn); + * }; + * this.isOuterOpen = function(i) { + * return toggles[i - 1].isOuterOpen(); + * }; + * }; + * var NgIfToggle = function() { + * var parent = element(by.css('[ng-if]')); + * this.toggle = function() { + * element(by.buttonText('ngIf Toggle')).click(); + * }; + * this.isOpen = function() { + * return by.binding('ngIfToggle.isOpen() | json').getText(); + * }; + * this.isOuterOpen = function() { + * return parent.element(by.binding('outerToggle.isOpen() | json')).getText(); + * }; + * }; + * + * it('should toggle the outer toggle', function() { + * var outerToggle = new OuterToggle(); + * expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): false'); + * outerToggle.toggle(); + * expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): true'); + * }); + * + * it('should toggle all outer toggles', function() { + * var outerToggle = new OuterToggle(); + * var repeatToggles = new NgRepeatToggles(); + * var ifToggle = new NgIfToggle(); + * expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): false'); + * expect(repeatToggles.isOuterOpen(1)).toEqual('outerToggle.isOpen(): false'); + * expect(repeatToggles.isOuterOpen(2)).toEqual('outerToggle.isOpen(): false'); + * expect(repeatToggles.isOuterOpen(3)).toEqual('outerToggle.isOpen(): false'); + * expect(ifToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): false'); + * outerToggle.toggle(); + * expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): true'); + * expect(repeatToggles.isOuterOpen(1)).toEqual('outerToggle.isOpen(): true'); + * expect(repeatToggles.isOuterOpen(2)).toEqual('outerToggle.isOpen(): true'); + * expect(repeatToggles.isOuterOpen(3)).toEqual('outerToggle.isOpen(): true'); + * expect(ifToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): true'); + * }); + * + * it('should toggle each repeat iteration separately', function() { + * var repeatToggles = new NgRepeatToggles(); + * + * repeatToggles.forEach(function(repeatToggle) { + * expect(repeatToggle.isOpen()).toEqual('ngRepeatToggle.isOpen(): false'); + * expect(repeatToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): false'); + * repeatToggle.toggle(); + * expect(repeatToggle.isOpen()).toEqual('ngRepeatToggle.isOpen(): true'); + * expect(repeatToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): false'); + * }); + * }); + * + * + * + */ + +var ngRefMinErr = minErr('ngRef'); + +var ngRefDirective = ['$parse', function($parse) { + return { + priority: -1, // Needed for compatibility with element transclusion on the same element + restrict: 'A', + compile: function(tElement, tAttrs) { + // Get the expected controller name, converts into "someThing" + var controllerName = directiveNormalize(nodeName_(tElement)); + + // Get the expression for value binding + var getter = $parse(tAttrs.ngRef); + var setter = getter.assign || function() { + throw ngRefMinErr('nonassign', 'Expression in ngRef="{0}" is non-assignable!', tAttrs.ngRef); + }; + + return function(scope, element, attrs) { + var refValue; + + if (attrs.hasOwnProperty('ngRefRead')) { + if (attrs.ngRefRead === '$element') { + refValue = element; + } else { + refValue = element.data('$' + attrs.ngRefRead + 'Controller'); + + if (!refValue) { + throw ngRefMinErr( + 'noctrl', + 'The controller for ngRefRead="{0}" could not be found on ngRef="{1}"', + attrs.ngRefRead, + tAttrs.ngRef + ); + } + } + } else { + refValue = element.data('$' + controllerName + 'Controller'); + } + + refValue = refValue || element; + + setter(scope, refValue); + + // when the element is removed, remove it (nullify it) + element.on('$destroy', function() { + // only remove it if value has not changed, + // because animations (and other procedures) may duplicate elements + if (getter(scope) === refValue) { + setter(scope, null); + } + }); + }; + } + }; +}]; diff --git a/test/helpers/matchers.js b/test/helpers/matchers.js index ac297609e579..5010b212f6d2 100644 --- a/test/helpers/matchers.js +++ b/test/helpers/matchers.js @@ -313,6 +313,7 @@ beforeEach(function() { function generateCompare(isNot) { return function(actual, namespace, code, content) { + var matcher = new MinErrMatcher(isNot, namespace, code, content, { inputType: 'error', expectedAction: 'equal', diff --git a/test/ng/directive/ngRefSpec.js b/test/ng/directive/ngRefSpec.js new file mode 100644 index 000000000000..ef62fae99cad --- /dev/null +++ b/test/ng/directive/ngRefSpec.js @@ -0,0 +1,561 @@ +'use strict'; + +describe('ngRef', function() { + + beforeEach(function() { + jasmine.addMatchers({ + toEqualJq: function(util) { + return { + compare: function(actual, expected) { + // Jquery <= 2.2 objects add a context property that is irrelevant for equality + if (actual && actual.hasOwnProperty('context')) { + delete actual.context; + } + + if (expected && expected.hasOwnProperty('context')) { + delete expected.context; + } + + return { + pass: util.equals(actual, expected) + }; + } + }; + } + }); + }); + + describe('on a component', function() { + + var myComponentController, attributeDirectiveController, $rootScope, $compile; + + beforeEach(module(function($compileProvider) { + $compileProvider.component('myComponent', { + template: 'foo', + controller: function() { + myComponentController = this; + } + }); + + $compileProvider.directive('attributeDirective', function() { + return { + restrict: 'A', + controller: function() { + attributeDirectiveController = this; + } + }; + }); + + })); + + beforeEach(inject(function(_$compile_, _$rootScope_) { + $rootScope = _$rootScope_; + $compile = _$compile_; + })); + + it('should bind in the current scope the controller of a component', function() { + $rootScope.$ctrl = 'undamaged'; + + $compile('')($rootScope); + expect($rootScope.$ctrl).toBe('undamaged'); + expect($rootScope.myComponentRef).toBe(myComponentController); + }); + + it('should throw if the expression is not assignable', function() { + expect(function() { + $compile('')($rootScope); + }).toThrowMinErr('ngRef', 'nonassign', 'Expression in ngRef="\'hello\'" is non-assignable!'); + }); + + it('should work with non:normalized entity name', function() { + $compile('')($rootScope); + expect($rootScope.myComponent1).toBe(myComponentController); + }); + + it('should work with data-non-normalized entity name', function() { + $compile('')($rootScope); + expect($rootScope.myComponent2).toBe(myComponentController); + }); + + it('should work with x-non-normalized entity name', function() { + $compile('')($rootScope); + expect($rootScope.myComponent3).toBe(myComponentController); + }); + + it('should work with data-non-normalized attribute name', function() { + $compile('')($rootScope); + expect($rootScope.myComponent1).toBe(myComponentController); + }); + + it('should work with x-non-normalized attribute name', function() { + $compile('')($rootScope); + expect($rootScope.myComponent2).toBe(myComponentController); + }); + + it('should not bind the controller of an attribute directive', function() { + $compile('')($rootScope); + expect($rootScope.myComponentRef).toBe(myComponentController); + }); + + it('should not leak to parent scopes', function() { + var template = + '
' + + '' + + '
'; + $compile(template)($rootScope); + expect($rootScope.myComponent).toBe(undefined); + }); + + it('should nullify the variable once the component is destroyed', function() { + var template = '
'; + + var element = $compile(template)($rootScope); + expect($rootScope.myComponent).toBe(myComponentController); + + var componentElement = element.children(); + var isolateScope = componentElement.isolateScope(); + componentElement.remove(); + isolateScope.$destroy(); + expect($rootScope.myComponent).toBe(null); + }); + + it('should be compatible with entering/leaving components', inject(function($animate) { + var template = ''; + $rootScope.$ctrl = {}; + var parent = $compile('
')($rootScope); + + var leaving = $compile(template)($rootScope); + var leavingController = myComponentController; + + $animate.enter(leaving, parent); + expect($rootScope.myComponent).toBe(leavingController); + + var entering = $compile(template)($rootScope); + var enteringController = myComponentController; + + $animate.enter(entering, parent); + $animate.leave(leaving, parent); + expect($rootScope.myComponent).toBe(enteringController); + })); + + it('should allow binding to a nested property', function() { + $rootScope.obj = {}; + + $compile('')($rootScope); + expect($rootScope.obj.myComponent).toBe(myComponentController); + }); + + }); + + it('should bind the jqlite wrapped DOM element if there is no component', inject(function($compile, $rootScope) { + + var el = $compile('my text')($rootScope); + + expect($rootScope.mySpan).toEqualJq(el); + expect($rootScope.mySpan[0].textContent).toBe('my text'); + })); + + it('should nullify the expression value if the DOM element is destroyed', inject(function($compile, $rootScope) { + var element = $compile('
my text
')($rootScope); + element.children().remove(); + expect($rootScope.mySpan).toBe(null); + })); + + it('should bind the controller of an element directive', function() { + var myDirectiveController; + + module(function($compileProvider) { + $compileProvider.directive('myDirective', function() { + return { + controller: function() { + myDirectiveController = this; + } + }; + }); + }); + + inject(function($compile, $rootScope) { + $compile('')($rootScope); + + expect($rootScope.myDirective).toBe(myDirectiveController); + }); + }); + + describe('ngRefRead', function() { + + it('should bind the element instead of the controller of a component if ngRefRead="$element" is set', function() { + + module(function($compileProvider) { + + $compileProvider.component('myComponent', { + template: 'my text', + controller: function() {} + }); + }); + + inject(function($compile, $rootScope) { + + var el = $compile('')($rootScope); + expect($rootScope.myEl).toEqualJq(el); + expect($rootScope.myEl[0].textContent).toBe('my text'); + }); + }); + + + it('should bind the element instead an element-directive controller if ngRefRead="$element" is set', function() { + + module(function($compileProvider) { + $compileProvider.directive('myDirective', function() { + return { + restrict: 'E', + template: 'my text', + controller: function() {} + }; + }); + }); + + inject(function($compile, $rootScope) { + var el = $compile('')($rootScope); + + expect($rootScope.myEl).toEqualJq(el); + expect($rootScope.myEl[0].textContent).toBe('my text'); + }); + }); + + + it('should bind an attribute-directive controller if ngRefRead="controllerName" is set', function() { + var attrDirective1Controller; + + module(function($compileProvider) { + $compileProvider.directive('elementDirective', function() { + return { + restrict: 'E', + template: 'my text', + controller: function() {} + }; + }); + + $compileProvider.directive('attributeDirective1', function() { + return { + restrict: 'A', + controller: function() { + attrDirective1Controller = this; + } + }; + }); + + $compileProvider.directive('attributeDirective2', function() { + return { + restrict: 'A', + controller: function() {} + }; + }); + + }); + + inject(function($compile, $rootScope) { + var el = $compile('')($rootScope); + + expect($rootScope.myController).toBe(attrDirective1Controller); + }); + }); + + it('should throw if no controller is found for the ngRefRead value', function() { + + module(function($compileProvider) { + $compileProvider.directive('elementDirective', function() { + return { + restrict: 'E', + template: 'my text', + controller: function() {} + }; + }); + }); + + inject(function($compile, $rootScope) { + + expect(function() { + $compile('')($rootScope); + }).toThrowMinErr('ngRef', 'noctrl', 'The controller for ngRefRead="attribute" could not be found on ngRef="myController"'); + + }); + }); + + }); + + + it('should bind the jqlite element if the controller is on an attribute-directive', function() { + var myDirectiveController; + + module(function($compileProvider) { + $compileProvider.directive('myDirective', function() { + return { + restrict: 'A', + template: 'my text', + controller: function() { + myDirectiveController = this; + } + }; + }); + }); + + inject(function($compile, $rootScope) { + var el = $compile('
')($rootScope); + + expect(myDirectiveController).toBeDefined(); + expect($rootScope.myEl).toEqualJq(el); + expect($rootScope.myEl[0].textContent).toBe('my text'); + }); + }); + + + it('should bind the jqlite element if the controller is on an class-directive', function() { + var myDirectiveController; + + module(function($compileProvider) { + $compileProvider.directive('myDirective', function() { + return { + restrict: 'C', + template: 'my text', + controller: function() { + myDirectiveController = this; + } + }; + }); + }); + + inject(function($compile, $rootScope) { + var el = $compile('
')($rootScope); + + expect(myDirectiveController).toBeDefined(); + expect($rootScope.myEl).toEqualJq(el); + expect($rootScope.myEl[0].textContent).toBe('my text'); + }); + }); + + describe('transclusion', function() { + + it('should work with simple transclusion', function() { + module(function($compileProvider) { + $compileProvider + .component('myComponent', { + transclude: true, + template: '', + controller: function() { + this.text = 'SUCCESS'; + } + }); + }); + + inject(function($compile, $rootScope) { + var template = '{{myComponent.text}}'; + var element = $compile(template)($rootScope); + $rootScope.$apply(); + expect(element.text()).toBe('SUCCESS'); + dealoc(element); + }); + }); + + it('should be compatible with element transclude components', function() { + + module(function($compileProvider) { + $compileProvider + .component('myComponent', { + transclude: 'element', + controller: function($animate, $element, $transclude) { + this.text = 'SUCCESS'; + this.$postLink = function() { + $transclude(function(clone, newScope) { + $animate.enter(clone, $element.parent(), $element); + }); + }; + } + }); + }); + + inject(function($compile, $rootScope) { + var template = + '
' + + '' + + '{{myComponent.text}}' + + '' + + '
'; + var element = $compile(template)($rootScope); + $rootScope.$apply(); + expect(element.text()).toBe('SUCCESS'); + dealoc(element); + }); + }); + + it('should be compatible with ngIf and transclusion on same element', function() { + module(function($compileProvider) { + $compileProvider.component('myComponent', { + template: '', + transclude: true, + controller: function($scope) { + this.text = 'SUCCESS'; + } + }); + }); + + inject(function($compile, $rootScope) { + var template = + '
' + + '' + + '{{myComponent.text}}' + + '' + + '
'; + var element = $compile(template)($rootScope); + + $rootScope.$apply('present = false'); + expect(element.text()).toBe(''); + $rootScope.$apply('present = true'); + expect(element.text()).toBe('SUCCESS'); + $rootScope.$apply('present = false'); + expect(element.text()).toBe(''); + $rootScope.$apply('present = true'); + expect(element.text()).toBe('SUCCESS'); + dealoc(element); + }); + }); + + it('should be compatible with element transclude & destroy components', function() { + var myComponentController; + module(function($compileProvider) { + $compileProvider + .component('myTranscludingComponent', { + transclude: 'element', + controller: function($animate, $element, $transclude) { + myComponentController = this; + + var currentClone, currentScope; + this.transclude = function(text) { + this.text = text; + $transclude(function(clone, newScope) { + currentClone = clone; + currentScope = newScope; + $animate.enter(clone, $element.parent(), $element); + }); + }; + this.destroy = function() { + currentClone.remove(); + currentScope.$destroy(); + }; + } + }); + }); + + inject(function($compile, $rootScope) { + var template = + '
' + + '' + + '{{myComponent.text}}' + + '' + + '
'; + var element = $compile(template)($rootScope); + $rootScope.$apply(); + expect(element.text()).toBe(''); + + myComponentController.transclude('transcludedOk'); + $rootScope.$apply(); + expect(element.text()).toBe('transcludedOk'); + + myComponentController.destroy(); + $rootScope.$apply(); + expect(element.text()).toBe(''); + }); + }); + + it('should be compatible with element transclude directives', function() { + module(function($compileProvider) { + $compileProvider + .directive('myDirective', function($animate) { + return { + transclude: 'element', + controller: function() { + this.text = 'SUCCESS'; + }, + link: function(scope, element, attrs, ctrl, $transclude) { + $transclude(function(clone, newScope) { + $animate.enter(clone, element.parent(), element); + }); + } + }; + }); + }); + + inject(function($compile, $rootScope) { + var template = + '
' + + '' + + '{{myDirective.text}}' + + '' + + '
'; + var element = $compile(template)($rootScope); + $rootScope.$apply(); + expect(element.text()).toBe('SUCCESS'); + dealoc(element); + }); + }); + + }); + + it('should work with components with templates via $http', function() { + module(function($compileProvider) { + $compileProvider.component('httpComponent', { + templateUrl: 'template.html', + controller: function() { + this.me = true; + } + }); + }); + + inject(function($compile, $httpBackend, $rootScope) { + var template = '
'; + var element = $compile(template)($rootScope); + $httpBackend.expect('GET', 'template.html').respond('ok'); + $rootScope.$apply(); + expect($rootScope.controller).toBeUndefined(); + $httpBackend.flush(); + expect($rootScope.controller.me).toBe(true); + dealoc(element); + }); + }); + + + it('should work with ngRepeat-ed components', function() { + var controllers = []; + + module(function($compileProvider) { + $compileProvider.component('myComponent', { + template: 'foo', + controller: function() { + controllers.push(this); + } + }); + }); + + + inject(function($compile, $rootScope) { + $rootScope.elements = [0,1,2,3,4]; + $rootScope.controllers = []; // Initialize the array because ngRepeat creates a child scope + + var template = '
'; + var element = $compile(template)($rootScope); + $rootScope.$apply(); + + expect($rootScope.controllers).toEqual(controllers); + + $rootScope.$apply('elements = []'); + + expect($rootScope.controllers).toEqual([null, null, null, null, null]); + }); + }); + +}); From 0ed36430da8216194e6e228f9e9b5d0a5106bf2b Mon Sep 17 00:00:00 2001 From: Jakub Freisler Date: Mon, 28 May 2018 01:48:36 +0200 Subject: [PATCH 015/217] docs(ngAnimate): add "animating between value changes" section Add a section which covers use case when users need to animate upon a variable's value changes (not between two states). Refers #16561 Closes #16582 --- src/ngAnimate/module.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ngAnimate/module.js b/src/ngAnimate/module.js index 0f929f3b0018..d7ef5d873c50 100644 --- a/src/ngAnimate/module.js +++ b/src/ngAnimate/module.js @@ -275,9 +275,22 @@ * .message.ng-enter-prepare { * opacity: 0; * } - * * ``` * + * ### Animating between value changes + * + * Sometimes you need to animate between different expression states, whose values + * don't necessary need to be known or referenced in CSS styles. + * Unless possible with another ["animation aware" directive](#directive-support), that specific + * use case can always be covered with {@link ngAnimate.directive:ngAnimateSwap} as can be seen in + * {@link ngAnimate.directive:ngAnimateSwap#examples this example}. + * + * Note that {@link ngAnimate.directive:ngAnimateSwap} is a *structural directive*, which means it + * creates a new instance of the element (including any other/child directives it may have) and + * links it to a new scope every time *swap* happens. In some cases this might not be desirable + * (e.g. for performance reasons, or when you wish to retain internal state on the original + * element instance). + * * ## JavaScript-based Animations * * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared From 03a4782a35e036a6b1b4fc8137fae58f73f3bb6f Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Wed, 6 Jun 2018 15:03:09 +0200 Subject: [PATCH 016/217] feat(errorHandlingConfig): add option to exclude error params from url Specific errors, such as those during nested module loading, can create very long error urls because the error message includes the error stack. These urls create visual clutter in the browser console, are often not clickable, and may be rejected by the docs page because they are simply too long. We've already made improvements to the error display in #16283, which excludes the error url from error parameters, which results in cleaner error messages. Further, modern browsers restrict console message length intelligently. This option can still be useful for older browsers like Internet Explorer, or in general to reduce visual clutter in the console. Closes #14744 Closes #15707 Closes #16283 Closes #16299 Closes #16591 --- src/minErr.js | 19 +++++++++++--- test/minErrSpec.js | 64 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/minErr.js b/src/minErr.js index a2f0ddc2d544..234d244f544f 100644 --- a/src/minErr.js +++ b/src/minErr.js @@ -7,7 +7,8 @@ */ var minErrConfig = { - objectMaxDepth: 5 + objectMaxDepth: 5, + urlErrorParamsEnabled: true }; /** @@ -30,12 +31,21 @@ var minErrConfig = { * * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a * non-positive or non-numeric value, removes the max depth limit. * Default: 5 + * + * * `urlErrorParamsEnabled` **{Boolean}** - Specifies wether the generated error url will + * contain the parameters of the thrown error. Disabling the parameters can be useful if the + * generated error url is very long. + * + * Default: true. When used without argument, it returns the current value. */ function errorHandlingConfig(config) { if (isObject(config)) { if (isDefined(config.objectMaxDepth)) { minErrConfig.objectMaxDepth = isValidObjectMaxDepth(config.objectMaxDepth) ? config.objectMaxDepth : NaN; } + if (isDefined(config.urlErrorParamsEnabled) && isBoolean(config.urlErrorParamsEnabled)) { + minErrConfig.urlErrorParamsEnabled = config.urlErrorParamsEnabled; + } } else { return minErrConfig; } @@ -50,6 +60,7 @@ function isValidObjectMaxDepth(maxDepth) { return isNumber(maxDepth) && maxDepth > 0; } + /** * @description * @@ -113,8 +124,10 @@ function minErr(module, ErrorConstructor) { message += '\n' + url + (module ? module + '/' : '') + code; - for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') { - message += paramPrefix + 'p' + i + '=' + encodeURIComponent(templateArgs[i]); + if (minErrConfig.urlErrorParamsEnabled) { + for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') { + message += paramPrefix + 'p' + i + '=' + encodeURIComponent(templateArgs[i]); + } } return new ErrorConstructor(message); diff --git a/test/minErrSpec.js b/test/minErrSpec.js index 4319fd88d569..66e018b077c8 100644 --- a/test/minErrSpec.js +++ b/test/minErrSpec.js @@ -2,32 +2,57 @@ describe('errors', function() { var originalObjectMaxDepthInErrorMessage = minErrConfig.objectMaxDepth; + var originalUrlErrorParamsEnabled = minErrConfig.urlErrorParamsEnabled; afterEach(function() { minErrConfig.objectMaxDepth = originalObjectMaxDepthInErrorMessage; + minErrConfig.urlErrorParamsEnabled = originalUrlErrorParamsEnabled; }); describe('errorHandlingConfig', function() { - it('should get default objectMaxDepth', function() { - expect(errorHandlingConfig().objectMaxDepth).toBe(5); - }); + describe('objectMaxDepth',function() { + it('should get default objectMaxDepth', function() { + expect(errorHandlingConfig().objectMaxDepth).toBe(5); + }); + + it('should set objectMaxDepth', function() { + errorHandlingConfig({objectMaxDepth: 3}); + expect(errorHandlingConfig().objectMaxDepth).toBe(3); + }); - it('should set objectMaxDepth', function() { - errorHandlingConfig({objectMaxDepth: 3}); - expect(errorHandlingConfig().objectMaxDepth).toBe(3); + it('should not change objectMaxDepth when undefined is supplied', function() { + errorHandlingConfig({objectMaxDepth: undefined}); + expect(errorHandlingConfig().objectMaxDepth).toBe(originalObjectMaxDepthInErrorMessage); + }); + + they('should set objectMaxDepth to NaN when $prop is supplied', + [NaN, null, true, false, -1, 0], function(maxDepth) { + errorHandlingConfig({objectMaxDepth: maxDepth}); + expect(errorHandlingConfig().objectMaxDepth).toBeNaN(); + } + ); }); - it('should not change objectMaxDepth when undefined is supplied', function() { - errorHandlingConfig({objectMaxDepth: undefined}); - expect(errorHandlingConfig().objectMaxDepth).toBe(originalObjectMaxDepthInErrorMessage); + + describe('urlErrorParamsEnabled',function() { + + it('should get default urlErrorParamsEnabled', function() { + expect(errorHandlingConfig().urlErrorParamsEnabled).toBe(true); + }); + + it('should set urlErrorParamsEnabled', function() { + errorHandlingConfig({urlErrorParamsEnabled: false}); + expect(errorHandlingConfig().urlErrorParamsEnabled).toBe(false); + errorHandlingConfig({urlErrorParamsEnabled: true}); + expect(errorHandlingConfig().urlErrorParamsEnabled).toBe(true); + }); + + it('should not change its value when non-boolean is supplied', function() { + errorHandlingConfig({urlErrorParamsEnabled: 123}); + expect(errorHandlingConfig().urlErrorParamsEnabled).toBe(originalUrlErrorParamsEnabled); + }); }); - they('should set objectMaxDepth to NaN when $prop is supplied', - [NaN, null, true, false, -1, 0], function(maxDepth) { - errorHandlingConfig({objectMaxDepth: maxDepth}); - expect(errorHandlingConfig().objectMaxDepth).toBeNaN(); - } - ); }); describe('minErr', function() { @@ -165,7 +190,6 @@ describe('errors', function() { .toMatch(/^[\s\S]*\?p0=a&p1=b&p2=value%20with%20space$/); }); - it('should strip error reference urls from the error message parameters', function() { var firstError = testError('firstcode', 'longer string and so on'); @@ -177,5 +201,13 @@ describe('errors', function() { '%3A%2F%2Ferrors.angularjs.org%2F%22NG_VERSION_FULL%22%2Ftest%2Ffirstcode'); }); + it('should not generate URL query parameters when urlErrorParamsEnabled is false', function() { + + errorHandlingConfig({urlErrorParamsEnabled: false}); + + expect(testError('acode', 'aproblem', 'a', 'b', 'c').message).toBe('[test:acode] aproblem\n' + + 'https://errors.angularjs.org/"NG_VERSION_FULL"/test/acode'); + }); + }); }); From 84d80be2b4624b9fcfac81204ff047eba108d804 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Wed, 6 Jun 2018 17:40:55 +0200 Subject: [PATCH 017/217] feat(ngMessages): add support for default message add support for showing default message when a truthy value is not matched by an ng-message directive. Closes #12008 Closes #12213 Closes #16587 --- src/ngMessages/messages.js | 176 +++++++++++++++++++++++--------- test/ngMessages/messagesSpec.js | 94 +++++++++++++++++ 2 files changed, 223 insertions(+), 47 deletions(-) diff --git a/src/ngMessages/messages.js b/src/ngMessages/messages.js index 445122b67102..bc0026a14f7c 100644 --- a/src/ngMessages/messages.js +++ b/src/ngMessages/messages.js @@ -18,7 +18,7 @@ var jqLite; * sequencing based on the order of how the messages are defined in the template. * * Currently, the ngMessages module only contains the code for the `ngMessages`, `ngMessagesInclude` - * `ngMessage` and `ngMessageExp` directives. + * `ngMessage`, `ngMessageExp` and `ngMessageDefault` directives. * * ## Usage * The `ngMessages` directive allows keys in a key/value collection to be associated with a child element @@ -257,7 +257,26 @@ var jqLite; * .some-message.ng-leave.ng-leave-active {} * ``` * - * {@link ngAnimate Click here} to learn how to use JavaScript animations or to learn more about ngAnimate. + * {@link ngAnimate See the ngAnimate docs} to learn how to use JavaScript animations or to learn + * more about ngAnimate. + * + * ## Displaying a default message + * If the ngMessages renders no inner ngMessage directive (i.e. when none of the truthy + * keys are matched by a defined message), then it will render a default message + * using the {@link ngMessageDefault} directive. + * Note that matched messages will always take precedence over unmatched messages. That means + * the default message will not be displayed when another message is matched. This is also + * true for `ng-messages-multiple`. + * + * ```html + *
+ *
This field is required
+ *
This field is too short
+ *
This field has an input error
+ *
+ * ``` + * + */ angular.module('ngMessages', [], function initAngularHelpers() { // Access helpers from AngularJS core. @@ -286,8 +305,11 @@ angular.module('ngMessages', [], function initAngularHelpers() { * at a time and this depends on the prioritization of the messages within the template. (This can * be changed by using the `ng-messages-multiple` or `multiple` attribute on the directive container.) * - * A remote template can also be used to promote message reusability and messages can also be - * overridden. + * A remote template can also be used (With {@link ngMessagesInclude}) to promote message + * reusability and messages can also be overridden. + * + * A default message can also be displayed when no `ngMessage` directive is inserted, using the + * {@link ngMessageDefault} directive. * * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`. * @@ -298,6 +320,7 @@ angular.module('ngMessages', [], function initAngularHelpers() { * ... * ... * ... + * ... * * * @@ -305,6 +328,7 @@ angular.module('ngMessages', [], function initAngularHelpers() { * ... * ... * ... + * ... * * ``` * @@ -333,6 +357,7 @@ angular.module('ngMessages', [], function initAngularHelpers() { *
You did not enter a field
*
Your field is too short
*
Your field is too long
+ *
This field has an input error
*
* *
@@ -370,6 +395,7 @@ angular.module('ngMessages', [], function initAngularHelpers() { var unmatchedMessages = []; var matchedKeys = {}; + var truthyKeys = 0; var messageItem = ctrl.head; var messageFound = false; var totalMessages = 0; @@ -382,13 +408,17 @@ angular.module('ngMessages', [], function initAngularHelpers() { var messageUsed = false; if (!messageFound) { forEach(collection, function(value, key) { - if (!messageUsed && truthy(value) && messageCtrl.test(key)) { - // this is to prevent the same error name from showing up twice - if (matchedKeys[key]) return; - matchedKeys[key] = true; + if (truthy(value) && !messageUsed) { + truthyKeys++; + + if (messageCtrl.test(key)) { + // this is to prevent the same error name from showing up twice + if (matchedKeys[key]) return; + matchedKeys[key] = true; - messageUsed = true; - messageCtrl.attach(); + messageUsed = true; + messageCtrl.attach(); + } } }); } @@ -408,7 +438,16 @@ angular.module('ngMessages', [], function initAngularHelpers() { messageCtrl.detach(); }); - if (unmatchedMessages.length !== totalMessages) { + var messageMatched = unmatchedMessages.length !== totalMessages; + var attachDefault = ctrl.default && !messageMatched && truthyKeys > 0; + + if (attachDefault) { + ctrl.default.attach(); + } else if (ctrl.default) { + ctrl.default.detach(); + } + + if (messageMatched || attachDefault) { $animate.setClass($element, ACTIVE_CLASS, INACTIVE_CLASS); } else { $animate.setClass($element, INACTIVE_CLASS, ACTIVE_CLASS); @@ -428,23 +467,31 @@ angular.module('ngMessages', [], function initAngularHelpers() { } }; - this.register = function(comment, messageCtrl) { - var nextKey = latestKey.toString(); - messages[nextKey] = { - message: messageCtrl - }; - insertMessageNode($element[0], comment, nextKey); - comment.$$ngMessageNode = nextKey; - latestKey++; + this.register = function(comment, messageCtrl, isDefault) { + if (isDefault) { + ctrl.default = messageCtrl; + } else { + var nextKey = latestKey.toString(); + messages[nextKey] = { + message: messageCtrl + }; + insertMessageNode($element[0], comment, nextKey); + comment.$$ngMessageNode = nextKey; + latestKey++; + } ctrl.reRender(); }; - this.deregister = function(comment) { - var key = comment.$$ngMessageNode; - delete comment.$$ngMessageNode; - removeMessageNode($element[0], comment, key); - delete messages[key]; + this.deregister = function(comment, isDefault) { + if (isDefault) { + delete ctrl.default; + } else { + var key = comment.$$ngMessageNode; + delete comment.$$ngMessageNode; + removeMessageNode($element[0], comment, key); + delete messages[key]; + } ctrl.reRender(); }; @@ -647,9 +694,41 @@ angular.module('ngMessages', [], function initAngularHelpers() { * * @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key. */ - .directive('ngMessageExp', ngMessageDirectiveFactory()); + .directive('ngMessageExp', ngMessageDirectiveFactory()) + + /** + * @ngdoc directive + * @name ngMessageDefault + * @restrict AE + * @scope + * + * @description + * `ngMessageDefault` is a directive with the purpose to show and hide a default message for + * {@link ngMessages}, when none of provided messages matches. + * + * More information about using `ngMessageDefault` can be found in the + * {@link module:ngMessages `ngMessages` module documentation}. + * + * @usage + * ```html + * + * + * ... + * ... + * ... + * + * + * + * + * ... + * ... + * ... + * + * + */ + .directive('ngMessageDefault', ngMessageDirectiveFactory(true)); -function ngMessageDirectiveFactory() { +function ngMessageDirectiveFactory(isDefault) { return ['$animate', function($animate) { return { restrict: 'AE', @@ -658,25 +737,28 @@ function ngMessageDirectiveFactory() { terminal: true, require: '^^ngMessages', link: function(scope, element, attrs, ngMessagesCtrl, $transclude) { - var commentNode = element[0]; - - var records; - var staticExp = attrs.ngMessage || attrs.when; - var dynamicExp = attrs.ngMessageExp || attrs.whenExp; - var assignRecords = function(items) { - records = items - ? (isArray(items) - ? items - : items.split(/[\s,]+/)) - : null; - ngMessagesCtrl.reRender(); - }; + var commentNode, records, staticExp, dynamicExp; + + if (!isDefault) { + commentNode = element[0]; + staticExp = attrs.ngMessage || attrs.when; + dynamicExp = attrs.ngMessageExp || attrs.whenExp; + + var assignRecords = function(items) { + records = items + ? (isArray(items) + ? items + : items.split(/[\s,]+/)) + : null; + ngMessagesCtrl.reRender(); + }; - if (dynamicExp) { - assignRecords(scope.$eval(dynamicExp)); - scope.$watchCollection(dynamicExp, assignRecords); - } else { - assignRecords(staticExp); + if (dynamicExp) { + assignRecords(scope.$eval(dynamicExp)); + scope.$watchCollection(dynamicExp, assignRecords); + } else { + assignRecords(staticExp); + } } var currentElement, messageCtrl; @@ -701,7 +783,7 @@ function ngMessageDirectiveFactory() { // If the message element was removed via a call to `detach` then `currentElement` will be null // So this handler only handles cases where something else removed the message element. if (currentElement && currentElement.$$attachId === $$attachId) { - ngMessagesCtrl.deregister(commentNode); + ngMessagesCtrl.deregister(commentNode, isDefault); messageCtrl.detach(); } newScope.$destroy(); @@ -716,14 +798,14 @@ function ngMessageDirectiveFactory() { $animate.leave(elm); } } - }); + }, isDefault); // We need to ensure that this directive deregisters itself when it no longer exists // Normally this is done when the attached element is destroyed; but if this directive // gets removed before we attach the message to the DOM there is nothing to watch // in which case we must deregister when the containing scope is destroyed. scope.$on('$destroy', function() { - ngMessagesCtrl.deregister(commentNode); + ngMessagesCtrl.deregister(commentNode, isDefault); }); } }; diff --git a/test/ngMessages/messagesSpec.js b/test/ngMessages/messagesSpec.js index b86f764f37d0..527a577b1f18 100644 --- a/test/ngMessages/messagesSpec.js +++ b/test/ngMessages/messagesSpec.js @@ -661,6 +661,100 @@ describe('ngMessages', function() { ); + describe('default message', function() { + it('should render a default message when no message matches', inject(function($rootScope, $compile) { + element = $compile('
' + + '
Message is set
' + + '
Default message is set
' + + '
')($rootScope); + $rootScope.$apply(function() { + $rootScope.col = { unexpected: false }; + }); + + $rootScope.$digest(); + + expect(element.text().trim()).toBe(''); + expect(element).not.toHaveClass('ng-active'); + + $rootScope.$apply(function() { + $rootScope.col = { unexpected: true }; + }); + + expect(element.text().trim()).toBe('Default message is set'); + expect(element).toHaveClass('ng-active'); + + $rootScope.$apply(function() { + $rootScope.col = { unexpected: false }; + }); + + expect(element.text().trim()).toBe(''); + expect(element).not.toHaveClass('ng-active'); + + $rootScope.$apply(function() { + $rootScope.col = { val: true, unexpected: true }; + }); + + expect(element.text().trim()).toBe('Message is set'); + expect(element).toHaveClass('ng-active'); + })); + + it('should not render a default message with ng-messages-multiple if another error matches', + inject(function($rootScope, $compile) { + element = $compile('
' + + '
Message is set
' + + '
Other message is set
' + + '
Default message is set
' + + '
')($rootScope); + + expect(element.text().trim()).toBe(''); + + $rootScope.$apply(function() { + $rootScope.col = { val: true, other: false, unexpected: false }; + }); + + expect(element.text().trim()).toBe('Message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { val: true, other: true, unexpected: true }; + }); + + expect(element.text().trim()).toBe('Message is set Other message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { val: false, other: false, unexpected: true }; + }); + + expect(element.text().trim()).toBe('Default message is set'); + }) + ); + + it('should handle a default message with ngIf', inject(function($rootScope, $compile) { + element = $compile('
' + + '
Message is set
' + + '
Default message is set
' + + '
')($rootScope); + $rootScope.default = true; + $rootScope.col = {unexpected: true}; + $rootScope.$digest(); + + expect(element.text().trim()).toBe('Default message is set'); + + $rootScope.$apply('default = false'); + + expect(element.text().trim()).toBe(''); + + $rootScope.$apply('default = true'); + + expect(element.text().trim()).toBe('Default message is set'); + + $rootScope.$apply(function() { + $rootScope.col = { val: true }; + }); + + expect(element.text().trim()).toBe('Message is set'); + })); + }); + describe('when including templates', function() { they('should work with a dynamic collection model which is managed by ngRepeat', {'
': '
' + From 60069e67aeb0352a7849ebfef15a6183bc3b7235 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Sun, 7 Aug 2016 17:34:14 +0300 Subject: [PATCH 018/217] feat($route): add support for the `reloadOnUrl` configuration option Enables users to specify that a particular route should not be reloaded after a URL change (including a change in `$location.path()`), if the new URL maps to the same route. The default behavior is still to always load the matched route when any part of the URL changes. Related to #1699, #5860, #14999 (potentially closing the first two). Fixes #7925 Closes #15002 --- src/ngRoute/route.js | 50 ++++- test/ngRoute/routeSpec.js | 424 +++++++++++++++++++++++++++++++++----- 2 files changed, 421 insertions(+), 53 deletions(-) diff --git a/src/ngRoute/route.js b/src/ngRoute/route.js index f0e6c19b9079..6902a3e654d2 100644 --- a/src/ngRoute/route.js +++ b/src/ngRoute/route.js @@ -183,11 +183,22 @@ function $RouteProvider() { * `redirectTo` takes precedence over `resolveRedirectTo`, so specifying both on the same * route definition, will cause the latter to be ignored. * + * - `[reloadOnUrl=true]` - `{boolean=}` - reload route when any part of the URL changes + * (inluding the path) even if the new URL maps to the same route. + * + * If the option is set to `false` and the URL in the browser changes, but the new URL maps + * to the same route, then a `$routeUpdate` event is broadcasted on the root scope (without + * reloading the route). + * * - `[reloadOnSearch=true]` - `{boolean=}` - reload route when only `$location.search()` * or `$location.hash()` changes. * - * If the option is set to `false` and url in the browser changes, then - * `$routeUpdate` event is broadcasted on the root scope. + * If the option is set to `false` and the URL in the browser changes, then a `$routeUpdate` + * event is broadcasted on the root scope (without reloading the route). + * + *
+ * **Note:** This option has no effect if `reloadOnUrl` is set to `false`. + *
* * - `[caseInsensitiveMatch=false]` - `{boolean=}` - match routes without being case sensitive * @@ -202,6 +213,9 @@ function $RouteProvider() { this.when = function(path, route) { //copy original route object to preserve params inherited from proto chain var routeCopy = shallowCopy(route); + if (angular.isUndefined(routeCopy.reloadOnUrl)) { + routeCopy.reloadOnUrl = true; + } if (angular.isUndefined(routeCopy.reloadOnSearch)) { routeCopy.reloadOnSearch = true; } @@ -544,8 +558,9 @@ function $RouteProvider() { * @name $route#$routeUpdate * @eventType broadcast on root scope * @description - * The `reloadOnSearch` property has been set to false, and we are reusing the same - * instance of the Controller. + * Broadcasted if the same instance of a route (including template, controller instance, + * resolved dependencies, etc.) is being reused. This can happen if either `reloadOnSearch` or + * `reloadOnUrl` has been set to `false`. * * @param {Object} angularEvent Synthetic event object * @param {Route} current Current/previous route information. @@ -653,9 +668,7 @@ function $RouteProvider() { var lastRoute = $route.current; preparedRoute = parseRoute(); - preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route - && angular.equals(preparedRoute.pathParams, lastRoute.pathParams) - && !preparedRoute.reloadOnSearch && !forceReload; + preparedRouteIsUpdateOnly = isNavigationUpdateOnly(preparedRoute, lastRoute); if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) { if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) { @@ -835,6 +848,29 @@ function $RouteProvider() { return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); } + /** + * @param {Object} newRoute - The new route configuration (as returned by `parseRoute()`). + * @param {Object} oldRoute - The previous route configuration (as returned by `parseRoute()`). + * @returns {boolean} Whether this is an "update-only" navigation, i.e. the URL maps to the same + * route and it can be reused (based on the config and the type of change). + */ + function isNavigationUpdateOnly(newRoute, oldRoute) { + // IF this is not a forced reload + return !forceReload + // AND both `newRoute`/`oldRoute` are defined + && newRoute && oldRoute + // AND they map to the same Route Definition Object + && (newRoute.$$route === oldRoute.$$route) + // AND `reloadOnUrl` is disabled + && (!newRoute.reloadOnUrl + // OR `reloadOnSearch` is disabled + || (!newRoute.reloadOnSearch + // AND both routes have the same path params + && angular.equals(newRoute.pathParams, oldRoute.pathParams) + ) + ); + } + /** * @returns {string} interpolation of the redirect path with the parameters */ diff --git a/test/ngRoute/routeSpec.js b/test/ngRoute/routeSpec.js index 36832ab57884..14d655af83e9 100644 --- a/test/ngRoute/routeSpec.js +++ b/test/ngRoute/routeSpec.js @@ -65,8 +65,8 @@ describe('$route', function() { $httpBackend.when('GET', 'Chapter.html').respond('chapter'); $httpBackend.when('GET', 'test.html').respond('test'); $httpBackend.when('GET', 'foo.html').respond('foo'); - $httpBackend.when('GET', 'baz.html').respond('baz'); $httpBackend.when('GET', 'bar.html').respond('bar'); + $httpBackend.when('GET', 'baz.html').respond('baz'); $httpBackend.when('GET', 'http://example.com/trusted-template.html').respond('cross domain trusted template'); $httpBackend.when('GET', '404.html').respond('not found'); }; @@ -76,6 +76,7 @@ describe('$route', function() { dealoc(element); }); + it('should allow cancellation via $locationChangeStart via $routeChangeStart', function() { module(function($routeProvider) { $routeProvider.when('/Edit', { @@ -1677,95 +1678,413 @@ describe('$route', function() { }); - describe('reloadOnSearch', function() { - it('should reload a route when reloadOnSearch is enabled and .search() changes', function() { - var reloaded = jasmine.createSpy('route reload'); + describe('reloadOnUrl', function() { + it('should reload when `reloadOnUrl` is true and `.url()` changes', function() { + var routeChange = jasmine.createSpy('routeChange'); module(function($routeProvider) { - $routeProvider.when('/foo', {controller: angular.noop}); + $routeProvider.when('/path/:param', {}); }); - inject(function($route, $location, $rootScope, $routeParams) { - $rootScope.$on('$routeChangeStart', reloaded); - $location.path('/foo'); + inject(function($location, $rootScope, $routeParams) { + $rootScope.$on('$routeChangeStart', routeChange); + + // Initial load + $location.path('/path/foo'); $rootScope.$digest(); - expect(reloaded).toHaveBeenCalled(); - expect($routeParams).toEqual({}); - reloaded.calls.reset(); + expect(routeChange).toHaveBeenCalledOnce(); + expect($routeParams).toEqual({param: 'foo'}); - // trigger reload - $location.search({foo: 'bar'}); + routeChange.calls.reset(); + + // Reload on `path` change + $location.path('/path/bar'); $rootScope.$digest(); - expect(reloaded).toHaveBeenCalled(); - expect($routeParams).toEqual({foo:'bar'}); + expect(routeChange).toHaveBeenCalledOnce(); + expect($routeParams).toEqual({param: 'bar'}); + + routeChange.calls.reset(); + + // Reload on `search` change + $location.search('foo', 'bar'); + $rootScope.$digest(); + expect(routeChange).toHaveBeenCalledOnce(); + expect($routeParams).toEqual({param: 'bar', foo: 'bar'}); + + routeChange.calls.reset(); + + // Reload on `hash` change + $location.hash('baz'); + $rootScope.$digest(); + expect(routeChange).toHaveBeenCalledOnce(); + expect($routeParams).toEqual({param: 'bar', foo: 'bar'}); }); }); - it('should not reload a route when reloadOnSearch is disabled and only .search() changes', function() { - var routeChange = jasmine.createSpy('route change'), - routeUpdate = jasmine.createSpy('route update'); + it('should reload when `reloadOnUrl` is false and URL maps to different route', + function() { + var routeChange = jasmine.createSpy('routeChange'); + var routeUpdate = jasmine.createSpy('routeUpdate'); + + module(function($routeProvider) { + $routeProvider. + when('/path/:param', {reloadOnUrl: false}). + otherwise({}); + }); + + inject(function($location, $rootScope, $routeParams) { + $rootScope.$on('$routeChangeStart', routeChange); + $rootScope.$on('$routeChangeSuccess', routeChange); + $rootScope.$on('$routeUpdate', routeUpdate); + + expect(routeChange).not.toHaveBeenCalled(); + + // Initial load + $location.path('/path/foo'); + $rootScope.$digest(); + expect(routeChange).toHaveBeenCalledTimes(2); + expect(routeUpdate).not.toHaveBeenCalled(); + expect($routeParams).toEqual({param: 'foo'}); + + routeChange.calls.reset(); + + // Route change + $location.path('/other/path/bar'); + $rootScope.$digest(); + expect(routeChange).toHaveBeenCalledTimes(2); + expect(routeUpdate).not.toHaveBeenCalled(); + expect($routeParams).toEqual({}); + }); + } + ); + + + it('should not reload when `reloadOnUrl` is false and URL maps to the same route', + function() { + var routeChange = jasmine.createSpy('routeChange'); + var routeUpdate = jasmine.createSpy('routeUpdate'); + + module(function($routeProvider) { + $routeProvider.when('/path/:param', {reloadOnUrl: false}); + }); + + inject(function($location, $rootScope, $routeParams) { + $rootScope.$on('$routeChangeStart', routeChange); + $rootScope.$on('$routeChangeSuccess', routeChange); + $rootScope.$on('$routeUpdate', routeUpdate); + + expect(routeChange).not.toHaveBeenCalled(); + + // Initial load + $location.path('/path/foo'); + $rootScope.$digest(); + expect(routeChange).toHaveBeenCalledTimes(2); + expect(routeUpdate).not.toHaveBeenCalled(); + expect($routeParams).toEqual({param: 'foo'}); + + routeChange.calls.reset(); + + // Route update (no reload) + $location.path('/path/bar').search('foo', 'bar').hash('baz'); + $rootScope.$digest(); + expect(routeChange).not.toHaveBeenCalled(); + expect(routeUpdate).toHaveBeenCalledOnce(); + expect($routeParams).toEqual({param: 'bar', foo: 'bar'}); + }); + } + ); + + + it('should update `$routeParams` even when not reloading a route', function() { + var routeChange = jasmine.createSpy('routeChange'); module(function($routeProvider) { - $routeProvider.when('/foo', {controller: angular.noop, reloadOnSearch: false}); + $routeProvider.when('/path/:param', {reloadOnUrl: false}); }); - inject(function($route, $location, $rootScope) { + inject(function($location, $rootScope, $routeParams) { $rootScope.$on('$routeChangeStart', routeChange); $rootScope.$on('$routeChangeSuccess', routeChange); - $rootScope.$on('$routeUpdate', routeUpdate); expect(routeChange).not.toHaveBeenCalled(); - $location.path('/foo'); + // Initial load + $location.path('/path/foo'); $rootScope.$digest(); - expect(routeChange).toHaveBeenCalled(); expect(routeChange).toHaveBeenCalledTimes(2); - expect(routeUpdate).not.toHaveBeenCalled(); + expect($routeParams).toEqual({param: 'foo'}); + routeChange.calls.reset(); - // don't trigger reload - $location.search({foo: 'bar'}); + // Route update (no reload) + $location.path('/path/bar'); $rootScope.$digest(); expect(routeChange).not.toHaveBeenCalled(); - expect(routeUpdate).toHaveBeenCalled(); + expect($routeParams).toEqual({param: 'bar'}); }); }); - it('should reload reloadOnSearch route when url differs only in route path param', function() { - var routeChange = jasmine.createSpy('route change'); + describe('with `$route.reload()`', function() { + var $location; + var $log; + var $rootScope; + var $route; + var routeChangeStart; + var routeChangeSuccess; - module(function($routeProvider) { - $routeProvider.when('/foo/:fooId', {controller: angular.noop, reloadOnSearch: false}); + beforeEach(module(function($routeProvider) { + $routeProvider.when('/path/:param', { + template: '', + reloadOnUrl: false, + controller: function Controller($log) { + $log.debug('initialized'); + } + }); + })); + + beforeEach(inject(function($compile, _$location_, _$log_, _$rootScope_, _$route_) { + $location = _$location_; + $log = _$log_; + $rootScope = _$rootScope_; + $route = _$route_; + + routeChangeStart = jasmine.createSpy('routeChangeStart'); + routeChangeSuccess = jasmine.createSpy('routeChangeSuccess'); + + $rootScope.$on('$routeChangeStart', routeChangeStart); + $rootScope.$on('$routeChangeSuccess', routeChangeSuccess); + + element = $compile('
')($rootScope); + })); + + + it('should reload the current route', function() { + $location.path('/path/foo'); + $rootScope.$digest(); + expect($location.path()).toBe('/path/foo'); + expect(routeChangeStart).toHaveBeenCalledOnce(); + expect(routeChangeSuccess).toHaveBeenCalledOnce(); + expect($log.debug.logs).toEqual([['initialized']]); + + routeChangeStart.calls.reset(); + routeChangeSuccess.calls.reset(); + $log.reset(); + + $route.reload(); + $rootScope.$digest(); + expect($location.path()).toBe('/path/foo'); + expect(routeChangeStart).toHaveBeenCalledOnce(); + expect(routeChangeSuccess).toHaveBeenCalledOnce(); + expect($log.debug.logs).toEqual([['initialized']]); + + $log.reset(); }); - inject(function($route, $location, $rootScope) { - $rootScope.$on('$routeChangeStart', routeChange); - $rootScope.$on('$routeChangeSuccess', routeChange); - expect(routeChange).not.toHaveBeenCalled(); + it('should support preventing a route reload', function() { + $location.path('/path/foo'); + $rootScope.$digest(); + expect($location.path()).toBe('/path/foo'); + expect(routeChangeStart).toHaveBeenCalledOnce(); + expect(routeChangeSuccess).toHaveBeenCalledOnce(); + expect($log.debug.logs).toEqual([['initialized']]); + + routeChangeStart.calls.reset(); + routeChangeSuccess.calls.reset(); + $log.reset(); - $location.path('/foo/aaa'); + routeChangeStart.and.callFake(function(evt) { evt.preventDefault(); }); + + $route.reload(); $rootScope.$digest(); - expect(routeChange).toHaveBeenCalled(); - expect(routeChange).toHaveBeenCalledTimes(2); - routeChange.calls.reset(); + expect($location.path()).toBe('/path/foo'); + expect(routeChangeStart).toHaveBeenCalledOnce(); + expect(routeChangeSuccess).not.toHaveBeenCalled(); + expect($log.debug.logs).toEqual([]); + }); + + + it('should reload the current route even if `reloadOnUrl` is disabled', + inject(function($routeParams) { + $location.path('/path/foo'); + $rootScope.$digest(); + expect(routeChangeStart).toHaveBeenCalledOnce(); + expect(routeChangeSuccess).toHaveBeenCalledOnce(); + expect($log.debug.logs).toEqual([['initialized']]); + expect($routeParams).toEqual({param: 'foo'}); + + routeChangeStart.calls.reset(); + routeChangeSuccess.calls.reset(); + $log.reset(); + + $location.path('/path/bar'); + $rootScope.$digest(); + expect(routeChangeStart).not.toHaveBeenCalled(); + expect(routeChangeSuccess).not.toHaveBeenCalled(); + expect($log.debug.logs).toEqual([]); + expect($routeParams).toEqual({param: 'bar'}); + + $route.reload(); + $rootScope.$digest(); + expect(routeChangeStart).toHaveBeenCalledOnce(); + expect(routeChangeSuccess).toHaveBeenCalledOnce(); + expect($log.debug.logs).toEqual([['initialized']]); + expect($routeParams).toEqual({param: 'bar'}); + + $log.reset(); + }) + ); + }); + }); + + describe('reloadOnSearch', function() { + it('should not have any effect if `reloadOnUrl` is false', function() { + var reloaded = jasmine.createSpy('route reload'); + + module(function($routeProvider) { + $routeProvider.when('/foo', { + reloadOnUrl: false, + reloadOnSearch: true + }); + }); + + inject(function($route, $location, $rootScope, $routeParams) { + $rootScope.$on('$routeChangeStart', reloaded); - $location.path('/foo/bbb'); + $location.path('/foo'); $rootScope.$digest(); - expect(routeChange).toHaveBeenCalled(); - expect(routeChange).toHaveBeenCalledTimes(2); - routeChange.calls.reset(); + expect(reloaded).toHaveBeenCalledOnce(); + expect($routeParams).toEqual({}); + reloaded.calls.reset(); + + // trigger reload (via .search()) $location.search({foo: 'bar'}); $rootScope.$digest(); - expect(routeChange).not.toHaveBeenCalled(); + expect(reloaded).not.toHaveBeenCalled(); + expect($routeParams).toEqual({foo: 'bar'}); + + // trigger reload (via .hash()) + $location.hash('baz'); + $rootScope.$digest(); + expect(reloaded).not.toHaveBeenCalled(); + expect($routeParams).toEqual({foo: 'bar'}); }); }); - it('should update params when reloadOnSearch is disabled and .search() changes', function() { + it('should reload when `reloadOnSearch` is true and `.search()`/`.hash()` changes', + function() { + var reloaded = jasmine.createSpy('route reload'); + + module(function($routeProvider) { + $routeProvider.when('/foo', {controller: angular.noop}); + }); + + inject(function($route, $location, $rootScope, $routeParams) { + $rootScope.$on('$routeChangeStart', reloaded); + + $location.path('/foo'); + $rootScope.$digest(); + expect(reloaded).toHaveBeenCalledOnce(); + expect($routeParams).toEqual({}); + + reloaded.calls.reset(); + + // trigger reload (via .search()) + $location.search({foo: 'bar'}); + $rootScope.$digest(); + expect(reloaded).toHaveBeenCalledOnce(); + expect($routeParams).toEqual({foo: 'bar'}); + + reloaded.calls.reset(); + + // trigger reload (via .hash()) + $location.hash('baz'); + $rootScope.$digest(); + expect(reloaded).toHaveBeenCalledOnce(); + expect($routeParams).toEqual({foo: 'bar'}); + }); + } + ); + + + it('should not reload when `reloadOnSearch` is false and `.search()`/`.hash()` changes', + function() { + var routeChange = jasmine.createSpy('route change'), + routeUpdate = jasmine.createSpy('route update'); + + module(function($routeProvider) { + $routeProvider.when('/foo', {controller: angular.noop, reloadOnSearch: false}); + }); + + inject(function($route, $location, $rootScope) { + $rootScope.$on('$routeChangeStart', routeChange); + $rootScope.$on('$routeChangeSuccess', routeChange); + $rootScope.$on('$routeUpdate', routeUpdate); + + expect(routeChange).not.toHaveBeenCalled(); + + $location.path('/foo'); + $rootScope.$digest(); + expect(routeChange).toHaveBeenCalledTimes(2); + expect(routeUpdate).not.toHaveBeenCalled(); + + routeChange.calls.reset(); + + // don't trigger reload (via .search()) + $location.search({foo: 'bar'}); + $rootScope.$digest(); + expect(routeChange).not.toHaveBeenCalled(); + expect(routeUpdate).toHaveBeenCalledOnce(); + + routeUpdate.calls.reset(); + + // don't trigger reload (via .hash()) + $location.hash('baz'); + $rootScope.$digest(); + expect(routeChange).not.toHaveBeenCalled(); + expect(routeUpdate).toHaveBeenCalled(); + }); + } + ); + + + it('should reload when `reloadOnSearch` is false and url differs only in route path param', + function() { + var routeChange = jasmine.createSpy('route change'); + + module(function($routeProvider) { + $routeProvider.when('/foo/:fooId', {controller: angular.noop, reloadOnSearch: false}); + }); + + inject(function($route, $location, $rootScope) { + $rootScope.$on('$routeChangeStart', routeChange); + $rootScope.$on('$routeChangeSuccess', routeChange); + + expect(routeChange).not.toHaveBeenCalled(); + + $location.path('/foo/aaa'); + $rootScope.$digest(); + expect(routeChange).toHaveBeenCalledTimes(2); + routeChange.calls.reset(); + + $location.path('/foo/bbb'); + $rootScope.$digest(); + expect(routeChange).toHaveBeenCalledTimes(2); + routeChange.calls.reset(); + + $location.search({foo: 'bar'}).hash('baz'); + $rootScope.$digest(); + expect(routeChange).not.toHaveBeenCalled(); + }); + } + ); + + + it('should update params when `reloadOnSearch` is false and `.search()` changes', function() { var routeParamsWatcher = jasmine.createSpy('routeParamsWatcher'); module(function($routeProvider) { @@ -1852,7 +2171,8 @@ describe('$route', function() { }); }); - describe('reload', function() { + + describe('with `$route.reload()`', function() { var $location; var $log; var $rootScope; @@ -1886,6 +2206,7 @@ describe('$route', function() { element = $compile('
')($rootScope); })); + it('should reload the current route', function() { $location.path('/bar/123'); $rootScope.$digest(); @@ -1908,6 +2229,7 @@ describe('$route', function() { $log.reset(); }); + it('should support preventing a route reload', function() { $location.path('/bar/123'); $rootScope.$digest(); @@ -1930,6 +2252,7 @@ describe('$route', function() { expect($log.debug.logs).toEqual([]); }); + it('should reload even if reloadOnSearch is false', inject(function($routeParams) { $location.path('/bar/123'); $rootScope.$digest(); @@ -1946,6 +2269,15 @@ describe('$route', function() { expect(routeChangeSuccessSpy).not.toHaveBeenCalled(); expect($log.debug.logs).toEqual([]); + routeChangeSuccessSpy.calls.reset(); + $log.reset(); + + $location.hash('c'); + $rootScope.$digest(); + expect($routeParams).toEqual({barId: '123', a: 'b'}); + expect(routeChangeSuccessSpy).not.toHaveBeenCalled(); + expect($log.debug.logs).toEqual([]); + $route.reload(); $rootScope.$digest(); expect($routeParams).toEqual({barId: '123', a: 'b'}); From 83d1229c87d41954a5446073fbae1c779439f262 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Sun, 26 Jun 2016 22:24:57 +0300 Subject: [PATCH 019/217] refactor(ngAria): move test helpers inside of closure --- test/ngAria/ariaSpec.js | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/test/ngAria/ariaSpec.js b/test/ngAria/ariaSpec.js index 201608498961..58cd6584157f 100644 --- a/test/ngAria/ariaSpec.js +++ b/test/ngAria/ariaSpec.js @@ -9,18 +9,6 @@ describe('$aria', function() { dealoc(element); }); - function injectScopeAndCompiler() { - return inject(function(_$compile_, _$rootScope_) { - $compile = _$compile_; - scope = _$rootScope_; - }); - } - - function compileElement(inputHtml) { - element = $compile(inputHtml)(scope); - scope.$digest(); - } - describe('aria-hidden', function() { beforeEach(injectScopeAndCompiler); @@ -895,19 +883,31 @@ describe('$aria', function() { expect(element.attr('tabindex')).toBe('0'); }); }); -}); -function expectAriaAttrOnEachElement(elem, ariaAttr, expected) { - angular.forEach(elem, function(val) { - expect(angular.element(val).attr(ariaAttr)).toBe(expected); - }); -} + // Helpers + function compileElement(inputHtml) { + element = $compile(inputHtml)(scope); + scope.$digest(); + } + + function configAriaProvider(config) { + return function() { + module(function($ariaProvider) { + $ariaProvider.config(config); + }); + }; + } -function configAriaProvider(config) { - return function() { - angular.module('ariaTest', ['ngAria']).config(function($ariaProvider) { - $ariaProvider.config(config); + function expectAriaAttrOnEachElement(elem, ariaAttr, expected) { + angular.forEach(elem, function(val) { + expect(angular.element(val).attr(ariaAttr)).toBe(expected); }); - module('ariaTest'); - }; -} + } + + function injectScopeAndCompiler() { + return inject(function(_$compile_, _$rootScope_) { + $compile = _$compile_; + scope = _$rootScope_; + }); + } +}); From db584f7835b995a20fe1f5f68f3344ceb0b99db2 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Tue, 28 Jun 2016 00:50:54 +0300 Subject: [PATCH 020/217] feat(ngAria): add support for ignoring a specific element Fixes #14602 Fixes #14672 Closes #14833 --- src/ngAria/aria.js | 24 ++++- test/ngAria/ariaSpec.js | 231 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+), 4 deletions(-) diff --git a/src/ngAria/aria.js b/src/ngAria/aria.js index bf82141b2123..904d9a0e5959 100644 --- a/src/ngAria/aria.js +++ b/src/ngAria/aria.js @@ -14,8 +14,8 @@ * * For ngAria to do its magic, simply include the module `ngAria` as a dependency. The following * directives are supported: - * `ngModel`, `ngChecked`, `ngReadonly`, `ngRequired`, `ngValue`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`, - * `ngDblClick`, and `ngMessages`. + * `ngModel`, `ngChecked`, `ngReadonly`, `ngRequired`, `ngValue`, `ngDisabled`, `ngShow`, `ngHide`, + * `ngClick`, `ngDblClick`, and `ngMessages`. * * Below is a more detailed breakdown of the attributes handled by ngAria: * @@ -46,11 +46,17 @@ * * ``` * - * ## Disabling Attributes - * It's possible to disable individual attributes added by ngAria with the + * ## Disabling Specific Attributes + * It is possible to disable individual attributes added by ngAria with the * {@link ngAria.$ariaProvider#config config} method. For more details, see the * {@link guide/accessibility Developer Guide}. + * + * ## Disabling `ngAria` on Specific Elements + * It is possible to make `ngAria` ignore a specific element, by adding the `ng-aria-disable` + * attribute on it. Note that only the element itself (and not its child elements) will be ignored. */ +var ARIA_DISABLE_ATTR = 'ngAriaDisable'; + var ngAriaModule = angular.module('ngAria', ['ng']). info({ angularVersion: '"NG_VERSION_FULL"' }). provider('$aria', $AriaProvider); @@ -132,6 +138,8 @@ function $AriaProvider() { function watchExpr(attrName, ariaAttr, nodeBlackList, negate) { return function(scope, elem, attr) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + var ariaCamelName = attr.$normalize(ariaAttr); if (config[ariaCamelName] && !isNodeOneOf(elem, nodeBlackList) && !attr[ariaCamelName]) { scope.$watch(attr[attrName], function(boolVal) { @@ -251,6 +259,8 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) { require: 'ngModel', priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value compile: function(elem, attr) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + var shape = getShape(attr, elem); return { @@ -347,6 +357,8 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) { restrict: 'A', require: '?ngMessages', link: function(scope, elem, attr, ngMessages) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + if (!elem.attr('aria-live')) { elem.attr('aria-live', 'assertive'); } @@ -357,6 +369,8 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) { return { restrict: 'A', compile: function(elem, attr) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + var fn = $parse(attr.ngClick); return function(scope, elem, attr) { @@ -389,6 +403,8 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) { }]) .directive('ngDblclick', ['$aria', function($aria) { return function(scope, elem, attr) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + if ($aria.config('tabindex') && !elem.attr('tabindex') && !isNodeOneOf(elem, nodeBlackList)) { elem.attr('tabindex', 0); } diff --git a/test/ngAria/ariaSpec.js b/test/ngAria/ariaSpec.js index 58cd6584157f..1970b01438b0 100644 --- a/test/ngAria/ariaSpec.js +++ b/test/ngAria/ariaSpec.js @@ -9,6 +9,237 @@ describe('$aria', function() { dealoc(element); }); + describe('with `ngAriaDisable`', function() { + beforeEach(injectScopeAndCompiler); + beforeEach(function() { + jasmine.addMatchers({ + toHaveAttribute: function toHaveAttributeMatcher() { + return { + compare: function toHaveAttributeCompare(element, attr) { + var node = element[0]; + var pass = node.hasAttribute(attr); + var message = 'Expected `' + node.outerHTML + '` ' + (pass ? 'not ' : '') + + 'to have attribute `' + attr + '`.'; + + return { + pass: pass, + message: message + }; + } + }; + } + }); + }); + + // ariaChecked + it('should not attach aria-checked to custom checkbox', function() { + compileElement('
'); + + scope.$apply('val = false'); + expect(element).not.toHaveAttribute('aria-checked'); + + scope.$apply('val = true'); + expect(element).not.toHaveAttribute('aria-checked'); + }); + + it('should not attach aria-checked to custom radio controls', function() { + compileElement( + '
' + + '
'); + + var radio1 = element.eq(0); + var radio2 = element.eq(1); + + scope.$apply('val = "one"'); + expect(radio1).not.toHaveAttribute('aria-checked'); + expect(radio2).not.toHaveAttribute('aria-checked'); + + scope.$apply('val = "two"'); + expect(radio1).not.toHaveAttribute('aria-checked'); + expect(radio2).not.toHaveAttribute('aria-checked'); + }); + + // ariaDisabled + it('should not attach aria-disabled to custom controls', function() { + compileElement('
'); + + scope.$apply('val = false'); + expect(element).not.toHaveAttribute('aria-disabled'); + + scope.$apply('val = true'); + expect(element).not.toHaveAttribute('aria-disabled'); + }); + + // ariaHidden + it('should not attach aria-hidden to `ngShow`', function() { + compileElement('
'); + + scope.$apply('val = false'); + expect(element).not.toHaveAttribute('aria-hidden'); + + scope.$apply('val = true'); + expect(element).not.toHaveAttribute('aria-hidden'); + }); + + it('should not attach aria-hidden to `ngHide`', function() { + compileElement('
'); + + scope.$apply('val = false'); + expect(element).not.toHaveAttribute('aria-hidden'); + + scope.$apply('val = true'); + expect(element).not.toHaveAttribute('aria-hidden'); + }); + + // ariaInvalid + it('should not attach aria-invalid to input', function() { + compileElement(''); + + scope.$apply('val = "lt 10"'); + expect(element).not.toHaveAttribute('aria-invalid'); + + scope.$apply('val = "gt 10 characters"'); + expect(element).not.toHaveAttribute('aria-invalid'); + }); + + it('should not attach aria-invalid to custom controls', function() { + compileElement('
'); + + scope.$apply('val = "lt 10"'); + expect(element).not.toHaveAttribute('aria-invalid'); + + scope.$apply('val = "gt 10 characters"'); + expect(element).not.toHaveAttribute('aria-invalid'); + }); + + // ariaLive + it('should not attach aria-live to `ngMessages`', function() { + compileElement('
'); + expect(element).not.toHaveAttribute('aria-live'); + }); + + // ariaReadonly + it('should not attach aria-readonly to custom controls', function() { + compileElement('
'); + + scope.$apply('val = false'); + expect(element).not.toHaveAttribute('aria-readonly'); + + scope.$apply('val = true'); + expect(element).not.toHaveAttribute('aria-readonly'); + }); + + // ariaRequired + it('should not attach aria-required to custom controls with `required`', function() { + compileElement('
'); + expect(element).not.toHaveAttribute('aria-required'); + }); + + it('should not attach aria-required to custom controls with `ngRequired`', function() { + compileElement('
'); + + scope.$apply('val = false'); + expect(element).not.toHaveAttribute('aria-required'); + + scope.$apply('val = true'); + expect(element).not.toHaveAttribute('aria-required'); + }); + + // ariaValue + it('should not attach aria-value* to input[range]', function() { + compileElement(''); + + expect(element).not.toHaveAttribute('aria-valuemax'); + expect(element).not.toHaveAttribute('aria-valuemin'); + expect(element).not.toHaveAttribute('aria-valuenow'); + + scope.$apply('val = 50'); + expect(element).not.toHaveAttribute('aria-valuemax'); + expect(element).not.toHaveAttribute('aria-valuemin'); + expect(element).not.toHaveAttribute('aria-valuenow'); + + scope.$apply('val = 150'); + expect(element).not.toHaveAttribute('aria-valuemax'); + expect(element).not.toHaveAttribute('aria-valuemin'); + expect(element).not.toHaveAttribute('aria-valuenow'); + }); + + it('should not attach aria-value* to custom controls', function() { + compileElement( + '
' + + '
'); + + var progressbar = element.eq(0); + var slider = element.eq(1); + + ['aria-valuemax', 'aria-valuemin', 'aria-valuenow'].forEach(function(attr) { + expect(progressbar).not.toHaveAttribute(attr); + expect(slider).not.toHaveAttribute(attr); + }); + + scope.$apply('val = 50'); + ['aria-valuemax', 'aria-valuemin', 'aria-valuenow'].forEach(function(attr) { + expect(progressbar).not.toHaveAttribute(attr); + expect(slider).not.toHaveAttribute(attr); + }); + + scope.$apply('val = 150'); + ['aria-valuemax', 'aria-valuemin', 'aria-valuenow'].forEach(function(attr) { + expect(progressbar).not.toHaveAttribute(attr); + expect(slider).not.toHaveAttribute(attr); + }); + }); + + // bindKeypress + it('should not bind keypress to `ngClick`', function() { + scope.onClick = jasmine.createSpy('onClick'); + compileElement( + '
' + + '
'); + + var div = element.find('div'); + var li = element.find('li'); + + div.triggerHandler({type: 'keypress', keyCode: 32}); + li.triggerHandler({type: 'keypress', keyCode: 32}); + + expect(scope.onClick).not.toHaveBeenCalled(); + }); + + // bindRoleForClick + it('should not attach role to custom controls', function() { + compileElement( + '
' + + '
' + + '
' + + '
'); + + expect(element.eq(0)).not.toHaveAttribute('role'); + expect(element.eq(1)).not.toHaveAttribute('role'); + expect(element.eq(2)).not.toHaveAttribute('role'); + expect(element.eq(3)).not.toHaveAttribute('role'); + }); + + // tabindex + it('should not attach tabindex to custom controls', function() { + compileElement( + '
' + + '
'); + + expect(element.eq(0)).not.toHaveAttribute('tabindex'); + expect(element.eq(1)).not.toHaveAttribute('tabindex'); + }); + + it('should not attach tabindex to `ngClick` or `ngDblclick`', function() { + compileElement( + '
' + + '
'); + + expect(element.eq(0)).not.toHaveAttribute('tabindex'); + expect(element.eq(1)).not.toHaveAttribute('tabindex'); + }); + }); + describe('aria-hidden', function() { beforeEach(injectScopeAndCompiler); From 05170bf3716359f81b32bf5113330dd6240a0cf7 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Fri, 8 Jun 2018 16:14:14 +0300 Subject: [PATCH 021/217] docs(CHANGELOG): add release notes for 1.7.1 --- CHANGELOG.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0f1531a96b2..a20798781423 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,59 @@ + +# 1.7.1 momentum-defiance (2018-06-08) + + +## Bug Fixes +- **$compile:** support transcluding multi-element directives + ([789db8](https://github.com/angular/angular.js/commit/789db83a8ae0e2db5db13289b2c29e56093d967a), + [#15554](https://github.com/angular/angular.js.git/issues/15554), + [#15555](https://github.com/angular/angular.js.git/issues/15555)) +- **ngModel:** do not throw if view value changes on destroyed scope + ([2b6c98](https://github.com/angular/angular.js/commit/2b6c9867369fd3ef1ddb687af1153478ab62ee1b), + [#16583](https://github.com/angular/angular.js.git/issues/16583), + [#16585](https://github.com/angular/angular.js.git/issues/16585)) + + +## New Features +- **$compile:** add one-way collection bindings + ([f9d1ca](https://github.com/angular/angular.js/commit/f9d1ca20c38f065f15769fbe23aee5314cb58bd4), + [#14039](https://github.com/angular/angular.js.git/issues/14039), + [#16553](https://github.com/angular/angular.js.git/issues/16553), + [#15874](https://github.com/angular/angular.js.git/issues/15874)) +- **ngRef:** add directive to publish controller, or element into scope + ([bf841d](https://github.com/angular/angular.js/commit/bf841d35120bf3c4655fde46af4105c85a0f1cdc), + [#16511](https://github.com/angular/angular.js.git/issues/16511)) +- **errorHandlingConfig:** add option to exclude error params from url + ([3d6c45](https://github.com/angular/angular.js/commit/3d6c45d76e30b1b3c4eb9672cf4a93e5251c06b3), + [#14744](https://github.com/angular/angular.js.git/issues/14744), + [#15707](https://github.com/angular/angular.js.git/issues/15707), + [#16283](https://github.com/angular/angular.js.git/issues/16283), + [#16299](https://github.com/angular/angular.js.git/issues/16299), + [#16591](https://github.com/angular/angular.js.git/issues/16591)) +- **ngAria:** add support for ignoring a specific element + ([7d9d38](https://github.com/angular/angular.js/commit/7d9d387195292cb5e04984602b752d31853cfea6), + [#14602](https://github.com/angular/angular.js.git/issues/14602), + [#14672](https://github.com/angular/angular.js.git/issues/14672), + [#14833](https://github.com/angular/angular.js.git/issues/14833)) +- **ngCookies:** support samesite option + ([10a229](https://github.com/angular/angular.js/commit/10a229ce1befdeaf6295d1635dc11391c252a91a), + [#16543](https://github.com/angular/angular.js.git/issues/16543), + [#16544](https://github.com/angular/angular.js.git/issues/16544)) +- **ngMessages:** add support for default message + ([a8c263](https://github.com/angular/angular.js/commit/a8c263c1947cc85ee60b4732f7e4bcdc7ba463e8), + [#12008](https://github.com/angular/angular.js.git/issues/12008), + [#12213](https://github.com/angular/angular.js.git/issues/12213), + [#16587](https://github.com/angular/angular.js.git/issues/16587)) +- **ngMock, ngMockE2E:** add option to match latest definition for `$httpBackend` request + ([773f39](https://github.com/angular/angular.js/commit/773f39c9345479f5f8b6321236ce6ad96f77aa92), + [#16251](https://github.com/angular/angular.js.git/issues/16251), + [#11637](https://github.com/angular/angular.js.git/issues/11637), + [#16560](https://github.com/angular/angular.js.git/issues/16560)) +- **$route:** add support for the `reloadOnUrl` configuration option + ([f4f571](https://github.com/angular/angular.js/commit/f4f571efdf86d6acbcd5c6b1de66b4b33a259125), + [#7925](https://github.com/angular/angular.js.git/issues/7925), + [#15002](https://github.com/angular/angular.js.git/issues/15002)) + + # 1.7.0 nonexistent-physiology (2018-05-11) From ad0ba99d8a231da9796eb94adcfa670665ea0eed Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Fri, 8 Jun 2018 17:09:30 +0300 Subject: [PATCH 022/217] docs(CHANGELOG): fix links to issues/PRs --- CHANGELOG.md | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a20798781423..29176742999d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,53 +5,53 @@ ## Bug Fixes - **$compile:** support transcluding multi-element directives ([789db8](https://github.com/angular/angular.js/commit/789db83a8ae0e2db5db13289b2c29e56093d967a), - [#15554](https://github.com/angular/angular.js.git/issues/15554), - [#15555](https://github.com/angular/angular.js.git/issues/15555)) + [#15554](https://github.com/angular/angular.js/issues/15554), + [#15555](https://github.com/angular/angular.js/issues/15555)) - **ngModel:** do not throw if view value changes on destroyed scope ([2b6c98](https://github.com/angular/angular.js/commit/2b6c9867369fd3ef1ddb687af1153478ab62ee1b), - [#16583](https://github.com/angular/angular.js.git/issues/16583), - [#16585](https://github.com/angular/angular.js.git/issues/16585)) + [#16583](https://github.com/angular/angular.js/issues/16583), + [#16585](https://github.com/angular/angular.js/issues/16585)) ## New Features - **$compile:** add one-way collection bindings ([f9d1ca](https://github.com/angular/angular.js/commit/f9d1ca20c38f065f15769fbe23aee5314cb58bd4), - [#14039](https://github.com/angular/angular.js.git/issues/14039), - [#16553](https://github.com/angular/angular.js.git/issues/16553), - [#15874](https://github.com/angular/angular.js.git/issues/15874)) + [#14039](https://github.com/angular/angular.js/issues/14039), + [#16553](https://github.com/angular/angular.js/issues/16553), + [#15874](https://github.com/angular/angular.js/issues/15874)) - **ngRef:** add directive to publish controller, or element into scope ([bf841d](https://github.com/angular/angular.js/commit/bf841d35120bf3c4655fde46af4105c85a0f1cdc), - [#16511](https://github.com/angular/angular.js.git/issues/16511)) + [#16511](https://github.com/angular/angular.js/issues/16511)) - **errorHandlingConfig:** add option to exclude error params from url ([3d6c45](https://github.com/angular/angular.js/commit/3d6c45d76e30b1b3c4eb9672cf4a93e5251c06b3), - [#14744](https://github.com/angular/angular.js.git/issues/14744), - [#15707](https://github.com/angular/angular.js.git/issues/15707), - [#16283](https://github.com/angular/angular.js.git/issues/16283), - [#16299](https://github.com/angular/angular.js.git/issues/16299), - [#16591](https://github.com/angular/angular.js.git/issues/16591)) + [#14744](https://github.com/angular/angular.js/issues/14744), + [#15707](https://github.com/angular/angular.js/issues/15707), + [#16283](https://github.com/angular/angular.js/issues/16283), + [#16299](https://github.com/angular/angular.js/issues/16299), + [#16591](https://github.com/angular/angular.js/issues/16591)) - **ngAria:** add support for ignoring a specific element ([7d9d38](https://github.com/angular/angular.js/commit/7d9d387195292cb5e04984602b752d31853cfea6), - [#14602](https://github.com/angular/angular.js.git/issues/14602), - [#14672](https://github.com/angular/angular.js.git/issues/14672), - [#14833](https://github.com/angular/angular.js.git/issues/14833)) + [#14602](https://github.com/angular/angular.js/issues/14602), + [#14672](https://github.com/angular/angular.js/issues/14672), + [#14833](https://github.com/angular/angular.js/issues/14833)) - **ngCookies:** support samesite option ([10a229](https://github.com/angular/angular.js/commit/10a229ce1befdeaf6295d1635dc11391c252a91a), - [#16543](https://github.com/angular/angular.js.git/issues/16543), - [#16544](https://github.com/angular/angular.js.git/issues/16544)) + [#16543](https://github.com/angular/angular.js/issues/16543), + [#16544](https://github.com/angular/angular.js/issues/16544)) - **ngMessages:** add support for default message ([a8c263](https://github.com/angular/angular.js/commit/a8c263c1947cc85ee60b4732f7e4bcdc7ba463e8), - [#12008](https://github.com/angular/angular.js.git/issues/12008), - [#12213](https://github.com/angular/angular.js.git/issues/12213), - [#16587](https://github.com/angular/angular.js.git/issues/16587)) + [#12008](https://github.com/angular/angular.js/issues/12008), + [#12213](https://github.com/angular/angular.js/issues/12213), + [#16587](https://github.com/angular/angular.js/issues/16587)) - **ngMock, ngMockE2E:** add option to match latest definition for `$httpBackend` request ([773f39](https://github.com/angular/angular.js/commit/773f39c9345479f5f8b6321236ce6ad96f77aa92), - [#16251](https://github.com/angular/angular.js.git/issues/16251), - [#11637](https://github.com/angular/angular.js.git/issues/11637), - [#16560](https://github.com/angular/angular.js.git/issues/16560)) + [#16251](https://github.com/angular/angular.js/issues/16251), + [#11637](https://github.com/angular/angular.js/issues/11637), + [#16560](https://github.com/angular/angular.js/issues/16560)) - **$route:** add support for the `reloadOnUrl` configuration option ([f4f571](https://github.com/angular/angular.js/commit/f4f571efdf86d6acbcd5c6b1de66b4b33a259125), - [#7925](https://github.com/angular/angular.js.git/issues/7925), - [#15002](https://github.com/angular/angular.js.git/issues/15002)) + [#7925](https://github.com/angular/angular.js/issues/7925), + [#15002](https://github.com/angular/angular.js/issues/15002)) From 42e622b751d1ad1520b824473f9ad31e7efb75b3 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Mon, 11 Jun 2018 15:05:27 +0300 Subject: [PATCH 023/217] revert: refactor($compile): remove preAssignBindingsEnabled leftovers This reverts commit 8e104ee508418bc2ebb65e5b4ac73d22285cc224. This internal clean-up turned out to break popular UI libraries (e.g. `ngMaterial`, `ui-bootstrap`) and cause pain to developers. Fixes #16594 Closes #16595 --- src/auto/injector.js | 30 +++++++-- src/ng/compile.js | 130 ++++++++++++++++++++---------------- src/ng/controller.js | 42 +++++++++++- src/ngMock/angular-mocks.js | 13 ++-- test/auto/injectorSpec.js | 19 ++++++ 5 files changed, 167 insertions(+), 67 deletions(-) diff --git a/src/auto/injector.js b/src/auto/injector.js index c1cea832acde..b4995af8f6f6 100644 --- a/src/auto/injector.js +++ b/src/auto/injector.js @@ -70,8 +70,12 @@ var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; var $injectorMinErr = minErr('$injector'); +function stringifyFn(fn) { + return Function.prototype.toString.call(fn); +} + function extractArgs(fn) { - var fnText = Function.prototype.toString.call(fn).replace(STRIP_COMMENTS, ''), + var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''), args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS); return args; } @@ -910,6 +914,19 @@ function createInjector(modulesToLoad, strictDi) { return args; } + function isClass(func) { + // Support: IE 9-11 only + // IE 9-11 do not support classes and IE9 leaks with the code below. + if (msie || typeof func !== 'function') { + return false; + } + var result = func.$$ngIsClass; + if (!isBoolean(result)) { + result = func.$$ngIsClass = /^class\b/.test(stringifyFn(func)); + } + return result; + } + function invoke(fn, self, locals, serviceName) { if (typeof locals === 'string') { serviceName = locals; @@ -921,9 +938,14 @@ function createInjector(modulesToLoad, strictDi) { fn = fn[fn.length - 1]; } - // http://jsperf.com/angularjs-invoke-apply-vs-switch - // #5388 - return fn.apply(self, args); + if (!isClass(fn)) { + // http://jsperf.com/angularjs-invoke-apply-vs-switch + // #5388 + return fn.apply(self, args); + } else { + args.unshift(null); + return new (Function.prototype.bind.apply(fn, args))(); + } } diff --git a/src/ng/compile.js b/src/ng/compile.js index 470640d2d329..a257c0b5f096 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -2790,6 +2790,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { }; } + if (controllerDirectives) { + elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective); + } + if (newIsolateScopeDirective) { // Initialize isolate scope bindings for new isolate scope directive. compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || @@ -2805,69 +2809,53 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } } - if (controllerDirectives) { - elementControllers = createMap(); - for (var name in controllerDirectives) { - var directive = controllerDirectives[name]; - var locals = { - $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, - $element: $element, - $attrs: attrs, - $transclude: transcludeFn - }; - - var controllerConstructor = directive.controller; - if (controllerConstructor === '@') { - controllerConstructor = attrs[name]; - } + // Initialize bindToController bindings + for (var name in elementControllers) { + var controllerDirective = controllerDirectives[name]; + var controller = elementControllers[name]; + var bindings = controllerDirective.$$bindings.bindToController; - var instance = $controller(controllerConstructor, locals, directive.controllerAs); - - $element.data('$' + name + 'Controller', instance); - - // Initialize bindToController bindings - var bindings = directive.$$bindings.bindToController; - var bindingInfo = initializeDirectiveBindings(controllerScope, attrs, instance, bindings, directive); - - elementControllers[name] = { instance: instance, bindingInfo: bindingInfo }; + controller.instance = controller(); + $element.data('$' + controllerDirective.name + 'Controller', controller.instance); + controller.bindingInfo = + initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective); } - // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy - forEach(controllerDirectives, function(controllerDirective, name) { - var require = controllerDirective.require; - if (controllerDirective.bindToController && !isArray(require) && isObject(require)) { - extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers)); - } - }); + // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy + forEach(controllerDirectives, function(controllerDirective, name) { + var require = controllerDirective.require; + if (controllerDirective.bindToController && !isArray(require) && isObject(require)) { + extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers)); + } + }); - // Handle the init and destroy lifecycle hooks on all controllers that have them - forEach(elementControllers, function(controller) { - var controllerInstance = controller.instance; - if (isFunction(controllerInstance.$onChanges)) { - try { - controllerInstance.$onChanges(controller.bindingInfo.initialChanges); - } catch (e) { - $exceptionHandler(e); - } - } - if (isFunction(controllerInstance.$onInit)) { - try { - controllerInstance.$onInit(); - } catch (e) { - $exceptionHandler(e); - } - } - if (isFunction(controllerInstance.$doCheck)) { - controllerScope.$watch(function() { controllerInstance.$doCheck(); }); - controllerInstance.$doCheck(); + // Handle the init and destroy lifecycle hooks on all controllers that have them + forEach(elementControllers, function(controller) { + var controllerInstance = controller.instance; + if (isFunction(controllerInstance.$onChanges)) { + try { + controllerInstance.$onChanges(controller.bindingInfo.initialChanges); + } catch (e) { + $exceptionHandler(e); } - if (isFunction(controllerInstance.$onDestroy)) { - controllerScope.$on('$destroy', function callOnDestroyHook() { - controllerInstance.$onDestroy(); - }); + } + if (isFunction(controllerInstance.$onInit)) { + try { + controllerInstance.$onInit(); + } catch (e) { + $exceptionHandler(e); } - }); - } + } + if (isFunction(controllerInstance.$doCheck)) { + controllerScope.$watch(function() { controllerInstance.$doCheck(); }); + controllerInstance.$doCheck(); + } + if (isFunction(controllerInstance.$onDestroy)) { + controllerScope.$on('$destroy', function callOnDestroyHook() { + controllerInstance.$onDestroy(); + }); + } + }); // PRELINKING for (i = 0, ii = preLinkFns.length; i < ii; i++) { @@ -2995,6 +2983,34 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return value || null; } + function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective) { + var elementControllers = createMap(); + for (var controllerKey in controllerDirectives) { + var directive = controllerDirectives[controllerKey]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; + + var controller = directive.controller; + if (controller === '@') { + controller = attrs[directive.name]; + } + + var controllerInstance = $controller(controller, locals, true, directive.controllerAs); + + // For directives with element transclusion the element is a comment. + // In this case .data will not attach any data. + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } + return elementControllers; + } + // Depending upon the context in which a directive finds itself it might need to have a new isolated // or child scope created. For instance: // * if the directive has been pulled into a template because another directive with a higher priority diff --git a/src/ng/controller.js b/src/ng/controller.js index 8148307bd431..3b8d6196449b 100644 --- a/src/ng/controller.js +++ b/src/ng/controller.js @@ -81,11 +81,16 @@ function $ControllerProvider() { * It's just a simple call to {@link auto.$injector $injector}, but extracted into * a service, so that one can override this service with [BC version](https://gist.github.com/1649788). */ - return function $controller(expression, locals, ident) { + return function $controller(expression, locals, later, ident) { // PRIVATE API: + // param `later` --- indicates that the controller's constructor is invoked at a later time. + // If true, $controller will allocate the object with the correct + // prototype chain, but will not invoke the controller until a returned + // callback is invoked. // param `ident` --- An optional label which overrides the label parsed from the controller // expression, if any. var instance, match, constructor, identifier; + later = later === true; if (ident && isString(ident)) { identifier = ident; } @@ -111,6 +116,41 @@ function $ControllerProvider() { assertArgFn(expression, constructor, true); } + if (later) { + // Instantiate controller later: + // This machinery is used to create an instance of the object before calling the + // controller's constructor itself. + // + // This allows properties to be added to the controller before the constructor is + // invoked. Primarily, this is used for isolate scope bindings in $compile. + // + // This feature is not intended for use by applications, and is thus not documented + // publicly. + // Object creation: http://jsperf.com/create-constructor/2 + var controllerPrototype = (isArray(expression) ? + expression[expression.length - 1] : expression).prototype; + instance = Object.create(controllerPrototype || null); + + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + + return extend(function $controllerInit() { + var result = $injector.invoke(expression, instance, locals, constructor); + if (result !== instance && (isObject(result) || isFunction(result))) { + instance = result; + if (identifier) { + // If result changed, re-assign controllerAs value to scope. + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + } + return instance; + }, { + instance: instance, + identifier: identifier + }); + } + instance = $injector.instantiate(expression, locals, constructor); if (identifier) { diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index d051ab18a7ef..4be9d7ab2d47 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -2345,11 +2345,14 @@ angular.mock.$RootElementProvider = function() { */ function createControllerDecorator() { angular.mock.$ControllerDecorator = ['$delegate', function($delegate) { - return function(expression, locals, bindings, ident) { - if (angular.isString(bindings)) ident = bindings; - var instance = $delegate(expression, locals, ident); - angular.extend(instance, bindings); - return instance; + return function(expression, locals, later, ident) { + if (later && typeof later === 'object') { + var instantiate = $delegate(expression, locals, true, ident); + var instance = instantiate(); + angular.extend(instance, later); + return instance; + } + return $delegate(expression, locals, later, ident); }; }]; diff --git a/test/auto/injectorSpec.js b/test/auto/injectorSpec.js index 7189c95de5f7..7f5254e201e6 100644 --- a/test/auto/injectorSpec.js +++ b/test/auto/injectorSpec.js @@ -482,6 +482,25 @@ describe('injector', function() { expect(instance).toEqual(new Clazz('a-value')); expect(instance.aVal()).toEqual('a-value'); }); + + they('should detect ES6 classes regardless of whitespace/comments ($prop)', [ + 'class Test {}', + 'class Test{}', + 'class //<--ES6 stuff\nTest {}', + 'class//<--ES6 stuff\nTest {}', + 'class {}', + 'class{}', + 'class //<--ES6 stuff\n {}', + 'class//<--ES6 stuff\n {}', + 'class/* Test */{}', + 'class /* Test */ {}' + ], function(classDefinition) { + // eslint-disable-next-line no-eval + var Clazz = eval('(' + classDefinition + ')'); + var instance = injector.invoke(Clazz); + + expect(instance).toEqual(jasmine.any(Clazz)); + }); } }); From 9a065c0fa921e452678ed669c634b113089a2c9c Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 12 Jun 2018 11:27:34 +0300 Subject: [PATCH 024/217] docs(*): fix dangling or ambiguous links --- .../content/misc/version-support-status.ngdoc | 24 ++++++++++++------- src/ngAnimate/module.js | 6 ++--- src/ngMessages/messages.js | 2 +- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/docs/content/misc/version-support-status.ngdoc b/docs/content/misc/version-support-status.ngdoc index aff4309393dd..e2d1625f18e8 100644 --- a/docs/content/misc/version-support-status.ngdoc +++ b/docs/content/misc/version-support-status.ngdoc @@ -30,13 +30,21 @@ Any version branch not shown in the following table (e.g. 1.5.x) is no longer be Any version branch not shown in the following table (e.g. 1.6.x) is no longer being developed. - - - - - - - + + + + + + + + + + + + + + +
VersionStatusComments
1.2.xLong Term SupportLast version to provide IE 8 support
1.7.xLong Term SupportSee [Long Term Support](#long-term-support) section below.
VersionStatusComments
1.2.xLong Term SupportLast version to provide IE 8 support
1.7.xLong Term SupportSee {@link version-support-status#long-term-support Long Term Support} section below.
### Long Term Support @@ -51,4 +59,4 @@ At this time we will focus exclusively on providing fixes to bugs that satisfy a ### Blog Post -You can read more about these plans in our [blog post announcement](https://blog.angular.io/stable-angularjs-and-long-term-support-7e077635ee9c). \ No newline at end of file +You can read more about these plans in our [blog post announcement](https://blog.angular.io/stable-angularjs-and-long-term-support-7e077635ee9c). diff --git a/src/ngAnimate/module.js b/src/ngAnimate/module.js index d7ef5d873c50..70c9570904c1 100644 --- a/src/ngAnimate/module.js +++ b/src/ngAnimate/module.js @@ -281,9 +281,9 @@ * * Sometimes you need to animate between different expression states, whose values * don't necessary need to be known or referenced in CSS styles. - * Unless possible with another ["animation aware" directive](#directive-support), that specific - * use case can always be covered with {@link ngAnimate.directive:ngAnimateSwap} as can be seen in - * {@link ngAnimate.directive:ngAnimateSwap#examples this example}. + * Unless possible with another {@link ngAnimate#directive-support "animation aware" directive}, + * that specific use case can always be covered with {@link ngAnimate.directive:ngAnimateSwap} as + * can be seen in {@link ngAnimate.directive:ngAnimateSwap#examples this example}. * * Note that {@link ngAnimate.directive:ngAnimateSwap} is a *structural directive*, which means it * creates a new instance of the element (including any other/child directives it may have) and diff --git a/src/ngMessages/messages.js b/src/ngMessages/messages.js index bc0026a14f7c..6ab4da49646c 100644 --- a/src/ngMessages/messages.js +++ b/src/ngMessages/messages.js @@ -704,7 +704,7 @@ angular.module('ngMessages', [], function initAngularHelpers() { * * @description * `ngMessageDefault` is a directive with the purpose to show and hide a default message for - * {@link ngMessages}, when none of provided messages matches. + * {@link directive:ngMessages}, when none of provided messages matches. * * More information about using `ngMessageDefault` can be found in the * {@link module:ngMessages `ngMessages` module documentation}. From f7b2fffa5116247c74e770ac124474ae2b7baf19 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 12 Jun 2018 11:28:08 +0300 Subject: [PATCH 025/217] chore(doc-gen): error on unmatched links Closes #16597 --- docs/config/index.js | 1 + package.json | 4 +- yarn.lock | 725 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 704 insertions(+), 26 deletions(-) diff --git a/docs/config/index.js b/docs/config/index.js index 12777f6a8f5e..6bf3a2744a53 100644 --- a/docs/config/index.js +++ b/docs/config/index.js @@ -148,6 +148,7 @@ module.exports = new Package('angularjs', [ .config(function(checkAnchorLinksProcessor) { checkAnchorLinksProcessor.base = '/'; + checkAnchorLinksProcessor.errorOnUnmatchedLinks = true; // We are only interested in docs that have an area (i.e. they are pages) checkAnchorLinksProcessor.checkDoc = function(doc) { return doc.area; }; }) diff --git a/package.json b/package.json index 0d62777e5d36..c3fa4d7db7db 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,8 @@ "commitplease": "^2.7.10", "cross-spawn": "^4.0.0", "cz-conventional-changelog": "1.1.4", - "dgeni": "^0.4.0", - "dgeni-packages": "^0.16.4", + "dgeni": "^0.4.9", + "dgeni-packages": "^0.26.2", "eslint-plugin-promise": "^3.6.0", "event-stream": "~3.1.0", "glob": "^6.0.1", diff --git a/yarn.lock b/yarn.lock index f635a238b14d..05b4a587aa52 100644 --- a/yarn.lock +++ b/yarn.lock @@ -43,6 +43,10 @@ JSONStream@~0.8.3, JSONStream@~0.8.4: jsonparse "0.0.5" through ">=2.2.7 <3" +a-sync-waterfall@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.0.tgz#38e8319d79379e24628845b53b96722b29e0e47c" + abbrev@1: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" @@ -183,6 +187,13 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -235,10 +246,18 @@ arr-diff@^2.0.0: dependencies: arr-flatten "^1.0.1" -arr-flatten@^1.0.1: +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + array-differ@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" @@ -281,6 +300,10 @@ array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + arraybuffer.slice@~0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" @@ -325,6 +348,10 @@ assert@~1.1.0: dependencies: util "0.10.3" +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + ast-types@0.x.x: version "0.10.1" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.10.1.tgz#f52fca9715579a14f841d67d7f8d25432ab6a3dd" @@ -377,6 +404,10 @@ asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" +atob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + atob@~1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" @@ -435,6 +466,18 @@ base64id@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + basic-auth@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.1.0.tgz#45221ee429f7ee1e5035be3f51533f1cdfd29884" @@ -583,6 +626,21 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" +braces@^2.3.0, braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + brorand@^1.0.1: version "1.0.7" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.0.7.tgz#6677fa5e4901bdbf9c9ec2a748e28dca407a9bfc" @@ -860,6 +918,20 @@ bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + cached-path-relative@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" @@ -1022,6 +1094,28 @@ chokidar@^1.4.1, chokidar@^1.6.0: optionalDependencies: fsevents "^1.0.0" +chokidar@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176" + dependencies: + anymatch "^2.0.0" + async-each "^1.0.0" + braces "^2.3.0" + glob-parent "^3.1.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^2.1.1" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + upath "^1.0.0" + optionalDependencies: + fsevents "^1.1.2" + +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + cipher-base@^1.0.0, cipher-base@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.3.tgz#eeabf194419ce900da3018c207d212f2a6df0a07" @@ -1036,6 +1130,15 @@ circular-json@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.4.0.tgz#c448ea998b7fe31ecf472ec29c6b608e2e2a62fd" +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + cli-cursor@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" @@ -1112,6 +1215,13 @@ coffee-script@~1.7.1: dependencies: mkdirp "~0.3.5" +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + collections@^0.2.0, collections@~0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/collections/-/collections-0.2.2.tgz#1f23026b2ef36f927eecc901e99c5f0d48fa334e" @@ -1220,7 +1330,7 @@ component-bind@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" -component-emitter@1.2.1: +component-emitter@1.2.1, component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" @@ -1342,6 +1452,10 @@ cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + core-js@^2.2.0: version "2.5.3" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" @@ -1531,7 +1645,7 @@ debug@2.6.0, debug@2.X, debug@^2.1.1: dependencies: ms "0.7.2" -debug@2.6.9, debug@^2.2.0, debug@~2.6.4, debug@~2.6.6, debug@~2.6.9: +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@~2.6.4, debug@~2.6.6, debug@~2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -1547,6 +1661,10 @@ decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + dedent@0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.6.0.tgz#0e6da8f0ce52838ef5cec5c8f9396b0c1b64a3cb" @@ -1569,6 +1687,25 @@ defaults@^1.0.0: dependencies: clone "^1.0.2" +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -1673,14 +1810,14 @@ detective@^4.0.0: acorn "^3.1.0" defined "^1.0.0" -dgeni-packages@^0.16.4: - version "0.16.5" - resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.16.5.tgz#3f4d59b312dc11cf216933d0fc368a954ac7c268" +dgeni-packages@^0.26.2: + version "0.26.2" + resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.26.2.tgz#dac22d7e861d4d72ed42af5272714f42b6b5bf3d" dependencies: canonical-path "0.0.2" catharsis "^0.8.1" change-case "3.0.0" - dgeni "^0.4.0" + dgeni "^0.4.9" espree "^2.2.3" estraverse "^4.1.0" glob "^7.0.5" @@ -1691,21 +1828,24 @@ dgeni-packages@^0.16.4: mkdirp "^0.5.1" mkdirp-promise "^5.0.0" node-html-encoder "0.0.2" - nunjucks "^2.4.2" + nunjucks "^3.0.1" semver "^5.2.0" shelljs "^0.7.0" + source-map-support "^0.4.15" spdx-license-list "^2.1.0" stringmap "^0.2.2" - typescript "^1.7.5" + typescript "~2.7.1" + urlencode "^1.1.0" -dgeni@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/dgeni/-/dgeni-0.4.2.tgz#c5f7297922444e9e149368f7d3c3fdb17cc96d28" +dgeni@^0.4.9: + version "0.4.9" + resolved "https://registry.yarnpkg.com/dgeni/-/dgeni-0.4.9.tgz#9e42775b1386ca5eb824753ac2cd169d8f61ced1" dependencies: canonical-path "~0.0.2" dependency-graph "~0.4.1" di "0.0.1" lodash "^3.10.1" + objectdiff "^1.1.0" optimist "~0.6.1" q "~1.4.1" validate.js "^0.9.0" @@ -2142,6 +2282,18 @@ expand-brackets@^0.1.4: dependencies: is-posix-bracket "^0.1.0" +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + expand-range@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044" @@ -2192,6 +2344,19 @@ express@^4.8.6: utils-merge "1.0.0" vary "~1.1.0" +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + extend@3: version "3.0.0" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" @@ -2214,6 +2379,19 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -2281,6 +2459,15 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + finalhandler@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.5.0.tgz#e9508abece9b6dba871a6942a1d7911b91911ac7" @@ -2391,7 +2578,7 @@ follow-redirects@1.0.0: dependencies: debug "^2.2.0" -for-in@^1.0.1: +for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2439,6 +2626,12 @@ forwarded@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363" +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + fresh@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" @@ -2465,6 +2658,12 @@ fs-extra@^1.0.0: jsonfile "^2.1.0" klaw "^1.0.0" +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2476,6 +2675,13 @@ fsevents@^1.0.0: nan "^2.3.0" node-pre-gyp "^0.6.39" +fsevents@^1.1.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + fstream-ignore@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" @@ -2566,6 +2772,10 @@ get-uri@2: ftp "~0.3.10" readable-stream "2" +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + getobject@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c" @@ -2595,6 +2805,13 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + glob-stream@^3.1.5: version "3.1.18" resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" @@ -3092,6 +3309,33 @@ has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + has@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" @@ -3266,10 +3510,22 @@ iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +iconv-lite@^0.4.4, iconv-lite@~0.4.11: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + ignore@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.2.tgz#1c51e1ef53bab6ddc15db4d9ac4ec139eceb3410" @@ -3441,6 +3697,18 @@ is-absolute@^0.2.3: is-relative "^0.2.1" is-windows "^0.2.0" +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + is-array@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-array/-/is-array-1.0.1.tgz#e9850cc2cc860c3bc0977e84ccf0dd464584279a" @@ -3469,6 +3737,34 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -3479,14 +3775,24 @@ is-equal-shallow@^0.1.3: dependencies: is-primitive "^2.0.0" -is-extendable@^0.1.1: +is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" @@ -3509,6 +3815,18 @@ is-glob@^2.0.0, is-glob@^2.0.1: dependencies: is-extglob "^1.0.0" +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + dependencies: + is-extglob "^2.1.1" + is-lower-case@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393" @@ -3549,6 +3867,16 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + +is-odd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" + dependencies: + is-number "^4.0.0" + is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" @@ -3565,6 +3893,12 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -3621,6 +3955,10 @@ is-windows@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + isarray@0.0.1, isarray@~0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -3647,6 +3985,10 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -3884,7 +4226,7 @@ karma@^2.0.0: tmp "0.0.33" useragent "^2.1.12" -kind-of@^3.0.2: +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: @@ -3896,6 +4238,14 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -4338,7 +4688,7 @@ mailgun-js@^0.7.0: q "~1.4.0" tsscmp "~1.0.0" -map-cache@^0.2.0: +map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -4350,6 +4700,12 @@ map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + marked@^0.3.2, marked@~0.3.0: version "0.3.6" resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" @@ -4410,6 +4766,24 @@ micromatch@^2.1.5, micromatch@^2.3.7: parse-glob "^3.0.4" regex-cache "^0.4.2" +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + miller-rabin@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.0.tgz#4a62fb1d42933c05583982f4c716f6fb9e6c6d3d" @@ -4502,6 +4876,26 @@ minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + mkdirp-promise@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" @@ -4633,6 +5027,27 @@ nan@^2.4.0: version "2.5.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2" +nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +nanomatch@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-odd "^2.0.0" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + natives@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.0.tgz#e9ff841418a6b2ec7a495e939984f78f163e6e31" @@ -4641,6 +5056,14 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" +needle@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -4659,6 +5082,21 @@ node-html-encoder@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/node-html-encoder/-/node-html-encoder-0.0.2.tgz#8973618d727da5526a830b47d07c0d803e0a15c6" +node-pre-gyp@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz#6e4ef5bb5c5203c6552448828c852c40111aac46" + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.0" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.1.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + node-pre-gyp@^0.6.39: version "0.6.39" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" @@ -4750,12 +5188,23 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.0, normalize-path@^2.0.1: +normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: 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" +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-packlist@^1.1.6: + version "1.1.10" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-path@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.3.tgz#15cff4e1c89a38da77f56f6055b24f975dfb2bbe" @@ -4810,7 +5259,7 @@ nunjucks-date@^1.2.0: dependencies: moment "^2.8.4" -nunjucks@^2.4.2, nunjucks@^2.5.2: +nunjucks@^2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-2.5.2.tgz#ea7d346e785b8a4874666c3cca9e18c577fba22c" dependencies: @@ -4818,6 +5267,17 @@ nunjucks@^2.4.2, nunjucks@^2.5.2: chokidar "^1.6.0" yargs "^3.32.0" +nunjucks@^3.0.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.1.3.tgz#9a23c844af01c143a0b40f3bdd1212a9d7877260" + dependencies: + a-sync-waterfall "^1.0.0" + asap "^2.0.3" + postinstall-build "^5.0.1" + yargs "^3.32.0" + optionalDependencies: + chokidar "^2.0.0" + oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -4838,6 +5298,20 @@ object-component@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -4845,6 +5319,16 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + +objectdiff@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/objectdiff/-/objectdiff-1.1.0.tgz#8d7a15be6cb8670df8a490cc6be12a4f05ea82f4" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -5075,6 +5559,10 @@ pascal-case@^2.0.0: camel-case "^3.0.0" upper-case-first "^1.1.0" +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + path-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" @@ -5085,6 +5573,10 @@ path-case@^2.1.0: dependencies: no-case "^2.2.0" +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + path-exists@2.1.0, path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" @@ -5193,6 +5685,14 @@ portscanner@^1.0.0: dependencies: async "1.5.2" +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + +postinstall-build@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postinstall-build/-/postinstall-build-5.0.1.tgz#b917a9079b26178d9a24af5a5cd8cb4a991d11b9" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -5576,6 +6076,13 @@ regex-cache@^0.4.2: dependencies: is-equal-shallow "^0.1.3" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -5588,7 +6095,7 @@ repeat-string@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae" -repeat-string@^1.5.2: +repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" @@ -5752,7 +6259,7 @@ resolve-pkg@^0.1.0: dependencies: resolve-from "^2.0.0" -resolve-url@~0.2.1: +resolve-url@^0.2.1, resolve-url@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -5781,6 +6288,10 @@ restore-cursor@^1.0.1: exit-hook "^1.0.0" onetime "^1.0.0" +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + rewire@~2.1.0: version "2.1.5" resolved "https://registry.yarnpkg.com/rewire/-/rewire-2.1.5.tgz#764599179cae5e393839bf3ad6e0be371ee49d81" @@ -5867,6 +6378,20 @@ safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +safe-buffer@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + samsam@1.1.2, samsam@~1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" @@ -5901,6 +6426,10 @@ sax@>=0.6.0, sax@^1.1.1: version "1.2.2" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828" +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + selenium-webdriver@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.0.1.tgz#a2dea5da4a97f6672e89e7ca7276cefa365147a7" @@ -6013,6 +6542,24 @@ set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + "setimmediate@>= 1.0.1 < 2", "setimmediate@>= 1.0.2 < 2": version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -6138,6 +6685,33 @@ snake-case@^2.1.0: dependencies: no-case "^2.2.0" +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" @@ -6226,12 +6800,32 @@ source-map-resolve@^0.3.0: source-map-url "~0.3.0" urix "~0.1.0" +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + source-map-support@~0.4.0: version "0.4.11" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.11.tgz#647f939978b38535909530885303daf23279f322" dependencies: source-map "^0.5.3" +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + source-map-url@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" @@ -6252,7 +6846,7 @@ source-map@^0.1.38, source-map@~0.1.31, source-map@~0.1.7: dependencies: amdefine ">=0.0.4" -source-map@^0.5.3, source-map@~0.5.3, source-map@~0.5.6: +source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.3, source-map@~0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -6305,6 +6899,12 @@ spdx-license-list@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/spdx-license-list/-/spdx-license-list-2.1.0.tgz#3788ffb5c80b24afbe8283934e9e6684ea6a218d" +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + split@0.2: version "0.2.10" resolved "https://registry.yarnpkg.com/split/-/split-0.2.10.tgz#67097c601d697ce1368f418f06cd201cf0521a57" @@ -6333,6 +6933,13 @@ stack-trace@0.0.x: version "0.0.9" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + "statuses@>= 1.3.1 < 2": version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" @@ -6568,6 +7175,18 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" +tar@^4: + version "4.4.4" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -6669,6 +7288,28 @@ to-iso-string@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + tough-cookie@~2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" @@ -6740,9 +7381,9 @@ typedarray@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@^1.7.5: - version "1.8.10" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-1.8.10.tgz#b475d6e0dff0bf50f296e5ca6ef9fbb5c7320f1e" +typescript@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" uglify-js@2.6.4: version "2.6.4" @@ -6835,6 +7476,15 @@ underscore@~1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + unique-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" @@ -6843,6 +7493,13 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + unzip@~0.1.9: version "0.1.11" resolved "https://registry.yarnpkg.com/unzip/-/unzip-0.1.11.tgz#89749c63b058d7d90d619f86b98aa1535d3b97f0" @@ -6854,6 +7511,10 @@ unzip@~0.1.9: readable-stream "~1.0.31" setimmediate ">= 1.0.1 < 2" +upath@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" + upper-case-first@^1.1.0, upper-case-first@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115" @@ -6886,6 +7547,18 @@ url@~0.11.0: punycode "1.3.2" querystring "0.2.0" +urlencode@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/urlencode/-/urlencode-1.1.0.tgz#1f2ba26f013c85f0133f7a3ad6ff2730adf7cbb7" + dependencies: + iconv-lite "~0.4.11" + +use@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" + dependencies: + kind-of "^6.0.2" + user-home@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" @@ -7215,6 +7888,10 @@ yallist@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.0.0.tgz#306c543835f09ee1a4cb23b7bce9ab341c91cdd4" +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + yargs@^3.32.0: version "3.32.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" From c9a92fcad52477f93ddbee5091e76d8763cde0bd Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 12 Jun 2018 16:24:32 +0300 Subject: [PATCH 026/217] docs(CHANGELOG): add release notes for 1.7.2 --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29176742999d..b3fbcff12acd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ + +# 1.7.2 extreme-compatiplication (2018-06-12) + +In the previous release, we removed a private, undocumented API that was no longer used by +AngularJS. It turned out that several popular UI libraries (such as +[AngularJS Material](https://material.angularjs.org/), +[UI Bootstrap](https://angular-ui.github.io/bootstrap/), +[ngDialog](http://likeastore.github.io/ngDialog/) and probably others) relied on that API. + +In order to avoid unnecessary pain for developers, this release reverts the removal of the private +API and restores compatibility of the aforementioned libraries with the latest AngularJS. + +## Reverts +- **$compile:** remove `preAssignBindingsEnabled` leftovers + ([2da495](https://github.com/angular/angular.js/commit/2da49504065e9e2b71a7a5622e45118d8abbe87e), + [#16580](https://github.com/angular/angular.js/pull/16580), + [a81232](https://github.com/angular/angular.js/commit/a812327acda8bc890a4c4e809f0debb761c29625), + [#16595](https://github.com/angular/angular.js/pull/16595)) + + # 1.7.1 momentum-defiance (2018-06-08) From 83f7980e2f2e9ea6a373a5e1e301edfc90c8daa8 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Tue, 12 Jun 2018 22:45:17 +0100 Subject: [PATCH 027/217] feat(ngModelOptions): add `timeStripZeroSeconds` and `timeSecondsFormat` Closes #10721 Closes #16510 Closes #16584 --- src/ng/directive/input.js | 35 +++++- src/ng/directive/ngModelOptions.js | 92 +++++++++++++-- test/ng/directive/inputSpec.js | 172 ++++++++++++++++++++++++++++- 3 files changed, 286 insertions(+), 13 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 2eb4b0d7227d..bf6576f81a09 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -255,6 +255,10 @@ var inputType = { * The timezone to be used to read/write the `Date` instance in the model can be defined using * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. * + * The format of the displayed time can be adjusted with the + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` + * and `timeStripZeroSeconds`. + * * @param {string} ngModel Assignable AngularJS expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. @@ -356,7 +360,12 @@ var inputType = { * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. * * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions}. By default, + * this is the timezone of the browser. + * + * The format of the displayed time can be adjusted with the + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` + * and `timeStripZeroSeconds`. * * @param {string} ngModel Assignable AngularJS expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. @@ -1491,6 +1500,8 @@ function createDateInputType(type, regexp, parseDate, format) { return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) { badInputChecker(scope, element, attr, ctrl, type); baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + + var isTimeType = type === 'time' || type === 'datetimelocal'; var previousDate; var previousTimezone; @@ -1514,11 +1525,13 @@ function createDateInputType(type, regexp, parseDate, format) { if (isValidDate(value)) { previousDate = value; var timezone = ctrl.$options.getOption('timezone'); + if (timezone) { previousTimezone = timezone; previousDate = convertTimezoneToLocal(previousDate, timezone, true); } - return $filter('date')(value, format, timezone); + + return formatter(value, timezone); } else { previousDate = null; previousTimezone = null; @@ -1573,6 +1586,24 @@ function createDateInputType(type, regexp, parseDate, format) { } return parsedDate; } + + function formatter(value, timezone) { + var targetFormat = format; + + if (isTimeType && isString(ctrl.$options.getOption('timeSecondsFormat'))) { + targetFormat = format + .replace('ss.sss', ctrl.$options.getOption('timeSecondsFormat')) + .replace(/:$/, ''); + } + + var formatted = $filter('date')(value, targetFormat, timezone); + + if (isTimeType && ctrl.$options.getOption('timeStripZeroSeconds')) { + formatted = formatted.replace(/(?::00)?(?:\.000)?$/, ''); + } + + return formatted; + } }; } diff --git a/src/ng/directive/ngModelOptions.js b/src/ng/directive/ngModelOptions.js index aefc7355c9c0..1f242001adf9 100644 --- a/src/ng/directive/ngModelOptions.js +++ b/src/ng/directive/ngModelOptions.js @@ -406,12 +406,6 @@ defaultModelOptions = new ModelOptions({ * * * - * ## Specifying timezones - * - * You can specify the timezone that date/time input directives expect by providing its name in the - * `timezone` property. - * - * * ## Programmatically changing options * * The `ngModelOptions` expression is only evaluated once when the directive is linked; it is not @@ -423,8 +417,70 @@ defaultModelOptions = new ModelOptions({ * Default events, extra triggers, and catch-all debounce values}. * * + * ## Specifying timezones + * + * You can specify the timezone that date/time input directives expect by providing its name in the + * `timezone` property. + * + * + * ## Formatting the value of `time` and `datetime-local` + * + * With the options `timeSecondsFormat` and `timeStripZeroSeconds` it is possible to adjust the value + * that is displayed in the control. Note that browsers may apply their own formatting + * in the user interface. + * + + + + + + angular.module('timeExample', []) + .component('timeExample', { + templateUrl: 'timeExample.html', + controller: function() { + this.time = new Date(1970, 0, 1, 14, 57, 0); + + this.options = { + timeSecondsFormat: 'ss', + timeStripZeroSeconds: true + }; + + this.optionChange = function() { + this.timeForm.timeFormatted.$overrideModelOptions(this.options); + this.time = new Date(this.time); + }; + } + }); + + +
+ Default: +
+ With options: + +
+ + Options:
+ timeSecondsFormat: + +
+ timeStripZeroSeconds: + +
+
+ *
+ * * @param {Object} ngModelOptions options to apply to {@link ngModel} directives on this element and - * and its descendents. Valid keys are: + * and its descendents. + * + * **General options**: + * * - `updateOn`: string specifying which event should the input be bound to. You can set several * events using an space delimited list. There is a special event called `default` that * matches the default events belonging to the control. These are the events that are bound to @@ -457,6 +513,10 @@ defaultModelOptions = new ModelOptions({ * not validate correctly instead of the default behavior of setting the model to undefined. * - `getterSetter`: boolean value which determines whether or not to treat functions bound to * `ngModel` as getters/setters. + * + * + * **Input-type specific options**: + * * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for * ``, ``, ... . It understands UTC/GMT and the * continental US time zone abbreviations, but for general use, use a time zone offset, for @@ -465,6 +525,24 @@ defaultModelOptions = new ModelOptions({ * Note that changing the timezone will have no effect on the current date, and is only applied after * the next input / model change. * + * - `timeSecondsFormat`: Defines if the `time` and `datetime-local` types should show seconds and + * milliseconds. The option follows the format string of {@link date date filter}. + * By default, the options is `undefined` which is equal to `'ss.sss'` (seconds and milliseconds). + * The other options are `'ss'` (strips milliseconds), and `''` (empty string), which strips both + * seconds and milliseconds. + * Note that browsers that support `time` and `datetime-local` require the hour and minutes + * part of the time string, and may show the value differently in the user interface. + * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. + * + * - `timeStripZeroSeconds`: Defines if the `time` and `datetime-local` types should strip the + * seconds and milliseconds from the formatted value if they are zero. This option is applied + * after `timeSecondsFormat`. + * This option can be used to make the formatting consistent over different browsers, as some + * browsers with support for `time` will natively hide the milliseconds and + * seconds if they are zero, but others won't, and browsers that don't implement these input + * types will always show the full string. + * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. + * */ var ngModelOptionsDirective = function() { NgModelOptionsController.$inject = ['$attrs', '$scope']; diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index fdb5af255624..79b44c910170 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -1384,6 +1384,88 @@ describe('input', function() { expect($rootScope.form.alias.$error.datetimelocal).toBeTruthy(); }); + it('should use the timeSecondsFormat specified in ngModelOptions', function() { + var inputElm = helper.compileInput( + '' + ); + + var ctrl = inputElm.controller('ngModel'); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + expect(inputElm.val()).toBe('1970-01-01T15:41'); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + expect(inputElm.val()).toBe('1970-01-01T15:41'); + + ctrl.$overrideModelOptions({timeSecondsFormat: 'ss'}); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 5, 500); + }); + expect(inputElm.val()).toBe('1970-01-01T15:41:05'); + + ctrl.$overrideModelOptions({timeSecondsFormat: 'ss.sss'}); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 50); + }); + expect(inputElm.val()).toBe('1970-01-01T15:41:50.050'); + }); + + + it('should strip empty milliseconds and seconds if specified in ngModelOptions', function() { + var inputElm = helper.compileInput( + '' + ); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41:50.500'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41:00.500'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 0); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41:50'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 0); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41'); + }); + + + it('should apply timeStripZeroSeconds after timeSecondsFormat', function() { + var inputElm = helper.compileInput(''); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41:50'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41'); + }); + describe('min', function() { var inputElm; beforeEach(function() { @@ -1593,7 +1675,7 @@ describe('input', function() { }); - it('should set the view if the model if a valid Date object.', function() { + it('should set the view if the model is a valid Date object.', function() { var inputElm = helper.compileInput(''); $rootScope.$apply(function() { @@ -1604,7 +1686,7 @@ describe('input', function() { }); - it('should set the model undefined if the view is invalid', function() { + it('should set the model to undefined if the view is invalid', function() { var inputElm = helper.compileInput(''); $rootScope.$apply(function() { @@ -1623,7 +1705,7 @@ describe('input', function() { }); - it('should render as blank if null', function() { + it('should set blank if null', function() { var inputElm = helper.compileInput(''); $rootScope.$apply('test = null'); @@ -1633,7 +1715,7 @@ describe('input', function() { }); - it('should come up blank when no value specified', function() { + it('should set blank when no value specified', function() { var inputElm = helper.compileInput(''); expect(inputElm.val()).toBe(''); @@ -1644,6 +1726,88 @@ describe('input', function() { expect(inputElm.val()).toBe(''); }); + it('should use the timeSecondsFormat specified in ngModelOptions', function() { + var inputElm = helper.compileInput( + '' + ); + + var ctrl = inputElm.controller('ngModel'); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + expect(inputElm.val()).toBe('15:41'); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + expect(inputElm.val()).toBe('15:41'); + + ctrl.$overrideModelOptions({timeSecondsFormat: 'ss'}); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 5, 500); + }); + expect(inputElm.val()).toBe('15:41:05'); + + ctrl.$overrideModelOptions({timeSecondsFormat: 'ss.sss'}); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 50); + }); + expect(inputElm.val()).toBe('15:41:50.050'); + }); + + + it('should strip empty milliseconds and seconds if specified in ngModelOptions', function() { + var inputElm = helper.compileInput( + '' + ); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + + expect(inputElm.val()).toBe('15:41:50.500'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + + expect(inputElm.val()).toBe('15:41:00.500'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 0); + }); + + expect(inputElm.val()).toBe('15:41:50'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 0); + }); + + expect(inputElm.val()).toBe('15:41'); + }); + + + it('should apply timeStripZeroSeconds after timeSecondsFormat', function() { + var inputElm = helper.compileInput(''); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + + expect(inputElm.val()).toBe('15:41:50'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + + expect(inputElm.val()).toBe('15:41'); + }); + it('should parse empty string to null', function() { var inputElm = helper.compileInput(''); From 2472d621d7d4a09a53704f4809aaa3b594ea8e04 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Thu, 14 Jun 2018 08:37:07 +0100 Subject: [PATCH 028/217] chore(code.angularjs.org): update firebase libraries --- .../functions/index.js | 16 +- .../functions/package-lock.json | 3743 +++++++++++++++++ .../functions/package.json | 4 +- 3 files changed, 3750 insertions(+), 13 deletions(-) create mode 100644 scripts/code.angularjs.org-firebase/functions/package-lock.json diff --git a/scripts/code.angularjs.org-firebase/functions/index.js b/scripts/code.angularjs.org-firebase/functions/index.js index 33f7ba04df7d..2a4666e590da 100644 --- a/scripts/code.angularjs.org-firebase/functions/index.js +++ b/scripts/code.angularjs.org-firebase/functions/index.js @@ -15,11 +15,14 @@ function sendStoredFile(request, response) { return segment !== ''; }); + const version = filePathSegments[0]; const isDocsPath = filePathSegments[1] === 'docs'; const lastSegment = filePathSegments[filePathSegments.length - 1]; const bucket = gcs.bucket(gcsBucketId); + console.log(request.path, lastSegment); + let downloadSource; let fileName; @@ -190,9 +193,7 @@ const snapshotRegex = /^snapshot(-stable)?\//; * When a new zip file is uploaded into snapshot or snapshot-stable, * delete the previous zip file. */ -function deleteOldSnapshotZip(event) { - const object = event.data; - +function deleteOldSnapshotZip(object, context) { const bucketId = object.bucket; const filePath = object.name; const contentType = object.contentType; @@ -202,13 +203,6 @@ function deleteOldSnapshotZip(event) { const snapshotFolderMatch = filePath.match(snapshotRegex); - if (!snapshotFolderMatch || - contentType !== 'application/zip' || - resourceState === 'not_exists' // Deletion event - ) { - return; - } - bucket.getFiles({ prefix: snapshotFolderMatch[0], delimiter: '/', @@ -230,4 +224,4 @@ function deleteOldSnapshotZip(event) { } exports.sendStoredFile = functions.https.onRequest(sendStoredFile); -exports.deleteOldSnapshotZip = functions.storage.object().onChange(deleteOldSnapshotZip); +exports.deleteOldSnapshotZip = functions.storage.object().onFinalize(deleteOldSnapshotZip); diff --git a/scripts/code.angularjs.org-firebase/functions/package-lock.json b/scripts/code.angularjs.org-firebase/functions/package-lock.json new file mode 100644 index 000000000000..6bd5ab47a101 --- /dev/null +++ b/scripts/code.angularjs.org-firebase/functions/package-lock.json @@ -0,0 +1,3743 @@ +{ + "name": "functions-firebase-code.angularjs.org", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@firebase/app": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.1.10.tgz", + "integrity": "sha512-2GTXt3b2QZXkmx6/5nNJq+pEN/VTjAG55MFJS1WMoLVZkwKuNpWNk65QVyPaoL88x1iHtuLqAMFgJUOnhOg+Pw==", + "requires": { + "@firebase/app-types": "0.1.2", + "@firebase/util": "0.1.10", + "tslib": "1.9.2" + } + }, + "@firebase/app-types": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.1.2.tgz", + "integrity": "sha512-bCIZGeMtP0ibrXNNaU214/1tRNw0jHnir/cfiAao1gjUyIS7RzOTQoH+zbwPJNEwUqJ0T3ykw/Tv4/khGqbVBg==" + }, + "@firebase/database": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.2.2.tgz", + "integrity": "sha512-iTNEN33D3V0hAG2hdx+guFBXaN4hcFS2k2EGp/bzNviAG7n2AotMscdbkS6xDS2e3Uk2/D3lfibHQO4zgJ3LIg==", + "requires": { + "@firebase/database-types": "0.2.1", + "@firebase/logger": "0.1.1", + "@firebase/util": "0.1.11", + "faye-websocket": "0.11.1", + "tslib": "1.9.0" + }, + "dependencies": { + "@firebase/util": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.1.11.tgz", + "integrity": "sha512-xUMugOJBSKVKOjrKJIVeIr4Z/6iDxSuOlOJRdz0xsOBJ9+lZVxGZs0U4oZmszWhQER1zzR+EQWIYFYePt6/QMQ==", + "requires": { + "tslib": "1.9.0" + } + }, + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "requires": { + "websocket-driver": "0.7.0" + } + }, + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } + } + }, + "@firebase/database-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.2.1.tgz", + "integrity": "sha512-LyvTpLImnhSTyHfPGcBxhD0tHw+R7FUb+als23Ad5hPCcGxlRgLhA+ukrhFIGA8Mt8FYHWgFm7TCX4YDRDxK6w==" + }, + "@firebase/logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.1.tgz", + "integrity": "sha512-5jn3HHbEfdOwychyIEIkP1cik+MW/vvoOavTOzwDkH+fv6Bx+HBUOzh09M7sCYzXFtKzjbUax9+g39mJNBLklQ==" + }, + "@firebase/util": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.1.10.tgz", + "integrity": "sha512-XEogRfUQBZ4T37TMq/3ZbuiTdRAKX8hF3TgJglUZNCJf/6QnQ+jlupCuMAXBqCGfw2Mw0m2matoCUBWpsyevOA==", + "requires": { + "tslib": "1.9.2" + } + }, + "@google-cloud/common": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.17.0.tgz", + "integrity": "sha512-HRZLSU762E6HaKoGfJGa8W95yRjb9rY7LePhjaHK9ILAnFacMuUGVamDbTHu1csZomm1g3tZTtXfX/aAhtie/Q==", + "requires": { + "array-uniq": "1.0.3", + "arrify": "1.0.1", + "concat-stream": "1.6.2", + "create-error-class": "3.0.2", + "duplexify": "3.6.0", + "ent": "2.2.0", + "extend": "3.0.1", + "google-auto-auth": "0.10.1", + "is": "3.2.1", + "log-driver": "1.2.7", + "methmeth": "1.1.0", + "modelo": "4.2.3", + "request": "2.87.0", + "retry-request": "3.3.2", + "split-array-stream": "1.0.3", + "stream-events": "1.0.4", + "string-format-obj": "1.1.1", + "through2": "2.0.3" + } + }, + "@google-cloud/common-grpc": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@google-cloud/common-grpc/-/common-grpc-0.6.1.tgz", + "integrity": "sha512-pspOZVfmrCTP0svTNwFE8nYJsQp5rTUaeUpJwpgslDk5tDWFbYT3dZkANbiURcTSq0mo6hZmd+M5rPIzWMVUmA==", + "requires": { + "@google-cloud/common": "0.17.0", + "dot-prop": "4.2.0", + "duplexify": "3.6.0", + "extend": "3.0.1", + "grpc": "1.12.3", + "is": "3.2.1", + "modelo": "4.2.3", + "retry-request": "3.3.2", + "through2": "2.0.3" + } + }, + "@google-cloud/firestore": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-0.13.1.tgz", + "integrity": "sha512-70PPCDg++AGx4OGW/FhDoDtIh4Z2WuwPMkHkvFWNvEDGghCxGrYgRvpCsfcZBU0TLYpcbsndrweLp972cwItrQ==", + "requires": { + "@google-cloud/common": "0.17.0", + "@google-cloud/common-grpc": "0.6.1", + "bun": "0.0.12", + "deep-equal": "1.0.1", + "extend": "3.0.1", + "functional-red-black-tree": "1.0.1", + "google-gax": "0.16.1", + "is": "3.2.1", + "safe-buffer": "5.1.1", + "through2": "2.0.3" + } + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "requires": { + "call-me-maybe": "1.0.1", + "glob-to-regexp": "0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz", + "integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==" + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/inquire": "1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@types/body-parser": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", + "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", + "requires": { + "@types/connect": "3.4.32", + "@types/node": "10.3.3" + } + }, + "@types/connect": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", + "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", + "requires": { + "@types/node": "10.3.3" + } + }, + "@types/cors": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.4.tgz", + "integrity": "sha512-ipZjBVsm2tF/n8qFGOuGBkUij9X9ZswVi9G3bx/6dz7POpVa6gVHcj1wsX/LVEn9MMF41fxK/PnZPPoTD1UFPw==", + "requires": { + "@types/express": "4.16.0" + } + }, + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" + }, + "@types/express": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz", + "integrity": "sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==", + "requires": { + "@types/body-parser": "1.17.0", + "@types/express-serve-static-core": "4.16.0", + "@types/serve-static": "1.13.2" + } + }, + "@types/express-serve-static-core": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz", + "integrity": "sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==", + "requires": { + "@types/events": "1.2.0", + "@types/node": "10.3.3", + "@types/range-parser": "1.2.2" + } + }, + "@types/google-cloud__storage": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@types/google-cloud__storage/-/google-cloud__storage-1.1.7.tgz", + "integrity": "sha512-010Llp+5ze+XWWmZuLDxs0pZgFjOgtJQVt9icJ0Ed67ZFLq7PnXkYx8x/k9nwDojR5/X4XoLPNqB1F627TScdQ==", + "requires": { + "@types/node": "10.3.3" + } + }, + "@types/jsonwebtoken": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.7.tgz", + "integrity": "sha512-lq9X76APpxGJDUe1VptL1P5GrogqhPCH+SDy94+gaBJw7Hhj6hwrVC6zuxAx2GrgktkBuwydESZBvPfrdBoOEg==", + "requires": { + "@types/node": "10.3.3" + } + }, + "@types/lodash": { + "version": "4.14.109", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.109.tgz", + "integrity": "sha512-hop8SdPUEzbcJm6aTsmuwjIYQo1tqLseKCM+s2bBqTU2gErwI4fE+aqUVOlscPSQbKHKgtMMPoC+h4AIGOJYvw==" + }, + "@types/long": { + "version": "3.0.32", + "resolved": "https://registry.npmjs.org/@types/long/-/long-3.0.32.tgz", + "integrity": "sha512-ZXyOOm83p7X8p3s0IYM3VeueNmHpkk/yMlP8CLeOnEcu6hIwPH7YjZBvhQkR0ZFS2DqZAxKtJ/M5fcuv3OU5BA==" + }, + "@types/mime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", + "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" + }, + "@types/node": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.3.tgz", + "integrity": "sha512-/gwCgiI2e9RzzZTKbl+am3vgNqOt7a9fJ/uxv4SqYKxenoEDNVU3KZEadlpusWhQI0A0dOrZ0T68JYKVjzmgdQ==" + }, + "@types/range-parser": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz", + "integrity": "sha512-HtKGu+qG1NPvYe1z7ezLsyIaXYyi8SoAVqWDZgDQ8dLrsZvSzUNCwZyfX33uhWxL/SU0ZDQZ3nwZ0nimt507Kw==" + }, + "@types/serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", + "requires": { + "@types/express-serve-static-core": "4.16.0", + "@types/mime": "2.0.0" + } + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.2.tgz", + "integrity": "sha512-zUzo1E5dI2Ey8+82egfnttyMlMZ2y0D8xOCO3PNPPlYXpl8NZvF6Qk9L9BEtJs+43FqEmfBViDqc5d1ckRDguw==" + }, + "acorn-es7-plugin": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz", + "integrity": "sha1-8u4fMiipDurRJF+asZIusucdM2s=" + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "0.7.1", + "optjs": "3.2.2" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "4.17.10" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + }, + "axios": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "1.5.0", + "is-buffer": "1.1.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + }, + "bun": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/bun/-/bun-0.0.12.tgz", + "integrity": "sha512-Toms18J9DqnT+IfWkwxVTB2EaBprHvjlMWrTIsfX4xbu3ZBqVBwrERU0em1IgtRe04wT+wJxMlKHZok24hrcSQ==", + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "3.2.0" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "call-signature": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/call-signature/-/call-signature-0.0.2.tgz", + "integrity": "sha1-qEq8glpV70yysCi9dOIFpluaSZY=" + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "compressible": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz", + "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=", + "requires": { + "mime-db": "1.34.0" + }, + "dependencies": { + "mime-db": { + "version": "1.34.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.34.0.tgz", + "integrity": "sha1-RS0Oz/XDA0am3B5kseruDTcZ/5o=" + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", + "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", + "requires": { + "object-assign": "4.1.1", + "vary": "1.1.2" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "diff-match-patch": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.1.tgz", + "integrity": "sha512-A0QEhr4PxGUMEtKxd6X+JLnOTFd3BfIPSDpsc4dMvj+CbSaErDwTpoTo/nFJDMSrjxLW4BiNq+FbNisAAHhWeQ==" + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "1.0.1" + } + }, + "duplexify": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", + "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "empower": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/empower/-/empower-1.3.0.tgz", + "integrity": "sha512-tP2WqM7QzrPguCCQEQfFFDF+6Pw6YWLQal3+GHQaV+0uIr0S+jyREQPWljE02zFCYPFYLZ3LosiRV+OzTrxPpQ==", + "requires": { + "core-js": "2.5.7", + "empower-core": "1.2.0" + } + }, + "empower-core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-1.2.0.tgz", + "integrity": "sha512-g6+K6Geyc1o6FdXs9HwrXleCFan7d66G5xSCfSF7x1mJDCes6t0om9lFQG3zOrzh3Bkb/45N0cZ5Gqsf7YrzGQ==", + "requires": { + "call-signature": "0.0.2", + "core-js": "2.5.7" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "espurify": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.8.0.tgz", + "integrity": "sha512-jdkJG9jswjKCCDmEridNUuIQei9algr+o66ZZ19610ZoBsiWLRsQGNYS4HGez3Z/DsR0lhANGAqiwBUclPuNag==", + "requires": { + "core-js": "2.5.7" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "express": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.3", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "1.4.0", + "type-is": "1.6.16", + "utils-merge": "1.0.1", + "vary": "1.1.2" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", + "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", + "requires": { + "@mrmlnc/readdir-enhanced": "2.2.1", + "@nodelib/fs.stat": "1.1.0", + "glob-parent": "3.1.0", + "is-glob": "4.0.0", + "merge2": "1.2.2", + "micromatch": "3.1.10" + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "faye-websocket": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.3.tgz", + "integrity": "sha1-SCpQWw3wrmJrlphm0710DNuWLoM=", + "requires": { + "websocket-driver": "0.7.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.4.0", + "unpipe": "1.0.0" + } + }, + "firebase-admin": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-5.11.0.tgz", + "integrity": "sha1-D9Aj/kbJt7Cb3lwF5rY+eNY/Lg0=", + "requires": { + "@firebase/app": "0.1.10", + "@firebase/database": "0.2.2", + "@google-cloud/firestore": "0.13.1", + "@google-cloud/storage": "1.7.0", + "@types/google-cloud__storage": "1.1.7", + "@types/node": "8.10.20", + "faye-websocket": "0.9.3", + "jsonwebtoken": "8.1.0", + "node-forge": "0.7.1" + }, + "dependencies": { + "@google-cloud/storage": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-1.7.0.tgz", + "integrity": "sha512-QaAxzCkbhspwajoaEnT0GcnQcpjPRcBrHYuQsXtD05BtOJgVnHCLXSsfUiRdU0nVpK+Thp7+sTkQ0fvk5PanKg==", + "requires": { + "@google-cloud/common": "0.17.0", + "arrify": "1.0.1", + "async": "2.6.1", + "compressible": "2.0.14", + "concat-stream": "1.6.2", + "create-error-class": "3.0.2", + "duplexify": "3.6.0", + "extend": "3.0.1", + "gcs-resumable-upload": "0.10.2", + "hash-stream-validation": "0.2.1", + "is": "3.2.1", + "mime": "2.3.1", + "mime-types": "2.1.18", + "once": "1.4.0", + "pumpify": "1.5.1", + "request": "2.87.0", + "safe-buffer": "5.1.1", + "snakeize": "0.1.0", + "stream-events": "1.0.4", + "through2": "2.0.3", + "xdg-basedir": "3.0.0" + } + }, + "@types/node": { + "version": "8.10.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.20.tgz", + "integrity": "sha512-M7x8+5D1k/CuA6jhiwuSCmE8sbUWJF0wYsjcig9WrXvwUI5ArEoUBdOXpV4JcEMrLp02/QbDjw+kI+vQeKyQgg==" + }, + "jsonwebtoken": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", + "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", + "requires": { + "jws": "3.1.5", + "lodash.includes": "4.3.0", + "lodash.isboolean": "3.0.3", + "lodash.isinteger": "4.0.4", + "lodash.isnumber": "3.0.3", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.once": "4.1.1", + "ms": "2.0.0", + "xtend": "4.0.1" + } + }, + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==" + } + } + }, + "firebase-functions": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-1.0.4.tgz", + "integrity": "sha1-MwLZI03m1wj9jLJKpduHLMiVORk=", + "requires": { + "@types/cors": "2.8.4", + "@types/express": "4.16.0", + "@types/jsonwebtoken": "7.2.7", + "@types/lodash": "4.14.109", + "cors": "2.8.4", + "express": "4.16.3", + "jsonwebtoken": "8.3.0", + "lodash": "4.17.10" + } + }, + "follow-redirects": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz", + "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==", + "requires": { + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "gcp-metadata": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.6.3.tgz", + "integrity": "sha512-MSmczZctbz91AxCvqp9GHBoZOSbJKAICV7Ow/AIWSJZRrRchUd5NL1b2P4OfP+4m490BEUPhhARfpHdqCxuCvg==", + "requires": { + "axios": "0.18.0", + "extend": "3.0.1", + "retry-axios": "0.3.2" + } + }, + "gcs-resumable-upload": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-0.10.2.tgz", + "integrity": "sha1-fymz7iPc7EFwNnwHEUGCScZgVF8=", + "requires": { + "configstore": "3.1.2", + "google-auto-auth": "0.10.1", + "pumpify": "1.5.1", + "request": "2.87.0", + "stream-events": "1.0.4" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" + }, + "globby": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", + "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "fast-glob": "2.2.2", + "glob": "7.1.2", + "ignore": "3.3.8", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "google-auth-library": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-1.6.1.tgz", + "integrity": "sha512-jYiWC8NA9n9OtQM7ANn0Tk464do9yhKEtaJ72pKcaBiEwn4LwcGYIYOfwtfsSm3aur/ed3tlSxbmg24IAT6gAg==", + "requires": { + "axios": "0.18.0", + "gcp-metadata": "0.6.3", + "gtoken": "2.3.0", + "jws": "3.1.5", + "lodash.isstring": "4.0.1", + "lru-cache": "4.1.3", + "retry-axios": "0.3.2" + } + }, + "google-auto-auth": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.10.1.tgz", + "integrity": "sha512-iIqSbY7Ypd32mnHGbYctp80vZzXoDlvI9gEfvtl3kmyy5HzOcrZCIGCBdSlIzRsg7nHpQiHE3Zl6Ycur6TSodQ==", + "requires": { + "async": "2.6.1", + "gcp-metadata": "0.6.3", + "google-auth-library": "1.6.1", + "request": "2.87.0" + } + }, + "google-gax": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-0.16.1.tgz", + "integrity": "sha512-eP7UUkKvaHmmvCrr+rxzkIOeEKOnXmoib7/AkENDAuqlC9T2+lWlzwpthDRnitQcV8SblDMzsk73YPMPCDwPyQ==", + "requires": { + "duplexify": "3.6.0", + "extend": "3.0.1", + "globby": "8.0.1", + "google-auto-auth": "0.10.1", + "google-proto-files": "0.15.1", + "grpc": "1.12.3", + "is-stream-ended": "0.1.4", + "lodash": "4.17.10", + "protobufjs": "6.8.6", + "through2": "2.0.3" + }, + "dependencies": { + "@types/node": { + "version": "8.10.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.20.tgz", + "integrity": "sha512-M7x8+5D1k/CuA6jhiwuSCmE8sbUWJF0wYsjcig9WrXvwUI5ArEoUBdOXpV4JcEMrLp02/QbDjw+kI+vQeKyQgg==" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "protobufjs": { + "version": "6.8.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.6.tgz", + "integrity": "sha512-eH2OTP9s55vojr3b7NBaF9i4WhWPkv/nq55nznWNp/FomKrLViprUcqnBjHph2tFQ+7KciGPTPsVWGz0SOhL0Q==", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/base64": "1.1.2", + "@protobufjs/codegen": "2.0.4", + "@protobufjs/eventemitter": "1.1.0", + "@protobufjs/fetch": "1.1.0", + "@protobufjs/float": "1.0.2", + "@protobufjs/inquire": "1.1.0", + "@protobufjs/path": "1.1.2", + "@protobufjs/pool": "1.1.0", + "@protobufjs/utf8": "1.1.0", + "@types/long": "3.0.32", + "@types/node": "8.10.20", + "long": "4.0.0" + } + } + } + }, + "google-p12-pem": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-1.0.2.tgz", + "integrity": "sha512-+EuKr4CLlGsnXx4XIJIVkcKYrsa2xkAmCvxRhX2HsazJzUBAJ35wARGeApHUn4nNfPD03Vl057FskNr20VaCyg==", + "requires": { + "node-forge": "0.7.5", + "pify": "3.0.0" + }, + "dependencies": { + "node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==" + } + } + }, + "google-proto-files": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/google-proto-files/-/google-proto-files-0.15.1.tgz", + "integrity": "sha512-ebtmWgi/ooR5Nl63qRVZZ6VLM6JOb5zTNxTT/ZAU8yfMOdcauoOZNNMOVg0pCmTjqWXeuuVbgPP0CwO5UHHzBQ==", + "requires": { + "globby": "7.1.1", + "power-assert": "1.6.0", + "protobufjs": "6.8.6" + }, + "dependencies": { + "@types/node": { + "version": "8.10.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.20.tgz", + "integrity": "sha512-M7x8+5D1k/CuA6jhiwuSCmE8sbUWJF0wYsjcig9WrXvwUI5ArEoUBdOXpV4JcEMrLp02/QbDjw+kI+vQeKyQgg==" + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.8", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "protobufjs": { + "version": "6.8.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.6.tgz", + "integrity": "sha512-eH2OTP9s55vojr3b7NBaF9i4WhWPkv/nq55nznWNp/FomKrLViprUcqnBjHph2tFQ+7KciGPTPsVWGz0SOhL0Q==", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/base64": "1.1.2", + "@protobufjs/codegen": "2.0.4", + "@protobufjs/eventemitter": "1.1.0", + "@protobufjs/fetch": "1.1.0", + "@protobufjs/float": "1.0.2", + "@protobufjs/inquire": "1.1.0", + "@protobufjs/path": "1.1.2", + "@protobufjs/pool": "1.1.0", + "@protobufjs/utf8": "1.1.0", + "@types/long": "3.0.32", + "@types/node": "8.10.20", + "long": "4.0.0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grpc": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.12.3.tgz", + "integrity": "sha512-QPwbAXRXd8IyXAhTdUVgjEqSdvXoTq5uFWSo+eGMTcra12PBJUkAceD+1AUVOx1GqBY74/7T7eB7BB+UOcOY8w==", + "requires": { + "lodash": "4.17.10", + "nan": "2.10.0", + "node-pre-gyp": "0.10.0", + "protobufjs": "5.0.3" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "2.3.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "requires": { + "minipass": "2.3.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "needle": { + "version": "2.2.1", + "bundled": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.23", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.1", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "4.4.2", + "bundled": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.0", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "gtoken": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-2.3.0.tgz", + "integrity": "sha512-Jc9/8mV630cZE9FC5tIlJCZNdUjwunvlwOtCz6IDlaiB4Sz68ki29a1+q97sWTnTYroiuF9B135rod9zrQdHLw==", + "requires": { + "axios": "0.18.0", + "google-p12-pem": "1.0.2", + "jws": "3.1.5", + "mime": "2.3.1", + "pify": "3.0.0" + }, + "dependencies": { + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==" + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hash-stream-validation": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.1.tgz", + "integrity": "sha1-7Mm5l7IYvluzEphii7gHhptz3NE=", + "requires": { + "through2": "2.0.3" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": "1.4.0" + } + }, + "http-parser-js": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "ignore": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", + "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "is": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", + "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "3.0.1" + } + }, + "is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonwebtoken": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz", + "integrity": "sha512-oge/hvlmeJCH+iIz1DwcO7vKPkNGJHhgkspk8OH3VKlw+mbi42WtD4ig1+VXRln765vxptAv+xT26Fd3cteqag==", + "requires": { + "jws": "3.1.5", + "lodash.includes": "4.3.0", + "lodash.isboolean": "3.0.3", + "lodash.isinteger": "4.0.4", + "lodash.isnumber": "3.0.3", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.once": "4.1.1", + "ms": "2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jwa": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", + "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.10", + "safe-buffer": "5.1.1" + } + }, + "jws": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", + "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==", + "requires": { + "jwa": "1.1.6", + "safe-buffer": "5.1.1" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "3.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "1.0.1" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge2": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", + "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==" + }, + "methmeth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/methmeth/-/methmeth-1.1.0.tgz", + "integrity": "sha1-6AomYY5S9cQiKGG7dIUQvRDikIk=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "modelo": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/modelo/-/modelo-4.2.3.tgz", + "integrity": "sha512-9DITV2YEMcw7XojdfvGl3gDD8J9QjZTJ7ZOUuSAkP+F3T6rDbzMJuPktxptsdHYEvZcmXrCD3LMOhdSAEq6zKA==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "node-forge": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", + "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "3.0.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "3.0.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "3.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "power-assert": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/power-assert/-/power-assert-1.6.0.tgz", + "integrity": "sha512-nDb6a+p2C7Wj8Y2zmFtLpuv+xobXz4+bzT5s7dr0nn71tLozn7nRMQqzwbefzwZN5qOm0N7Cxhw4kXP75xboKA==", + "requires": { + "define-properties": "1.1.2", + "empower": "1.3.0", + "power-assert-formatter": "1.4.1", + "universal-deep-strict-equal": "1.2.2", + "xtend": "4.0.1" + } + }, + "power-assert-context-formatter": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-context-formatter/-/power-assert-context-formatter-1.2.0.tgz", + "integrity": "sha512-HLNEW8Bin+BFCpk/zbyKwkEu9W8/zThIStxGo7weYcFkKgMuGCHUJhvJeBGXDZf0Qm2xis4pbnnciGZiX0EpSg==", + "requires": { + "core-js": "2.5.7", + "power-assert-context-traversal": "1.2.0" + } + }, + "power-assert-context-reducer-ast": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.2.0.tgz", + "integrity": "sha512-EgOxmZ/Lb7tw4EwSKX7ZnfC0P/qRZFEG28dx/690qvhmOJ6hgThYFm5TUWANDLK5NiNKlPBi5WekVGd2+5wPrw==", + "requires": { + "acorn": "5.6.2", + "acorn-es7-plugin": "1.1.7", + "core-js": "2.5.7", + "espurify": "1.8.0", + "estraverse": "4.2.0" + } + }, + "power-assert-context-traversal": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-context-traversal/-/power-assert-context-traversal-1.2.0.tgz", + "integrity": "sha512-NFoHU6g2umNajiP2l4qb0BRWD773Aw9uWdWYH9EQsVwIZnog5bd2YYLFCVvaxWpwNzWeEfZIon2xtyc63026pQ==", + "requires": { + "core-js": "2.5.7", + "estraverse": "4.2.0" + } + }, + "power-assert-formatter": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/power-assert-formatter/-/power-assert-formatter-1.4.1.tgz", + "integrity": "sha1-XcEl7VCj37HdomwZNH879Y7CiEo=", + "requires": { + "core-js": "2.5.7", + "power-assert-context-formatter": "1.2.0", + "power-assert-context-reducer-ast": "1.2.0", + "power-assert-renderer-assertion": "1.2.0", + "power-assert-renderer-comparison": "1.2.0", + "power-assert-renderer-diagram": "1.2.0", + "power-assert-renderer-file": "1.2.0" + } + }, + "power-assert-renderer-assertion": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.2.0.tgz", + "integrity": "sha512-3F7Q1ZLmV2ZCQv7aV7NJLNK9G7QsostrhOU7U0RhEQS/0vhEqrRg2jEJl1jtUL4ZyL2dXUlaaqrmPv5r9kRvIg==", + "requires": { + "power-assert-renderer-base": "1.1.1", + "power-assert-util-string-width": "1.2.0" + } + }, + "power-assert-renderer-base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/power-assert-renderer-base/-/power-assert-renderer-base-1.1.1.tgz", + "integrity": "sha1-lqZQxv0F7hvB9mtUrWFELIs/Y+s=" + }, + "power-assert-renderer-comparison": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.2.0.tgz", + "integrity": "sha512-7c3RKPDBKK4E3JqdPtYRE9cM8AyX4LC4yfTvvTYyx8zSqmT5kJnXwzR0yWQLOavACllZfwrAGQzFiXPc5sWa+g==", + "requires": { + "core-js": "2.5.7", + "diff-match-patch": "1.0.1", + "power-assert-renderer-base": "1.1.1", + "stringifier": "1.3.0", + "type-name": "2.0.2" + } + }, + "power-assert-renderer-diagram": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.2.0.tgz", + "integrity": "sha512-JZ6PC+DJPQqfU6dwSmpcoD7gNnb/5U77bU5KgNwPPa+i1Pxiz6UuDeM3EUBlhZ1HvH9tMjI60anqVyi5l2oNdg==", + "requires": { + "core-js": "2.5.7", + "power-assert-renderer-base": "1.1.1", + "power-assert-util-string-width": "1.2.0", + "stringifier": "1.3.0" + } + }, + "power-assert-renderer-file": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-renderer-file/-/power-assert-renderer-file-1.2.0.tgz", + "integrity": "sha512-/oaVrRbeOtGoyyd7e4IdLP/jIIUFJdqJtsYzP9/88R39CMnfF/S/rUc8ZQalENfUfQ/wQHu+XZYRMaCEZmEesg==", + "requires": { + "power-assert-renderer-base": "1.1.1" + } + }, + "power-assert-util-string-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/power-assert-util-string-width/-/power-assert-util-string-width-1.2.0.tgz", + "integrity": "sha512-lX90G0igAW0iyORTILZ/QjZWsa1MZ6VVY3L0K86e2eKun3S4LKPH4xZIl8fdeMYLfOjkaszbNSzf1uugLeAm2A==", + "requires": { + "eastasianwidth": "0.2.0" + } + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "protobufjs": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", + "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", + "requires": { + "ascli": "1.0.1", + "bytebuffer": "5.0.1", + "glob": "7.1.2", + "yargs": "3.32.0" + } + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "3.6.0", + "inherits": "2.0.3", + "pump": "2.0.1" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "retry-axios": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-0.3.2.tgz", + "integrity": "sha512-jp4YlI0qyDFfXiXGhkCOliBN1G7fRH03Nqy8YdShzGqbY5/9S2x/IR6C88ls2DFkbWuL3ASkP7QD3pVrNpPgwQ==" + }, + "retry-request": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.3.2.tgz", + "integrity": "sha512-WIiGp37XXDC6e7ku3LFoi7LCL/Gs9luGeeqvbPRb+Zl6OQMw4RCRfSaW+aLfE6lhz1R941UavE6Svl3Dm5xGIQ==", + "requires": { + "request": "2.87.0", + "through2": "2.0.3" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.3", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.4.0" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.2" + } + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "snakeize": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", + "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "split-array-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/split-array-stream/-/split-array-stream-1.0.3.tgz", + "integrity": "sha1-0rdajl4Ngk1S/eyLgiWDncLjXfo=", + "requires": { + "async": "2.6.1", + "is-stream-ended": "0.1.4" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "stream-events": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.4.tgz", + "integrity": "sha512-D243NJaYs/xBN2QnoiMDY7IesJFIK7gEhnvAYqJa5JvDdnh2dC4qDBwlCf0ohPpX2QRlA/4gnbnPd3rs3KxVcA==", + "requires": { + "stubs": "3.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "string-format-obj": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string-format-obj/-/string-format-obj-1.1.1.tgz", + "integrity": "sha512-Mm+sROy+pHJmx0P/0Bs1uxIX6UhGJGj6xDGQZ5zh9v/SZRmLGevp+p0VJxV7lirrkAmQ2mvva/gHKpnF/pTb+Q==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringifier": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz", + "integrity": "sha1-3vGDQvaTPbDy2/yaoCF1tEjBeVk=", + "requires": { + "core-js": "2.5.7", + "traverse": "0.6.6", + "type-name": "2.0.2" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } + }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" + }, + "tslib": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.2.tgz", + "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, + "type-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/type-name/-/type-name-2.0.2.tgz", + "integrity": "sha1-7+fUEj2KxSr/9/QMfk3sUmYAj7Q=" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "universal-deep-strict-equal": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/universal-deep-strict-equal/-/universal-deep-strict-equal-1.2.2.tgz", + "integrity": "sha1-DaSsL3PP95JMgfpN4BjKViyisKc=", + "requires": { + "array-filter": "1.0.0", + "indexof": "0.0.1", + "object-keys": "1.0.11" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "requires": { + "kind-of": "6.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "requires": { + "http-parser-js": "0.4.13", + "websocket-extensions": "0.1.3" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + } + } +} diff --git a/scripts/code.angularjs.org-firebase/functions/package.json b/scripts/code.angularjs.org-firebase/functions/package.json index 71a68bd6d34a..3e11c15cd8eb 100644 --- a/scripts/code.angularjs.org-firebase/functions/package.json +++ b/scripts/code.angularjs.org-firebase/functions/package.json @@ -3,8 +3,8 @@ "description": "Cloud Functions to serve files from gcs to code.angularjs.org", "dependencies": { "@google-cloud/storage": "^1.1.1", - "firebase-admin": "^4.2.1", - "firebase-functions": "^0.5.9" + "firebase-admin": "^5.11.0", + "firebase-functions": "^1.0.4" }, "private": true } From 998d8b4b55656f5a0c8e36fa1ddded0dafc0e338 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Thu, 14 Jun 2018 10:48:59 +0100 Subject: [PATCH 029/217] chore(code.angularjs.org): fix directory list paging --- .../functions/index.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/code.angularjs.org-firebase/functions/index.js b/scripts/code.angularjs.org-firebase/functions/index.js index 2a4666e590da..9dadc5495bdb 100644 --- a/scripts/code.angularjs.org-firebase/functions/index.js +++ b/scripts/code.angularjs.org-firebase/functions/index.js @@ -10,19 +10,17 @@ const BROWSER_CACHE_DURATION = 60 * 10; const CDN_CACHE_DURATION = 60 * 60 * 12; function sendStoredFile(request, response) { - let filePathSegments = request.path.split('/').filter((segment) => { + const requestPath = request.path || '/'; + let filePathSegments = requestPath.split('/').filter((segment) => { // Remove empty leading or trailing path parts return segment !== ''; }); - const version = filePathSegments[0]; const isDocsPath = filePathSegments[1] === 'docs'; const lastSegment = filePathSegments[filePathSegments.length - 1]; const bucket = gcs.bucket(gcsBucketId); - console.log(request.path, lastSegment); - let downloadSource; let fileName; @@ -162,7 +160,11 @@ function sendStoredFile(request, response) { const nextQuery = data[1]; const apiResponse = data[2]; - if (!files.length && (!apiResponse || !apiResponse.prefixes)) { + if ( + // we got no files or directories from previous query pages + !fileList.length && !directoryList.length && + // this query page has no file or directories + !files.length && (!apiResponse || !apiResponse.prefixes)) { return Promise.reject({ code: 404 }); @@ -197,12 +199,15 @@ function deleteOldSnapshotZip(object, context) { const bucketId = object.bucket; const filePath = object.name; const contentType = object.contentType; - const resourceState = object.resourceState; const bucket = gcs.bucket(bucketId); const snapshotFolderMatch = filePath.match(snapshotRegex); + if (!snapshotFolderMatch || contentType !== 'application/zip') { + return; + } + bucket.getFiles({ prefix: snapshotFolderMatch[0], delimiter: '/', From d7d64cc363d86e486bb9e9db13f0e1374af3738e Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 14 Jun 2018 18:05:25 +0200 Subject: [PATCH 030/217] docs(downloading.ngdoc): remove link to Google CDN overview page AngularJS is no longer listed on the CDN page, because the available versions were almost always out of date due to the need to manually update the list --- docs/content/misc/downloading.ngdoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/content/misc/downloading.ngdoc b/docs/content/misc/downloading.ngdoc index 8131946f2472..40bf84446293 100644 --- a/docs/content/misc/downloading.ngdoc +++ b/docs/content/misc/downloading.ngdoc @@ -3,8 +3,7 @@ @description # Including AngularJS scripts from the Google CDN -The quickest way to get started is to point your html ` + + + diff --git a/test/e2e/fixtures/directive-require-html/script.js b/test/e2e/fixtures/directive-require-html/script.js new file mode 100644 index 000000000000..6035f4a0bf62 --- /dev/null +++ b/test/e2e/fixtures/directive-require-html/script.js @@ -0,0 +1,28 @@ +'use strict'; + +angular. + module('test', []). + provider('$exceptionHandler', /** @this */ function() { + this.$get = [function() { + return function(error) { + window.document.querySelector('#container').textContent = error && error.message; + }; + }]; + }). + + directive('requireDirective', function() { + return { + require: '^^requireTargetDirective', + link: function(scope, element, attrs, ctrl) { + window.document.querySelector('#container').textContent = ctrl.content; + } + }; + }). + directive('requireTargetDirective', function() { + return { + controller: function() { + this.content = 'requiredContent'; + } + }; + }); + diff --git a/test/e2e/tests/directive-require-html.spec.js b/test/e2e/tests/directive-require-html.spec.js new file mode 100644 index 000000000000..be85fdf478fb --- /dev/null +++ b/test/e2e/tests/directive-require-html.spec.js @@ -0,0 +1,10 @@ +'use strict'; + +describe('require parent controller on html element', function() { + it('should not use the html element as the parent element', function() { + + loadFixture('directive-require-html'); + + expect(element(by.id('container')).getText()).toContain('Controller \'requireTargetDirective\', required by directive \'requireDirective\', can\'t be found!'); + }); +}); From c133ef8360c81c9f42713616e6ac8414c0e119c0 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Fri, 27 Jul 2018 17:26:04 +0300 Subject: [PATCH 067/217] fix($animate): avoid memory leak with `$animate.enabled(element, enabled)` When disabling/enabling animations on a specific element (via `$animate.enabled(element, enabled)`), the element is added in a map to track its state. Previously, the element was never removed from the map, causing AngularJS to hold on to the element even after it is removed from the DOM, thus preventing it from being garbage collected. This commit fixes it by removing the element from the map on `$destroy`. Fixes #16637. Closes #16649 --- src/apis.js | 12 ++++++++---- src/ngAnimate/animateQueue.js | 9 +++++++++ test/ApiSpecs.js | 28 ++++++++++++++++++++++++++++ test/ngAnimate/animateSpec.js | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/apis.js b/src/apis.js index 856b86e8b709..1767b9134f4b 100644 --- a/src/apis.js +++ b/src/apis.js @@ -45,11 +45,10 @@ function NgMapShim() { } NgMapShim.prototype = { _idx: function(key) { - if (key === this._lastKey) { - return this._lastIndex; + if (key !== this._lastKey) { + this._lastKey = key; + this._lastIndex = this._keys.indexOf(key); } - this._lastKey = key; - this._lastIndex = this._keys.indexOf(key); return this._lastIndex; }, _transformKey: function(key) { @@ -62,6 +61,11 @@ NgMapShim.prototype = { return this._values[idx]; } }, + has: function(key) { + key = this._transformKey(key); + var idx = this._idx(key); + return idx !== -1; + }, set: function(key, value) { key = this._transformKey(key); var idx = this._idx(key); diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index 9183abc11ef5..f8f9e4b9389d 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -120,6 +120,10 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate var disabledElementsLookup = new $$Map(); var animationsEnabled = null; + function removeFromDisabledElementsLookup(evt) { + disabledElementsLookup.delete(evt.target); + } + function postDigestTaskFactory() { var postDigestCalled = false; return function(fn) { @@ -303,6 +307,11 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate bool = !disabledElementsLookup.get(node); } else { // (element, bool) - Element setter + if (!disabledElementsLookup.has(node)) { + // The element is added to the map for the first time. + // Create a listener to remove it on `$destroy` (to avoid memory leak). + jqLite(element).on('$destroy', removeFromDisabledElementsLookup); + } disabledElementsLookup.set(node, !bool); } } diff --git a/test/ApiSpecs.js b/test/ApiSpecs.js index bc87caa07105..79a4d850c762 100644 --- a/test/ApiSpecs.js +++ b/test/ApiSpecs.js @@ -89,6 +89,34 @@ describe('api', function() { expect(map.get(keys[2])).toBe(values[2]); }); + it('should return if a key exists or not', function() { + var map = new NgMapShim(); + var keys = ['foo', {}]; + + expect(map.has(keys[0])).toBe(false); + expect(map.has(keys[1])).toBe(false); + + map.set(keys[0], 'bar'); + expect(map.has(keys[0])).toBe(true); + expect(map.has(keys[1])).toBe(false); + + map.set(keys[1], 'baz'); + expect(map.has(keys[0])).toBe(true); + expect(map.has(keys[1])).toBe(true); + + map.delete(keys[0]); + expect(map.has(keys[0])).toBe(false); + expect(map.has(keys[1])).toBe(true); + + map.delete(keys[1]); + expect(map.has(keys[0])).toBe(false); + expect(map.has(keys[1])).toBe(false); + + map.set(keys[1], 'qux'); + expect(map.has(keys[0])).toBe(false); + expect(map.has(keys[1])).toBe(true); + }); + it('should be able to deal with `NaN` keys', function() { var map = new NgMapShim(); diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index c8d70b5a32fe..b584d0a1c8b1 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -577,6 +577,41 @@ describe('animations', function() { $rootScope.$digest(); expect(capturedAnimation).toBeTruthy(); })); + + it('should remove the element from the `disabledElementsLookup` map on `$destroy`', + inject(function($$Map, $animate, $rootScope) { + + var setSpy = spyOn($$Map.prototype, 'set').and.callThrough(); + var deleteSpy = spyOn($$Map.prototype, 'delete').and.callThrough(); + + parent.append(element); + + $animate.enabled(element, false); + $animate.enabled(element, true); + $animate.enabled(element, false); + expect(setSpy).toHaveBeenCalledWith(element[0], jasmine.any(Boolean)); + expect(deleteSpy).not.toHaveBeenCalledWith(element[0]); + expect($animate.enabled(element)).toBe(false); + + // No clean-up on `detach` (no `$destroy` event). + element.detach(); + expect(deleteSpy).not.toHaveBeenCalledWith(element[0]); + expect($animate.enabled(element)).toBe(false); + + // Clean-up on `remove` (causes `$destroy` event). + element.remove(); + expect(deleteSpy).toHaveBeenCalledOnceWith(element[0]); + expect($animate.enabled(element)).toBe(true); + + deleteSpy.calls.reset(); + + element.triggerHandler('$destroy'); + expect(deleteSpy).not.toHaveBeenCalledWith(element[0]); + + $animate.enabled(element, true); + element.triggerHandler('$destroy'); + expect(deleteSpy).toHaveBeenCalledOnceWith(element[0]); + })); }); it('should strip all comment nodes from the animation and not issue an animation if not real elements are found', From a07191727dcc324943ffa718d77dbd93ad2858c8 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 19 Jul 2018 18:10:11 +0300 Subject: [PATCH 068/217] refactor($location): minor changes (unused deps, exported globals, unused deps, etc) --- src/ng/location.js | 1 + test/ng/locationSpec.js | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ng/location.js b/src/ng/location.js index cc064becd727..62174412b064 100644 --- a/src/ng/location.js +++ b/src/ng/location.js @@ -1,4 +1,5 @@ 'use strict'; +/* global stripHash: true */ var PATH_MATCH = /^([^?#]*)(\?([^#]*))?(#(.*))?$/, DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21}; diff --git a/test/ng/locationSpec.js b/test/ng/locationSpec.js index 58d4d013d968..c4b08be83bae 100644 --- a/test/ng/locationSpec.js +++ b/test/ng/locationSpec.js @@ -693,10 +693,10 @@ describe('$location', function() { describe('location watch', function() { - it('should not update browser if only the empty hash fragment is cleared by updating the search', function() { + it('should not update browser if only the empty hash fragment is cleared', function() { initService({supportHistory: true}); - mockUpBrowser({initialUrl:'http://new.com/a/b#', baseHref:'/base/'}); - inject(function($rootScope, $browser, $location) { + mockUpBrowser({initialUrl: 'http://new.com/a/b#', baseHref: '/base/'}); + inject(function($browser, $rootScope) { $browser.url('http://new.com/a/b'); var $browserUrl = spyOnlyCallsWithArgs($browser, 'url').and.callThrough(); $rootScope.$digest(); @@ -707,8 +707,8 @@ describe('$location', function() { it('should not replace browser url if only the empty hash fragment is cleared', function() { initService({html5Mode: true, supportHistory: true}); - mockUpBrowser({initialUrl:'http://new.com/#', baseHref: '/'}); - inject(function($browser, $location) { + mockUpBrowser({initialUrl: 'http://new.com/#', baseHref: '/'}); + inject(function($browser, $location, $window) { expect($browser.url()).toBe('http://new.com/#'); expect($location.absUrl()).toBe('http://new.com/'); }); From fdfba097da8eefc6fe433e682bf89ead93a82885 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 19 Jul 2018 18:11:56 +0300 Subject: [PATCH 069/217] refactor($location): remove unnecessary capturing group in RegExp --- src/ng/location.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/location.js b/src/ng/location.js index 62174412b064..098309520c01 100644 --- a/src/ng/location.js +++ b/src/ng/location.js @@ -102,7 +102,7 @@ function stripHash(url) { } function trimEmptyHash(url) { - return url.replace(/(#.+)|#$/, '$1'); + return url.replace(/#$/, ''); } From 8562a621975876e7e695534127ceefd6e2dbd087 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 19 Jul 2018 19:20:33 +0300 Subject: [PATCH 070/217] refactor($browser): correctly export helper used in specs The helper is used in `fakeWindow.location.hash`. ATM, no test is using the `hash` getter, so there were no errors. --- src/ng/browser.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ng/browser.js b/src/ng/browser.js index 2f1494c905bf..a47a6c09f496 100644 --- a/src/ng/browser.js +++ b/src/ng/browser.js @@ -1,5 +1,10 @@ 'use strict'; -/* global stripHash: true */ +/* global getHash: true, stripHash: false */ + +function getHash(url) { + var index = url.indexOf('#'); + return index === -1 ? '' : url.substr(index); +} /** * ! This is a private undocumented service ! @@ -62,11 +67,6 @@ function Browser(window, document, $log, $sniffer, $$taskTrackerFactory) { cacheState(); - function getHash(url) { - var index = url.indexOf('#'); - return index === -1 ? '' : url.substr(index); - } - /** * @name $browser#url * From 2907798ca58f24065711efdadb984f945c6e9df2 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 19 Jul 2018 18:11:06 +0300 Subject: [PATCH 071/217] test($location): add assertion --- test/ng/locationSpec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/ng/locationSpec.js b/test/ng/locationSpec.js index c4b08be83bae..c187930dad39 100644 --- a/test/ng/locationSpec.js +++ b/test/ng/locationSpec.js @@ -711,6 +711,7 @@ describe('$location', function() { inject(function($browser, $location, $window) { expect($browser.url()).toBe('http://new.com/#'); expect($location.absUrl()).toBe('http://new.com/'); + expect($window.location.href).toBe('http://new.com/#'); }); }); From 864c7f00c46ce86a0c808c112287d5eeac21f780 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 19 Jul 2018 19:14:57 +0300 Subject: [PATCH 072/217] fix($location): avoid unnecessary `$locationChange*` events due to empty hash Fixes #16632 Closes #16636 --- src/ng/browser.js | 19 ++++++++++++------- src/ng/location.js | 13 +++---------- src/ngMock/angular-mocks.js | 3 ++- test/ng/browserSpecs.js | 34 ++++++++++++++++++++++++++++++++++ test/ng/locationSpec.js | 2 +- 5 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/ng/browser.js b/src/ng/browser.js index a47a6c09f496..699602bc9b2d 100644 --- a/src/ng/browser.js +++ b/src/ng/browser.js @@ -6,6 +6,10 @@ function getHash(url) { return index === -1 ? '' : url.substr(index); } +function trimEmptyHash(url) { + return url.replace(/#$/, ''); +} + /** * ! This is a private undocumented service ! * @@ -72,20 +76,21 @@ function Browser(window, document, $log, $sniffer, $$taskTrackerFactory) { * * @description * GETTER: - * Without any argument, this method just returns current value of location.href. + * Without any argument, this method just returns current value of `location.href` (with a + * trailing `#` stripped of if the hash is empty). * * SETTER: * With at least one argument, this method sets url to new value. - * If html5 history api supported, pushState/replaceState is used, otherwise - * location.href/location.replace is used. - * Returns its own instance to allow chaining + * If html5 history api supported, `pushState`/`replaceState` is used, otherwise + * `location.href`/`location.replace` is used. + * Returns its own instance to allow chaining. * - * NOTE: this api is intended for use only by the $location service. Please use the + * NOTE: this api is intended for use only by the `$location` service. Please use the * {@link ng.$location $location service} to change url. * * @param {string} url New url (when used as setter) * @param {boolean=} replace Should new url replace current history record? - * @param {object=} state object to use with pushState/replaceState + * @param {object=} state State object to use with `pushState`/`replaceState` */ self.url = function(url, replace, state) { // In modern browsers `history.state` is `null` by default; treating it separately @@ -143,7 +148,7 @@ function Browser(window, document, $log, $sniffer, $$taskTrackerFactory) { // - pendingLocation is needed as browsers don't allow to read out // the new location.href if a reload happened or if there is a bug like in iOS 9 (see // https://openradar.appspot.com/22186109). - return pendingLocation || location.href; + return trimEmptyHash(pendingLocation || location.href); } }; diff --git a/src/ng/location.js b/src/ng/location.js index 098309520c01..3904c7290e77 100644 --- a/src/ng/location.js +++ b/src/ng/location.js @@ -95,17 +95,11 @@ function stripBaseUrl(base, url) { } } - function stripHash(url) { var index = url.indexOf('#'); return index === -1 ? url : url.substr(0, index); } -function trimEmptyHash(url) { - return url.replace(/#$/, ''); -} - - function stripFile(url) { return url.substr(0, stripHash(url).lastIndexOf('/') + 1); } @@ -944,7 +938,7 @@ function $LocationProvider() { // rewrite hashbang url <> html5 url - if (trimEmptyHash($location.absUrl()) !== trimEmptyHash(initialUrl)) { + if ($location.absUrl() !== initialUrl) { $browser.url(https://github.com/$location.absUrl(), true); } @@ -963,7 +957,6 @@ function $LocationProvider() { var oldUrl = $location.absUrl(); var oldState = $location.$$state; var defaultPrevented; - newUrl = trimEmptyHash(newUrl); $location.$$parse(newUrl); $location.$$state = newState; @@ -991,8 +984,8 @@ function $LocationProvider() { if (initializing || $location.$$urlUpdatedByLocation) { $location.$$urlUpdatedByLocation = false; - var oldUrl = trimEmptyHash($browser.url()); - var newUrl = trimEmptyHash($location.absUrl()); + var oldUrl = $browser.url(); + var newUrl = $location.absUrl(); var oldState = $browser.state(); var currentReplace = $location.$$replace; var urlOrStateChanged = !urlsEqual(oldUrl, newUrl) || diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 0352bac958c3..20dc9b2e8c9b 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -225,7 +225,8 @@ angular.mock.$Browser.prototype = { state = null; } if (url) { - this.$$url = url; + // The `$browser` service trims empty hashes; simulate it. + this.$$url = url.replace(/#$/, ''); // Native pushState serializes & copies the object; simulate it. this.$$state = angular.copy(state); return this; diff --git a/test/ng/browserSpecs.js b/test/ng/browserSpecs.js index acaf63e18d23..07f3683b76ad 100644 --- a/test/ng/browserSpecs.js +++ b/test/ng/browserSpecs.js @@ -404,6 +404,14 @@ describe('browser', function() { expect(browser.url()).toEqual('https://another.com/'); }); + it('should strip an empty hash fragment', function() { + fakeWindow.location.href = 'http://test.com/#'; + expect(browser.url()).toEqual('http://test.com/'); + + fakeWindow.location.href = 'https://another.com/#foo'; + expect(browser.url()).toEqual('https://another.com/#foo'); + }); + it('should use history.pushState when available', function() { sniffer.history = true; browser.url('http://new.org/'); @@ -1047,6 +1055,32 @@ describe('browser', function() { expect($location.absUrl()).toEqual('http://server/#otherHash'); }); }); + + // issue #16632 + it('should not trigger `$locationChangeStart` more than once due to trailing `#`', function() { + setup({ + history: true, + html5Mode: true + }); + + inject(function($flushPendingTasks, $location, $rootScope) { + $rootScope.$digest(); + + var spy = jasmine.createSpy('$locationChangeStart'); + $rootScope.$on('$locationChangeStart', spy); + + $rootScope.$evalAsync(function() { + fakeWindow.location.href += '#'; + }); + $rootScope.$digest(); + + expect(fakeWindow.location.href).toBe('http://server/#'); + expect($location.absUrl()).toBe('http://server/'); + + expect(spy.calls.count()).toBe(0); + expect(spy).not.toHaveBeenCalled(); + }); + }); }); describe('integration test with $rootScope', function() { diff --git a/test/ng/locationSpec.js b/test/ng/locationSpec.js index c187930dad39..e5719ae84dc0 100644 --- a/test/ng/locationSpec.js +++ b/test/ng/locationSpec.js @@ -709,7 +709,7 @@ describe('$location', function() { initService({html5Mode: true, supportHistory: true}); mockUpBrowser({initialUrl: 'http://new.com/#', baseHref: '/'}); inject(function($browser, $location, $window) { - expect($browser.url()).toBe('http://new.com/#'); + expect($browser.url()).toBe('http://new.com/'); expect($location.absUrl()).toBe('http://new.com/'); expect($window.location.href).toBe('http://new.com/#'); }); From ebeb1c94917eaf53358ae0892232e6a7bb987ce2 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Tue, 24 Jul 2018 19:45:29 +0300 Subject: [PATCH 073/217] fix(ngMock): pass failed HTTP expectations to `$exceptionHandler` This was only partially fixed in f18dd2957. Closes #16644 --- src/ngMock/angular-mocks.js | 34 +++++++++++--------- test/ngMock/angular-mocksSpec.js | 54 ++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 20dc9b2e8c9b..f6e5cce71e96 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -1511,16 +1511,25 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { } } + function createFatalError(message) { + var error = new Error(message); + // In addition to being converted to a rejection, these errors also need to be passed to + // the $exceptionHandler and be rethrown (so that the test fails). + error.$$passToExceptionHandler = true; + return error; + } + if (expectation && expectation.match(method, url)) { if (!expectation.matchData(data)) { - throw new Error('Expected ' + expectation + ' with different data\n' + - 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data); + throw createFatalError('Expected ' + expectation + ' with different data\n' + + 'EXPECTED: ' + prettyPrint(expectation.data) + '\n' + + 'GOT: ' + data); } if (!expectation.matchHeaders(headers)) { - throw new Error('Expected ' + expectation + ' with different headers\n' + - 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + - prettyPrint(headers)); + throw createFatalError('Expected ' + expectation + ' with different headers\n' + + 'EXPECTED: ' + prettyPrint(expectation.headers) + '\n' + + 'GOT: ' + prettyPrint(headers)); } expectations.shift(); @@ -1541,20 +1550,17 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { ($browser ? $browser.defer : responsesPush)(wrapResponse(definition)); } else if (definition.passThrough) { originalHttpBackend(method, url, data, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers); - } else throw new Error('No response defined !'); + } else throw createFatalError('No response defined !'); return; } } - var error = wasExpected ? - new Error('No response defined !') : - new Error('Unexpected request: ' + method + ' ' + url + '\n' + - (expectation ? 'Expected ' + expectation : 'No more request expected')); - // In addition to be being converted to a rejection, this error also needs to be passed to - // the $exceptionHandler and be rethrown (so that the test fails). - error.$$passToExceptionHandler = true; + if (wasExpected) { + throw createFatalError('No response defined !'); + } - throw error; + throw createFatalError('Unexpected request: ' + method + ' ' + url + '\n' + + (expectation ? 'Expected ' + expectation : 'No more request expected')); } /** diff --git a/test/ngMock/angular-mocksSpec.js b/test/ngMock/angular-mocksSpec.js index 3470241fb2af..5595e9675d2c 100644 --- a/test/ngMock/angular-mocksSpec.js +++ b/test/ngMock/angular-mocksSpec.js @@ -1506,6 +1506,42 @@ describe('ngMock', function() { }); + it('should throw error when expectation fails', function() { + expect(function() { + hb.expectPOST('/some', {foo: 1}).respond({}); + hb('POST', '/some', {foo: 2}, callback); + hb.flush(); + }).toThrowError(/^Expected POST \/some with different data/); + }); + + + it('should throw error when expectation about headers fails', function() { + expect(function() { + hb.expectPOST('/some', {foo: 1}, {X: 'val1'}).respond({}); + hb('POST', '/some', {foo: 1}, callback, {X: 'val2'}); + hb.flush(); + }).toThrowError(/^Expected POST \/some with different headers/); + }); + + + it('should throw error about data when expectations about both data and headers fail', function() { + expect(function() { + hb.expectPOST('/some', {foo: 1}, {X: 'val1'}).respond({}); + hb('POST', '/some', {foo: 2}, callback, {X: 'val2'}); + hb.flush(); + }).toThrowError(/^Expected POST \/some with different data/); + }); + + + it('should throw error when response is not defined for a backend definition', function() { + expect(function() { + hb.whenGET('/some'); // no .respond(...) ! + hb('GET', '/some', null, callback); + hb.flush(); + }).toThrowError('No response defined !'); + }); + + it('should match headers if specified', function() { hb.when('GET', '/url', null, {'X': 'val1'}).respond(201, 'content1'); hb.when('GET', '/url', null, {'X': 'val2'}).respond(202, 'content2'); @@ -2833,6 +2869,24 @@ describe('ngMockE2E', function() { }).toThrowError('Unexpected request: GET /some\nNo more request expected'); }); + it('should throw error when expectation fails - without error callback', function() { + expect(function() { + hb.expectPOST('/some', { foo: 1 }).respond({}); + $http.post('/some', { foo: 2 }).then(noop); + + hb.flush(); + }).toThrowError(/^Expected POST \/some with different data/); + }); + + it('should throw error when unexpected request - with error callback', function() { + expect(function() { + hb.expectPOST('/some', { foo: 1 }).respond({}); + $http.post('/some', { foo: 2 }).then(noop, noop); + + hb.flush(); + }).toThrowError(/^Expected POST \/some with different data/); + }); + describe('passThrough()', function() { it('should delegate requests to the real backend when passThrough is invoked', function() { From 88a12f8623d53579f8a21ac48d02ae1834fa7acb Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Sun, 24 Jun 2018 23:58:54 -0700 Subject: [PATCH 074/217] refactor($compile): move img[srcset] sanitizing to helper method --- src/ng/compile.js | 98 +++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 7a6366f9f29b..73684da77a09 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1631,6 +1631,57 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } + function sanitizeSrcset(value) { + if (!value) { + return value; + } + if (!isString(value)) { + throw $compileMinErr('srcset', 'Can\'t pass trusted values to `$set(\'srcset\', value)`: "{0}"', value.toString()); + } + + // Such values are a bit too complex to handle automatically inside $sce. + // Instead, we sanitize each of the URIs individually, which works, even dynamically. + + // It's not possible to work around this using `$sce.trustAsMediaUrl`. + // If you want to programmatically set explicitly trusted unsafe URLs, you should use + // `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the + // `ng-bind-html` directive. + + var result = ''; + + // first check if there are spaces because it's not the same pattern + var trimmedSrcset = trim(value); + // ( 999x ,| 999w ,| ,|, ) + var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; + var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; + + // split srcset into tuple of uri and descriptor except for the last item + var rawUris = trimmedSrcset.split(pattern); + + // for each tuples + var nbrUrisWith2parts = Math.floor(rawUris.length / 2); + for (var i = 0; i < nbrUrisWith2parts; i++) { + var innerIdx = i * 2; + // sanitize the uri + result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx])); + // add the descriptor + result += ' ' + trim(rawUris[innerIdx + 1]); + } + + // split the last item into uri and descriptor + var lastTuple = trim(rawUris[i * 2]).split(/\s/); + + // sanitize the last uri + result += $sce.getTrustedMediaUrl(trim(lastTuple[0])); + + // and add the last descriptor if any + if (lastTuple.length === 2) { + result += (' ' + trim(lastTuple[1])); + } + return result; + } + + function Attributes(element, attributesToCopy) { if (attributesToCopy) { var keys = Object.keys(attributesToCopy); @@ -1767,51 +1818,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { nodeName = nodeName_(this.$$element); // Sanitize img[srcset] values. - if (nodeName === 'img' && key === 'srcset' && value) { - if (!isString(value)) { - throw $compileMinErr('srcset', 'Can\'t pass trusted values to `$set(\'srcset\', value)`: "{0}"', value.toString()); - } - - // Such values are a bit too complex to handle automatically inside $sce. - // Instead, we sanitize each of the URIs individually, which works, even dynamically. - - // It's not possible to work around this using `$sce.trustAsMediaUrl`. - // If you want to programmatically set explicitly trusted unsafe URLs, you should use - // `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the - // `ng-bind-html` directive. - - var result = ''; - - // first check if there are spaces because it's not the same pattern - var trimmedSrcset = trim(value); - // ( 999x ,| 999w ,| ,|, ) - var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; - var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; - - // split srcset into tuple of uri and descriptor except for the last item - var rawUris = trimmedSrcset.split(pattern); - - // for each tuples - var nbrUrisWith2parts = Math.floor(rawUris.length / 2); - for (var i = 0; i < nbrUrisWith2parts; i++) { - var innerIdx = i * 2; - // sanitize the uri - result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx])); - // add the descriptor - result += ' ' + trim(rawUris[innerIdx + 1]); - } - - // split the last item into uri and descriptor - var lastTuple = trim(rawUris[i * 2]).split(/\s/); - - // sanitize the last uri - result += $sce.getTrustedMediaUrl(trim(lastTuple[0])); - - // and add the last descriptor if any - if (lastTuple.length === 2) { - result += (' ' + trim(lastTuple[1])); - } - this[key] = value = result; + if (nodeName === 'img' && key === 'srcset') { + this[key] = value = sanitizeSrcset(value, '$set(\'srcset\', value)'); } if (writeAttr !== false) { From dedb10c0b89a92f5c43b4c4d3f1054cd8179a58e Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Mon, 25 Jun 2018 21:23:50 -0700 Subject: [PATCH 075/217] feat($compile): add support for arbitrary DOM property and event bindings Properties: Previously only arbitrary DOM attribute bindings were supported via interpolation such as `my-attribute="{{expression}}"` or `ng-attr-my-attribute="{{expression}}"`, and only a set of distinct properties could be bound. `ng-prop-*` adds support for binding expressions to any DOM properties. For example `ng-prop-foo="x"` will assign the value of the expression `x` to the `foo` property, and re-assign whenever the expression `x` changes. Events: Previously only a distinct set of DOM events could be bound using directives such as `ng-click`, `ng-blur` etc. `ng-on-*` adds support for binding expressions to any DOM event. For example `ng-on-bar="barOccured($event)"` will add a listener to the "bar" event and invoke the `barOccured($event)` expression. Since HTML attributes are case-insensitive, property and event names are specified in snake_case for `ng-prop-*` and `ng-on-*`. For example, to bind property `fooBar` use `ng-prop-foo_bar`, to listen to event `fooBar` use `ng-on-foo_bar`. Fixes #16428 Fixes #16235 Closes #16614 --- docs/content/error/$compile/ctxoverride.ngdoc | 13 + docs/content/error/$compile/nodomevents.ngdoc | 10 +- src/.eslintrc.json | 6 + src/ng/compile.js | 227 ++++- src/ng/directive/ngEventDirs.js | 62 +- test/ng/compileSpec.js | 156 +++- test/ng/ngOnSpec.js | 158 ++++ test/ng/ngPropSpec.js | 836 ++++++++++++++++++ 8 files changed, 1392 insertions(+), 76 deletions(-) create mode 100644 docs/content/error/$compile/ctxoverride.ngdoc create mode 100644 test/ng/ngOnSpec.js create mode 100644 test/ng/ngPropSpec.js diff --git a/docs/content/error/$compile/ctxoverride.ngdoc b/docs/content/error/$compile/ctxoverride.ngdoc new file mode 100644 index 000000000000..839b304d47a3 --- /dev/null +++ b/docs/content/error/$compile/ctxoverride.ngdoc @@ -0,0 +1,13 @@ +@ngdoc error +@name $compile:ctxoverride +@fullName DOM Property Security Context Override +@description + +This error occurs when the security context for a property is defined via {@link ng.$compileProvider#addPropertySecurityContext addPropertySecurityContext()} multiple times under different security contexts. + +For example: + +```js +$compileProvider.addPropertySecurityContext("my-element", "src", $sce.MEDIA_URL); +$compileProvider.addPropertySecurityContext("my-element", "src", $sce.RESOURCE_URL); //throws +``` diff --git a/docs/content/error/$compile/nodomevents.ngdoc b/docs/content/error/$compile/nodomevents.ngdoc index ed1888c73956..283bd76fa669 100644 --- a/docs/content/error/$compile/nodomevents.ngdoc +++ b/docs/content/error/$compile/nodomevents.ngdoc @@ -1,12 +1,12 @@ @ngdoc error @name $compile:nodomevents -@fullName Interpolated Event Attributes +@fullName Event Attribute/Property Binding @description -This error occurs when one tries to create a binding for event handler attributes like `onclick`, `onload`, `onsubmit`, etc. +This error occurs when one tries to create a binding for event handler attributes or properties like `onclick`, `onload`, `onsubmit`, etc. -There is no practical value in binding to these attributes and doing so only exposes your application to security vulnerabilities like XSS. -For these reasons binding to event handler attributes (all attributes that start with `on` and `formaction` attribute) is not supported. +There is no practical value in binding to these attributes/properties and doing so only exposes your application to security vulnerabilities like XSS. +For these reasons binding to event handler attributes and properties (`formaction` and all starting with `on`) is not supported. An example code that would allow XSS vulnerability by evaluating user input in the window context could look like this: @@ -17,4 +17,4 @@ An example code that would allow XSS vulnerability by evaluating user input in t Since the `onclick` evaluates the value as JavaScript code in the window context, setting the `username` model to a value like `javascript:alert('PWND')` would result in script injection when the `div` is clicked. - +Please use the `ng-*` or `ng-on-*` versions instead (such as `ng-click` or `ng-on-click` rather than `onclick`). diff --git a/src/.eslintrc.json b/src/.eslintrc.json index cf2331ef6f98..dca5e4b006ef 100644 --- a/src/.eslintrc.json +++ b/src/.eslintrc.json @@ -171,9 +171,15 @@ /* ng/q.js */ "markQExceptionHandled": false, + /* sce.js */ + "SCE_CONTEXTS": false, + /* ng/directive/directives.js */ "ngDirective": false, + /* ng/directive/ngEventDirs.js */ + "createEventDirective": false, + /* ng/directive/input.js */ "VALID_CLASS": false, "INVALID_CLASS": false, diff --git a/src/ng/compile.js b/src/ng/compile.js index 73684da77a09..e259cb3efcbe 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1586,6 +1586,91 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return cssClassDirectivesEnabledConfig; }; + + /** + * The security context of DOM Properties. + * @private + */ + var PROP_CONTEXTS = createMap(); + + /** + * @ngdoc method + * @name $compileProvider#addPropertySecurityContext + * @description + * + * Defines the security context for DOM properties bound by ng-prop-*. + * + * @param {string} elementName The element name or '*' to match any element. + * @param {string} propertyName The DOM property name. + * @param {string} ctx The {@link $sce} security context in which this value is safe for use, e.g. `$sce.URL` + * @returns {object} `this` for chaining + */ + this.addPropertySecurityContext = function(elementName, propertyName, ctx) { + var key = (elementName.toLowerCase() + '|' + propertyName.toLowerCase()); + + if (key in PROP_CONTEXTS && PROP_CONTEXTS[key] !== ctx) { + throw $compileMinErr('ctxoverride', 'Property context \'{0}.{1}\' already set to \'{2}\', cannot override to \'{3}\'.', elementName, propertyName, PROP_CONTEXTS[key], ctx); + } + + PROP_CONTEXTS[key] = ctx; + return this; + }; + + /* Default property contexts. + * + * Copy of https://github.com/angular/angular/blob/6.0.6/packages/compiler/src/schema/dom_security_schema.ts#L31-L58 + * Changing: + * - SecurityContext.* => SCE_CONTEXTS/$sce.* + * - STYLE => CSS + * - various URL => MEDIA_URL + * - *|formAction, form|action URL => RESOURCE_URL (like the attribute) + */ + (function registerNativePropertyContexts() { + function registerContext(ctx, values) { + forEach(values, function(v) { PROP_CONTEXTS[v.toLowerCase()] = ctx; }); + } + + registerContext(SCE_CONTEXTS.HTML, [ + 'iframe|srcdoc', + '*|innerHTML', + '*|outerHTML' + ]); + registerContext(SCE_CONTEXTS.CSS, ['*|style']); + registerContext(SCE_CONTEXTS.URL, [ + 'area|href', 'area|ping', + 'a|href', 'a|ping', + 'blockquote|cite', + 'body|background', + 'del|cite', + 'input|src', + 'ins|cite', + 'q|cite' + ]); + registerContext(SCE_CONTEXTS.MEDIA_URL, [ + 'audio|src', + 'img|src', 'img|srcset', + 'source|src', 'source|srcset', + 'track|src', + 'video|src', 'video|poster' + ]); + registerContext(SCE_CONTEXTS.RESOURCE_URL, [ + '*|formAction', + 'applet|code', 'applet|codebase', + 'base|href', + 'embed|src', + 'frame|src', + 'form|action', + 'head|profile', + 'html|manifest', + 'iframe|src', + 'link|href', + 'media|src', + 'object|codebase', 'object|data', + 'script|src' + ]); + })(); + + this.$get = [ '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', '$controller', '$rootScope', '$sce', '$animate', @@ -1631,12 +1716,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } - function sanitizeSrcset(value) { + function sanitizeSrcset(value, invokeType) { if (!value) { return value; } if (!isString(value)) { - throw $compileMinErr('srcset', 'Can\'t pass trusted values to `$set(\'srcset\', value)`: "{0}"', value.toString()); + throw $compileMinErr('srcset', 'Can\'t pass trusted values to `{0}`: "{1}"', invokeType, value.toString()); } // Such values are a bit too complex to handle automatically inside $sce. @@ -1916,7 +2001,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { : function denormalizeTemplate(template) { return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); }, - NG_ATTR_BINDING = /^ngAttr[A-Z]/; + NG_PREFIX_BINDING = /^ng(Attr|Prop|On)([A-Z].*)$/; var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/; compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { @@ -2252,43 +2337,66 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { directiveNormalize(nodeName), 'E', maxPriority, ignoreDirective); // iterate over the attributes - for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes, + for (var attr, name, nName, value, ngPrefixMatch, nAttrs = node.attributes, j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { var attrStartName = false; var attrEndName = false; + var isNgAttr = false, isNgProp = false, isNgEvent = false; + var multiElementMatch; + attr = nAttrs[j]; name = attr.name; value = attr.value; - // support ngAttr attribute binding - ngAttrName = directiveNormalize(name); - isNgAttr = NG_ATTR_BINDING.test(ngAttrName); - if (isNgAttr) { + nName = directiveNormalize(name.toLowerCase()); + + // Support ng-attr-*, ng-prop-* and ng-on-* + if ((ngPrefixMatch = nName.match(NG_PREFIX_BINDING))) { + isNgAttr = ngPrefixMatch[1] === 'Attr'; + isNgProp = ngPrefixMatch[1] === 'Prop'; + isNgEvent = ngPrefixMatch[1] === 'On'; + + // Normalize the non-prefixed name name = name.replace(PREFIX_REGEXP, '') - .substr(8).replace(/_(.)/g, function(match, letter) { + .toLowerCase() + .substr(4 + ngPrefixMatch[1].length).replace(/_(.)/g, function(match, letter) { return letter.toUpperCase(); }); - } - var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE); - if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) { + // Support *-start / *-end multi element directives + } else if ((multiElementMatch = nName.match(MULTI_ELEMENT_DIR_RE)) && directiveIsMultiElement(multiElementMatch[1])) { attrStartName = name; attrEndName = name.substr(0, name.length - 5) + 'end'; name = name.substr(0, name.length - 6); } - nName = directiveNormalize(name.toLowerCase()); - attrsMap[nName] = name; - if (isNgAttr || !attrs.hasOwnProperty(nName)) { + if (isNgProp || isNgEvent) { + attrs[nName] = value; + attrsMap[nName] = attr.name; + + if (isNgProp) { + addPropertyDirective(node, directives, nName, name); + } else { + addEventDirective(directives, nName, name); + } + } else { + // Update nName for cases where a prefix was removed + // NOTE: the .toLowerCase() is unnecessary and causes https://github.com/angular/angular.js/issues/16624 for ng-attr-* + nName = directiveNormalize(name.toLowerCase()); + attrsMap[nName] = name; + + if (isNgAttr || !attrs.hasOwnProperty(nName)) { attrs[nName] = value; if (getBooleanAttrName(node, nName)) { attrs[nName] = true; // presence means true } + } + + addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); + addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, + attrEndName); } - addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); - addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, - attrEndName); } if (nodeName === 'input' && node.getAttribute('type') === 'hidden') { @@ -3332,42 +3440,95 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } - function getTrustedContext(node, attrNormalizedName) { + function getTrustedAttrContext(nodeName, attrNormalizedName) { if (attrNormalizedName === 'srcdoc') { return $sce.HTML; } - var tag = nodeName_(node); - // All tags with src attributes require a RESOURCE_URL value, except for - // img and various html5 media tags, which require the MEDIA_URL context. + // All nodes with src attributes require a RESOURCE_URL value, except for + // img and various html5 media nodes, which require the MEDIA_URL context. if (attrNormalizedName === 'src' || attrNormalizedName === 'ngSrc') { - if (['img', 'video', 'audio', 'source', 'track'].indexOf(tag) === -1) { + if (['img', 'video', 'audio', 'source', 'track'].indexOf(nodeName) === -1) { return $sce.RESOURCE_URL; } return $sce.MEDIA_URL; } else if (attrNormalizedName === 'xlinkHref') { // Some xlink:href are okay, most aren't - if (tag === 'image') return $sce.MEDIA_URL; - if (tag === 'a') return $sce.URL; + if (nodeName === 'image') return $sce.MEDIA_URL; + if (nodeName === 'a') return $sce.URL; return $sce.RESOURCE_URL; } else if ( // Formaction - (tag === 'form' && attrNormalizedName === 'action') || + (nodeName === 'form' && attrNormalizedName === 'action') || // If relative URLs can go where they are not expected to, then // all sorts of trust issues can arise. - (tag === 'base' && attrNormalizedName === 'href') || + (nodeName === 'base' && attrNormalizedName === 'href') || // links can be stylesheets or imports, which can run script in the current origin - (tag === 'link' && attrNormalizedName === 'href') + (nodeName === 'link' && attrNormalizedName === 'href') ) { return $sce.RESOURCE_URL; - } else if (tag === 'a' && (attrNormalizedName === 'href' || + } else if (nodeName === 'a' && (attrNormalizedName === 'href' || attrNormalizedName === 'ngHref')) { return $sce.URL; } } + function getTrustedPropContext(nodeName, propNormalizedName) { + var prop = propNormalizedName.toLowerCase(); + return PROP_CONTEXTS[nodeName + '|' + prop] || PROP_CONTEXTS['*|' + prop]; + } + + function sanitizeSrcsetPropertyValue(value) { + return sanitizeSrcset($sce.valueOf(value), 'ng-prop-srcset'); + } + function addPropertyDirective(node, directives, attrName, propName) { + if (EVENT_HANDLER_ATTR_REGEXP.test(propName)) { + throw $compileMinErr('nodomevents', 'Property bindings for HTML DOM event properties are disallowed'); + } + + var nodeName = nodeName_(node); + var trustedContext = getTrustedPropContext(nodeName, propName); + + var sanitizer = identity; + // Sanitize img[srcset] + source[srcset] values. + if (propName === 'srcset' && (nodeName === 'img' || nodeName === 'source')) { + sanitizer = sanitizeSrcsetPropertyValue; + } else if (trustedContext) { + sanitizer = $sce.getTrusted.bind($sce, trustedContext); + } + + directives.push({ + priority: 100, + compile: function ngPropCompileFn(_, attr) { + var ngPropGetter = $parse(attr[attrName]); + var ngPropWatch = $parse(attr[attrName], function sceValueOf(val) { + // Unwrap the value to compare the actual inner safe value, not the wrapper object. + return $sce.valueOf(val); + }); + + return { + pre: function ngPropPreLinkFn(scope, $element) { + function applyPropValue() { + var propValue = ngPropGetter(scope); + $element.prop(propName, sanitizer(propValue)); + } + + applyPropValue(); + scope.$watch(ngPropWatch, applyPropValue); + } + }; + } + }); + } + + function addEventDirective(directives, attrName, eventName) { + directives.push( + createEventDirective($parse, $rootScope, $exceptionHandler, attrName, eventName, /*forceAsync=*/false) + ); + } function addAttrInterpolateDirective(node, directives, value, name, isNgAttr) { - var trustedContext = getTrustedContext(node, name); + var nodeName = nodeName_(node); + var trustedContext = getTrustedAttrContext(nodeName, name); var mustHaveExpression = !isNgAttr; var allOrNothing = ALL_OR_NOTHING_ATTRS[name] || isNgAttr; @@ -3376,16 +3537,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // no interpolation found -> ignore if (!interpolateFn) return; - if (name === 'multiple' && nodeName_(node) === 'select') { + if (name === 'multiple' && nodeName === 'select') { throw $compileMinErr('selmulti', 'Binding to the \'multiple\' attribute is not supported. Element: {0}', startingTag(node)); } if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { - throw $compileMinErr('nodomevents', - 'Interpolations for HTML DOM event attributes are disallowed. Please use the ' + - 'ng- versions (such as ng-click instead of onclick) instead.'); + throw $compileMinErr('nodomevents', 'Interpolations for HTML DOM event attributes are disallowed'); } directives.push({ diff --git a/src/ng/directive/ngEventDirs.js b/src/ng/directive/ngEventDirs.js index faee43da465a..dbb7c4b1bda1 100644 --- a/src/ng/directive/ngEventDirs.js +++ b/src/ng/directive/ngEventDirs.js @@ -51,39 +51,43 @@ forEach( function(eventName) { var directiveName = directiveNormalize('ng-' + eventName); ngEventDirectives[directiveName] = ['$parse', '$rootScope', '$exceptionHandler', function($parse, $rootScope, $exceptionHandler) { - return { - restrict: 'A', - compile: function($element, attr) { - // NOTE: - // We expose the powerful `$event` object on the scope that provides access to the Window, - // etc. This is OK, because expressions are not sandboxed any more (and the expression - // sandbox was never meant to be a security feature anyway). - var fn = $parse(attr[directiveName]); - return function ngEventHandler(scope, element) { - element.on(eventName, function(event) { - var callback = function() { - fn(scope, {$event: event}); - }; - - if (!$rootScope.$$phase) { - scope.$apply(callback); - } else if (forceAsyncEvents[eventName]) { - scope.$evalAsync(callback); - } else { - try { - callback(); - } catch (error) { - $exceptionHandler(error); - } - } - }); - }; - } - }; + return createEventDirective($parse, $rootScope, $exceptionHandler, directiveName, eventName, forceAsyncEvents[eventName]); }]; } ); +function createEventDirective($parse, $rootScope, $exceptionHandler, directiveName, eventName, forceAsync) { + return { + restrict: 'A', + compile: function($element, attr) { + // NOTE: + // We expose the powerful `$event` object on the scope that provides access to the Window, + // etc. This is OK, because expressions are not sandboxed any more (and the expression + // sandbox was never meant to be a security feature anyway). + var fn = $parse(attr[directiveName]); + return function ngEventHandler(scope, element) { + element.on(eventName, function(event) { + var callback = function() { + fn(scope, {$event: event}); + }; + + if (!$rootScope.$$phase) { + scope.$apply(callback); + } else if (forceAsync) { + scope.$evalAsync(callback); + } else { + try { + callback(); + } catch (error) { + $exceptionHandler(error); + } + } + }); + }; + } + }; +} + /** * @ngdoc directive * @name ngDblclick diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index a0b8b7204439..48b5e565e088 100644 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -11480,7 +11480,7 @@ describe('$compile', function() { expect(element.attr('srcset')).toEqual('http://example.com/'); })); - it('does not work with trusted values', inject(function($rootScope, $compile, $sce) { + it('should NOT work with trusted values', inject(function($rootScope, $compile, $sce) { // A limitation of the approach used for srcset is that you cannot use `trustAsUrl`. // Use trustAsHtml and ng-bind-html to work around this. element = $compile('')($rootScope); @@ -11705,18 +11705,19 @@ describe('$compile', function() { expect(function() { $compile('')($rootScope); + $rootScope.$digest(); + expect(element.prop('disabled')).toBe(false); + $rootScope.isDisabled = true; + $rootScope.$digest(); + expect(element.prop('disabled')).toBe(true); + $rootScope.isDisabled = false; + $rootScope.$digest(); + expect(element.prop('disabled')).toBe(false); + })); + + it('should bind boolean properties (input checked)', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope); + expect(element.prop('checked')).toBe(false); + $rootScope.isChecked = true; + $rootScope.$digest(); + expect(element.prop('checked')).toBe(true); + $rootScope.isChecked = false; + $rootScope.$digest(); + expect(element.prop('checked')).toBe(false); + })); + + it('should bind string properties (title)', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope); + $rootScope.title = 123; + $rootScope.$digest(); + expect(element.prop('title')).toBe('123'); + $rootScope.title = 'foobar'; + $rootScope.$digest(); + expect(element.prop('title')).toBe('foobar'); + })); + + it('should bind variable type properties', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope); + $rootScope.asdf = 123; + $rootScope.$digest(); + expect(element.prop('asdf')).toBe(123); + $rootScope.asdf = 'foobar'; + $rootScope.$digest(); + expect(element.prop('asdf')).toBe('foobar'); + $rootScope.asdf = true; + $rootScope.$digest(); + expect(element.prop('asdf')).toBe(true); + })); + + it('should support mixed case using underscore-separated names', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope); + $rootScope.value = 123; + $rootScope.$digest(); + expect(element.prop('aBcdE')).toBe(123); + })); + + it('should work with different prefixes', inject(function($rootScope, $compile) { + $rootScope.name = 'Misko'; + var element = $compile('')($rootScope); + expect(element.prop('test')).toBe('Misko'); + expect(element.prop('test2')).toBe('Misko'); + expect(element.prop('test3')).toBe('Misko'); + })); + + it('should work with the "href" property', inject(function($rootScope, $compile) { + $rootScope.value = 'test'; + var element = $compile('')($rootScope); + $rootScope.$digest(); + expect(element.prop('href')).toMatch(/\/test\/test$/); + })); + + it('should work if they are prefixed with x- or data- and different prefixes', inject(function($rootScope, $compile) { + $rootScope.name = 'Misko'; + var element = $compile('')($rootScope); + expect(element.prop('test2')).toBe('Misko'); + expect(element.prop('test3')).toBe('Misko'); + expect(element.prop('test4')).toBe('Misko'); + expect(element.prop('test5')).toBe('Misko'); + expect(element.prop('test6')).toBe('Misko'); + })); + + it('should work independently of attributes with the same name', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope); + $rootScope.asdf = 123; + $rootScope.$digest(); + expect(element.prop('asdf')).toBe(123); + expect(element.attr('asdf')).toBe('foo'); + })); + + it('should work independently of (ng-)attributes with the same name', inject(function($rootScope, $compile) { + var element = $compile('')($rootScope); + $rootScope.asdf = 123; + $rootScope.$digest(); + expect(element.prop('asdf')).toBe(123); + expect(element.attr('asdf')).toBe('foo'); + })); + + it('should use the full ng-prop-* attribute name in $attr mappings', function() { + var attrs; + module(function($compileProvider) { + $compileProvider.directive('attrExposer', valueFn({ + link: function($scope, $element, $attrs) { + attrs = $attrs; + } + })); + }); + inject(function($compile, $rootScope) { + $compile('
')($rootScope); + + expect(attrs.title).toBeUndefined(); + expect(attrs.$attr.title).toBeUndefined(); + expect(attrs.ngPropTitle).toBe('12'); + expect(attrs.$attr.ngPropTitle).toBe('ng-prop-title'); + + expect(attrs.superTitle).toBeUndefined(); + expect(attrs.$attr.superTitle).toBeUndefined(); + expect(attrs.ngPropSuperTitle).toBe('34'); + expect(attrs.$attr.ngPropSuperTitle).toBe('ng-prop-super-title'); + + expect(attrs.myCamelTitle).toBeUndefined(); + expect(attrs.$attr.myCamelTitle).toBeUndefined(); + expect(attrs.ngPropMyCamelTitle).toBe('56'); + expect(attrs.$attr.ngPropMyCamelTitle).toBe('ng-prop-my-camel_title'); + }); + }); + + it('should not conflict with (ng-attr-)attribute mappings of the same name', function() { + var attrs; + module(function($compileProvider) { + $compileProvider.directive('attrExposer', valueFn({ + link: function($scope, $element, $attrs) { + attrs = $attrs; + } + })); + }); + inject(function($compile, $rootScope) { + $compile('
')($rootScope); + expect(attrs.title).toBe('foo'); + expect(attrs.$attr.title).toBe('title'); + expect(attrs.$attr.ngPropTitle).toBe('ng-prop-title'); + }); + }); + + it('should disallow property binding to onclick', inject(function($compile, $rootScope) { + // All event prop bindings are disallowed. + expect(function() { + $compile(''; + * this.trustedUnsafeContent = $sce.trustAsHtml(this.unsafeContent); + * } + * }); + * + * + *
+ *
+ * Binding to a property without security context: + *
+ * innerText (safeContent) + *
+ * + *
+ * "Safe" content that requires a security context will throw because the contents could potentially be dangerous ... + *
+ * innerHTML (safeContent) + *
+ * + *
+ * ... so that actually dangerous content cannot be executed: + *
+ * innerHTML (unsafeContent) + *
+ * + *
+ * ... but unsafe Content that has been trusted explicitly works - only do this if you are 100% sure! + *
+ * innerHTML (trustedUnsafeContent) + *
+ *
+ *
+ * + *
+ *
+ * + * .prop-unit { + * margin-bottom: 10px; + * } + * + * .prop-binding { + * min-height: 30px; + * border: 1px solid blue; + * } + * + * .prop-note { + * font-family: Monospace; + * } + * + * + * + * + * @example + * ### Binding to innerHTML with ngSanitize + * + * + * + * angular.module('exampleNgProp', ['ngSanitize']) + * .component('main', { + * templateUrl: 'main.html', + * controller: function($sce) { + * this.safeContent = 'Safe content'; + * this.unsafeContent = ''; + * this.trustedUnsafeContent = $sce.trustAsHtml(this.unsafeContent); + * } + * }); + * + * + *
+ *
+ * "Safe" content will be sanitized ... + *
+ * innerHTML (safeContent) + *
+ * + *
+ * ... as will dangerous content: + *
+ * innerHTML (unsafeContent) + *
+ * + *
+ * ... and content that has been trusted explicitly works the same as without ngSanitize: + *
+ * innerHTML (trustedUnsafeContent) + *
+ *
+ *
+ * + *
+ *
+ * + * .prop-unit { + * margin-bottom: 10px; + * } + * + * .prop-binding { + * min-height: 30px; + * border: 1px solid blue; + * } + * + * .prop-note { + * font-family: Monospace; + * } + * + *
+ * + */ + +/** @ngdoc directive + * @name ngOn + * @restrict A + * @element ANY + * + * @usage + * + * ```html + * + * + * ``` + * + * or with uppercase letters in property (e.g. "eventName"): + * + * + * ```html + * + * + * ``` + * + * @description + * The `ngOn` directive adds an event listener to a DOM element via + * {@link angular.element angular.element().on()}, and evaluates an expression when the event is + * fired. + * `ngOn` allows adding listeners for arbitrary events by including + * the event name in the attribute, e.g. `ng-on-drop="onDrop()"` executes the 'onDrop()' expression + * when the `drop` event is fired. + * + * AngularJS provides specific directives for many events, such as {@link ngClick}, so in most + * cases it is not necessary to use `ngOn`. However, AngularJS does not support all events + * (e.g. the `drop` event in the example above), and new events might be introduced in later DOM + * standards. + * + * Another use-case for `ngOn` is listening to + * [custom events](https://developer.mozilla.org/docs/Web/Guide/Events/Creating_and_triggering_events) + * fired by + * [custom elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements). + * + * ## Binding to camelCase properties + * + * Since HTML attributes are case-insensitive, camelCase properties like `myEvent` must be escaped. + * AngularJS uses the underscore (_) in front of a character to indicate that it is uppercase, so + * `myEvent` must be written as `ng-on-my_event="expression"`. + * + * @example + * ### Bind to built-in DOM events + * + * + * + * angular.module('exampleNgOn', []) + * .component('main', { + * templateUrl: 'main.html', + * controller: function() { + * this.clickCount = 0; + * this.mouseoverCount = 0; + * + * this.loadingState = 0; + * } + * }); + * + * + *
+ * This is equivalent to `ngClick` and `ngMouseover`:
+ *
+ * clickCount: {{$ctrl.clickCount}}
+ * mouseover: {{$ctrl.mouseoverCount}} + * + *
+ * + * For the `error` and `load` event on images no built-in AngularJS directives exist:
+ *
+ *
+ * Image is loading + * Image load error + * Image loaded successfully + *
+ *
+ *
+ * + *
+ *
+ *
+ * + * + * @example + * ### Bind to custom DOM events + * + * + * + * angular.module('exampleNgOn', []) + * .component('main', { + * templateUrl: 'main.html', + * controller: function() { + * this.eventLog = ''; + * + * this.listener = function($event) { + * this.eventLog = 'Event with type "' + $event.type + '" fired at ' + $event.detail; + * }; + * } + * }) + * .component('childComponent', { + * templateUrl: 'child.html', + * controller: function($element) { + * this.fireEvent = function() { + * var event = new CustomEvent('customtype', { detail: new Date()}); + * + * $element[0].dispatchEvent(event); + * }; + * } + * }); + * + * + *
+ * Event log: {{$ctrl.eventLog}} + *
+ * + + * + * + *
+ *
+ *
+ */ + var $compileMinErr = minErr('$compile'); function UNINITIALIZED_VALUE() {} diff --git a/src/ng/sce.js b/src/ng/sce.js index a5f618ef8fe4..6bc99f23761f 100644 --- a/src/ng/sce.js +++ b/src/ng/sce.js @@ -623,7 +623,7 @@ function $SceDelegateProvider() { * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. | * | `$sce.MEDIA_URL` | For URLs that are safe to render as media. Is automatically converted from string by sanitizing when needed. | * | `$sce.URL` | For URLs that are safe to follow as links. Is automatically converted from string by sanitizing when needed. Note that `$sce.URL` makes a stronger statement about the URL than `$sce.MEDIA_URL` does and therefore contexts requiring values trusted for `$sce.URL` can be used anywhere that values trusted for `$sce.MEDIA_URL` are required.| - * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)

Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` or `$sce.MEDIA_URL` do and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` or `$sce.MEDIA_URL` are required. | + * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)

Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` or `$sce.MEDIA_URL` do and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` or `$sce.MEDIA_URL` are required.

The {@link $sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider#resourceUrlWhitelist()} and {@link $sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider#resourceUrlBlacklist()} can be used to restrict trusted origins for `RESOURCE_URL` | * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. | * * From 16b0692885eec3d1789f800e2a6a61b79b7dc122 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 3 Aug 2018 13:27:42 +0200 Subject: [PATCH 077/217] docs(CHANGELOG.md): add changes for 1.7.3 --- CHANGELOG.md | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23df2398dc30..b906429d8f2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,92 @@ + +# 1.7.3 eventful-proposal (2018-08-03) + +## Bug Fixes +- **$location:** + - fix infinite recursion/digest on URLs with special characters + ([e68697](https://github.com/angular/angular.js/commit/e68697e2e30695f509e6c2c1e43c2c02b7af41f0), + [#16592](https://github.com/angular/angular.js/issues/16592), + [#16611](https://github.com/angular/angular.js/issues/16611)) + - avoid unnecessary `$locationChange*` events due to empty hash + ([1144b1](https://github.com/angular/angular.js/commit/1144b1eccb886ea0e4a80bcb07d38a305c3263b4), + [#16632](https://github.com/angular/angular.js/issues/16632), + [#16636](https://github.com/angular/angular.js/issues/16636)) +- **ngMock.$httpBackend:** + - pass failed HTTP expectations to `$exceptionHandler` + ([4adbf8](https://github.com/angular/angular.js/commit/4adbf82a84a564a8d3f0982c17a64c6163200bcd), + [#16644](https://github.com/angular/angular.js/issues/16644)) + - correctly ignore query params in {expect,when}Route + ([be417f](https://github.com/angular/angular.js/commit/be417f28549e184fbc3c7f74251ac21fca965ae8), + [#14173](https://github.com/angular/angular.js/issues/14173), + [#16589](https://github.com/angular/angular.js/issues/16589)) +- **Angular:** add workaround for Safari / Webdriver problem + ([0a1db2](https://github.com/angular/angular.js/commit/0a1db2ad5f8da6902b1711a738ae4177ce9685fa), + [#16645](https://github.com/angular/angular.js/issues/16645)) +- **$animate:** avoid memory leak with `$animate.enabled(element, enabled)` + ([4bd424](https://github.com/angular/angular.js/commit/4bd424690612885ca06028e9b27de585edc3d3c3), + [#16649](https://github.com/angular/angular.js/issues/16649)) +- **$compile:** + - use correct parent element when requiring on html element + ([05ac70](https://github.com/angular/angular.js/commit/05ac702bc7edae5f89c363ea661774910735ea8b), + [#16535](https://github.com/angular/angular.js/issues/16535), + [#16647](https://github.com/angular/angular.js/issues/16647)) + - work around Firefox `DocumentFragment` bug + ([10973c](https://github.com/angular/angular.js/commit/10973c3366676ac8e5b2728b1e006cdef4ea197e), + [#16607](https://github.com/angular/angular.js/issues/16607), + [#16615](https://github.com/angular/angular.js/issues/16615)) +- **ngEventDirs:** + - pass error in handler to $exceptionHandler when event was triggered in a digest + ([688211](https://github.com/angular/angular.js/commit/6882113bc194fb10081db9bab3dd7d69dd59f311)) + - don't wrap the event handler in $apply if already in $digest + ([535ee3](https://github.com/angular/angular.js/commit/535ee32a0b4881c9fd526fb5e0ffc10919ba1800), + [#14673](https://github.com/angular/angular.js/issues/14673), + [#14674](https://github.com/angular/angular.js/issues/14674)) +- **angular.element:** do not break on `cleanData()` if `_data()` returns undefined + ([7cf4a2](https://github.com/angular/angular.js/commit/7cf4a2933cb017e45b0c97b0a836cbbd905ee31a), + [#16641](https://github.com/angular/angular.js/issues/16641), + [#16642](https://github.com/angular/angular.js/issues/16642)) +- **ngAria:** do not scroll when pressing spacebar on custom buttons + ([3a517c](https://github.com/angular/angular.js/commit/3a517c25f677294a7a9eca1660654a3edcc9e103), + [#14665](https://github.com/angular/angular.js/issues/14665), + [#16604](https://github.com/angular/angular.js/issues/16604)) + + +## New Features +- **$compile:** add support for arbitrary DOM property and event bindings + ([a5914c](https://github.com/angular/angular.js/commit/a5914c94a8fa5b1eceeab9e4e6849cbf467bc26d), + [#16428](https://github.com/angular/angular.js/issues/16428), + [#16235](https://github.com/angular/angular.js/issues/16235), + [#16614](https://github.com/angular/angular.js/issues/16614)) +- **ngMock:** add `$flushPendingTasks()` and `$verifyNoPendingTasks()` + ([6f7674](https://github.com/angular/angular.js/commit/6f7674a7d063d434205f75f5b861f167e8125999), + [#14336](https://github.com/angular/angular.js/issues/14336)) +- **core:** implement more granular pending task tracking + ([17b139](https://github.com/angular/angular.js/commit/17b139f107e5471a9351af638093a8e13a69e42a)) +- **$animate:** add option data to event callbacks + ([fc64e6](https://github.com/angular/angular.js/commit/fc64e6807642512b567deb52b497bd2bff570a1f), + [#12697](https://github.com/angular/angular.js/issues/12697), + [#13059](https://github.com/angular/angular.js/issues/13059)) +- **form.FormController:** add $getControls() + ([c9d1e6](https://github.com/angular/angular.js/commit/c9d1e690aa597283373b78e646676fa8f1ba1b4d), + [#16601](https://github.com/angular/angular.js/issues/16601), + [#14749](https://github.com/angular/angular.js/issues/14749), + [#14517](https://github.com/angular/angular.js/issues/14517), + [#13202](https://github.com/angular/angular.js/issues/13202)) +- **ngModelOptions:** add `timeStripZeroSeconds` and `timeSecondsFormat` + ([b68221](https://github.com/angular/angular.js/commit/b682213d72d65c996a6a31ea57b79d4c4f4e3c98), + [#10721](https://github.com/angular/angular.js/issues/10721), + [#16510](https://github.com/angular/angular.js/issues/16510), + [#16584](https://github.com/angular/angular.js/issues/16584)) + + +## Performance Improvements +- **ngAnimate:** avoid repeated calls to addClass/removeClass when animation has no duration + ([093635](https://github.com/angular/angular.js/commit/0936353e9a03f072bc3c4056888fd154a96530ef), + [#14165](https://github.com/angular/angular.js/issues/14165), + [#14166](https://github.com/angular/angular.js/issues/14166), + [#16613](https://github.com/angular/angular.js/issues/16613)) + + # 1.7.2 extreme-compatiplication (2018-06-12) From 848c9b51f12b40306fcc2fe1dc7194c6ce5e7c90 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 3 Aug 2018 18:16:19 +0200 Subject: [PATCH 078/217] docs(select): remove solved known issue The issue in question has been resolved some time in 2017. The bug report is still open, but the behavior has changed: https://bugzilla.mozilla.org/show_bug.cgi?id=126379 Let's hope they have tests for this! --- src/ng/directive/select.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/ng/directive/select.js b/src/ng/directive/select.js index ba8d82874b21..7904ff9bf1a8 100644 --- a/src/ng/directive/select.js +++ b/src/ng/directive/select.js @@ -556,18 +556,6 @@ var SelectController = * {@link guide/interpolation#-ngattr-for-binding-to-arbitrary-attributes ngAttr} directive. * * - * @knownIssue - * - * In Firefox, the select model is only updated when the select element is blurred. For example, - * when switching between options with the keyboard, the select model is only set to the - * currently selected option when the select is blurred, e.g via tab key or clicking the mouse - * outside the select. - * - * This is due to an ambiguity in the select element specification. See the - * [issue on the Firefox bug tracker](https://bugzilla.mozilla.org/show_bug.cgi?id=126379) - * for more information, and this - * [Github comment for a workaround](https://github.com/angular/angular.js/issues/9134#issuecomment-130800488) - * * @example * ### Simple `select` elements with static options * From 79ca0f1e914d9176167e55062900414fe5cc4557 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 6 Aug 2018 12:47:43 +0200 Subject: [PATCH 079/217] fix(select): allow to select first option with value `undefined` Previously, the value observer incorrectly assumed a value had changed even if it was the first time it was set, which caused it to remove an option with the value `undefined` from the internal option map. Fixes #16653 Closes #16656 --- src/ng/directive/select.js | 2 +- test/ng/directive/selectSpec.js | 53 +++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/ng/directive/select.js b/src/ng/directive/select.js index 7904ff9bf1a8..fd684046df81 100644 --- a/src/ng/directive/select.js +++ b/src/ng/directive/select.js @@ -383,7 +383,7 @@ var SelectController = if (optionAttrs.$attr.ngValue) { // The value attribute is set by ngValue - var oldVal, hashedVal = NaN; + var oldVal, hashedVal; optionAttrs.$observe('value', function valueAttributeObserveAction(newVal) { var removal; diff --git a/test/ng/directive/selectSpec.js b/test/ng/directive/selectSpec.js index 05122fcced25..53b5e4c5023c 100644 --- a/test/ng/directive/selectSpec.js +++ b/test/ng/directive/selectSpec.js @@ -1530,11 +1530,14 @@ describe('select', function() { ['a'], NaN ], function(prop) { + scope.option1 = prop; + scope.option2 = 'red'; scope.selected = 'NOMATCH'; compile(''); scope.$digest(); @@ -1571,10 +1574,12 @@ describe('select', function() { NaN ], function(prop) { scope.option = prop; + scope.option2 = 'red'; scope.selected = 'NOMATCH'; compile(''); var selectController = element.controller('select'); @@ -1604,7 +1609,7 @@ describe('select', function() { expect(scope.selected).toBe(null); expect(element[0].selectedIndex).toBe(0); - expect(element.find('option').length).toBe(2); + expect(element.find('option').length).toBe(3); expect(element.find('option').eq(0).prop('selected')).toBe(true); expect(element.find('option').eq(0).val()).toBe(unknownValue(prop)); expect(element.find('option').eq(1).prop('selected')).toBe(false); @@ -1617,6 +1622,7 @@ describe('select', function() { expect(element.find('option').eq(0).val()).toBe('string:UPDATEDVALUE'); }); + it('should interact with custom attribute $observe and $set calls', function() { var log = [], optionAttr; @@ -1638,26 +1644,43 @@ describe('select', function() { optionAttr.$set('value', 'update'); expect(log[1]).toBe('update'); expect(element.find('option').eq(1).val()).toBe('string:update'); + }); + + it('should ignore the option text / value attribute if the ngValue attribute exists', function() { + scope.ngvalue = 'abc'; + scope.value = 'def'; + scope.textvalue = 'ghi'; + + compile(''); + expect(element).toEqualSelect([unknownValue(undefined)], 'string:abc'); }); - it('should ignore the option text / value attribute if the ngValue attribute exists', function() { - scope.ngvalue = 'abc'; - scope.value = 'def'; - scope.textvalue = 'ghi'; - compile(''); - expect(element).toEqualSelect([unknownValue(undefined)], 'string:abc'); - }); + it('should ignore option text with multiple interpolations if the ngValue attribute exists', function() { + scope.ngvalue = 'abc'; + scope.textvalue = 'def'; + scope.textvalue2 = 'ghi'; - it('should ignore option text with multiple interpolations if the ngValue attribute exists', function() { - scope.ngvalue = 'abc'; - scope.textvalue = 'def'; - scope.textvalue2 = 'ghi'; + compile(''); + expect(element).toEqualSelect([unknownValue(undefined)], 'string:abc'); + }); + + + it('should select the first option if it is `undefined`', function() { + scope.selected = undefined; + + scope.option1 = undefined; + scope.option2 = 'red'; + + compile(''); + + expect(element).toEqualSelect(['undefined:undefined'], 'string:red'); + }); - compile(''); - expect(element).toEqualSelect([unknownValue(undefined)], 'string:abc'); - }); describe('and select[multiple]', function() { From fd4a284c858059cad72fc90a579d1ab80f49bfce Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Mon, 6 Aug 2018 15:51:03 +0300 Subject: [PATCH 080/217] docs(guide/migration): fix typos, format inline code --- docs/content/guide/migration.ngdoc | 236 +++++++++++++++-------------- 1 file changed, 126 insertions(+), 110 deletions(-) diff --git a/docs/content/guide/migration.ngdoc b/docs/content/guide/migration.ngdoc index e05027a6e558..74de3a418ffa 100644 --- a/docs/content/guide/migration.ngdoc +++ b/docs/content/guide/migration.ngdoc @@ -25,7 +25,7 @@ Additionally, we have removed some long-deprecated modules and APIs. The most notable changes are: -- $resource has now support for request and requestError interceptors +- `$resource` has now support for request and requestError interceptors - Several deprecated features have been removed: - the `$controllerProvider.allowGlobals()` flag @@ -36,8 +36,8 @@ The most notable changes are: - the complete `ngScenario` module Please note that feature development (without breaking changes) has happened in parallel on the -1.6.x branch, so 1.7 doesn't contain many new features, but you may still benefit from those features -that were added (with possible BCs), bugfixes, and a few smaller performance improvements. +1.6.x branch, so 1.7 doesn't contain many new features, but you may still benefit from those +features that were added (with possible BCs), bugfixes, and a few smaller performance improvements.
@@ -48,11 +48,11 @@ Below is the full list of breaking changes: ### Core: _Directives_ - #### **form** + **Due to [223de5](https://github.com/angular/angular.js/commit/223de59e988dc0cc8b4ec3a045b7c0735eba1c77)**, -forms will now set $submitted on child forms when they are submitted. +forms will now set `$submitted` on child forms when they are submitted. For example: ```
@@ -63,15 +63,16 @@ For example:
``` -Submitting this form will set $submitted on "parentform" and "childform". +Submitting this form will set `$submitted` on "parentform" and "childform". Previously, it was only set on "parentform". -This change was introduced because mixing form and ngForm does not create +This change was introduced because mixing `form` and `ngForm` does not create logically separate forms, but rather something like input groups. Therefore, child forms should inherit the submission state from their parent form. #### **input[radio]** and **input[checkbox]** + **Due to [656c8f](https://github.com/angular/angular.js/commit/656c8fa8f23b1277cc5c214c4d0237f3393afa1e)**, `input[radio]` and `input[checkbox]` now listen to the "change" event instead of the "click" event. Most apps should not be affected, as "change" is automatically fired by browsers after "click" @@ -84,10 +85,10 @@ Two scenarios might need migration: Before this change, custom click event listeners on radio / checkbox would be called after the input element and `ngModel` had been updated, unless they were specifically registered before the built-in click handlers. -After this change, they are called before the input is updated, and can call event.preventDefault() -to prevent the input from updating. +After this change, they are called before the input is updated, and can call +`event.preventDefault()` to prevent the input from updating. -If an app uses a click event listener that expects ngModel to be updated when it is called, it now +If an app uses a click event listener that expects `ngModel` to be updated when it is called, it now needs to register a change event listener instead. - Triggering click events: @@ -95,50 +96,52 @@ needs to register a change event listener instead. Conventional trigger functions: The change event might not be fired when the input element is not attached to the document. This -can happen in **tests** that compile input elements and -trigger click events on them. Depending on the browser (Chrome and Safari) and the trigger method, -the change event will not be fired when the input isn't attached to the document. +can happen in **tests** that compile input elements and trigger click events on them. Depending on +the browser (Chrome and Safari) and the trigger method, the change event will not be fired when the +input isn't attached to the document. Before: ```js - it('should update the model', inject(function($compile, $rootScope) { - var inputElm = $compile('')($rootScope); +it('should update the model', inject(function($compile, $rootScope) { + var inputElm = $compile('')($rootScope); - inputElm[0].click(); // Or different trigger mechanisms, such as jQuery.trigger() - expect($rootScope.checkbox).toBe(true); - }); + inputElm[0].click(); // Or different trigger mechanisms, such as jQuery.trigger() + expect($rootScope.checkbox).toBe(true); +}); ``` -With this patch, `$rootScope.checkbox` might not be true, because the click event -hasn't triggered the change event. To make the test, work append the inputElm to the app's -`$rootElement`, and the `$rootElement` to the `$document`. +With this patch, `$rootScope.checkbox` might not be true, because the click event hasn't triggered +the change event. To make the test, work append `inputElm` to the app's `$rootElement`, and the +`$rootElement` to the `$document`. After: ```js - it('should update the model', inject(function($compile, $rootScope, $rootElement, $document) { - var inputElm = $compile('')($rootScope); +it('should update the model', inject(function($compile, $rootScope, $rootElement, $document) { + var inputElm = $compile('')($rootScope); - $rootElement.append(inputElm); - $document.append($rootElement); + $rootElement.append(inputElm); + $document.append($rootElement); - inputElm[0].click(); // Or different trigger mechanisms, such as jQuery.trigger() - expect($rootScope.checkbox).toBe(true); - }); + inputElm[0].click(); // Or different trigger mechanisms, such as jQuery.trigger() + expect($rootScope.checkbox).toBe(true); +}); ``` #### **input\[number\]** + **Due to [aa3f95](https://github.com/angular/angular.js/commit/aa3f951330ec7b10b43ea884d9b5754e296770ec)**, `input[type=number]` with `ngModel` now validates the input for the `max`/`min` restriction against the `ngModelController.$viewValue` instead of against the `ngModelController.$modelValue`. This affects apps that use `$parsers` or `$formatters` to transform the input / model value. -If you rely on the $modelValue validation, you can overwrite the `min`/`max` validator from a custom directive, as seen in the following example directive definition object: +If you rely on the `$modelValue` validation, you can overwrite the `min`/`max` validator from a +custom directive, as seen in the following example directive definition object: -``` +```js { restrict: 'A', require: 'ngModel', @@ -154,11 +157,11 @@ If you rely on the $modelValue validation, you can overwrite the `min`/`max` val #### **ngModel, input** + **Due to [74b04c](https://github.com/angular/angular.js/commit/74b04c9403af4fc7df5b6420f22c9f45a3e84140)**, *Custom* parsers that fail to parse on input types "email", "url", "number", "date", "month", "time", "datetime-local", "week", no longer set `ngModelController.$error[inputType]`, and -the `ng-invalid-[inputType]` class. Also, custom parsers on input type "range" do no -longer set `ngModelController.$error.number` and the `ng-invalid-number` class. +the `ng-invalid-[inputType]` class. Also, custom parsers on input type "range" no longer set `ngModelController.$error.number` and the `ng-invalid-number` class. Instead, any custom parsers on these inputs set `ngModelController.$error.parse` and `ng-invalid-parse`. This change was made to make distinguishing errors from built-in parsers @@ -166,6 +169,7 @@ and custom parsers easier. #### **ngModelOptions** + **Due to [55ba44](https://github.com/angular/angular.js/commit/55ba44913e02650b56410aa9ab5eeea5d3492b68)**, the 'default' key in 'debounce' now only debounces the default event, i.e. the event that is added as an update trigger by the different input directives automatically. @@ -179,24 +183,24 @@ See the following example: Pre-1.7: 'mouseup' is also debounced by 500 milliseconds because 'default' is applied: -``` +```html ng-model-options="{ updateOn: 'default blur mouseup', debounce: { 'default': 500, 'blur': 0 } -} +}" ``` 1.7: The pre-1.7 behavior can be re-created by setting '*' as a catch-all debounce value: -``` +```html ng-model-options="{ updateOn: 'default blur mouseup', debounce: { '*': 500, 'blur': 0 } -} +}" ``` In contrast, when only 'default' is used, 'blur' and 'mouseup' are not debounced: -``` +```html ng-model-options="{ updateOn: 'default blur mouseup', debounce: { 'default': 500 } @@ -207,14 +211,15 @@ ng-model-options="{ #### **ngStyle** **Due to [15bbd3](https://github.com/angular/angular.js/commit/15bbd3e18cd89b91f7206a06c73d40e54a8a48a0)**, -previously the use of deep watch by ng-style would trigger styles to be -re-applied when nested state changed. Now only changes to direct -properties of the watched object will trigger changes. +the use of deep-watching in `ngStyle` has changed. Previously, `ngStyle` would trigger styles to be +re-applied whenever nested state changed. Now, only changes to direct properties of the watched +object will trigger changes. ### Core: _Services_ + #### **$compile** **Due to [38f8c9](https://github.com/angular/angular.js/commit/38f8c97af74649ce224b6dd45f433cc665acfbfb)**, @@ -238,16 +243,16 @@ migrating to AngularJS 1.7.0 shouldn't require any further action. 3. If you specified `$compileProvider.preAssignBindingsEnabled(true)` you need to first migrate your code so that the flag can be flipped to `false`. The instructions on how to do that are available in the "Migrating from 1.5 to 1.6" -guide: -https://docs.angularjs.org/guide/migration#migrating-from-1-5-to-1-6 +guide: https://docs.angularjs.org/guide/migration#migrating-from-1-5-to-1-6 Afterwards, remove the `$compileProvider.preAssignBindingsEnabled(true)` statement.
+ **Due to [6ccbfa](https://github.com/angular/angular.js/commit/6ccbfa65d60a3dc396d0cf6da21b993ad74653fd)**, the `xlink:href` security context for SVG's `a` and `image` elements has been lowered. -In the unlikely case that an app relied on RESOURCE_URL whitelisting for the +In the unlikely case that an app relied on `RESOURCE_URL` whitelisting for the purpose of binding to the `xlink:href` property of SVG's `` or `` elements and if the values do not pass the regular URL sanitization, they will break. @@ -258,37 +263,39 @@ To fix this you need to ensure that the values used for binding to the affected `imgSrcSanitizationWhitelist` (for `` elements).
+ **Due to [fd4f01](https://github.com/angular/angular.js/commit/fd4f0111188b62773b99ab6eab38b4d2b5d8d727)**, -deepWatch is no longer used in in literal one-way bindings. +deep-watching is no longer used in literal one-way bindings. -Previously when a literal value was passed into a directive/component via +Previously, when a literal value was passed into a directive/component via one-way binding it would be watched with a deep watcher. For example, for ``, a new instance of the array -would be passed into the directive/component (and trigger $onChanges) not +would be passed into the directive/component (and trigger `$onChanges`) not only if `a` changed but also if any sub property of `a` changed such as `a.b` or `a.b.c.d.e` etc. This also means a new but equal value for `a` would NOT trigger such a change. -Now literal values use an input-based watch similar to other directive/component +Now, literal values use an input-based watch similar to other directive/component one-way bindings. In this context inputs are the non-constant parts of the -literal. In the example above the input would be `a`. Changes are only -triggered when the inputs to the literal change. +literal. In the example above, the input would be `a`. Changes are only +triggered, when the inputs to the literal change.
+ **Due to [1cf728](https://github.com/angular/angular.js/commit/1cf728e209a9e0016068fac2769827e8f747760e)**, -`base[href]` was added to the list of RESOURCE_URL context attributes. +`base[href]` was added to the list of `RESOURCE_URL` context attributes. Previously, `` would not require `baseUrl` to -be trusted as a RESOURCE_URL. Now, `baseUrl` will be sent to `$sce`'s -RESOURCE_URL checks. By default, it will break unless `baseUrl` is of the same +be trusted as a `RESOURCE_URL`. Now, `baseUrl` will be sent to `$sce`'s +`RESOURCE_URL` checks. By default, it will break unless `baseUrl` is of the same origin as the application document. Refer to the [`$sce` API docs](https://code.angularjs.org/snapshot/docs/api/ng/service/$sce) -for more info on how to trust a value in a RESOURCE_URL context. +for more info on how to trust a value in a `RESOURCE_URL` context. Also, concatenation in trusted contexts is not allowed, which means that the following won't work: ``. @@ -315,10 +322,10 @@ except for the simplest of cases): **Due to ([c2b8fa](https://github.com/angular/angular.js/commit/c2b8fab0a480204374d561d6b9b3d47347ac5570))**, the arguments of `$watchGroup` callbacks have changed. -Previously when using `$watchGroup` the entries in `newValues` and +Previously, when using `$watchGroup`, the entries in `newValues` and `oldValues` represented the *most recent change of each entry*. -Now the entries in `oldValues` will always equal the `newValues` of the previous +Now, the entries in `oldValues` will always equal the `newValues` of the previous call of the listener. This means comparing the entries in `newValues` and `oldValues` can be used to determine which individual expressions changed. @@ -343,7 +350,7 @@ Now the `oldValue` will always equal the previous `newValue`: Note the last call now shows `a === 2` in the `oldValues` array. -This also makes the `oldValue` of one-time watchers more clear. Previously +This also makes the `oldValue` of one-time watchers more clear. Previously, the `oldValue` of a one-time watcher would remain `undefined` forever. For example `$scope.$watchGroup(['a', '::b'], fn)` would previously: @@ -367,7 +374,7 @@ Where now the `oldValue` will always equal the previous `newValue`: #### **$interval** **Due to [a8bef9](https://github.com/angular/angular.js/commit/a8bef95127775d83d80daa4617c33227c4b443d4)**, -`$interval.cancel() will throw an error if called with a promise that was not generated by +`$interval.cancel()` will throw an error if called with a promise that was not generated by `$interval()`. Previously, it would silently do nothing. Before: @@ -393,7 +400,7 @@ $interval.cancel(promise); // Interval canceled. #### **$timeout** **Due to [336525](https://github.com/angular/angular.js/commit/3365256502344970f86355d3ace1cb4251ae9828)**, -`$timeout.cancel() will throw an error if called with a promise that was not generated by +`$timeout.cancel()` will throw an error if called with a promise that was not generated by `$timeout()`. Previously, it would silently do nothing. Before: @@ -417,10 +424,11 @@ $timeout.cancel(promise); // Timeout canceled. #### **$cookies** + **Due to [73c646](https://github.com/angular/angular.js/commit/73c6467f1468353215dc689c019ed83aa4993c77)**, -the `$cookieStore`service has been removed. Migrate to the $cookies service. Note that -for object values you need to use the `putObject` & `getObject` methods as -`get`/`put` will not correctly save/retrieve them. +the `$cookieStore`service has been removed. Migrate to the `$cookies` service. Note that +for object values you need to use the `putObject` & `getObject` methods, as +`get`/`put` will not correctly save/retrieve the object values. Before: ```js @@ -433,29 +441,31 @@ $cookieStore.remove('name'); #### **$templateRequest** **Due to [c617d6](https://github.com/angular/angular.js/commit/c617d6dceee5b000bfceda44ced22fc16b48b18b)**, -give tpload error namespace has changed. Previously the `tpload` error was namespaced to `$compile`. -If you have code that matches errors of the form `[$compile:tpload]` it will no -longer run. You should change the code to match -`[$templateRequest:tpload]`. +the `tpload` error namespace has changed. Previously, the `tpload` error was namespaced to +`$compile`. If you have code that matches errors of the form `[$compile:tpload]` it will no longer +run. You should change the code to match `[$templateRequest:tpload]`.
+ **Due to ([fb0099](https://github.com/angular/angular.js/commit/fb00991460cf69ae8bc7f1f826363d09c73c0d5e)**, -the service now returns the result of `$templateCache.put()` when making a server request to the -template. Previously it would return the content of the response directly. -This now means if you are decorating `$templateCache.put()` to manipulate the template, you will -now get this manipulated result also on the first `$templateRequest` rather than only on subsequent -calls (when the template is retrived from the cache). -In practice this should not affect any apps, as it is unlikely that they rely on the template being +`$templateRequest()` now returns the result of `$templateCache.put()` when making a server request +for a template. Previously, it would return the content of the response directly. + +This means that if you are decorating `$templateCache.put()` to manipulate the template, you will +now get this manipulated result also on the first `$templateRequest()` call rather than only on +subsequent calls (when the template is retrieved from the cache). + +In practice, this should not affect any apps, as it is unlikely that they rely on the template being different in the first and subsequent calls. + #### **$animate** + **Due to [16b82c](https://github.com/angular/angular.js/commit/16b82c6afe0ab916fef1d6ca78053b00bf5ada83)**, -$animate.cancel(runner) now rejects the underlying -promise and calls the catch() handler on the runner -returned by $animate functions (enter, leave, move, -addClass, removeClass, setClass, animate). -Previously it would resolve the promise as if the animation -had ended successfully. +`$animate.cancel(runner)` now rejects the underlying promise and calls the `catch()` handler on the +runner returned by `$animate` functions (`enter`, `leave`, `move`, `addClass`, `removeClass`, +`setClass`, `animate`). +Previously, it would resolve the promise as if the animation had ended successfully. Example: @@ -468,7 +478,7 @@ runner.cancel(); ``` Pre-1.7.0, this logs 'success', 1.7.0 and later it logs 'cancelled'. -To migrate, add a catch() handler to your animation runners. +To migrate, add a `catch()` handler to your animation runners. #### **$controller** @@ -479,26 +489,29 @@ has been removed. Likewise, the deprecated `$controllerProvider.allowGlobals()` method that could enable this behavior, has been removed. This behavior had been deprecated since AngularJS v1.3.0, because polluting the global scope -is bad. To migrate, remove the call to $controllerProvider.allowGlobals() in the config, and -register your controller via the Module API or the $controllerProvider, e.g. +is considered bad practice. To migrate, remove the call to `$controllerProvider.allowGlobals()` in +the config, and register your controller via the Module API or the `$controllerProvider`, e.g.: -``` +```js angular.module('myModule', []).controller('myController', function() {...}); +// or + angular.module('myModule', []).config(function($controllerProvider) { $controllerProvider.register('myController', function() {...}); }); - ``` + #### **$sce** + **Due to [1e9ead](https://github.com/angular/angular.js/commit/1e9eadcd72dbbd5c67dae8328a63e535cfa91ff9)**, -if you use `attrs.$set` for URL attributes (a[href] and img[src]) there will no +if you use `attrs.$set` for URL attributes (`a[href]` and `img[src]`) there will no longer be any automated sanitization of the value. This is in line with other -programmatic operations, such as writing to the innerHTML of an element. +programmatic operations, such as writing to the `innerHTML` of an element. If you are programmatically writing URL values to attributes from untrusted -input then you must sanitize it yourself. You could write your own sanitizer or copy +input, then you must sanitize it yourself. You could write your own sanitizer or copy the private `$$sanitizeUri` service. Note that values that have been passed through the `$interpolate` service within the @@ -507,40 +520,43 @@ these values again.
-Due to **[1e9ead](https://github.com/angular/angular.js/commit/1e9eadcd72dbbd5c67dae8328a63e535cfa91ff9)**, +**Due to [1e9ead](https://github.com/angular/angular.js/commit/1e9eadcd72dbbd5c67dae8328a63e535cfa91ff9)**, binding {@link ng.$sce#trustAs trustAs()} and the short versions -({@link ng.$sce#trustAsResourceUrl trustAsResourceUrl()} et al.) to -{@link ng.ngSrc}, {@link ng.ngSrcset}, and {@link ng.ngHref} will now raise an infinite digest error: +({@link ng.$sce#trustAsResourceUrl trustAsResourceUrl()} et al.) to {@link ng.ngSrc}, +{@link ng.ngSrcset}, and {@link ng.ngHref} will now raise an infinite digest error: ```js - $scope.imgThumbFn = function(id) { - return $sce.trustAsResourceUrl(someService.someUrl(id)); - }; +$scope.imgThumbFn = function(id) { + return $sce.trustAsResourceUrl(someService.someUrl(id)); +}; ``` ```html - + ``` + This is because {@link ng.$interpolate} is now responsible for sanitizing the attribute value, and its watcher receives a new object from `trustAs()` on every digest. To migrate, compute the trusted value only when the input value changes: ```js - $scope.$watch('imgId', function(id) { - $scope.imgThumb = $sce.trustAsResourceUrl(someService.someUrl(id)); - }); +$scope.$watch('imgId', function(id) { + $scope.imgThumb = $sce.trustAsResourceUrl(someService.someUrl(id)); +}); ``` ```html - + ```
### Core: _Filters_ + #### **orderBy** + **Due to [1d8046](https://github.com/angular/angular.js/commit/1d804645f7656d592c90216a0355b4948807f6b8)**, when using `orderBy` to sort arrays containing `null` values, the `null` values will be considered "greater than" all other values, except for `undefined`. @@ -565,8 +581,9 @@ orderByFilter(['a', undefined, 'o', null, 'z']); #### **jqLite** + **Due to [b7d396](https://github.com/angular/angular.js/commit/b7d396b8b6e8f27a1f4556d58fc903321e8d532a)**, -removeData() no longer removes event handlers. +`removeData()` no longer removes event handlers. Before this commit `removeData()` invoked on an element removed its event handlers as well. If you want to trigger a full cleanup of an element, change: @@ -591,22 +608,20 @@ elem.remove(); will remove event handlers as well. - -#### **Angular** +#### **Helpers** **Due to [1daa4f](https://github.com/angular/angular.js/commit/1daa4f2231a89ee88345689f001805ffffa9e7de)**, -the helper functions `angular.lowercase` `and angular.uppercase` have been removed. +the helper functions `angular.lowercase` and `angular.uppercase` have been removed. These functions have been deprecated since 1.5.0. They are internally used, but should not be exposed as they contain special locale handling (for Turkish) to maintain internal consistency regardless of user-set locale. -Developers should generally use the built-ins `toLowerCase` and `toUpperCase` +Developers should generally use the built-in methods `toLowerCase` and `toUpperCase` or `toLocaleLowerCase` and `toLocaleUpperCase` for special cases. -Further, we generally discourage using the angular.x helpers in application code. -
+ **Due to [e3ece2](https://github.com/angular/angular.js/commit/e3ece2fad9e1e6d47b5f06815ff186d7e6f44948)**, `angular.isArray()` now supports Array subclasses. @@ -627,18 +642,19 @@ be able to handle these objects better when copying or watching. ### ngAria **Due to [6d5ef3](https://github.com/angular/angular.js/commit/6d5ef34fc6a974cde73157ba94f9706723dd8f5b)**, -the ngAria directive no longer sets aria-* attributes on input[type="hidden"] with ngModel. -This can affect apps that test for the presence of aria attributes on hidden inputs. +`ngAria` no longer sets `aria-*` attributes on `input[type="hidden"]` with `ngModel`. +This can affect apps that test for the presence of ARIA attributes on hidden inputs. To migrate, remove these assertions. In actual apps, this should not have a user-facing effect, as the previous behavior was incorrect, and the new behavior is correct for accessibility. - ### ngResource + #### **$resource** + **Due to [ea0585](https://github.com/angular/angular.js/commit/ea0585773bb93fd891576e2271254a17e15f1ddd)**, the behavior of interceptors and success/error callbacks has changed. @@ -720,6 +736,7 @@ User.get({id: 2}, onSuccess, onError); ```
+ **Due to [240a3d](https://github.com/angular/angular.js/commit/240a3ddbf12a9bb79754031be95dae4b6bd2dded)**, `$http` will be called asynchronously from `$resource` methods (regardless if a `request`/`requestError` interceptor has been defined). @@ -758,7 +775,6 @@ it('...', function() { ``` - ### ngScenario @@ -766,7 +782,7 @@ it('...', function() { the angular scenario runner end-to-end test framework has been removed from the project and will no longer be available on npm or bower starting with 1.7.0. -It was deprecated and removed from the documentation in 2014. +It has been deprecated and removed from the documentation since 2014. Applications that still use it should migrate to [Protractor](http://www.protractortest.org). Technically, it should also be possible to continue using an @@ -778,10 +794,10 @@ not changed. However, we do not guarantee future compatibility. ### ngTouch **Due to [11d9ad](https://github.com/angular/angular.js/commit/11d9ad1eb25eaf5967195e424108207427835d50)**, -the `ngClick` directive from the ngTouch module has been removed, and with it the +the `ngClick` directive of the `ngTouch` module has been removed, and with it the corresponding `$touchProvider` and `$touch` service. -If you have included ngTouch v1.5.0 or higher in your application, and have not +If you have included `ngTouch` v1.5.0 or higher in your application, and have not changed the value of `$touchProvider.ngClickOverrideEnabled()`, or injected and used the `$touch` service, then there are no migration steps for your code. Otherwise you must remove references to the provider and service. From ad7ea953868ac8ee376e8a44472793659cdd0589 Mon Sep 17 00:00:00 2001 From: John Mantas Date: Sat, 4 Aug 2018 17:23:49 +0300 Subject: [PATCH 081/217] docs(ngRepeat): redundant "and" on line 77 Closes #16657 --- src/ng/directive/ngRepeat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/directive/ngRepeat.js b/src/ng/directive/ngRepeat.js index d6f7dc847429..dacd67688006 100644 --- a/src/ng/directive/ngRepeat.js +++ b/src/ng/directive/ngRepeat.js @@ -74,7 +74,7 @@ * For example, if an item is added to the collection, `ngRepeat` will know that all other items * already have DOM elements, and will not re-render them. * - * All different types of tracking functions, their syntax, and and their support for duplicate + * All different types of tracking functions, their syntax, and their support for duplicate * items in collections can be found in the * {@link ngRepeat#ngRepeat-arguments ngRepeat expression description}. * From 837e519acc8cbe8e714c1f2bc14fa6adf9c1bf5d Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 20 Aug 2018 20:04:28 +0200 Subject: [PATCH 082/217] fix(ngHref): allow numbers and other objects in interpolation Interpolated content in ngHref must be stringified before being passed to $$sanitizeUri by $sce. Before 1.7.x, the sanitization had happened on the already interpolated value inside $compile. Closes #16652 Fixes #16626 --- src/ng/sce.js | 2 +- test/ng/directive/ngHrefSpec.js | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/ng/sce.js b/src/ng/sce.js index 6bc99f23761f..0ee69fc89d8b 100644 --- a/src/ng/sce.js +++ b/src/ng/sce.js @@ -440,7 +440,7 @@ function $SceDelegateProvider() { // If we get here, then we will either sanitize the value or throw an exception. if (type === SCE_CONTEXTS.MEDIA_URL || type === SCE_CONTEXTS.URL) { // we attempt to sanitize non-resource URLs - return $$sanitizeUri(maybeTrusted, type === SCE_CONTEXTS.MEDIA_URL); + return $$sanitizeUri(maybeTrusted.toString(), type === SCE_CONTEXTS.MEDIA_URL); } else if (type === SCE_CONTEXTS.RESOURCE_URL) { if (isResourceUrlAllowedByPolicy(maybeTrusted)) { return maybeTrusted; diff --git a/test/ng/directive/ngHrefSpec.js b/test/ng/directive/ngHrefSpec.js index 6d44ac8b5631..2c5e99c076b3 100644 --- a/test/ng/directive/ngHrefSpec.js +++ b/test/ng/directive/ngHrefSpec.js @@ -79,6 +79,42 @@ describe('ngHref', function() { })); } + + it('should bind numbers', inject(function($rootScope, $compile) { + element = $compile('')($rootScope); + $rootScope.$digest(); + expect(element.attr('href')).toEqual('1234'); + })); + + + it('should bind and sanitize the result of a (custom) toString() function', inject(function($rootScope, $compile) { + $rootScope.value = {}; + element = $compile('')($rootScope); + $rootScope.$digest(); + expect(element.attr('href')).toEqual('[object Object]'); + + function SafeClass() {} + + SafeClass.prototype.toString = function() { + return 'custom value'; + }; + + $rootScope.value = new SafeClass(); + $rootScope.$digest(); + expect(element.attr('href')).toEqual('custom value'); + + function UnsafeClass() {} + + UnsafeClass.prototype.toString = function() { + return 'javascript:alert(1);'; + }; + + $rootScope.value = new UnsafeClass(); + $rootScope.$digest(); + expect(element.attr('href')).toEqual('unsafe:javascript:alert(1);'); + })); + + if (isDefined(window.SVGElement)) { describe('SVGAElement', function() { it('should interpolate the expression and bind to xlink:href', inject(function($compile, $rootScope) { From aecd551bdeff476ea1076a6fee807366e1a584c9 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 21 Aug 2018 11:43:18 +0300 Subject: [PATCH 083/217] docs(angular.copy): fix formatting Using `
` messes formatting (due to a bug in `dgeni`/`dgeni-packages`). This started breaking in c387e0d79. Fixes #16671 --- src/Angular.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Angular.js b/src/Angular.js index 9ec66958aa68..d53e4b095442 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -791,16 +791,16 @@ function arrayRemove(array, value) { * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. * * If `source` is identical to `destination` an exception will be thrown. * - *
+ *

*
* Only enumerable properties are taken into account. Non-enumerable properties (both on `source` * and on `destination`) will be ignored. *
* - * @param {*} source The source that will be used to make a copy. - * Can be any type, including primitives, `null`, and `undefined`. - * @param {(Object|Array)=} destination Destination into which the source is copied. If - * provided, must be of the same type as `source`. + * @param {*} source The source that will be used to make a copy. Can be any type, including + * primitives, `null`, and `undefined`. + * @param {(Object|Array)=} destination Destination into which the source is copied. If provided, + * must be of the same type as `source`. * @returns {*} The copy or updated `destination`, if `destination` was specified. * * @example From 937fb891fa4fcf79e9fa02f8e0d517593e781077 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 23 Aug 2018 15:06:14 +0300 Subject: [PATCH 084/217] chore(doc-gen): upgrade `dgeni-packages` to 0.26.5 Related: #16671, angular/dgeni-packages#271 --- package.json | 2 +- src/Angular.js | 3 ++- yarn.lock | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 40e6c464aa0c..f483600300a9 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "cross-spawn": "^4.0.0", "cz-conventional-changelog": "1.1.4", "dgeni": "^0.4.9", - "dgeni-packages": "^0.26.2", + "dgeni-packages": "^0.26.5", "eslint-plugin-promise": "^3.6.0", "event-stream": "~3.1.0", "glob": "^6.0.1", diff --git a/src/Angular.js b/src/Angular.js index d53e4b095442..a71b3cbb38f0 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -791,7 +791,8 @@ function arrayRemove(array, value) { * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. * * If `source` is identical to `destination` an exception will be thrown. * - *

+ *
+ * *
* Only enumerable properties are taken into account. Non-enumerable properties (both on `source` * and on `destination`) will be ignored. diff --git a/yarn.lock b/yarn.lock index b3412ae20d05..c4f7a461c3e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1727,9 +1727,9 @@ detective@^4.0.0: acorn "^3.1.0" defined "^1.0.0" -dgeni-packages@^0.26.2: - version "0.26.2" - resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.26.2.tgz#dac22d7e861d4d72ed42af5272714f42b6b5bf3d" +dgeni-packages@^0.26.5: + version "0.26.5" + resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.26.5.tgz#a76da27b40ce92dfc37a9e629ef9f1d3897f6bde" dependencies: canonical-path "0.0.2" catharsis "^0.8.1" From 510404e5b34fcf47a4d0cc8094afe7431b0a0b63 Mon Sep 17 00:00:00 2001 From: Susisu Date: Mon, 20 Aug 2018 16:02:28 +0900 Subject: [PATCH 085/217] fix($route): correctly extract path params if path contains question mark or hash The `routeToRegExp()` function, introduced by 840b5f0, could not extract path params if the path contained question mark or hash. Although these characters would normally be encoded in the path, they are decoded by `$location.path()`, before being passed to the RegExp returned by `routeToRegExp()`. `routeToRegExp()` has to be able to deal with both encoded URL and decoded path, because it is being shared between `ngRoute` and `ngMocks`. This commit fixes the issue, by introducing an `isUrl` option that allows creating an appropriate RegExp for each usecase. --- src/ngMock/angular-mocks.js | 4 ++-- src/routeToRegExp.js | 10 ++++----- test/ngRoute/routeParamsSpec.js | 40 +++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index f6e5cce71e96..e7f78fcccdbc 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -1771,7 +1771,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * See {@link ngMock.$httpBackend#when `when`} for more info. */ $httpBackend.whenRoute = function(method, url) { - var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true}); + var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true, isUrl: true}); return $httpBackend.when(method, pathObj.regexp, undefined, undefined, pathObj.keys); }; @@ -1955,7 +1955,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * See {@link ngMock.$httpBackend#expect `expect`} for more info. */ $httpBackend.expectRoute = function(method, url) { - var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true}); + var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true, isUrl: true}); return $httpBackend.expect(method, pathObj.regexp, undefined, undefined, pathObj.keys); }; diff --git a/src/routeToRegExp.js b/src/routeToRegExp.js index ea0b94efe7f3..d8edd4706359 100644 --- a/src/routeToRegExp.js +++ b/src/routeToRegExp.js @@ -3,7 +3,7 @@ /* global routeToRegExp: true */ /** - * @param path {string} path + * @param pathOrUrl {string} path or url * @param opts {Object} options * @return {?Object} * @@ -13,10 +13,10 @@ * * Inspired by pathRexp in visionmedia/express/lib/utils.js. */ -function routeToRegExp(path, opts) { +function routeToRegExp(pathOrUrl, opts) { var keys = []; - var pattern = path + var pattern = pathOrUrl .replace(/([().])/g, '\\$1') .replace(/(\/)?:(\w+)(\*\?|[?*])?/g, function(_, slash, key, option) { var optional = option === '?' || option === '*?'; @@ -25,7 +25,7 @@ function routeToRegExp(path, opts) { slash = slash || ''; return ( (optional ? '(?:' + slash : slash + '(?:') + - (star ? '([^?#]+?)' : '([^/?#]+)') + + (opts.isUrl ? (star ? '([^?#]+?)' : '([^/?#]+)') : (star ? '(.+?)' : '([^/]+)')) + (optional ? '?)?' : ')') ); }) @@ -36,7 +36,7 @@ function routeToRegExp(path, opts) { } return { - originalPath: path, + originalPath: pathOrUrl, keys: keys, regexp: new RegExp( '^' + pattern + '(?:[?#]|$)', diff --git a/test/ngRoute/routeParamsSpec.js b/test/ngRoute/routeParamsSpec.js index e3357fee8152..88b27dd8409d 100644 --- a/test/ngRoute/routeParamsSpec.js +++ b/test/ngRoute/routeParamsSpec.js @@ -77,5 +77,45 @@ describe('$routeParams', function() { }); }); + it('should correctly extract path params containing hashes and/or question marks', function() { + module(function($routeProvider) { + $routeProvider.when('/foo/:bar', {}); + $routeProvider.when('/zoo/:bar/:baz/:qux', {}); + }); + + inject(function($location, $rootScope, $routeParams) { + $location.path('/foo/bar?baz'); + $rootScope.$digest(); + expect($routeParams).toEqual({bar: 'bar?baz'}); + + $location.path('/foo/bar?baz=val'); + $rootScope.$digest(); + expect($routeParams).toEqual({bar: 'bar?baz=val'}); + + $location.path('/foo/bar#baz'); + $rootScope.$digest(); + expect($routeParams).toEqual({bar: 'bar#baz'}); + + $location.path('/foo/bar?baz#qux'); + $rootScope.$digest(); + expect($routeParams).toEqual({bar: 'bar?baz#qux'}); + + $location.path('/foo/bar?baz=val#qux'); + $rootScope.$digest(); + expect($routeParams).toEqual({bar: 'bar?baz=val#qux'}); + + $location.path('/foo/bar#baz?qux'); + $rootScope.$digest(); + expect($routeParams).toEqual({bar: 'bar#baz?qux'}); + + $location.path('/zoo/bar?p1=v1#h1/baz?p2=v2#h2/qux?p3=v3#h3'); + $rootScope.$digest(); + expect($routeParams).toEqual({ + bar: 'bar?p1=v1#h1', + baz: 'baz?p2=v2#h2', + qux: 'qux?p3=v3#h3' + }); + }); + }); }); From 506fe73a4af3e874397137fd10a45d26d3aabd47 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 21 Aug 2018 14:57:10 +0300 Subject: [PATCH 086/217] test(ngMocks): use correct method name in `$httpBackend` test --- test/ngMock/angular-mocksSpec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/ngMock/angular-mocksSpec.js b/test/ngMock/angular-mocksSpec.js index 5595e9675d2c..9dd950f51adc 100644 --- a/test/ngMock/angular-mocksSpec.js +++ b/test/ngMock/angular-mocksSpec.js @@ -2251,7 +2251,7 @@ describe('ngMock', function() { } ); they('should ignore query params when matching in ' + routeShortcut + ' $prop method', methods, - function() { + function(method) { angular.forEach([ {route: '/route1/:id', url: '/route1/Alpha', expectedParams: {id: 'Alpha'}}, {route: '/route2/:id', url: '/route2/Bravo/?', expectedParams: {id: 'Bravo'}}, @@ -2268,14 +2268,14 @@ describe('ngMock', function() { ], function(testDataEntry) { callback.calls.reset(); var paramsSpy = jasmine.createSpy('params'); - hb[routeShortcut](this, testDataEntry.route).respond( + hb[routeShortcut](method, testDataEntry.route).respond( function(method, url, data, headers, params) { paramsSpy(params); // status, response, headers, statusText, xhrStatus return [200, 'path', { 'x-header': 'foo' }, 'OK', 'complete']; } ); - hb(this, testDataEntry.url, undefined, callback); + hb(method, testDataEntry.url, undefined, callback); hb.flush(); expect(callback).toHaveBeenCalledOnceWith(200, 'path', 'x-header: foo', 'OK', 'complete'); expect(paramsSpy).toHaveBeenCalledOnceWith(testDataEntry.expectedParams); From 9824c59dca4ab57a2de6b7844e46ea8a77560f4f Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 21 Aug 2018 14:58:56 +0300 Subject: [PATCH 087/217] refactor(ngRoute): do not unnecessarily return `originalPath` in `routeToRegExp` --- src/ngRoute/route.js | 3 ++- src/routeToRegExp.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ngRoute/route.js b/src/ngRoute/route.js index 706600a5bdeb..224455052ebd 100644 --- a/src/ngRoute/route.js +++ b/src/ngRoute/route.js @@ -225,6 +225,7 @@ function $RouteProvider() { } routes[path] = angular.extend( routeCopy, + {originalPath: path}, path && routeToRegExp(path, routeCopy) ); @@ -235,7 +236,7 @@ function $RouteProvider() { : path + '/'; routes[redirectPath] = angular.extend( - {redirectTo: path}, + {originalPath: path, redirectTo: path}, routeToRegExp(redirectPath, routeCopy) ); } diff --git a/src/routeToRegExp.js b/src/routeToRegExp.js index d8edd4706359..b570c6a083a4 100644 --- a/src/routeToRegExp.js +++ b/src/routeToRegExp.js @@ -36,7 +36,6 @@ function routeToRegExp(pathOrUrl, opts) { } return { - originalPath: pathOrUrl, keys: keys, regexp: new RegExp( '^' + pattern + '(?:[?#]|$)', From 321ee99647d7c0e0d939ea44971643212b9e2737 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 21 Aug 2018 15:03:16 +0300 Subject: [PATCH 088/217] refactor(ngMocks): clean up `MockHttpExpectation#params()` --- src/ngMock/angular-mocks.js | 41 +++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index e7f78fcccdbc..204503eb1dd0 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -2145,7 +2145,9 @@ function MockHttpExpectation(method, url, data, headers, keys) { }; this.params = function(u) { - return angular.extend(parseQuery(), pathParams()); + var queryStr = u.indexOf('?') === -1 ? '' : u.substring(u.indexOf('?') + 1); + + return angular.extend(parseQuery(queryStr), pathParams()); function pathParams() { var keyObj = {}; @@ -2164,30 +2166,29 @@ function MockHttpExpectation(method, url, data, headers, keys) { return keyObj; } - function parseQuery() { - var obj = {}, key_value, key, - queryStr = u.indexOf('?') > -1 - ? u.substring(u.indexOf('?') + 1) - : ''; - - angular.forEach(queryStr.split('&'), function(keyValue) { - if (keyValue) { - key_value = keyValue.replace(/\+/g,'%20').split('='); - key = tryDecodeURIComponent(key_value[0]); - if (angular.isDefined(key)) { - var val = angular.isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true; - if (!hasOwnProperty.call(obj, key)) { - obj[key] = val; - } else if (angular.isArray(obj[key])) { - obj[key].push(val); - } else { - obj[key] = [obj[key],val]; - } + function parseQuery(queryStr) { + var obj = {}, + keyValuePairs = queryStr.split('&'). + filter(angular.identity). // Ignore empty segments. + map(function(keyValue) { return keyValue.replace(/\+/g, '%20').split('='); }); + + angular.forEach(keyValuePairs, function(pair) { + var key = tryDecodeURIComponent(pair[0]); + if (angular.isDefined(key)) { + var val = angular.isDefined(pair[1]) ? tryDecodeURIComponent(pair[1]) : true; + if (!hasOwnProperty.call(obj, key)) { + obj[key] = val; + } else if (angular.isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [obj[key], val]; } } }); + return obj; } + function tryDecodeURIComponent(value) { try { return decodeURIComponent(value); From 132344c8670965be9d7e1fce8e44f3721c459e6e Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 21 Aug 2018 15:08:39 +0300 Subject: [PATCH 089/217] refactor(ngMocks): ignore query/hash when extracting path params for `MockHttpExpectation` --- src/ngMock/angular-mocks.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 204503eb1dd0..ecdc3a6a9430 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -2092,6 +2092,9 @@ function assertArgDefined(args, index, name) { } } +function stripQueryAndHash(url) { + return url.replace(/[?#].*$/, ''); +} function MockHttpExpectation(method, url, data, headers, keys) { @@ -2146,15 +2149,17 @@ function MockHttpExpectation(method, url, data, headers, keys) { this.params = function(u) { var queryStr = u.indexOf('?') === -1 ? '' : u.substring(u.indexOf('?') + 1); + var strippedUrl = stripQueryAndHash(u); - return angular.extend(parseQuery(queryStr), pathParams()); + return angular.extend(parseQuery(queryStr), pathParams(strippedUrl)); - function pathParams() { + function pathParams(strippedUrl) { var keyObj = {}; if (!url || !angular.isFunction(url.test) || !keys || keys.length === 0) return keyObj; - var m = url.exec(u); + var m = url.exec(strippedUrl); if (!m) return keyObj; + for (var i = 1, len = m.length; i < len; ++i) { var key = keys[i - 1]; var val = m[i]; From 99ad41fa3fb65421f52e640fcaebc7e38fd333a6 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Sat, 25 Aug 2018 15:25:10 +0300 Subject: [PATCH 090/217] refactor(ngMocks): clean up `MockHttpExpectation` --- src/ngMock/angular-mocks.js | 166 +++++++++++++++++++----------------- 1 file changed, 87 insertions(+), 79 deletions(-) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index ecdc3a6a9430..0e157bafcd6f 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -2096,112 +2096,120 @@ function stripQueryAndHash(url) { return url.replace(/[?#].*$/, ''); } -function MockHttpExpectation(method, url, data, headers, keys) { +function MockHttpExpectation(expectedMethod, expectedUrl, expectedData, expectedHeaders, + expectedKeys) { - function getUrlParams(u) { - var params = u.slice(u.indexOf('?') + 1).split('&'); - return params.sort(); - } - - function compareUrl(u) { - return (url.slice(0, url.indexOf('?')) === u.slice(0, u.indexOf('?')) && - getUrlParams(url).join() === getUrlParams(u).join()); - } - - this.data = data; - this.headers = headers; + this.data = expectedData; + this.headers = expectedHeaders; - this.match = function(m, u, d, h) { - if (method !== m) return false; - if (!this.matchUrl(u)) return false; - if (angular.isDefined(d) && !this.matchData(d)) return false; - if (angular.isDefined(h) && !this.matchHeaders(h)) return false; + this.match = function(method, url, data, headers) { + if (expectedMethod !== method) return false; + if (!this.matchUrl(url)) return false; + if (angular.isDefined(data) && !this.matchData(data)) return false; + if (angular.isDefined(headers) && !this.matchHeaders(headers)) return false; return true; }; - this.matchUrl = function(u) { - if (!url) return true; - if (angular.isFunction(url.test)) return url.test(u); - if (angular.isFunction(url)) return https://github.com/url(u); - return (url === u || compareUrl(u)); + this.matchUrl = function(url) { + if (!expectedUrl) return true; + if (angular.isFunction(expectedUrl.test)) return expectedUrl.test(url); + if (angular.isFunction(expectedUrl)) return expectedUrl(url); + return (expectedUrl === url || compareUrlWithQuery(url)); }; - this.matchHeaders = function(h) { - if (angular.isUndefined(headers)) return true; - if (angular.isFunction(headers)) return headers(h); - return angular.equals(headers, h); + this.matchHeaders = function(headers) { + if (angular.isUndefined(expectedHeaders)) return true; + if (angular.isFunction(expectedHeaders)) return expectedHeaders(headers); + return angular.equals(expectedHeaders, headers); }; - this.matchData = function(d) { - if (angular.isUndefined(data)) return true; - if (data && angular.isFunction(data.test)) return data.test(d); - if (data && angular.isFunction(data)) return data(d); - if (data && !angular.isString(data)) { - return angular.equals(angular.fromJson(angular.toJson(data)), angular.fromJson(d)); + this.matchData = function(data) { + if (angular.isUndefined(expectedData)) return true; + if (expectedData && angular.isFunction(expectedData.test)) return expectedData.test(data); + if (expectedData && angular.isFunction(expectedData)) return expectedData(data); + if (expectedData && !angular.isString(expectedData)) { + return angular.equals(angular.fromJson(angular.toJson(expectedData)), angular.fromJson(data)); } // eslint-disable-next-line eqeqeq - return data == d; + return expectedData == data; }; this.toString = function() { - return method + ' ' + url; + return expectedMethod + ' ' + expectedUrl; }; - this.params = function(u) { - var queryStr = u.indexOf('?') === -1 ? '' : u.substring(u.indexOf('?') + 1); - var strippedUrl = stripQueryAndHash(u); + this.params = function(url) { + var queryStr = url.indexOf('?') === -1 ? '' : url.substring(url.indexOf('?') + 1); + var strippedUrl = stripQueryAndHash(url); - return angular.extend(parseQuery(queryStr), pathParams(strippedUrl)); + return angular.extend(extractParamsFromQuery(queryStr), extractParamsFromPath(strippedUrl)); + }; - function pathParams(strippedUrl) { - var keyObj = {}; - if (!url || !angular.isFunction(url.test) || !keys || keys.length === 0) return keyObj; + function compareUrlWithQuery(url) { + var urlWithQueryRe = /^([^?]*)\?(.*)$/; - var m = url.exec(strippedUrl); - if (!m) return keyObj; + var expectedMatch = urlWithQueryRe.exec(expectedUrl); + var actualMatch = urlWithQueryRe.exec(url); - for (var i = 1, len = m.length; i < len; ++i) { - var key = keys[i - 1]; - var val = m[i]; - if (key && val) { - keyObj[key.name || key] = val; - } - } + return !!(expectedMatch && actualMatch) && + (expectedMatch[1] === actualMatch[1]) && + (normalizeQuery(expectedMatch[2]) === normalizeQuery(actualMatch[2])); + } - return keyObj; - } + function normalizeQuery(queryStr) { + return queryStr.split('&').sort().join('&'); + } - function parseQuery(queryStr) { - var obj = {}, - keyValuePairs = queryStr.split('&'). - filter(angular.identity). // Ignore empty segments. - map(function(keyValue) { return keyValue.replace(/\+/g, '%20').split('='); }); - - angular.forEach(keyValuePairs, function(pair) { - var key = tryDecodeURIComponent(pair[0]); - if (angular.isDefined(key)) { - var val = angular.isDefined(pair[1]) ? tryDecodeURIComponent(pair[1]) : true; - if (!hasOwnProperty.call(obj, key)) { - obj[key] = val; - } else if (angular.isArray(obj[key])) { - obj[key].push(val); - } else { - obj[key] = [obj[key], val]; - } - } - }); + function extractParamsFromPath(strippedUrl) { + var keyObj = {}; - return obj; + if (!expectedUrl || !angular.isFunction(expectedUrl.test) || + !expectedKeys || !expectedKeys.length) return keyObj; + + var match = expectedUrl.exec(strippedUrl); + if (!match) return keyObj; + + for (var i = 1, len = match.length; i < len; ++i) { + var key = expectedKeys[i - 1]; + var val = match[i]; + if (key && val) { + keyObj[key.name || key] = val; + } } - function tryDecodeURIComponent(value) { - try { - return decodeURIComponent(value); - } catch (e) { - // Ignore any invalid uri component + return keyObj; + } + + function extractParamsFromQuery(queryStr) { + var obj = {}, + keyValuePairs = queryStr.split('&'). + filter(angular.identity). // Ignore empty segments. + map(function(keyValue) { return keyValue.replace(/\+/g, '%20').split('='); }); + + angular.forEach(keyValuePairs, function(pair) { + var key = tryDecodeURIComponent(pair[0]); + if (angular.isDefined(key)) { + var val = angular.isDefined(pair[1]) ? tryDecodeURIComponent(pair[1]) : true; + if (!hasOwnProperty.call(obj, key)) { + obj[key] = val; + } else if (angular.isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [obj[key], val]; + } } + }); + + return obj; + } + + function tryDecodeURIComponent(value) { + try { + return decodeURIComponent(value); + } catch (e) { + // Ignore any invalid uri component } - }; + } } function createMockXhr() { From a5537359c531ca9c32ea481f9189e9d4354859c0 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 21 Aug 2018 15:13:21 +0300 Subject: [PATCH 091/217] refactor(ngMocks): simplify `routeToRegExp` by assuming `path` has query/hash stripped off Closes #16672 --- src/ngMock/angular-mocks.js | 14 ++++++++++---- src/routeToRegExp.js | 21 +++++++++++---------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 0e157bafcd6f..7537dcab463a 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -1771,8 +1771,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * See {@link ngMock.$httpBackend#when `when`} for more info. */ $httpBackend.whenRoute = function(method, url) { - var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true, isUrl: true}); - return $httpBackend.when(method, pathObj.regexp, undefined, undefined, pathObj.keys); + var parsed = parseRouteUrl(url); + return $httpBackend.when(method, parsed.regexp, undefined, undefined, parsed.keys); }; /** @@ -1955,8 +1955,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { * See {@link ngMock.$httpBackend#expect `expect`} for more info. */ $httpBackend.expectRoute = function(method, url) { - var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true, isUrl: true}); - return $httpBackend.expect(method, pathObj.regexp, undefined, undefined, pathObj.keys); + var parsed = parseRouteUrl(url); + return $httpBackend.expect(method, parsed.regexp, undefined, undefined, parsed.keys); }; @@ -2084,6 +2084,12 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) { }; }); } + + function parseRouteUrl(url) { + var strippedUrl = stripQueryAndHash(url); + var parseOptions = {caseInsensitiveMatch: true, ignoreTrailingSlashes: true}; + return routeToRegExp(strippedUrl, parseOptions); + } } function assertArgDefined(args, index, name) { diff --git a/src/routeToRegExp.js b/src/routeToRegExp.js index b570c6a083a4..c2dc8d817843 100644 --- a/src/routeToRegExp.js +++ b/src/routeToRegExp.js @@ -3,29 +3,30 @@ /* global routeToRegExp: true */ /** - * @param pathOrUrl {string} path or url - * @param opts {Object} options - * @return {?Object} + * @param {string} path - The path to parse. (It is assumed to have query and hash stripped off.) + * @param {Object} opts - Options. + * @return {Object} - An object containing an array of path parameter names (`keys`) and a regular + * expression (`regexp`) that can be used to identify a matching URL and extract the path + * parameter values. * * @description - * Normalizes the given path, returning a regular expression - * and the original path. + * Parses the given path, extracting path parameter names and a regular expression to match URLs. * - * Inspired by pathRexp in visionmedia/express/lib/utils.js. + * Originally inspired by `pathRexp` in `visionmedia/express/lib/utils.js`. */ -function routeToRegExp(pathOrUrl, opts) { +function routeToRegExp(path, opts) { var keys = []; - var pattern = pathOrUrl + var pattern = path .replace(/([().])/g, '\\$1') .replace(/(\/)?:(\w+)(\*\?|[?*])?/g, function(_, slash, key, option) { var optional = option === '?' || option === '*?'; var star = option === '*' || option === '*?'; - keys.push({ name: key, optional: optional }); + keys.push({name: key, optional: optional}); slash = slash || ''; return ( (optional ? '(?:' + slash : slash + '(?:') + - (opts.isUrl ? (star ? '([^?#]+?)' : '([^/?#]+)') : (star ? '(.+?)' : '([^/]+)')) + + (star ? '(.+?)' : '([^/]+)') + (optional ? '?)?' : ')') ); }) From f010d6c00f91da0e0297e64856360598ad7db15d Mon Sep 17 00:00:00 2001 From: Craig Johnson Date: Wed, 5 Sep 2018 23:04:58 +0530 Subject: [PATCH 092/217] docs(guide): grammar correction in security guide Closes #16683 --- docs/content/guide/security.ngdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/guide/security.ngdoc b/docs/content/guide/security.ngdoc index 2a8e6b6feda8..cfc224088c36 100644 --- a/docs/content/guide/security.ngdoc +++ b/docs/content/guide/security.ngdoc @@ -102,7 +102,7 @@ For more information please visit {@link $http#json-vulnerability-protection JSO Bear in mind that calling `$http.jsonp` gives the remote server (and, if the request is not secured, any Man-in-the-Middle attackers) instant remote code execution in your application: the result of these requests is handed off -to the browser as regular ` + + + \ No newline at end of file diff --git a/test/e2e/fixtures/back2dom/script.js b/test/e2e/fixtures/back2dom/script.js new file mode 100644 index 000000000000..04911865c39d --- /dev/null +++ b/test/e2e/fixtures/back2dom/script.js @@ -0,0 +1,11 @@ +'use strict'; + +angular + .module('test', []) + .run(function($rootScope) { + $rootScope.internalFnCalled = false; + + $rootScope.internalFn = function() { + $rootScope.internalFnCalled = true; + }; + }); diff --git a/test/e2e/tests/input-hidden.spec.js b/test/e2e/tests/input-hidden.spec.js index ef2669f0f64a..e1e76e0390a4 100644 --- a/test/e2e/tests/input-hidden.spec.js +++ b/test/e2e/tests/input-hidden.spec.js @@ -14,4 +14,72 @@ describe('hidden thingy', function() { var expectedValue = browser.params.browser === 'safari' ? '{{ 7 * 6 }}' : ''; expect(element(by.css('input')).getAttribute('value')).toEqual(expectedValue); }); + + it('should prevent browser autofill on browser.refresh', function() { + + loadFixture('back2dom'); + expect(element(by.css('#input1')).getAttribute('value')).toEqual(''); + expect(element(by.css('#input2')).getAttribute('value')).toEqual(''); + + element(by.css('textarea')).sendKeys('{{ internalFn() }}'); + + expect(element(by.css('#input1')).getAttribute('value')).toEqual('{{ internalFn() }}'); + expect(element(by.css('#input2')).getAttribute('value')).toEqual('{{ internalFn() }}'); + expect(element(by.css('body')).getAttribute('class')).toBe(''); + + browser.refresh(); + expect(element(by.css('body')).getAttribute('class')).toBe(''); + }); + + it('should prevent browser autofill on location.reload', function() { + + loadFixture('back2dom'); + expect(element(by.css('#input1')).getAttribute('value')).toEqual(''); + expect(element(by.css('#input2')).getAttribute('value')).toEqual(''); + + element(by.css('textarea')).sendKeys('{{ internalFn() }}'); + + expect(element(by.css('#input1')).getAttribute('value')).toEqual('{{ internalFn() }}'); + expect(element(by.css('#input2')).getAttribute('value')).toEqual('{{ internalFn() }}'); + expect(element(by.css('body')).getAttribute('class')).toBe(''); + + browser.driver.executeScript('location.reload()'); + expect(element(by.css('body')).getAttribute('class')).toBe(''); + }); + + it('should prevent browser autofill on history.back', function() { + + loadFixture('back2dom'); + expect(element(by.css('#input1')).getAttribute('value')).toEqual(''); + expect(element(by.css('#input2')).getAttribute('value')).toEqual(''); + + element(by.css('textarea')).sendKeys('{{ internalFn() }}'); + + expect(element(by.css('#input1')).getAttribute('value')).toEqual('{{ internalFn() }}'); + expect(element(by.css('#input2')).getAttribute('value')).toEqual('{{ internalFn() }}'); + expect(element(by.css('body')).getAttribute('class')).toBe(''); + + loadFixture('sample'); + + browser.driver.executeScript('history.back()'); + expect(element(by.css('body')).getAttribute('class')).toBe(''); + }); + + it('should prevent browser autofill on history.forward', function() { + + loadFixture('sample'); + loadFixture('back2dom'); + expect(element(by.css('#input1')).getAttribute('value')).toEqual(''); + expect(element(by.css('#input2')).getAttribute('value')).toEqual(''); + + element(by.css('textarea')).sendKeys('{{ internalFn() }}'); + + expect(element(by.css('#input1')).getAttribute('value')).toEqual('{{ internalFn() }}'); + expect(element(by.css('#input2')).getAttribute('value')).toEqual('{{ internalFn() }}'); + expect(element(by.css('body')).getAttribute('class')).toBe(''); + + browser.driver.executeScript('history.back()'); + browser.driver.executeScript('history.forward()'); + expect(element(by.css('body')).getAttribute('class')).toBe(''); + }); }); From 258713a77db1a68527760832f185efe28008e3c2 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Thu, 18 Oct 2018 14:47:50 +0100 Subject: [PATCH 111/217] chore(package): update protractor & webdriver dependencies --- package.json | 4 +- yarn.lock | 189 +++++++++++++++++++++++++++------------------------ 2 files changed, 103 insertions(+), 90 deletions(-) diff --git a/package.json b/package.json index a7b71fcaebee..b674a91bcaa0 100644 --- a/package.json +++ b/package.json @@ -83,13 +83,13 @@ "npm-run": "^4.1.0", "open-sans-fontface": "^1.4.0", "promises-aplus-tests": "~2.1.0", - "protractor": "^5.1.2", + "protractor": "^5.4.1", "q": "~1.0.0", "q-io": "^1.10.9", "qq": "^0.3.5", "rewire": "~2.1.0", "sax": "^1.1.1", - "selenium-webdriver": "^2.53.1", + "selenium-webdriver": "^4.0.0-alpha.1", "semver": "^5.4.1", "serve-favicon": "^2.3.0", "serve-index": "^1.8.0", diff --git a/yarn.lock b/yarn.lock index 79123f878d11..551675822fb2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,10 +12,10 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" integrity sha1-vShOV8hPEyXacCur/IKlMoGQwMU= -"@types/selenium-webdriver@^2.53.35", "@types/selenium-webdriver@~2.53.39": - version "2.53.42" - resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-2.53.42.tgz#74cb77fb6052edaff2a8984ddafd88d419f25cac" - integrity sha1-dMt3+2BS7a/yqJhN2v2I1BnyXKw= +"@types/selenium-webdriver@^3.0.0": + version "3.0.12" + resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.12.tgz#6affe5aed1ba379175075a889adbe2bc3aa62159" + integrity sha512-hYn+eoOehVUIdMwp5h34ZsGAO1ydja10GDup4BwyoFCdcH5MQ35nQq+AInSaBMEMopD5hEooFCyKo2Pajbe1ag== Base64@~0.2.0: version "0.2.1" @@ -106,11 +106,6 @@ addressparser@1.0.1: resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746" integrity sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y= -adm-zip@0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.4.tgz#a61ed5ae6905c3aea58b3a657d25033091052736" - integrity sha1-ph7VrmkFw66lizplfSUDMJEFJzY= - adm-zip@^0.4.7, adm-zip@~0.4.3: version "0.4.7" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" @@ -642,10 +637,10 @@ block-stream@*: dependencies: inherits "~2.0.0" -blocking-proxy@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/blocking-proxy/-/blocking-proxy-0.0.5.tgz#462905e0dcfbea970f41aa37223dda9c07b1912b" - integrity sha1-RikF4Nz76pcPQao3Ij3anAexkSs= +blocking-proxy@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/blocking-proxy/-/blocking-proxy-1.0.1.tgz#81d6fd1fe13a4c0d6957df7f91b75e98dac40cb2" + integrity sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA== dependencies: minimist "^1.2.0" @@ -902,6 +897,13 @@ browserstack@1.5.0: dependencies: https-proxy-agent "1.0.0" +browserstack@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.5.1.tgz#e2dfa66ffee940ebad0a07f7e00fd4687c455d66" + integrity sha512-O8VMT64P9NOLhuIoD4YngyxBURefaSdR4QdhG8l6HZ9VxtU7jc3m6jLufFwKA5gaf7fetfB2TnRJnMxyob+heg== + dependencies: + https-proxy-agent "^2.2.1" + browserstacktunnel-wrapper@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.0.tgz#4d6ebf6a667451ad4ee9325fddcf3546607b4d92" @@ -1607,6 +1609,11 @@ core-js@^2.2.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" integrity sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4= +core-js@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65" + integrity sha1-+rg/uwstjchfpjbEudNMdUIMbWU= + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2307,6 +2314,11 @@ es6-promise@^4.0.3: resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" integrity sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ== +es6-promise@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6" + integrity sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y= + es6-promisify@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" @@ -3984,6 +3996,11 @@ iltorb@^1.0.13: dependencies: nan "^2.4.0" +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -4505,7 +4522,7 @@ jade@0.26.3: commander "0.6.1" mkdirp "0.3.0" -jasmine-core@^2.8.0: +jasmine-core@^2.8.0, jasmine-core@~2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e" integrity sha1-vMl5rh+f0FcB5F5S5l06XWPxok4= @@ -4544,7 +4561,16 @@ jasmine-reporters@^2.2.0: mkdirp "^0.5.1" xmldom "^0.1.22" -jasmine@^2.4.1, jasmine@^2.5.3: +jasmine@2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.8.0.tgz#6b089c0a11576b1f16df11b80146d91d4e8b8a3e" + integrity sha1-awicChFXax8W3xG4AUbZHU6Lij4= + dependencies: + exit "^0.1.2" + glob "^7.0.6" + jasmine-core "~2.8.0" + +jasmine@^2.4.1: version "2.5.3" resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.5.3.tgz#5441f254e1fc2269deb1dfd93e0e57d565ff4d22" integrity sha1-VEHyVOH8Imnesd/ZPg5X1WX/TSI= @@ -4657,6 +4683,17 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jszip@^3.1.3: + version "3.1.5" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.1.5.tgz#e3c2a6c6d706ac6e603314036d43cd40beefdf37" + integrity sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ== + dependencies: + core-js "~2.3.0" + es6-promise "~3.0.2" + lie "~3.1.0" + pako "~1.0.2" + readable-stream "~2.0.6" + karma-browserstack-launcher@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/karma-browserstack-launcher/-/karma-browserstack-launcher-1.3.0.tgz#61fe3d36b1cf10681e40f9d874bf37271fb1c674" @@ -4864,6 +4901,13 @@ libqp@1.1.0: resolved "https://registry.yarnpkg.com/libqp/-/libqp-1.1.0.tgz#f5e6e06ad74b794fb5b5b66988bf728ef1dedbe8" integrity sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g= +lie@~3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" + integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4= + dependencies: + immediate "~3.0.5" + liftoff@^2.0.1: version "2.3.0" resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.3.0.tgz#a98f2ff67183d8ba7cfaca10548bd7ff0550b385" @@ -6101,11 +6145,6 @@ optionator@^0.8.1, optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" -options@>=0.0.5: - version "0.0.6" - resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" - integrity sha1-7CLTEoBrtT5zF3Pnza788cZDEo8= - orchestrator@^0.3.0: version "0.3.8" resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" @@ -6197,6 +6236,11 @@ pako@~0.2.0: resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= +pako@~1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" + integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== + param-case@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.0.tgz#2619f90fd6c829ed0b958f1c84ed03a745a6d70a" @@ -6507,25 +6551,26 @@ protochain@^1.0.5: resolved "https://registry.yarnpkg.com/protochain/-/protochain-1.0.5.tgz#991c407e99de264aadf8f81504b5e7faf7bfa260" integrity sha1-mRxAfpneJkqt+PgVBLXn+ve/omA= -protractor@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.1.2.tgz#9b221741709a4c62d5cd53c6aadd54a71137e95f" - integrity sha1-myIXQXCaTGLVzVPGqt1UpxE36V8= +protractor@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.4.1.tgz#011a99e38df7aa45d22455b889ffbb13a6ce0bd9" + integrity sha512-ORey5ewQMYiXQxcQohsqEiKYOg/r5yJoJbt0tuROmmgajdg/CA3gTOZNIFJncUVMAJIk5YFqBBLUjKVmQO6tfA== dependencies: "@types/node" "^6.0.46" "@types/q" "^0.0.32" - "@types/selenium-webdriver" "~2.53.39" - blocking-proxy "0.0.5" + "@types/selenium-webdriver" "^3.0.0" + blocking-proxy "^1.0.0" + browserstack "^1.5.1" chalk "^1.1.3" glob "^7.0.3" - jasmine "^2.5.3" + jasmine "2.8.0" jasminewd2 "^2.1.0" optimist "~0.6.0" q "1.4.1" - saucelabs "~1.3.0" - selenium-webdriver "3.0.1" + saucelabs "^1.5.0" + selenium-webdriver "3.6.0" source-map-support "~0.4.0" - webdriver-js-extender "^1.0.0" + webdriver-js-extender "2.1.0" webdriver-manager "^12.0.6" proxy-addr@~1.1.3: @@ -6828,7 +6873,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.1.5: string_decoder "~0.10.x" util-deprecate "~1.0.1" -readable-stream@~2.0.5: +readable-stream@~2.0.5, readable-stream@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" integrity sha1-j5A0HmilPMySh4jaz80Rs265t44= @@ -7285,17 +7330,12 @@ saucelabs@^1.4.0: dependencies: https-proxy-agent "^1.0.0" -saucelabs@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.3.0.tgz#d240e8009df7fa87306ec4578a69ba3b5c424fee" - integrity sha1-0kDoAJ33+ocwbsRXimm6O1xCT+4= +saucelabs@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.5.0.tgz#9405a73c360d449b232839919a86c396d379fd9d" + integrity sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ== dependencies: - https-proxy-agent "^1.0.0" - -sax@0.6.x: - version "0.6.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-0.6.1.tgz#563b19c7c1de892e09bfc4f2fc30e3c27f0952b9" - integrity sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk= + https-proxy-agent "^2.2.1" sax@>=0.6.0, sax@^1.1.1: version "1.2.2" @@ -7307,26 +7347,25 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -selenium-webdriver@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.0.1.tgz#a2dea5da4a97f6672e89e7ca7276cefa365147a7" - integrity sha1-ot6l2kqX9mcuiefKcnbO+jZRR6c= +selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz#2ba87a1662c020b8988c981ae62cb2a01298eafc" + integrity sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q== dependencies: - adm-zip "^0.4.7" + jszip "^3.1.3" rimraf "^2.5.4" tmp "0.0.30" xml2js "^0.4.17" -selenium-webdriver@^2.53.1, selenium-webdriver@^2.53.2: - version "2.53.3" - resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz#d29ff5a957dff1a1b49dc457756e4e4bfbdce085" - integrity sha1-0p/1qVff8aG0ncRXdW5OS/vc4IU= +selenium-webdriver@^4.0.0-alpha.1: + version "4.0.0-alpha.1" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.1.tgz#cc93415e21d2dc1dfd85dfc5f6b55f3ac53933b1" + integrity sha512-z88rdjHAv3jmTZ7KSGUkTvo4rGzcDGMq0oXWHNIDK96Gs31JKVdu9+FMtT4KBrVoibg8dUicJDok6GnqqttO5Q== dependencies: - adm-zip "0.4.4" - rimraf "^2.2.8" - tmp "0.0.24" - ws "^1.0.1" - xml2js "0.4.4" + jszip "^3.1.3" + rimraf "^2.5.4" + tmp "0.0.30" + xml2js "^0.4.17" "semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.2.0: version "5.3.0" @@ -8250,11 +8289,6 @@ title-case@^2.1.0: no-case "^2.2.0" upper-case "^1.0.3" -tmp@0.0.24: - version "0.0.24" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.24.tgz#d6a5e198d14a9835cc6f2d7c3d9e302428c8cf12" - integrity sha1-1qXhmNFKmDXMby18PZ4wJCjIzxI= - tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" @@ -8443,11 +8477,6 @@ uid-number@^0.0.6: resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= -ultron@1.0.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" - integrity sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po= - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -8791,13 +8820,13 @@ weak-map@1.0.0: resolved "https://registry.yarnpkg.com/weak-map/-/weak-map-1.0.0.tgz#b66e56a9df0bd25a76bbf1b514db129080614a37" integrity sha1-tm5Wqd8L0lp2u/G1FNsSkIBhSjc= -webdriver-js-extender@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-1.0.0.tgz#81c533a9e33d5bfb597b4e63e2cdb25b54777515" - integrity sha1-gcUzqeM9W/tZe05j4s2yW1R3dRU= +webdriver-js-extender@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz#57d7a93c00db4cc8d556e4d3db4b5db0a80c3bb7" + integrity sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ== dependencies: - "@types/selenium-webdriver" "^2.53.35" - selenium-webdriver "^2.53.2" + "@types/selenium-webdriver" "^3.0.0" + selenium-webdriver "^3.0.1" webdriver-manager@^12.0.6: version "12.0.6" @@ -8902,14 +8931,6 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -ws@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.1.tgz#082ddb6c641e85d4bb451f03d52f06eabdb1f018" - integrity sha1-CC3bbGQehdS7RR8D1S8G6r2x8Bg= - dependencies: - options ">=0.0.5" - ultron "1.0.x" - ws@~3.3.1: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -8919,14 +8940,6 @@ ws@~3.3.1: safe-buffer "~5.1.0" ultron "~1.1.0" -xml2js@0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.4.tgz#3111010003008ae19240eba17497b57c729c555d" - integrity sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0= - dependencies: - sax "0.6.x" - xmlbuilder ">=1.0.0" - xml2js@^0.4.17: version "0.4.17" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.17.tgz#17be93eaae3f3b779359c795b419705a8817e868" @@ -8935,7 +8948,7 @@ xml2js@^0.4.17: sax ">=0.6.0" xmlbuilder "^4.1.0" -xmlbuilder@8.2.2, xmlbuilder@>=1.0.0: +xmlbuilder@8.2.2: version "8.2.2" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773" integrity sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M= From 3df4ee421c4679e0d11dc6f6a843c6428b046078 Mon Sep 17 00:00:00 2001 From: Daniel Breen <38893467+dapperdandev@users.noreply.github.com> Date: Fri, 2 Nov 2018 10:21:02 -0600 Subject: [PATCH 112/217] docs(changelog): fix typos, change 'ctrk' to 'ctrl' --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d397c037d003..1f3e17c52ee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -746,7 +746,7 @@ If you rely on the $modelValue validation, you can overwrite the `min`/`max` val link: function(scope, element, attrs, ctrl) { var maxValidator = ctrl.$validators.max; - ctrk.$validators.max = function(modelValue, viewValue) { + ctrl.$validators.max = function(modelValue, viewValue) { return maxValidator(modelValue, modelValue); }; } @@ -1579,7 +1579,7 @@ If you rely on the $modelValue validation, you can overwrite the `min`/`max` val link: function(scope, element, attrs, ctrl) { var maxValidator = ctrl.$validators.max; - ctrk.$validators.max = function(modelValue, viewValue) { + ctrl.$validators.max = function(modelValue, viewValue) { return maxValidator(modelValue, modelValue); }; } From 4e372d93144b4dab7dcaa029fbbc5d7f3f1ceb8c Mon Sep 17 00:00:00 2001 From: Daniel Breen <38893467+dapperdandev@users.noreply.github.com> Date: Fri, 2 Nov 2018 10:22:22 -0600 Subject: [PATCH 113/217] docs(guide/migration): fix typos, change 'ctrk' to 'ctrl' Closes #16754 --- docs/content/guide/migration.ngdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/guide/migration.ngdoc b/docs/content/guide/migration.ngdoc index 74de3a418ffa..66137dbd4cfb 100644 --- a/docs/content/guide/migration.ngdoc +++ b/docs/content/guide/migration.ngdoc @@ -148,7 +148,7 @@ custom directive, as seen in the following example directive definition object: link: function(scope, element, attrs, ctrl) { var maxValidator = ctrl.$validators.max; - ctrk.$validators.max = function(modelValue, viewValue) { + ctrl.$validators.max = function(modelValue, viewValue) { return maxValidator(modelValue, modelValue); }; } From c3f6123de9df6e31e9b2e6806088038d5830a92a Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 6 Nov 2018 16:03:52 +0200 Subject: [PATCH 114/217] chore(package): fix scripts for Node 10.x on Windows --- package.json | 5 +++++ yarn.lock | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b674a91bcaa0..1e25cc44728e 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,11 @@ "stringmap": "^0.2.2" }, "dependencies": {}, + "resolutions": { + "//1": "`natives@1.1.0` does not work with Node.js 10.x on Windows 10", + "//2": "(E.g. see https://github.com/gulpjs/gulp/issues/2162.)", + "natives": "1.1.3" + }, "commitplease": { "style": "angular", "nohook": true diff --git a/yarn.lock b/yarn.lock index 551675822fb2..268669168f1c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5750,10 +5750,10 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -natives@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.0.tgz#e9ff841418a6b2ec7a495e939984f78f163e6e31" - integrity sha1-6f+EFBimsux6SV6TmYT3jxY+bjE= +natives@1.1.3, natives@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.3.tgz#44a579be64507ea2d6ed1ca04a9415915cf75558" + integrity sha512-BZGSYV4YOLxzoTK73l0/s/0sH9l8SHs2ocReMH1f8JYSh5FUWu4ZrKCpJdRkWXV6HFR/pZDz7bwWOVAY07q77g== natural-compare@^1.4.0: version "1.4.0" From 7240f31824b94d22ec382854b7b3dc47100374c2 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 6 Nov 2018 16:05:12 +0200 Subject: [PATCH 115/217] chore(docs): fix rendering of methods' `this` type --- docs/config/templates/ngdoc/lib/methods.template.html | 2 +- docs/config/templates/ngdoc/lib/this.template.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/config/templates/ngdoc/lib/methods.template.html b/docs/config/templates/ngdoc/lib/methods.template.html index 9f449f97cfba..ea9218a568b7 100644 --- a/docs/config/templates/ngdoc/lib/methods.template.html +++ b/docs/config/templates/ngdoc/lib/methods.template.html @@ -17,7 +17,7 @@

Parameters

{% endif %} {% if method.this %} -

Method's {% code %}this{% endcode %}

+

Method's `this`

{$ method.this | marked $} {% endif %} diff --git a/docs/config/templates/ngdoc/lib/this.template.html b/docs/config/templates/ngdoc/lib/this.template.html index 24881972b561..1829c1b374d6 100644 --- a/docs/config/templates/ngdoc/lib/this.template.html +++ b/docs/config/templates/ngdoc/lib/this.template.html @@ -1,4 +1,4 @@ {% if doc.this %} -

Method's {% code %}this{% endcode %}

+

Method's `this`

{$ doc.this | marked $} -{% endif %} \ No newline at end of file +{% endif %} From ba4d9035860fc23944c12b5e39d5da4ab4faf4bf Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 6 Nov 2018 16:06:26 +0200 Subject: [PATCH 116/217] chore(i18n): fix UCD extraction for Node 10.x Previously (e.g. Node.js 8.x), the 3rd argument to `fs.writeFile()` (i.e. the callback) could be undefined. On Node.js 10.x, this throws an error. This commit fixes it by switching to `fs.writeFileSync()` which seems to have been the original intention (based on the sorrounding code). --- i18n/ucd/src/extract.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/ucd/src/extract.js b/i18n/ucd/src/extract.js index ae8493fd2b74..bc6736597d77 100644 --- a/i18n/ucd/src/extract.js +++ b/i18n/ucd/src/extract.js @@ -20,7 +20,7 @@ function main() { } catch (e) { fs.mkdirSync(__dirname + '/../../../src/ngParseExt'); } - fs.writeFile(__dirname + '/../../../src/ngParseExt/ucd.js', code); + fs.writeFileSync(__dirname + '/../../../src/ngParseExt/ucd.js', code); } } From 06d154f91c67250864c590ce20c5ad5cf03a3191 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 8 Nov 2018 12:41:10 +0200 Subject: [PATCH 117/217] test($compile): fix incorrect markup in tests --- test/ng/compileSpec.js | 14 +++++++------- test/ng/ngPropSpec.js | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 48b5e565e088..2dd80560509c 100644 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -11703,37 +11703,37 @@ describe('$compile', function() { // All interpolations are disallowed. $rootScope.onClickJs = ''; expect(function() { - $compile(''); }).toThrowMinErr( '$compile', 'nodomevents', 'Interpolations for HTML DOM event attributes are disallowed'); expect(function() { - $compile(''); }).toThrowMinErr( '$compile', 'nodomevents', 'Interpolations for HTML DOM event attributes are disallowed'); expect(function() { - $compile(''); }).toThrowMinErr( '$compile', 'nodomevents', 'Interpolations for HTML DOM event attributes are disallowed'); expect(function() { - $compile(''); }).toThrowMinErr( '$compile', 'nodomevents', 'Interpolations for HTML DOM event attributes are disallowed'); })); it('should pass through arbitrary values on onXYZ event attributes that contain a hyphen', inject(function($compile, $rootScope) { - element = $compile('')($rootScope); $rootScope.onClickJs = 'javascript:doSomething()'; $rootScope.$apply(); expect(element.attr('on-click')).toEqual('javascript:doSomething()'); })); it('should pass through arbitrary values on "on" and "data-on" attributes', inject(function($compile, $rootScope) { - element = $compile('')($rootScope); $rootScope.dataOnVar = 'data-on text'; $rootScope.$apply(); expect(element.attr('data-on')).toEqual('data-on text'); - element = $compile('')($rootScope); $rootScope.onVar = 'on text'; $rootScope.$apply(); expect(element.attr('on')).toEqual('on text'); diff --git a/test/ng/ngPropSpec.js b/test/ng/ngPropSpec.js index 71bf67a5a5fb..9b4f9fab0637 100644 --- a/test/ng/ngPropSpec.js +++ b/test/ng/ngPropSpec.js @@ -147,11 +147,11 @@ describe('ngProp*', function() { it('should disallow property binding to onclick', inject(function($compile, $rootScope) { // All event prop bindings are disallowed. expect(function() { - $compile(''); }).toThrowMinErr( '$compile', 'nodomevents', 'Property bindings for HTML DOM event properties are disallowed'); expect(function() { - $compile(''); }).toThrowMinErr( '$compile', 'nodomevents', 'Property bindings for HTML DOM event properties are disallowed'); })); From 736e299ef3eb6f0acd36e242ead755998d27c48f Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 8 Nov 2018 12:57:35 +0200 Subject: [PATCH 118/217] test(ngOn*): add tests for binding to camelCased event names Closes #16757 --- test/ng/ngOnSpec.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/ng/ngOnSpec.js b/test/ng/ngOnSpec.js index 9da918e881c2..30dd92778392 100644 --- a/test/ng/ngOnSpec.js +++ b/test/ng/ngOnSpec.js @@ -155,4 +155,34 @@ describe('ngOn* event binding', function() { expect(attrs.$attr.ngOnTitle).toBe('ng-on-title'); }); }); + + it('should correctly bind to kebab-cased event names', inject(function($compile, $rootScope) { + var element = $compile('')($rootScope); + var cb = $rootScope.cb = jasmine.createSpy('ng-on cb'); + $rootScope.$digest(); + + element.triggerHandler('foobar'); + element.triggerHandler('fooBar'); + element.triggerHandler('foo_bar'); + element.triggerHandler('foo:bar'); + expect(cb).not.toHaveBeenCalled(); + + element.triggerHandler('foo-bar'); + expect(cb).toHaveBeenCalled(); + })); + + it('should correctly bind to camelCased event names', inject(function($compile, $rootScope) { + var element = $compile('')($rootScope); + var cb = $rootScope.cb = jasmine.createSpy('ng-on cb'); + $rootScope.$digest(); + + element.triggerHandler('foobar'); + element.triggerHandler('foo-bar'); + element.triggerHandler('foo_bar'); + element.triggerHandler('foo:bar'); + expect(cb).not.toHaveBeenCalled(); + + element.triggerHandler('fooBar'); + expect(cb).toHaveBeenCalled(); + })); }); From 362dd1786f585594de8295144dd161dc425e6676 Mon Sep 17 00:00:00 2001 From: teresy <43420401+teresy@users.noreply.github.com> Date: Thu, 18 Oct 2018 22:38:29 -0400 Subject: [PATCH 119/217] refactor(production): remove duplicate expression Remove a duplicate expression (the left and right sides both check `versionInfo.currentVersion.version`). [48f0957](https://github.com/angular/angular.js/blob/48f0957dde728b050e2d8f76db81cbf12cffd42a/docs/config/services/deployments/production.js#L18) is the most recent commit I found where these expressions differ. My best guess is the duplicated expression can be removed. Closes #16738 --- docs/config/services/deployments/production.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config/services/deployments/production.js b/docs/config/services/deployments/production.js index 7a8cace0d53e..a37c127df593 100644 --- a/docs/config/services/deployments/production.js +++ b/docs/config/services/deployments/production.js @@ -15,7 +15,7 @@ var cdnUrl = googleCdnUrl + versionInfo.cdnVersion; // docs.angularjs.org and code.angularjs.org need them. var versionPath = versionInfo.currentVersion.isSnapshot ? 'snapshot' : - (versionInfo.currentVersion.version || versionInfo.currentVersion.version); + versionInfo.currentVersion.version; var examplesDependencyPath = angularCodeUrl + versionPath + '/'; module.exports = function productionDeployment(getVersion) { From 1a14b58c6e3899cb791f7ccd73be1edf794c1879 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Fri, 2 Nov 2018 16:38:46 +0200 Subject: [PATCH 120/217] docs(tutotial): switch all links to `https` --- docs/content/tutorial/index.ngdoc | 12 ++++++------ docs/content/tutorial/step_00.ngdoc | 3 ++- docs/content/tutorial/step_02.ngdoc | 6 +++--- docs/content/tutorial/step_03.ngdoc | 6 +++--- docs/content/tutorial/step_09.ngdoc | 2 +- docs/content/tutorial/step_13.ngdoc | 2 +- docs/content/tutorial/step_14.ngdoc | 8 ++++---- docs/content/tutorial/the_end.ngdoc | 2 +- 8 files changed, 21 insertions(+), 20 deletions(-) diff --git a/docs/content/tutorial/index.ngdoc b/docs/content/tutorial/index.ngdoc index 823f91d7634d..a066a179a4d9 100644 --- a/docs/content/tutorial/index.ngdoc +++ b/docs/content/tutorial/index.ngdoc @@ -64,7 +64,7 @@ a few git commands. ### Install Git -You can download and install Git from http://git-scm.com/download. Once installed, you should have +You can download and install Git from https://git-scm.com/download. Once installed, you should have access to the `git` command line tool. The main commands that you will need to use are: * `git clone ...`: Clone a remote repository onto your local machine. @@ -324,14 +324,14 @@ Now that you have set up your local machine, let's get started with the tutorial [angular-phonecat]: https://github.com/angular/angular-phonecat -[bower]: http://bower.io/ -[git]: http://git-scm.com/ +[bower]: https://bower.io/ +[git]: https://git-scm.com/ [http-server]: https://github.com/nodeapps/http-server [jdk]: https://en.wikipedia.org/wiki/Java_Development_Kit -[jdk-download]: http://www.oracle.com/technetwork/java/javase/downloads/index.html +[jdk-download]: https://www.oracle.com/technetwork/java/javase/downloads/index.html [karma]: https://karma-runner.github.io/ -[node]: http://nodejs.org/ +[node]: https://nodejs.org/ [nvm]: https://github.com/creationix/nvm [nvm-windows]: https://github.com/coreybutler/nvm-windows [protractor]: https://github.com/angular/protractor -[selenium]: http://docs.seleniumhq.org/ +[selenium]: https://docs.seleniumhq.org/ diff --git a/docs/content/tutorial/step_00.ngdoc b/docs/content/tutorial/step_00.ngdoc index 4aca8850cfe6..58dc5b03343b 100644 --- a/docs/content/tutorial/step_00.ngdoc +++ b/docs/content/tutorial/step_00.ngdoc @@ -163,7 +163,7 @@ For the purposes of this tutorial, we modified the angular-seed with the followi * Removed unused dependencies. * Added phone images to `app/img/phones/`. * Added phone data files (JSON) to `app/phones/`. -* Added a dependency on [Bootstrap](http://getbootstrap.com) in the `bower.json` file. +* Added a dependency on [Bootstrap][bootstrap-3.3] in the `bower.json` file. ## Experiments @@ -186,3 +186,4 @@ Now let's go to {@link step_01 step 1} and add some content to the web app. [angular-seed]: https://github.com/angular/angular-seed +[bootstrap-3.3]: https://getbootstrap.com/docs/3.3 diff --git a/docs/content/tutorial/step_02.ngdoc b/docs/content/tutorial/step_02.ngdoc index 6b4a54388b3c..63d8a1337686 100644 --- a/docs/content/tutorial/step_02.ngdoc +++ b/docs/content/tutorial/step_02.ngdoc @@ -317,7 +317,7 @@ by utilizing components.
    -[jasmine-docs]: http://jasmine.github.io/2.4/introduction.html -[jasmine-home]: http://jasmine.github.io/ +[jasmine-docs]: https://jasmine.github.io/2.4/introduction.html +[jasmine-home]: https://jasmine.github.io/ [karma]: https://karma-runner.github.io/ -[mvc-pattern]: http://en.wikipedia.org/wiki/Model–View–Controller +[mvc-pattern]: https://en.wikipedia.org/wiki/Model–View–Controller diff --git a/docs/content/tutorial/step_03.ngdoc b/docs/content/tutorial/step_03.ngdoc index e7a16de54bd0..65f13d3dd6de 100644 --- a/docs/content/tutorial/step_03.ngdoc +++ b/docs/content/tutorial/step_03.ngdoc @@ -277,7 +277,7 @@ files, so it remains easy to locate as our application grows. [case-styles]: https://en.wikipedia.org/wiki/Letter_case#Special_case_styles -[jasmine-docs]: http://jasmine.github.io/2.4/introduction.html -[jasmine-home]: http://jasmine.github.io/ +[jasmine-docs]: https://jasmine.github.io/api/3.3/global +[jasmine-home]: https://jasmine.github.io/ [karma]: https://karma-runner.github.io/ -[mvc-pattern]: http://en.wikipedia.org/wiki/Model–View–Controller +[mvc-pattern]: https://en.wikipedia.org/wiki/Model–View–Controller diff --git a/docs/content/tutorial/step_09.ngdoc b/docs/content/tutorial/step_09.ngdoc index da1e92a7dfc6..e10f4b9bdac1 100644 --- a/docs/content/tutorial/step_09.ngdoc +++ b/docs/content/tutorial/step_09.ngdoc @@ -424,6 +424,6 @@ With the routing set up and the phone list view implemented, we are ready to go
      -[bower]: http://bower.io +[bower]: https://bower.io/ [deep-linking]: https://en.wikipedia.org/wiki/Deep_linking [wiki-di]: https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection diff --git a/docs/content/tutorial/step_13.ngdoc b/docs/content/tutorial/step_13.ngdoc index 2ad46e2c9459..22e5ef607312 100644 --- a/docs/content/tutorial/step_13.ngdoc +++ b/docs/content/tutorial/step_13.ngdoc @@ -319,6 +319,6 @@ Now that we have seen how to build a custom service as a RESTful client, we are
        -[bower]: http://bower.io/ +[bower]: https://bower.io/ [jasmine-equality]: https://jasmine.github.io/2.4/custom_equality.html [restful]: https://en.wikipedia.org/wiki/Representational_State_Transfer diff --git a/docs/content/tutorial/step_14.ngdoc b/docs/content/tutorial/step_14.ngdoc index 40667717ebee..375690d857d8 100644 --- a/docs/content/tutorial/step_14.ngdoc +++ b/docs/content/tutorial/step_14.ngdoc @@ -556,9 +556,9 @@ There you have it! We have created a web application in a relatively short amoun
          -[bower]: http://bower.io/ -[caniuse-css-animation]: http://caniuse.com/#feat=css-animation -[caniuse-css-transitions]: http://caniuse.com/#feat=css-transitions +[bower]: https://bower.io/ +[caniuse-css-animation]: https://caniuse.com/#feat=css-animation +[caniuse-css-transitions]: https://caniuse.com/#feat=css-transitions [jquery]: https://jquery.com/ -[jquery-animate]: https://api.jquery.com/animate/ +[jquery-animate]: https://api.jquery.com/animate [mdn-animations]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations diff --git a/docs/content/tutorial/the_end.ngdoc b/docs/content/tutorial/the_end.ngdoc index 84dc09246c8a..6b5e3fe94122 100644 --- a/docs/content/tutorial/the_end.ngdoc +++ b/docs/content/tutorial/the_end.ngdoc @@ -22,5 +22,5 @@ If you have questions or feedback or just want to say "hi", please post a messag [angular-seed]: https://github.com/angular/angular-seed [gitter]: https://gitter.im/angular/angular.js -[irc]: http://webchat.freenode.net/?channels=angularjs&uio=d4 +[irc]: https://webchat.freenode.net/?channels=angularjs&uio=d4 [mailing-list]: https://groups.google.com/forum/#!forum/angular From b77f0585053af0fffacc8e433bb07a46115c5d45 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Fri, 2 Nov 2018 16:41:12 +0200 Subject: [PATCH 121/217] docs(tutorial): switch from `bower` to `npm` and upgrade AngularJS to 1.7.x Related: angular/angular-phonecat#430 --- docs/content/tutorial/index.ngdoc | 39 +++++++------ docs/content/tutorial/step_00.ngdoc | 12 ++-- docs/content/tutorial/step_02.ngdoc | 4 +- docs/content/tutorial/step_03.ngdoc | 2 +- docs/content/tutorial/step_07.ngdoc | 4 +- docs/content/tutorial/step_08.ngdoc | 9 +-- docs/content/tutorial/step_09.ngdoc | 87 +++++++++++++---------------- docs/content/tutorial/step_13.ngdoc | 55 +++++++----------- docs/content/tutorial/step_14.ngdoc | 64 ++++++++------------- 9 files changed, 119 insertions(+), 157 deletions(-) diff --git a/docs/content/tutorial/index.ngdoc b/docs/content/tutorial/index.ngdoc index a066a179a4d9..3f8e417bdd76 100644 --- a/docs/content/tutorial/index.ngdoc +++ b/docs/content/tutorial/index.ngdoc @@ -99,8 +99,8 @@ The tutorial instructions, from now on, assume you are running all commands from ### Install Node.js -If you want to run the preconfigured local web server and the test tools then you will also need -[Node.js v4+][node]. +In order to install dependencies (such as the test tools and AngularJS itself) and run the +preconfigured local web server, you will also need [Node.js v6+][node]. You can download a Node.js installer for your operating system from https://nodejs.org/en/download/. @@ -125,22 +125,25 @@ npm --version [Node Version Manager (nvm)][nvm] or [Node Version Manager (nvm) for Windows][nvm-windows].
          -Once you have Node.js installed on your machine, you can download the tool dependencies by running: +By installing Node.js, you also get [npm][npm], which is a command line executable for downloading +and managing Node.js packages. We use it to download the AngularJS framework as well as development +and testing tools. + +Once you have Node.js installed on your machine, you can download these dependencies by running: ``` npm install ``` -This command reads angular-phonecat's `package.json` file and downloads the following tools into the -`node_modules` directory: +This command reads angular-phonecat's `package.json` file and downloads the following dependencies +into the `node_modules` directory: -* [Bower][bower] - client-side code package manager * [Http-Server][http-server] - simple local static web server * [Karma][karma] - unit test runner * [Protractor][protractor] - end-to-end (E2E) test runner -Running `npm install` will also automatically use bower to download the AngularJS framework into the -`app/bower_components` directory. +Running `npm install` will also automatically copy the AngularJS framework and other dependencies +necessary for our app to work into the `app/lib/` directory.
          Note the angular-phonecat project is setup to install and run these utilities via npm scripts. @@ -160,23 +163,23 @@ tasks that you will need while developing: ### Install Helper Tools (optional) -The Bower, Http-Server, Karma and Protractor modules are also executables, which can be installed -globally and run directly from a terminal/command prompt. You don't need to do this to follow the -tutorial, but if you decide you do want to run them directly, you can install these modules globally -using, `sudo npm install -g ...`. +The Http-Server, Karma and Protractor modules are also executables, which can be installed globally +and run directly from a terminal/command prompt. You don't need to do this to follow the tutorial, +but if you decide you do want to run them directly, you can install these modules globally using, +`sudo npm install --global ...`. -For instance, to install the Bower command line executable you would do: +For instance, to install the `http-server` command line executable you would do: ``` -sudo npm install -g bower +sudo npm install --global http-server ``` -_(Omit the sudo if running on Windows)_ +_(Omit the sudo if running on Windows.)_ -Then you can run the bower tool directly, such as: +Then you can run the `http-server` tool directly, such as: ``` -bower install +http-server ./app ``` @@ -324,13 +327,13 @@ Now that you have set up your local machine, let's get started with the tutorial [angular-phonecat]: https://github.com/angular/angular-phonecat -[bower]: https://bower.io/ [git]: https://git-scm.com/ [http-server]: https://github.com/nodeapps/http-server [jdk]: https://en.wikipedia.org/wiki/Java_Development_Kit [jdk-download]: https://www.oracle.com/technetwork/java/javase/downloads/index.html [karma]: https://karma-runner.github.io/ [node]: https://nodejs.org/ +[npm]: https://www.npmjs.com/ [nvm]: https://github.com/creationix/nvm [nvm-windows]: https://github.com/coreybutler/nvm-windows [protractor]: https://github.com/angular/protractor diff --git a/docs/content/tutorial/step_00.ngdoc b/docs/content/tutorial/step_00.ngdoc index 58dc5b03343b..c09f5d38dbbd 100644 --- a/docs/content/tutorial/step_00.ngdoc +++ b/docs/content/tutorial/step_00.ngdoc @@ -51,8 +51,8 @@ The code contains some key AngularJS elements that we will need as we progress. My HTML File - - + + @@ -84,7 +84,7 @@ For more info on `ngApp`, check out the {@link ngApp API Reference}. **`angular.js` script tag:** ```html - + ``` This code downloads the `angular.js` script which registers a callback that will be executed by the @@ -154,8 +154,8 @@ and one static binding, and our model is empty. That will soon change! Most of the files in your working directory come from the [angular-seed project][angular-seed], which is typically used to bootstrap new AngularJS projects. The seed project is pre-configured to -install the AngularJS framework (via `bower` into the `app/bower_components/` directory) and tools -for developing and testing a typical web application (via `npm`). +install the AngularJS framework (via `npm` into the `app/lib/` directory) and tools for developing +and testing a typical web application (via `npm`). For the purposes of this tutorial, we modified the angular-seed with the following changes: @@ -163,7 +163,7 @@ For the purposes of this tutorial, we modified the angular-seed with the followi * Removed unused dependencies. * Added phone images to `app/img/phones/`. * Added phone data files (JSON) to `app/phones/`. -* Added a dependency on [Bootstrap][bootstrap-3.3] in the `bower.json` file. +* Added a dependency on [Bootstrap][bootstrap-3.3] in the `package.json` file. ## Experiments diff --git a/docs/content/tutorial/step_02.ngdoc b/docs/content/tutorial/step_02.ngdoc index 63d8a1337686..226ab7d71ffe 100644 --- a/docs/content/tutorial/step_02.ngdoc +++ b/docs/content/tutorial/step_02.ngdoc @@ -33,7 +33,7 @@ The view is constructed by AngularJS from this template. ... - + @@ -317,7 +317,7 @@ by utilizing components.
            -[jasmine-docs]: https://jasmine.github.io/2.4/introduction.html +[jasmine-docs]: https://jasmine.github.io/api/3.3/global [jasmine-home]: https://jasmine.github.io/ [karma]: https://karma-runner.github.io/ [mvc-pattern]: https://en.wikipedia.org/wiki/Model–View–Controller diff --git a/docs/content/tutorial/step_03.ngdoc b/docs/content/tutorial/step_03.ngdoc index 65f13d3dd6de..ab8179b849a8 100644 --- a/docs/content/tutorial/step_03.ngdoc +++ b/docs/content/tutorial/step_03.ngdoc @@ -120,7 +120,7 @@ acquired skill. ... - + diff --git a/docs/content/tutorial/step_07.ngdoc b/docs/content/tutorial/step_07.ngdoc index 4b0d0e64aaaa..c0ef13d2497a 100644 --- a/docs/content/tutorial/step_07.ngdoc +++ b/docs/content/tutorial/step_07.ngdoc @@ -8,8 +8,8 @@ Enough of building an app with three phones in a hard-coded dataset! Let's fetch a larger dataset from our server using one of AngularJS's built-in {@link guide/services services} called -{@link ng.$http $http}. We will use AngularJS's {@link guide/di dependency injection (DI)} to provide -the service to the `phoneList` component's controller. +{@link ng.$http $http}. We will use AngularJS's {@link guide/di dependency injection (DI)} to +provide the service to the `phoneList` component's controller. * There is now a list of 20 phones, loaded from the server. diff --git a/docs/content/tutorial/step_08.ngdoc b/docs/content/tutorial/step_08.ngdoc index 5707ea4d9902..04329660c786 100644 --- a/docs/content/tutorial/step_08.ngdoc +++ b/docs/content/tutorial/step_08.ngdoc @@ -47,10 +47,10 @@ URLs point to the `app/img/phones/` directory. ... @@ -110,8 +110,9 @@ You can now rerun `npm run protractor` to see the tests run. ## Summary -Now that you have added phone images and links, go to {@link step_09 step 9} to learn about AngularJS -layout templates and how AngularJS makes it easy to create applications that have multiple views. +Now that you have added phone images and links, go to {@link step_09 step 9} to learn about +AngularJS layout templates and how AngularJS makes it easy to create applications that have +multiple views.
              diff --git a/docs/content/tutorial/step_09.ngdoc b/docs/content/tutorial/step_09.ngdoc index e10f4b9bdac1..555e382c5cc0 100644 --- a/docs/content/tutorial/step_09.ngdoc +++ b/docs/content/tutorial/step_09.ngdoc @@ -23,49 +23,33 @@ has multiple views by adding routing, using an AngularJS module called {@link ng The routing functionality added in this step is provided by AngularJS in the `ngRoute` module, which is distributed separately from the core AngularJS framework. -Since we are using [Bower][bower] to install client-side dependencies, this step updates the -`bower.json` configuration file to include the new dependency: +Since we are using [npm][npm] to install client-side dependencies, this step updates the +`package.json` configuration file to include the new dependency:
              -**`bower.json`:** +**`package.json`:** ```json { "name": "angular-phonecat", - "description": "A starter project for AngularJS", - "version": "0.0.0", - "homepage": "https://github.com/angular/angular-phonecat", - "license": "MIT", - "private": true, + ... "dependencies": { - "angular": "1.5.x", - "angular-mocks": "1.5.x", - "angular-route": "1.5.x", + "angular": "1.7.x", + "angular-route": "1.7.x", "bootstrap": "3.3.x" - } + }, + ... } ``` -The new dependency `"angular-route": "1.5.x"` tells bower to install a version of the angular-route -module that is compatible with version 1.5.x of AngularJS. We must tell bower to download and install +The new dependency `"angular-route": "1.7.x"` tells npm to install a version of the angular-route +module that is compatible with version 1.7.x of AngularJS. We must tell npm to download and install this dependency. ``` npm install ``` -
              - **Note:** If you have bower installed globally, you can run `bower install`, but for this project - we have preconfigured `npm install` to run bower for us. -
              - -
              - **Warning:** If a new version of AngularJS has been released since you last ran `npm install`, then - you may have a problem with the `bower install` due to a conflict between the versions of - angular.js that need to be installed. If you run into this issue, simply delete your - `app/bower_components` directory and then run `npm install`. -
              - ## Multiple Views, Routing and Layout Templates @@ -127,8 +111,8 @@ service, the `$routeProvider` exposes APIs that allow you to define routes for y
              AngularJS modules solve the problem of removing global variables from the application and provide a -way of configuring the injector. As opposed to AMD or require.js modules, AngularJS modules don't try -to solve the problem of script load ordering or lazy script fetching. These goals are totally +way of configuring the injector. As opposed to AMD or require.js modules, AngularJS modules don't +try to solve the problem of script load ordering or lazy script fetching. These goals are totally independent and both module systems can live side-by-side and fulfill their goals. To deepen your understanding on AngularJS's DI, see [Understanding Dependency Injection][wiki-di]. @@ -146,8 +130,8 @@ into the layout template. This makes it a perfect fit for our `index.html` templ ```html ... - - + + ... @@ -203,10 +187,8 @@ code, we put it into a separate file and used the `.config` suffix. ```js angular. module('phonecatApp'). - config(['$locationProvider', '$routeProvider', - function config($locationProvider, $routeProvider) { - $locationProvider.hashPrefix('!'); - + config(['$routeProvider', + function config($routeProvider) { $routeProvider. when('/phones', { template: '' @@ -226,18 +208,6 @@ the corresponding services. Here, we use the {@link ngRoute.$routeProvider#otherwise $routeProvider.otherwise()} methods to define our application routes. -
              -

              - We also used {@link $locationProvider#hashPrefix $locationProvider.hashPrefix()} to set the - hash-prefix to `!`. This prefix will appear in the links to our client-side routes, right after - the hash (`#`) symbol and before the actual path (e.g. `index.html#!/some/path`). -

              -

              - Setting a prefix is not necessary, but it is considered a good practice (for reasons that are - outside the scope of this tutorial). `!` is the most commonly used prefix. -

              -
              - Our routes are defined as follows: * `when('/phones')`: Determines the view that will be shown, when the URL hash fragment is @@ -261,6 +231,25 @@ the route declaration — `'/phones/:phoneId'` — as a template that is matched URL. All variables defined with the `:` prefix are extracted into the (injectable) {@link ngRoute.$routeParams $routeParams} object. +
              +

              + You may have noticed, that — while the configured route paths start with `/` (e.g. + `/phones`) — the URLs used in templates start with `#!/` (e.g. `#!/phones`). +

              +

              + Without getting into much detail, AngularJS (by default) uses the hash part of the URL (i.e. + what comes after the hash (`#`) symbol) to determine the current route. In addition to that, you + can also specify a {@link $locationProvider#hashPrefix hash-prefix} (`!` by default) that needs + to appear after the hash symbol in order for AngularJS to consider the value an "AngularJS path" + and process it (for example, try to match it to a route). +

              +

              + You can find out more about how all this works in the [Using $location](guide/$location) section + of the Developer Guide. But all you need to know for now, is that the URLs to our various routes + should be prefixed with `#!`. +

              +
              + ## The `phoneDetail` Component @@ -345,8 +334,8 @@ any modification. ```js files: [ - 'bower_components/angular/angular.js', - 'bower_components/angular-route/angular-route.js', + 'lib/angular/angular.js', + 'lib/angular-route/angular-route.js', ... ], ``` @@ -424,6 +413,6 @@ With the routing set up and the phone list view implemented, we are ready to go
                -[bower]: https://bower.io/ [deep-linking]: https://en.wikipedia.org/wiki/Deep_linking +[npm]: https://www.npmjs.com/ [wiki-di]: https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection diff --git a/docs/content/tutorial/step_13.ngdoc b/docs/content/tutorial/step_13.ngdoc index 22e5ef607312..9a09f417a238 100644 --- a/docs/content/tutorial/step_13.ngdoc +++ b/docs/content/tutorial/step_13.ngdoc @@ -21,50 +21,34 @@ In this step, we will change the way our application fetches data. The RESTful functionality is provided by AngularJS in the {@link ngResource ngResource} module, which is distributed separately from the core AngularJS framework. -Since we are using [Bower][bower] to install client-side dependencies, this step updates the -`bower.json` configuration file to include the new dependency: +Since we are using [npm][npm] to install client-side dependencies, this step updates the +`package.json` configuration file to include the new dependency:
                -**`bower.json`:** +**`package.json`:** -``` +```json { "name": "angular-phonecat", - "description": "A starter project for AngularJS", - "version": "0.0.0", - "homepage": "https://github.com/angular/angular-phonecat", - "license": "MIT", - "private": true, + ... "dependencies": { - "angular": "1.5.x", - "angular-mocks": "1.5.x", - "angular-resource": "1.5.x", - "angular-route": "1.5.x", + "angular": "1.7.x", + "angular-resource": "1.7.x", + "angular-route": "1.7.x", "bootstrap": "3.3.x" - } + }, + ... } ``` -The new dependency `"angular-resource": "1.5.x"` tells bower to install a version of the -angular-resource module that is compatible with version 1.5.x of AngularJS. We must tell bower to +The new dependency `"angular-resource": "1.7.x"` tells npm to install a version of the +angular-resource module that is compatible with version 1.7.x of AngularJS. We must tell npm to download and install this dependency. ``` npm install ``` -
                - **Note:** If you have bower installed globally, you can run `bower install`, but for this project - we have preconfigured `npm install` to run bower for us. -
                - -
                - **Warning:** If a new version of AngularJS has been released since you last ran `npm install`, then - you may have a problem with the `bower install` due to a conflict between the versions of - angular.js that need to be installed. If you run into this issue, simply delete your - `app/bower_components` directory and then run `npm install`. -
                - ## Service @@ -129,7 +113,7 @@ need to load the `angular-resource.js` file, which contains the `ngResource` mod ```html ... - + ... @@ -141,9 +125,10 @@ need to load the `angular-resource.js` file, which contains the `ngResource` mod ## Component Controllers We can now simplify our component controllers (`PhoneListController` and `PhoneDetailController`) by -factoring out the lower-level `$http` service, replacing it with the new `Phone` service. AngularJS's -`$resource` service is easier to use than `$http` for interacting with data sources exposed as -RESTful resources. It is also easier now to understand what the code in our controllers is doing. +factoring out the lower-level `$http` service, replacing it with the new `Phone` service. +AngularJS's `$resource` service is easier to use than `$http` for interacting with data sources +exposed as RESTful resources. It is also easier now to understand what the code in our controllers +is doing.
                **`app/phone-list/phone-list.module.js`:** @@ -240,8 +225,8 @@ Karma configuration file with angular-resource. ```js files: [ - 'bower_components/angular/angular.js', - 'bower_components/angular-resource/angular-resource.js', + 'lib/angular/angular.js', + 'lib/angular-resource/angular-resource.js', ... ], ``` @@ -319,6 +304,6 @@ Now that we have seen how to build a custom service as a RESTful client, we are
                  -[bower]: https://bower.io/ [jasmine-equality]: https://jasmine.github.io/2.4/custom_equality.html +[npm]: https://www.npmjs.com/ [restful]: https://en.wikipedia.org/wiki/Representational_State_Transfer diff --git a/docs/content/tutorial/step_14.ngdoc b/docs/content/tutorial/step_14.ngdoc index 375690d857d8..f7b09777ae02 100644 --- a/docs/content/tutorial/step_14.ngdoc +++ b/docs/content/tutorial/step_14.ngdoc @@ -22,59 +22,43 @@ the template code we created earlier. ## Dependencies The animation functionality is provided by AngularJS in the `ngAnimate` module, which is distributed -separately from the core AngularJS framework. In addition we will use [jQuery][jquery] in this project -to do extra JavaScript animations. +separately from the core AngularJS framework. In addition we will use [jQuery][jquery] in this +project to do extra JavaScript animations. -Since we are using [Bower][bower] to install client-side dependencies, this step updates the -`bower.json` configuration file to include the new dependencies: +Since we are using [npm][npm] to install client-side dependencies, this step updates the +`package.json` configuration file to include the new dependencies:
                  -**`bower.json`:** +**`package.json`:** -``` +```json { "name": "angular-phonecat", - "description": "A starter project for AngularJS", - "version": "0.0.0", - "homepage": "https://github.com/angular/angular-phonecat", - "license": "MIT", - "private": true, + ... "dependencies": { - "angular": "1.5.x", - "angular-animate": "1.5.x", - "angular-mocks": "1.5.x", - "angular-resource": "1.5.x", - "angular-route": "1.5.x", + "angular": "1.7.x", + "angular-animate": "1.7.x", + "angular-resource": "1.7.x", + "angular-route": "1.7.x", "bootstrap": "3.3.x", - "jquery": "3.2.x" - } + "jquery": "3.3.x" + }, + ... } ``` -* `"angular-animate": "1.5.x"` tells bower to install a version of the angular-animate module that - is compatible with version 1.5.x of AngularJS. -* `"jquery": "3.2.x"` tells bower to install the latest patch release of the 3.2 version of jQuery. - Note that this is not an AngularJS library; it is the standard jQuery library. We can use bower to +* `"angular-animate": "1.7.x"` tells npm to install a version of the angular-animate module that + is compatible with version 1.7.x of AngularJS. +* `"jquery": "3.3.x"` tells npm to install the latest patch release of the 3.3 version of jQuery. + Note that this is not an AngularJS library; it is the standard jQuery library. We can use npm to install a wide range of 3rd party libraries. -Now, we must tell bower to download and install these dependencies. +Now, we must tell npm to download and install these dependencies. ``` npm install ``` -
                  - **Note:** If you have bower installed globally, you can run `bower install`, but for this project - we have preconfigured `npm install` to run bower for us. -
                  - -
                  - **Warning:** If a new version of AngularJS has been released since you last ran `npm install`, then - you may have a problem with the `bower install` due to a conflict between the versions of - angular.js that need to be installed. If you run into this issue, simply delete your - `app/bower_components` directory and then run `npm install`. -
                  - ## How Animations work with `ngAnimate` @@ -101,12 +85,12 @@ code necessary to make your application "animation aware". ... - + ... - + @@ -115,8 +99,8 @@ code necessary to make your application "animation aware". ```
                  - **Important:** Be sure to use jQuery version 2.1 or newer, when using AngularJS 1.5 or newer; jQuery 1.x is - not officially supported. + **Important:** Be sure to use jQuery version 2.1 or newer, when using AngularJS 1.5 or newer; + jQuery 1.x is not officially supported. In order for AngularJS to detect jQuery and take advantage of it, make sure to include `jquery.js` before `angular.js`.
                  @@ -556,9 +540,9 @@ There you have it! We have created a web application in a relatively short amoun
                    -[bower]: https://bower.io/ [caniuse-css-animation]: https://caniuse.com/#feat=css-animation [caniuse-css-transitions]: https://caniuse.com/#feat=css-transitions [jquery]: https://jquery.com/ [jquery-animate]: https://api.jquery.com/animate [mdn-animations]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations +[npm]: https://www.npmjs.com/ From a48c47fec0e44bbc7eeae2ea1fb8b40cf93ad231 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Fri, 2 Nov 2018 16:48:48 +0200 Subject: [PATCH 122/217] docs(tutorial): replace `getLocationAbsUrl()` with `getCurrentUrl()` Protractor's `browser.getLocationAbsUrl()` has been deprecated and `browser.getCurrentUrl()` is the recommended alternative. Related: angular/angular-phonecat#430 --- docs/content/tutorial/step_08.ngdoc | 2 +- docs/content/tutorial/step_09.ngdoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/tutorial/step_08.ngdoc b/docs/content/tutorial/step_08.ngdoc index 04329660c786..1e4623a09a9d 100644 --- a/docs/content/tutorial/step_08.ngdoc +++ b/docs/content/tutorial/step_08.ngdoc @@ -83,7 +83,7 @@ HTTP request to an invalid location. query.sendKeys('nexus'); element.all(by.css('.phones li a')).first().click(); - expect(browser.getLocationAbsUrl()).toBe('/phones/nexus-s'); + expect(browser.getCurrentUrl()).toContain('index.html#!/phones/nexus-s'); }); ... diff --git a/docs/content/tutorial/step_09.ngdoc b/docs/content/tutorial/step_09.ngdoc index 555e382c5cc0..a6d3d7c652e1 100644 --- a/docs/content/tutorial/step_09.ngdoc +++ b/docs/content/tutorial/step_09.ngdoc @@ -352,7 +352,7 @@ various URLs and verifying that the correct view was rendered. it('should redirect `index.html` to `index.html#!/phones', function() { browser.get('index.html'); - expect(browser.getLocationAbsUrl()).toBe('/phones'); + expect(browser.getCurrentUrl()).toContain('index.html#!/phones'); }); ... From 67263f2bd0d076c5dd36910eec2078d6df01ce0d Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Fri, 2 Nov 2018 16:51:21 +0200 Subject: [PATCH 123/217] docs(tutorial): explain how to upgrade dependencies Related: angular/angular-seed#439 --- docs/content/tutorial/index.ngdoc | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/content/tutorial/index.ngdoc b/docs/content/tutorial/index.ngdoc index 3f8e417bdd76..329cb23c5358 100644 --- a/docs/content/tutorial/index.ngdoc +++ b/docs/content/tutorial/index.ngdoc @@ -282,6 +282,33 @@ the application as a whole is executing correctly. It is very common to run E2E a new commit of changes to a remote repository. +### Updating dependencies + +In order to avoid surprises, all dependencies listed in `package.json` are pinned to specific +versions (this is what the [package-lock.json][package-lock] file is about). This ensures that the +same version of a dependency is installed every time. + +Since all dependencies are acquired via npm, you can use the same tool to easily update them as +well (although you probably don't need to for the purpose of this tutorial). Simply run the +preconfigured script: + +``` +npm run update-deps +``` + +This will update all packages to the latest version that satisfy their version ranges (as specified +in `package.json`) and also copy the necessary files into `app/lib/`. For example, if `package.json` +contains `"some-package": "1.2.x"`, it will be updated to the latest 1.2.x version (e.g. 1.2.99), +but not to 1.3.x (e.g. 1.3.0). + +If you want to update a dependency to a version newer than what the specificed range would permit, +you can change the version range in `package.json` and then run `npm run update-deps` as usual. + +
                    + See [here][semver-ranges] for more info on the various version range formats. +
                    + + ### Common Issues
                    @@ -336,5 +363,7 @@ Now that you have set up your local machine, let's get started with the tutorial [npm]: https://www.npmjs.com/ [nvm]: https://github.com/creationix/nvm [nvm-windows]: https://github.com/coreybutler/nvm-windows +[package-lock]: https://docs.npmjs.com/files/package-lock.json [protractor]: https://github.com/angular/protractor [selenium]: https://docs.seleniumhq.org/ +[semver-ranges]: https://docs.npmjs.com/misc/semver#ranges From 4f2b2b61c5d0dd7f9e7a144e520e353cf835137c Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Fri, 2 Nov 2018 16:55:34 +0200 Subject: [PATCH 124/217] docs(tutorial): mention that Protractor might need upgrading Since Protractor requires specific WebDriver versions and these are only compatible with specific browser version ranges, it is often necessary to upgrade Protractor just so that it picks up a more recent WebDriver version. Related: #16739 Closes #16753 --- docs/content/tutorial/index.ngdoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/content/tutorial/index.ngdoc b/docs/content/tutorial/index.ngdoc index 329cb23c5358..aa16e0837810 100644 --- a/docs/content/tutorial/index.ngdoc +++ b/docs/content/tutorial/index.ngdoc @@ -281,6 +281,18 @@ It is good to run the E2E tests whenever you make changes to the HTML views or w the application as a whole is executing correctly. It is very common to run E2E tests before pushing a new commit of changes to a remote repository. +
                    +

                    + Each version of Protractor is compatible with specific browser versions. If you are reading this + some time in the future, it is possible that the specified Protractor version is no longer + compatible with the latest version of Chrome that you are using. +

                    +

                    + If that is the case, you can try upgrading Protractor to newer version. For instructions on how + to upgrade dependencies see [Updating dependencies](tutorial/#updating-dependencies). +

                    +
                    + ### Updating dependencies From 318e6ceea3a255413ac86a7d28f1eefb0478ca24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20L=C3=B3pez?= Date: Thu, 15 Jun 2017 01:09:56 +0200 Subject: [PATCH 125/217] test(e2e): replace the deprecated `browser.getLocationAbsUrl()` with `browser.getCurrentUrl()` According to angular/protractor#3969, `browser.getLocationAbsUrl()` is now deprecated and `browser.getCurrentUrl()` should be used instead. Closes #16053 --- test/e2e/tests/base-tag.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/tests/base-tag.spec.js b/test/e2e/tests/base-tag.spec.js index 4fdca58ffcf6..5bddf040c11e 100644 --- a/test/e2e/tests/base-tag.spec.js +++ b/test/e2e/tests/base-tag.spec.js @@ -7,7 +7,7 @@ describe('SCE URL policy when base tags are present', function() { it('allows the page URL (location.href)', function() { - expectToBeTrusted(browser.getLocationAbsUrl(), true); + expectToBeTrusted(browser.getCurrentUrl(), true); }); it('blocks off-origin URLs', function() { From 2dfb6b4af62d750032c91fd86dc1f8d684d179c6 Mon Sep 17 00:00:00 2001 From: Volker Braun Date: Mon, 26 Feb 2018 09:38:03 +0100 Subject: [PATCH 126/217] fix($q): allow third-party promise libraries For testing, it can be useful to overwrite `$q` with other promise implementions, such as Bluebird + angular-bluebird-promises. This broke in v1.6.x with "TypeError: Cannot set property 'pur' of undefined". Closes #16164 Closes #16471 --- src/ng/q.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ng/q.js b/src/ng/q.js index 3bfc61386295..2bc9d03aa005 100644 --- a/src/ng/q.js +++ b/src/ng/q.js @@ -683,5 +683,11 @@ function markQStateExceptionHandled(state) { state.pur = true; } function markQExceptionHandled(q) { - markQStateExceptionHandled(q.$$state); + // Built-in `$q` promises will always have a `$$state` property. This check is to allow + // overwriting `$q` with a different promise library (e.g. Bluebird + angular-bluebird-promises). + // (Currently, this is the only method that might be called with a promise, even if it is not + // created by the built-in `$q`.) + if (q.$$state) { + markQStateExceptionHandled(q.$$state); + } } From 622d32e805cfd9fc5515c17054d358aa9db541a7 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 24 Oct 2018 21:43:14 +0100 Subject: [PATCH 127/217] fix(interpolate): do not create directives for constant media URL attributes By creating attribute directives that watch the value of media url attributes (e.g. `img[src]`) we caused a conflict when both `src` and `data-src` were appearing on the same element. As each directive was trying to write to the attributes on the element, where AngularJS treats `src` and `data-src` as synonymous. This commit ensures that we do not create create such directives when the media url attribute is a constant (no interpolation). Because of this (and because we no longer sanitize URLs in the `$attr.$set()` method, this commit also updates `ngHref` and `ngSrc` to do a preliminary sanitization of URLs in case there is no interpolation in the attribute value. Fixes #16734 --- src/ng/directive/attrs.js | 8 ++++-- src/ng/interpolate.js | 2 +- test/ng/compileSpec.js | 52 ++++++++++++++++++++++++++++++++++ test/ng/directive/ngSrcSpec.js | 14 +++++++++ 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/ng/directive/attrs.js b/src/ng/directive/attrs.js index 1b646ff5d4c3..cd0990e60477 100644 --- a/src/ng/directive/attrs.js +++ b/src/ng/directive/attrs.js @@ -408,7 +408,7 @@ forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) { // ng-src, ng-srcset, ng-href are interpolated forEach(['src', 'srcset', 'href'], function(attrName) { var normalized = directiveNormalize('ng-' + attrName); - ngAttributeAliasDirectives[normalized] = function() { + ngAttributeAliasDirectives[normalized] = ['$sce', function($sce) { return { priority: 99, // it needs to run after the attributes are interpolated link: function(scope, element, attr) { @@ -422,6 +422,10 @@ forEach(['src', 'srcset', 'href'], function(attrName) { propName = null; } + // We need to sanitize the url at least once, in case it is a constant + // non-interpolated attribute. + attr.$set(normalized, $sce.getTrustedMediaUrl(attr[normalized])); + attr.$observe(normalized, function(value) { if (!value) { if (attrName === 'href') { @@ -441,5 +445,5 @@ forEach(['src', 'srcset', 'href'], function(attrName) { }); } }; - }; + }]; }); diff --git a/src/ng/interpolate.js b/src/ng/interpolate.js index 77b863ddcba9..955b816c202b 100644 --- a/src/ng/interpolate.js +++ b/src/ng/interpolate.js @@ -242,7 +242,7 @@ function $InterpolateProvider() { // Provide a quick exit and simplified result function for text with no interpolation if (!text.length || text.indexOf(startSymbol) === -1) { - if (mustHaveExpression && !contextAllowsConcatenation) return; + if (mustHaveExpression) return; var unescapedText = unescapeText(text); if (contextAllowsConcatenation) { diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 2dd80560509c..92fc545f3139 100644 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -3577,6 +3577,15 @@ describe('$compile', function() { }) ); + it('should support non-interpolated `src` and `data-src` on the same element', + inject(function($rootScope, $compile) { + var element = $compile('')($rootScope); + expect(element.attr('src')).toEqual('abc'); + expect(element.attr('data-src')).toEqual('123'); + $rootScope.$digest(); + expect(element.attr('src')).toEqual('abc'); + expect(element.attr('data-src')).toEqual('123'); + })); it('should call observer only when the attribute value changes', function() { module(function() { @@ -12084,6 +12093,49 @@ describe('$compile', function() { expect(element.attr('test6')).toBe('Misko'); })); + describe('with media url attributes', function() { + it('should work with interpolated ng-attr-src', inject(function() { + $rootScope.name = 'some-image.png'; + element = $compile('')($rootScope); + expect(element.attr('src')).toBeUndefined(); + + $rootScope.$digest(); + expect(element.attr('src')).toBe('some-image.png'); + + $rootScope.name = 'other-image.png'; + $rootScope.$digest(); + expect(element.attr('src')).toBe('other-image.png'); + })); + + it('should work with interpolated ng-attr-data-src', inject(function() { + $rootScope.name = 'some-image.png'; + element = $compile('')($rootScope); + expect(element.attr('data-src')).toBeUndefined(); + + $rootScope.$digest(); + expect(element.attr('data-src')).toBe('some-image.png'); + + $rootScope.name = 'other-image.png'; + $rootScope.$digest(); + expect(element.attr('data-src')).toBe('other-image.png'); + })); + + it('should work alongside constant [src]-attribute and [ng-attr-data-src] attributes', inject(function() { + $rootScope.name = 'some-image.png'; + element = $compile('')($rootScope); + expect(element.attr('data-src')).toBeUndefined(); + + $rootScope.$digest(); + expect(element.attr('src')).toBe('constant.png'); + expect(element.attr('data-src')).toBe('some-image.png'); + + $rootScope.name = 'other-image.png'; + $rootScope.$digest(); + expect(element.attr('src')).toBe('constant.png'); + expect(element.attr('data-src')).toBe('other-image.png'); + })); + }); + describe('when an attribute has a dash-separated name', function() { it('should work with different prefixes', inject(function() { $rootScope.name = 'JamieMason'; diff --git a/test/ng/directive/ngSrcSpec.js b/test/ng/directive/ngSrcSpec.js index 5d2a067026b8..fcc48f292afd 100644 --- a/test/ng/directive/ngSrcSpec.js +++ b/test/ng/directive/ngSrcSpec.js @@ -78,6 +78,20 @@ describe('ngSrc', function() { expect(element.prop('src')).toEqual('http://somewhere/abc'); })); } + + it('should work with `src` attribute on the same element', inject(function($rootScope, $compile) { + $rootScope.imageUrl = 'dynamic'; + element = $compile('')($rootScope); + expect(element.attr('src')).toBe('static'); + $rootScope.$digest(); + expect(element.attr('src')).toBe('dynamic'); + dealoc(element); + + element = $compile('')($rootScope); + expect(element.attr('src')).toBe('static'); + $rootScope.$digest(); + expect(element.attr('src')).toBe('dynamic'); + })); }); describe('iframe[ng-src]', function() { From dc90cbf6db105a588c3b793ae96fe3c7d021b17d Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Sat, 23 Jun 2018 11:42:44 -0700 Subject: [PATCH 128/217] test($browser): update MockWindow to normalize URLs similar to real window.location --- test/ng/browserSpecs.js | 43 +++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/test/ng/browserSpecs.js b/test/ng/browserSpecs.js index 07f3683b76ad..306cda81abdd 100644 --- a/test/ng/browserSpecs.js +++ b/test/ng/browserSpecs.js @@ -11,8 +11,9 @@ function MockWindow(options) { } var events = {}; var timeouts = this.timeouts = []; - var locationHref = 'http://server/'; - var committedHref = 'http://server/'; + var locationHref = window.document.createElement('a'); + var committedHref = window.document.createElement('a'); + locationHref.href = committedHref.href = 'http://server/'; var mockWindow = this; var msie = options.msie; var ieState; @@ -60,28 +61,28 @@ function MockWindow(options) { this.location = { get href() { - return committedHref; + return committedHref.href; }, set href(value) { - locationHref = value; + locationHref.href = value; mockWindow.history.state = null; historyEntriesLength++; if (!options.updateAsync) this.flushHref(); }, get hash() { - return getHash(committedHref); + return getHash(committedHref.href); }, set hash(value) { - locationHref = replaceHash(locationHref, value); + locationHref.href = replaceHash(locationHref.href, value); if (!options.updateAsync) this.flushHref(); }, replace: function(url) { - locationHref = url; + locationHref.href = url; mockWindow.history.state = null; if (!options.updateAsync) this.flushHref(); }, flushHref: function() { - committedHref = locationHref; + committedHref.href = locationHref.href; } }; @@ -91,13 +92,13 @@ function MockWindow(options) { historyEntriesLength++; }, replaceState: function(state, title, url) { - locationHref = url; - if (!options.updateAsync) committedHref = locationHref; + locationHref.href = url; + if (!options.updateAsync) committedHref.href = locationHref.href; mockWindow.history.state = copy(state); if (!options.updateAsync) this.flushHref(); }, flushHref: function() { - committedHref = locationHref; + committedHref.href = locationHref.href; } }; // IE 10-11 deserialize history.state on each read making subsequent reads @@ -398,18 +399,18 @@ describe('browser', function() { it('should return current location.href', function() { fakeWindow.location.href = 'http://test.com/'; - expect(browser.url()).toEqual('http://test.com/'); + expect(browser.url()).toEqual('http://test.com/'); fakeWindow.location.href = 'https://another.com/'; - expect(browser.url()).toEqual('https://another.com/'); + expect(browser.url()).toEqual('https://another.com/'); }); it('should strip an empty hash fragment', function() { - fakeWindow.location.href = 'http://test.com/#'; - expect(browser.url()).toEqual('http://test.com/'); + fakeWindow.location.href = 'http://test.com/#'; + expect(browser.url()).toEqual('http://test.com/'); - fakeWindow.location.href = 'https://another.com/#foo'; - expect(browser.url()).toEqual('https://another.com/#foo'); + fakeWindow.location.href = 'https://another.com/#foo'; + expect(browser.url()).toEqual('https://another.com/#foo'); }); it('should use history.pushState when available', function() { @@ -440,7 +441,7 @@ describe('browser', function() { sniffer.history = false; browser.url('http://new.org/'); - expect(fakeWindow.location.href).toEqual('http://new.org/'); + expect(fakeWindow.location.href).toEqual('http://new.org/'); expect(pushState).not.toHaveBeenCalled(); expect(replaceState).not.toHaveBeenCalled(); @@ -507,9 +508,9 @@ describe('browser', function() { it('should not set URL when the URL is already set', function() { var current = fakeWindow.location.href; sniffer.history = false; - fakeWindow.location.href = 'dontchange'; + fakeWindow.location.href = 'http://dontchange/'; browser.url(https://github.com/current); - expect(fakeWindow.location.href).toBe('dontchange'); + expect(fakeWindow.location.href).toBe('http://dontchange/'); }); it('should not read out location.href if a reload was triggered but still allow to change the url', function() { @@ -812,7 +813,7 @@ describe('browser', function() { it('should not fire urlChange if changed by browser.url method', function() { sniffer.history = false; browser.onUrlChange(callback); - browser.url('http://new.com/'); + browser.url('http://new.com/'); fakeWindow.fire('hashchange'); expect(callback).not.toHaveBeenCalled(); From 4a3ae43407f7a39a88fd6d7554b9dad6c248ac5c Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Sat, 23 Jun 2018 20:50:15 -0700 Subject: [PATCH 129/217] fix($browser): normalize inputted URLs Calls to `$browser.url` now normalize the inputted URL ensuring multiple calls only differing in formatting do not force a browser `pushState`. Normalization is done the same as the browser location URL and may differ per browser and may be changed by browsers. Today no browsers fully normalize URLs so this does not fix all instances of this issue. See #16100 Closes #16606 --- src/ng/browser.js | 3 ++ test/ng/browserSpecs.js | 75 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/ng/browser.js b/src/ng/browser.js index 699602bc9b2d..4bb96ee21f1f 100644 --- a/src/ng/browser.js +++ b/src/ng/browser.js @@ -108,6 +108,9 @@ function Browser(window, document, $log, $sniffer, $$taskTrackerFactory) { if (url) { var sameState = lastHistoryState === state; + // Normalize the inputted URL + url = urlResolve(url).href; + // Don't change anything if previous and current URLs and states match. This also prevents // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode. // See https://github.com/angular/angular.js/commit/ffb2701 diff --git a/test/ng/browserSpecs.js b/test/ng/browserSpecs.js index 306cda81abdd..46a7325c95a9 100644 --- a/test/ng/browserSpecs.js +++ b/test/ng/browserSpecs.js @@ -418,7 +418,7 @@ describe('browser', function() { browser.url('http://new.org/'); expect(pushState).toHaveBeenCalledOnce(); - expect(pushState.calls.argsFor(0)[2]).toEqual('http://new.org/'); + expect(pushState.calls.argsFor(0)[2]).toEqual('http://new.org/'); expect(replaceState).not.toHaveBeenCalled(); expect(locationReplace).not.toHaveBeenCalled(); @@ -430,7 +430,7 @@ describe('browser', function() { browser.url('http://new.org/', true); expect(replaceState).toHaveBeenCalledOnce(); - expect(replaceState.calls.argsFor(0)[2]).toEqual('http://new.org/'); + expect(replaceState.calls.argsFor(0)[2]).toEqual('http://new.org/'); expect(pushState).not.toHaveBeenCalled(); expect(locationReplace).not.toHaveBeenCalled(); @@ -474,7 +474,7 @@ describe('browser', function() { sniffer.history = false; browser.url('http://new.org/', true); - expect(locationReplace).toHaveBeenCalledWith('http://new.org/'); + expect(locationReplace).toHaveBeenCalledWith('http://new.org/'); expect(pushState).not.toHaveBeenCalled(); expect(replaceState).not.toHaveBeenCalled(); @@ -689,6 +689,73 @@ describe('browser', function() { expect(replaceState).not.toHaveBeenCalled(); expect(locationReplace).not.toHaveBeenCalled(); }); + + it('should not do pushState with a URL using relative protocol', function() { + browser.url('http://server/'); + + pushState.calls.reset(); + replaceState.calls.reset(); + locationReplace.calls.reset(); + + browser.url('https://server/'); + expect(pushState).not.toHaveBeenCalled(); + expect(replaceState).not.toHaveBeenCalled(); + expect(locationReplace).not.toHaveBeenCalled(); + }); + + it('should not do pushState with a URL only adding a trailing slash after domain', function() { + // A domain without a trailing / + browser.url('http://server/'); + + pushState.calls.reset(); + replaceState.calls.reset(); + locationReplace.calls.reset(); + + // A domain from something such as window.location.href with a trailing slash + browser.url('http://server/'); + expect(pushState).not.toHaveBeenCalled(); + expect(replaceState).not.toHaveBeenCalled(); + expect(locationReplace).not.toHaveBeenCalled(); + }); + + it('should not do pushState with a URL only removing a trailing slash after domain', function() { + // A domain from something such as window.location.href with a trailing slash + browser.url('http://server/'); + + pushState.calls.reset(); + replaceState.calls.reset(); + locationReplace.calls.reset(); + + // A domain without a trailing / + browser.url('http://server/'); + expect(pushState).not.toHaveBeenCalled(); + expect(replaceState).not.toHaveBeenCalled(); + expect(locationReplace).not.toHaveBeenCalled(); + }); + + it('should do pushState with a URL only adding a trailing slash after the path', function() { + browser.url('http://server/foo'); + + pushState.calls.reset(); + replaceState.calls.reset(); + locationReplace.calls.reset(); + + browser.url('http://server/foo/'); + expect(pushState).toHaveBeenCalledOnce(); + expect(fakeWindow.location.href).toEqual('http://server/foo/'); + }); + + it('should do pushState with a URL only removing a trailing slash after the path', function() { + browser.url('http://server/foo/'); + + pushState.calls.reset(); + replaceState.calls.reset(); + locationReplace.calls.reset(); + + browser.url('http://server/foo'); + expect(pushState).toHaveBeenCalledOnce(); + expect(fakeWindow.location.href).toEqual('http://server/foo'); + }); }; } }); @@ -1093,7 +1160,7 @@ describe('browser', function() { it('should not interfere with legacy browser url replace behavior', function() { inject(function($rootScope) { var current = fakeWindow.location.href; - var newUrl = 'notyet'; + var newUrl = 'http://notyet/'; sniffer.history = false; expect(historyEntriesLength).toBe(1); browser.url(https://github.com/newUrl,%20true); From e77a74472a1498cf8ceb776b22cbab6517b14dd3 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 25 Oct 2018 12:20:27 +0200 Subject: [PATCH 130/217] chore(*): update karma This allows us to remove the workaround added in #16645 --- package.json | 2 +- yarn.lock | 1300 +++++++++++++++----------------------------------- 2 files changed, 394 insertions(+), 908 deletions(-) diff --git a/package.json b/package.json index 1e25cc44728e..22e7364e9f2f 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "jquery": "3.2.1", "jquery-2.1": "npm:jquery@2.1.4", "jquery-2.2": "npm:jquery@2.2.4", - "karma": "^2.0.4", + "karma": "3.1.1", "karma-browserstack-launcher": "^1.3.0", "karma-chrome-launcher": "^2.2.0", "karma-edge-launcher": "^0.4.2", diff --git a/yarn.lock b/yarn.lock index 268669168f1c..116b3dfac50a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -61,7 +61,7 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= -accepts@1.3.3, accepts@~1.3.3: +accepts@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" integrity sha1-w8p0NJOGSMPg2cHjKN1otiLChMo= @@ -69,6 +69,14 @@ accepts@1.3.3, accepts@~1.3.3: mime-types "~2.1.11" negotiator "0.6.1" +accepts@~1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" + integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= + dependencies: + mime-types "~2.1.18" + negotiator "0.6.1" + acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" @@ -101,30 +109,30 @@ acorn@^3.0.4, acorn@^3.1.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= -addressparser@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746" - integrity sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y= - -adm-zip@^0.4.7, adm-zip@~0.4.3: +adm-zip@^0.4.7: version "0.4.7" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" integrity sha1-hgbCy/HEJs6MjsABdER/1Jtur8E= +adm-zip@~0.4.3: + version "0.4.11" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.11.tgz#2aa54c84c4b01a9d0fb89bb11982a51f13e3d62a" + integrity sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA== + after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= agent-base@2: - version "2.0.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.0.1.tgz#bd8f9e86a8eb221fffa07bd14befd55df142815e" - integrity sha1-vY+ehqjrIh//oHvRS+/VXfFCgV4= + version "2.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7" + integrity sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc= dependencies: extend "~3.0.0" semver "~5.0.1" -agent-base@4, agent-base@^4.1.0, agent-base@^4.2.0, agent-base@~4.2.0: +agent-base@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== @@ -176,17 +184,6 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= -amqplib@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/amqplib/-/amqplib-0.5.2.tgz#d2d7313c7ffaa4d10bcf1e6252de4591b6cc7b63" - integrity sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA== - dependencies: - bitsyntax "~0.0.4" - bluebird "^3.4.6" - buffer-more-ints "0.0.2" - readable-stream "1.x >=1.1.9" - safe-buffer "^5.0.1" - angular-benchpress@0.x.x: version "0.2.2" resolved "https://registry.yarnpkg.com/angular-benchpress/-/angular-benchpress-0.2.2.tgz#05754d36e6248e061dbaf6a30a801c06217f1f60" @@ -260,7 +257,21 @@ archiver-utils@^1.3.0: normalize-path "^2.0.0" readable-stream "^2.0.0" -archiver@1.3.0, archiver@^1.0.0: +archiver@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-2.1.1.tgz#ff662b4a78201494a3ee544d3a33fe7496509ebc" + integrity sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw= + dependencies: + archiver-utils "^1.3.0" + async "^2.0.0" + buffer-crc32 "^0.2.1" + glob "^7.0.0" + lodash "^4.8.0" + readable-stream "^2.0.0" + tar-stream "^1.5.0" + zip-stream "^1.2.0" + +archiver@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22" integrity sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI= @@ -384,9 +395,11 @@ asn1.js@^4.0.0: minimalistic-assert "^1.0.0" asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y= + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" @@ -410,11 +423,6 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -ast-types@0.x.x: - version "0.10.1" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.10.1.tgz#f52fca9715579a14f841d67d7f8d25432ab6a3dd" - integrity sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ== - astw@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astw/-/astw-2.0.0.tgz#08121ac8288d35611c0ceec663f6cd545604897d" @@ -445,11 +453,11 @@ async@2.0.1: lodash "^4.8.0" async@^2.0.0, async@^2.1.2: - version "2.1.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" - integrity sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ= + version "2.6.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== dependencies: - lodash "^4.14.0" + lodash "^4.17.10" async@~0.2.6: version "0.2.10" @@ -461,13 +469,6 @@ async@~1.0.0: resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= -async@~2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== - dependencies: - lodash "^4.17.10" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -494,16 +495,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - integrity sha1-g+9cqGCysy5KDe7e6MdxudtXRx4= - -axios@^0.15.3: - version "0.15.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.15.3.tgz#2c9d638b2e191a08ea1d6cc988eadd6ba5bdc053" - integrity sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM= - dependencies: - follow-redirects "1.0.0" + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== babel-code-frame@^6.16.0: version "6.22.0" @@ -539,6 +533,11 @@ base64-js@0.0.7: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.7.tgz#54400dc91d696cec32a8a47902f971522fee8f48" integrity sha1-VEANyR1pbOwyqKR5AvlxUi/uj0g= +base64-js@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + base64id@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" @@ -568,9 +567,9 @@ batch@0.5.3: integrity sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ= bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - integrity sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40= + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" @@ -604,26 +603,13 @@ binary-extensions@^1.0.0: buffers "~0.1.1" chainsaw "~0.1.0" -bitsyntax@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/bitsyntax/-/bitsyntax-0.0.4.tgz#eb10cc6f82b8c490e3e85698f07e83d46e0cba82" - integrity sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI= - dependencies: - buffer-more-ints "0.0.2" - bl@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.0.tgz#1397e7ec42c5f5dc387470c500e34a9f6be9ea98" - integrity sha1-E5fn7ELF9dw4dHDFAONKn2vp6pg= - dependencies: - readable-stream "^2.0.5" - -bl@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398" - integrity sha1-/cqHGplxOqANGeO7ukHER4emU5g= + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== dependencies: - readable-stream "~2.0.5" + readable-stream "^2.3.5" + safe-buffer "^5.1.1" blob@0.0.4: version "0.0.4" @@ -715,9 +701,9 @@ brace-expansion@^1.0.0: concat-map "0.0.1" brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - integrity sha1-wHshHHyVLsH479Uad+8NHTmQopI= + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -919,15 +905,28 @@ browserstacktunnel-wrapper@~2.0.1: https-proxy-agent "^2.2.1" unzip "~0.1.11" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + buffer-crc32@^0.2.1: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= -buffer-more-ints@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz#26b3885d10fa13db7fc01aae3aab870199e0124c" - integrity sha1-JrOIXRD6E9t/wBquOquHAZngEkw= +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= buffer-shims@^1.0.0: version "1.0.0" @@ -948,6 +947,14 @@ buffer@^2.3.0: ieee754 "^1.1.4" is-array "^1.0.1" +buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" + integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + buffers@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" @@ -960,19 +967,6 @@ bufferstreams@^1.1.1: dependencies: readable-stream "^2.0.2" -buildmail@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/buildmail/-/buildmail-4.0.1.tgz#877f7738b78729871c9a105e3b837d2be11a7a72" - integrity sha1-h393OLeHKYccmhBeO4N9K+EaenI= - dependencies: - addressparser "1.0.1" - libbase64 "0.1.0" - libmime "3.0.0" - libqp "1.1.0" - nodemailer-fetch "1.6.0" - nodemailer-shared "1.1.0" - punycode "1.4.1" - builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -1238,10 +1232,10 @@ circular-json@^0.3.1: resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" integrity sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0= -circular-json@^0.5.4: - version "0.5.5" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.5.tgz#64182ef359042d37cd8e767fc9de878b1e9447d3" - integrity sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA== +circular-json@^0.5.5: + version "0.5.9" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d" + integrity sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ== class-utils@^0.3.5: version "0.3.6" @@ -1390,17 +1384,10 @@ combine-source-map@~0.6.1: lodash.memoize "~3.0.3" source-map "~0.4.2" -combined-stream@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= - dependencies: - delayed-stream "~1.0.0" - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - integrity sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk= +combined-stream@^1.0.5, combined-stream@^1.0.6, combined-stream@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== dependencies: delayed-stream "~1.0.0" @@ -1422,9 +1409,9 @@ commander@>=1.1: graceful-readlink ">= 1.0.0" commander@^2.9.0: - version "2.12.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" - integrity sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA== + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commitizen@^2.3.0: version "2.9.5" @@ -1478,13 +1465,13 @@ component-inherit@0.0.3: resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= -compress-commons@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.1.0.tgz#9f4460bb1288564c7473916e0298aa3c320dcadb" - integrity sha1-n0RguxKIVkx0c5FuApiqPDINyts= +compress-commons@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.2.tgz#524a9f10903f3a813389b0225d27c48bb751890f" + integrity sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8= dependencies: buffer-crc32 "^0.2.1" - crc32-stream "^1.0.0" + crc32-stream "^2.0.0" normalize-path "^2.0.0" readable-stream "^2.0.0" @@ -1619,18 +1606,20 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -crc32-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-1.0.1.tgz#ce2c5dc3bd8ffb3830f9cb47f540222c63c90fab" - integrity sha1-zixdw72P+zgw+ctH9UAiLGPJD6s= +crc32-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-2.0.0.tgz#e3cdd3b4df3168dd74e3de3fbbcb7b297fe908f4" + integrity sha1-483TtN8xaN10494/u8t7KX/pCPQ= dependencies: crc "^3.4.4" readable-stream "^2.0.0" crc@^3.4.4: - version "3.4.4" - resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b" - integrity sha1-naHpgOO9RPxck79as9ozeNheRms= + version "3.8.0" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" + integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== + dependencies: + buffer "^5.1.0" create-ecdh@^4.0.0: version "4.0.0" @@ -1765,11 +1754,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -data-uri-to-buffer@1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz#77163ea9c20d8641b4707e8f18abdf9a78f34835" - integrity sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ== - date-format@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/date-format/-/date-format-1.2.0.tgz#615e828e233dd1ab9bb9ae0950e0ceccfa6ecad8" @@ -1807,12 +1791,12 @@ debug-fabulous@0.0.X: lazy-debug-legacy "0.0.X" object-assign "4.1.0" -debug@2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.3.tgz#0f7eb8c30965ec08c72accfa0130c8b79984141d" - integrity sha1-D364wwll7AjHKsz6ATDIt5mEFB0= +debug@2, debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: - ms "0.7.2" + ms "2.0.0" debug@2.2.0, debug@~2.2.0: version "2.2.0" @@ -1828,14 +1812,7 @@ debug@2.6.0, debug@2.X, debug@^2.1.1: dependencies: ms "0.7.2" -debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@~2.6.4, debug@~2.6.6, debug@~2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@3.1.0, debug@^3.1.0, debug@~3.1.0: +debug@^3.1.0, debug@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== @@ -1911,15 +1888,6 @@ defined@~0.0.0: resolved "https://registry.yarnpkg.com/defined/-/defined-0.0.0.tgz#f35eea7d705e933baf13b2f03b3f83d921403b3e" integrity sha1-817qfXBekzuvE7LwOz+D2SFAOz4= -degenerator@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-1.0.4.tgz#fcf490a37ece266464d9cc431ab98c5819ced095" - integrity sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU= - dependencies: - ast-types "0.x.x" - escodegen "1.x.x" - esprima "3.x.x" - del@^2.0.2, del@^2.2.0: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" @@ -1948,11 +1916,6 @@ depd@1.1.1, depd@~1.1.0, depd@~1.1.1: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" integrity sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k= -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - dependency-graph@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.4.1.tgz#302e58218d85c51a97638730dbf9b7d852a19693" @@ -2153,11 +2116,6 @@ dot-case@^2.1.0: dependencies: no-case "^2.2.0" -double-ended-queue@^2.1.0-0: - version "2.1.0-0" - resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" - integrity sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw= - duplexer2@0.0.2, duplexer2@~0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" @@ -2171,11 +2129,12 @@ duplexer@~0.1.1: integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - integrity sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU= + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" + safer-buffer "^2.1.0" edge-launcher@1.2.2: version "1.2.2" @@ -2203,11 +2162,11 @@ encodeurl@~1.0.1: integrity sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA= end-of-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e" - integrity sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4= + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: - once "~1.3.0" + once "^1.4.0" end-of-stream@~0.1.5: version "0.1.5" @@ -2216,14 +2175,14 @@ end-of-stream@~0.1.5: dependencies: once "~1.3.0" -engine.io-client@~3.1.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.4.tgz#4fcf1370b47163bd2ce9be2733972430350d4ea1" - integrity sha1-T88TcLRxY70s6b4nM5ckMDUNTqE= +engine.io-client@~3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" + integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw== dependencies: component-emitter "1.2.1" component-inherit "0.0.3" - debug "~2.6.9" + debug "~3.1.0" engine.io-parser "~2.1.1" has-cors "1.1.0" indexof "0.0.1" @@ -2244,19 +2203,17 @@ engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: blob "0.0.4" has-binary2 "~1.0.2" -engine.io@~3.1.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.1.4.tgz#3d0211b70a552ce841ffc7da8627b301a9a4162e" - integrity sha1-PQIRtwpVLOhB/8fahiezAamkFi4= +engine.io@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.0.tgz#54332506f42f2edc71690d2f2a42349359f3bf7d" + integrity sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw== dependencies: - accepts "1.3.3" + accepts "~1.3.4" base64id "1.0.0" cookie "0.3.1" - debug "~2.6.9" + debug "~3.1.0" engine.io-parser "~2.1.0" ws "~3.3.1" - optionalDependencies: - uws "~0.14.4" ent@~2.2.0: version "2.2.0" @@ -2375,18 +2332,6 @@ escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@1.x.x: - version "1.9.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.0.tgz#9811a2f265dc1cd3894420ee3717064b632b8852" - integrity sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.5.6" - escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" @@ -2455,11 +2400,6 @@ espree@^3.4.0: acorn "4.0.4" acorn-jsx "^3.0.0" -esprima@3.x.x, esprima@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= - esprima@^2.6.0: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" @@ -2644,12 +2584,12 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" - integrity sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ= +extend@3, extend@~3.0.0, extend@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: +extend@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" integrity sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ= @@ -2708,9 +2648,9 @@ fancy-log@^1.0.0, fancy-log@^1.1.0: time-stamp "^1.0.0" fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8= + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= fast-json-stable-stringify@^2.0.0: version "2.0.0" @@ -2743,11 +2683,6 @@ file-sync-cmp@^0.1.0: resolved "https://registry.yarnpkg.com/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz#a5e7a8ffbfa493b43b923bbd4ca89a53b63b612b" integrity sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs= -file-uri-to-path@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -2892,13 +2827,6 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" -follow-redirects@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.0.0.tgz#8e34298cbd2e176f254effec75a1c78cc849fd37" - integrity sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc= - dependencies: - debug "^2.2.0" - for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2916,15 +2844,6 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -form-data@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.0.0.tgz#6f0aebadcc5da16c13e1ecc11137d85f9b883b25" - integrity sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU= - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.11" - form-data@~2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" @@ -2934,22 +2853,13 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -form-data@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" - form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - integrity sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8= + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" - combined-stream "^1.0.5" + combined-stream "^1.0.6" mime-types "^2.1.12" formatio@1.1.1: @@ -2988,6 +2898,11 @@ fs-access@^1.0.0: dependencies: null-check "^1.0.0" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-exists-sync@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" @@ -3069,14 +2984,6 @@ fstream@^1.0.10: mkdirp ">=0.5 0" rimraf "2" -ftp@~0.3.10: - version "0.3.10" - resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d" - integrity sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0= - dependencies: - readable-stream "1.1.x" - xregexp "2.0.0" - gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -3099,9 +3006,11 @@ gaze@^0.5.1, gaze@~0.5.1: globule "~0.1.0" generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - integrity sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ= + version "2.3.1" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" + integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== + dependencies: + is-property "^1.0.2" generate-object-property@^1.1.0: version "1.2.0" @@ -3115,18 +3024,6 @@ get-stdin@^4.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= -get-uri@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-2.0.2.tgz#5c795e71326f6ca1286f2fc82575cd2bab2af578" - integrity sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw== - dependencies: - data-uri-to-buffer "1" - debug "2" - extend "3" - file-uri-to-path "1" - ftp "~0.3.10" - readable-stream "2" - get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -3208,7 +3105,7 @@ glob@3.2.11: inherits "2" minimatch "0.3" -glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.6: +glob@7.1.1, glob@^7.0.3, glob@^7.0.6: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= @@ -3251,7 +3148,19 @@ glob@^6.0.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.5, glob@^7.1.1: +glob@^7.0.0, glob@^7.0.5: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== @@ -3798,23 +3707,15 @@ header-case@^1.0.0: no-case "^2.2.0" upper-case "^1.1.3" -hipchat-notifier@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz#b6d249755437c191082367799d3ba9a0f23b231e" - integrity sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4= - dependencies: - lodash "^4.0.0" - request "^2.0.0" - hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" - integrity sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ== + version "4.2.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" + integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA== homedir-polyfill@^1.0.0: version "1.0.1" @@ -3862,16 +3763,6 @@ http-errors@1.6.2, http-errors@~1.6.2: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" -http-errors@1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - http-errors@~1.5.0, http-errors@~1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750" @@ -3881,14 +3772,6 @@ http-errors@~1.5.0, http-errors@~1.5.1: setprototypeof "1.0.2" statuses ">= 1.3.1 < 2" -http-proxy-agent@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" - integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== - dependencies: - agent-base "4" - debug "3.1.0" - http-proxy@^1.13.0: version "1.16.2" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" @@ -3920,25 +3803,12 @@ http2@^3.3.4: resolved "https://registry.yarnpkg.com/http2/-/http2-3.3.6.tgz#7df06227e02b5b5a5841deea08239b3198d04bec" integrity sha1-ffBiJ+ArW1pYQd7qCCObMZjQS+w= -httpntlm@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/httpntlm/-/httpntlm-1.6.1.tgz#ad01527143a2e8773cfae6a96f58656bb52a34b2" - integrity sha1-rQFScUOi6Hc8+uapb1hla7UqNLI= - dependencies: - httpreq ">=0.4.22" - underscore "~1.7.0" - -httpreq@>=0.4.22: - version "0.4.24" - resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-0.4.24.tgz#4335ffd82cd969668a39465c929ac61d6393627f" - integrity sha1-QzX/2CzZaWaKOUZckprGHWOTYn8= - https-browserify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" integrity sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI= -https-proxy-agent@1.0.0, https-proxy-agent@^1.0.0, https-proxy-agent@~1.0.0: +https-proxy-agent@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6" integrity sha1-NffabEjOTdv6JkiRrFk+5f+GceY= @@ -3955,23 +3825,23 @@ https-proxy-agent@^2.2.1: agent-base "^4.1.0" debug "^3.1.0" -iconv-lite@0.4.15, iconv-lite@~0.4.13: - version "0.4.15" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" - integrity sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es= - iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ== -iconv-lite@0.4.23, iconv-lite@^0.4.4, iconv-lite@~0.4.11: +iconv-lite@^0.4.4, iconv-lite@~0.4.11: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@~0.4.13: + version "0.4.15" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" + integrity sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es= + ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" @@ -4018,16 +3888,6 @@ indexof@0.0.1: resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= -inflection@~1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" - integrity sha1-ogCTVlbW9fa8TcdQLhrstwMihBY= - -inflection@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.3.8.tgz#cbd160da9f75b14c3cc63578d4f396784bf3014e" - integrity sha1-y9Fg2p91sUw8xjV41POWeEvzAU4= - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -4143,11 +4003,6 @@ invert-kv@^1.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= -ip@^1.1.2, ip@^1.1.4, ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - ipaddr.js@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.2.0.tgz#8aba49c9192799585bdd643e0ccb50e8ae777ba4" @@ -4322,6 +4177,11 @@ is-lower-case@^1.1.0: dependencies: lower-case "^1.1.0" +is-my-ip-valid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" + integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== + is-my-json-valid@^2.10.0: version "2.15.0" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b" @@ -4333,12 +4193,13 @@ is-my-json-valid@^2.10.0: xtend "^4.0.0" is-my-json-valid@^2.12.4: - version "2.17.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" - integrity sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ== + version "2.19.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz#8fd6e40363cd06b963fa877d444bfb5eddc62175" + integrity sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q== dependencies: generate-function "^2.0.0" generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" jsonpointer "^4.0.0" xtend "^4.0.0" @@ -4414,7 +4275,7 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= -is-property@^1.0.0: +is-property@^1.0.0, is-property@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= @@ -4641,7 +4502,7 @@ json-stable-stringify@~0.0.0: dependencies: jsonify "~0.0.0" -json-stringify-safe@5.0.x, json-stringify-safe@~5.0.1: +json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= @@ -4770,10 +4631,10 @@ karma-spec-reporter@^0.0.32: dependencies: colors "^1.1.2" -karma@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/karma/-/karma-2.0.4.tgz#b399785f57e9bab1d3c4384db33fef4dec8ae349" - integrity sha512-32yhTwoi6BZgJZhR78GwhzyFABbYG/1WwQqYgY7Vh96Demvua2jM3+FyRltIMTUH/Kd5xaQvDw2L7jTvkYFeXg== +karma@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/karma/-/karma-3.1.1.tgz#94c8edd20fb9597ccde343326da009737fb0423a" + integrity sha512-NetT3wPCQMNB36uiL9LLyhrOt8SQwrEKt0xD3+KpTCfm0VxVyUJdPL5oTq2Ic5ouemgL/Iz4wqXEbF3zea9kQQ== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" @@ -4790,15 +4651,15 @@ karma@^2.0.4: http-proxy "^1.13.0" isbinaryfile "^3.0.0" lodash "^4.17.4" - log4js "^2.5.3" - mime "^1.3.4" + log4js "^3.0.0" + mime "^2.3.1" minimatch "^3.0.2" optimist "^0.6.1" qjobs "^1.1.4" range-parser "^1.2.0" rimraf "^2.6.0" safe-buffer "^5.0.1" - socket.io "2.0.4" + socket.io "2.1.1" source-map "^0.6.1" tmp "0.0.33" useragent "2.2.1" @@ -4882,25 +4743,6 @@ lexical-scope@^1.2.0: dependencies: astw "^2.0.0" -libbase64@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/libbase64/-/libbase64-0.1.0.tgz#62351a839563ac5ff5bd26f12f60e9830bb751e6" - integrity sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY= - -libmime@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/libmime/-/libmime-3.0.0.tgz#51a1a9e7448ecbd32cda54421675bb21bc093da6" - integrity sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY= - dependencies: - iconv-lite "0.4.15" - libbase64 "0.1.0" - libqp "1.1.0" - -libqp@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/libqp/-/libqp-1.1.0.tgz#f5e6e06ad74b794fb5b5b66988bf728ef1dedbe8" - integrity sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g= - lie@~3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" @@ -5196,12 +5038,12 @@ lodash.values@~2.4.1: dependencies: lodash.keys "~2.4.1" -lodash@4.16.2: - version "4.16.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" - integrity sha1-PmJtuCcEimmSgaihJSJjJs/A5lI= +lodash@4.17.10: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== -lodash@4.17.2, lodash@^4.0.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.16.6, lodash@^4.17.2, lodash@^4.3.0, lodash@^4.7.0, lodash@^4.8.0: +lodash@4.17.2, lodash@^4.0.0, lodash@^4.13.1, lodash@^4.17.2, lodash@^4.3.0, lodash@^4.7.0: version "4.17.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.2.tgz#34a3055babe04ce42467b607d700072c7ff6bf42" integrity sha1-NKMFW6vgTOQkZ7YH1wAHLH/2v0I= @@ -5211,16 +5053,16 @@ lodash@^3.10.1, lodash@~3.10.1: resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= -lodash@^4.15.0, lodash@^4.17.4, lodash@^4.5.0, lodash@^4.6.1: +lodash@^4.16.6, lodash@^4.17.10, lodash@^4.8.0: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== + +lodash@^4.17.4, lodash@^4.5.0, lodash@^4.6.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= -lodash@^4.17.10: - version "4.17.10" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" - integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== - lodash@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" @@ -5244,34 +5086,16 @@ log4js@^0.6.27: readable-stream "~1.0.2" semver "~4.3.3" -log4js@^2.5.3: - version "2.11.0" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-2.11.0.tgz#bf3902eff65c6923d9ce9cfbd2db54160e34005a" - integrity sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ== +log4js@^3.0.0: + version "3.0.6" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-3.0.6.tgz#e6caced94967eeeb9ce399f9f8682a4b2b28c8ff" + integrity sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ== dependencies: - circular-json "^0.5.4" + circular-json "^0.5.5" date-format "^1.2.0" debug "^3.1.0" - semver "^5.5.0" + rfdc "^1.1.2" streamroller "0.7.0" - optionalDependencies: - amqplib "^0.5.2" - axios "^0.15.3" - hipchat-notifier "^1.1.0" - loggly "^1.1.0" - mailgun-js "^0.18.0" - nodemailer "^2.5.0" - redis "^2.7.1" - slack-node "~0.2.0" - -loggly@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/loggly/-/loggly-1.1.1.tgz#0a0fc1d3fa3a5ec44fdc7b897beba2a4695cebee" - integrity sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4= - dependencies: - json-stringify-safe "5.0.x" - request "2.75.x" - timespan "2.3.x" lolex@1.3.2: version "1.3.2" @@ -5321,42 +5145,11 @@ lru-cache@^4.0.1: pseudomap "^1.0.1" yallist "^2.0.0" -lru-cache@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" - integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - lunr@^0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/lunr/-/lunr-0.7.2.tgz#79a30e932e216cba163541ee37a3607c12cd7281" integrity sha1-eaMOky4hbLoWNUHuN6NgfBLNcoE= -mailcomposer@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/mailcomposer/-/mailcomposer-4.0.1.tgz#0e1c44b2a07cf740ee17dc149ba009f19cadfeb4" - integrity sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ= - dependencies: - buildmail "4.0.1" - libmime "3.0.0" - -mailgun-js@^0.18.0: - version "0.18.1" - resolved "https://registry.yarnpkg.com/mailgun-js/-/mailgun-js-0.18.1.tgz#ee39aa18d7bb598a5ce9ede84afb681defc8a6b0" - integrity sha512-lvuMP14u24HS2uBsJEnzSyPMxzU2b99tQsIx1o6QNjqxjk8b3WvR+vq5oG1mjqz/IBYo+5gF+uSoDS0RkMVHmg== - dependencies: - async "~2.6.0" - debug "~3.1.0" - form-data "~2.3.0" - inflection "~1.12.0" - is-stream "^1.1.0" - path-proxy "~1.0.0" - promisify-call "^2.0.2" - proxy-agent "~3.0.0" - tsscmp "~1.0.0" - map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -5479,7 +5272,19 @@ mime-db@~1.30.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" integrity sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE= -mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.17, mime-types@~2.1.7: +mime-db@~1.37.0: + version "1.37.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" + integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== + +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: + version "2.1.21" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" + integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== + dependencies: + mime-db "~1.37.0" + +mime-types@~2.1.11, mime-types@~2.1.15: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo= @@ -5491,10 +5296,10 @@ mime@1.3.4, mime@^1.2.11: resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" integrity sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM= -mime@^1.3.4: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" + integrity sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg== mime@~1.2.11: version "1.2.11" @@ -5774,11 +5579,6 @@ negotiator@0.6.1: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= -netmask@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35" - integrity sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU= - no-case@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.1.tgz#7aeba1c73a52184265554b7dc03baf720df80081" @@ -5824,67 +5624,6 @@ node-pre-gyp@^0.6.39: tar "^2.2.1" tar-pack "^3.4.0" -node-uuid@~1.4.7: - version "1.4.8" - resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" - integrity sha1-sEDrCSOWivq/jTL7HxfxFn/auQc= - -nodemailer-direct-transport@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz#e96fafb90358560947e569017d97e60738a50a86" - integrity sha1-6W+vuQNYVglH5WkBfZfmBzilCoY= - dependencies: - nodemailer-shared "1.1.0" - smtp-connection "2.12.0" - -nodemailer-fetch@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz#79c4908a1c0f5f375b73fe888da9828f6dc963a4" - integrity sha1-ecSQihwPXzdbc/6IjamCj23JY6Q= - -nodemailer-shared@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz#cf5994e2fd268d00f5cf0fa767a08169edb07ec0" - integrity sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA= - dependencies: - nodemailer-fetch "1.6.0" - -nodemailer-smtp-pool@2.8.2: - version "2.8.2" - resolved "https://registry.yarnpkg.com/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz#2eb94d6cf85780b1b4725ce853b9cbd5e8da8c72" - integrity sha1-LrlNbPhXgLG0clzoU7nL1ejajHI= - dependencies: - nodemailer-shared "1.1.0" - nodemailer-wellknown "0.1.10" - smtp-connection "2.12.0" - -nodemailer-smtp-transport@2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz#03d71c76314f14ac7dbc7bf033a6a6d16d67fb77" - integrity sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c= - dependencies: - nodemailer-shared "1.1.0" - nodemailer-wellknown "0.1.10" - smtp-connection "2.12.0" - -nodemailer-wellknown@0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz#586db8101db30cb4438eb546737a41aad0cf13d5" - integrity sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U= - -nodemailer@^2.5.0: - version "2.7.2" - resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-2.7.2.tgz#f242e649aeeae39b6c7ed740ef7b061c404d30f9" - integrity sha1-8kLmSa7q45tsftdA73sGHEBNMPk= - dependencies: - libmime "3.0.0" - mailcomposer "4.0.1" - nodemailer-direct-transport "3.3.2" - nodemailer-shared "1.1.0" - nodemailer-smtp-pool "2.8.2" - nodemailer-smtp-transport "2.7.2" - socks "1.1.9" - nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -6086,7 +5825,7 @@ on-headers@~1.0.1: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" integrity sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c= -once@^1.3.0, once@^1.3.3: +once@^1.3.0, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -6133,7 +5872,7 @@ optimist@~0.3.5: dependencies: wordwrap "~0.0.2" -optionator@^0.8.1, optionator@^0.8.2: +optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= @@ -6199,31 +5938,6 @@ osenv@^0.1.4: resolved "https://registry.yarnpkg.com/over/-/over-0.0.5.tgz#f29852e70fd7e25f360e013a8ec44c82aedb5708" integrity sha1-8phS5w/X4l82DgE6jsRMgq7bVwg= -pac-proxy-agent@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz#90d9f6730ab0f4d2607dcdcd4d3d641aa26c3896" - integrity sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA== - dependencies: - agent-base "^4.2.0" - debug "^3.1.0" - get-uri "^2.0.0" - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - pac-resolver "^3.0.0" - raw-body "^2.2.0" - socks-proxy-agent "^3.0.0" - -pac-resolver@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-3.0.0.tgz#6aea30787db0a891704deb7800a722a7615a6f26" - integrity sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA== - dependencies: - co "^4.6.0" - degenerator "^1.0.4" - ip "^1.1.5" - netmask "^1.0.6" - thunkify "^2.1.2" - pad-right@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/pad-right/-/pad-right-0.2.2.tgz#6fbc924045d244f2a2a244503060d3bfc6009774" @@ -6385,13 +6099,6 @@ path-platform@~0.11.15: resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= -path-proxy@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/path-proxy/-/path-proxy-1.0.0.tgz#18e8a36859fc9d2f1a53b48dee138543c020de5e" - integrity sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4= - dependencies: - inflection "~1.3.0" - path-root-regex@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" @@ -6515,6 +6222,11 @@ process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + process@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/process/-/process-0.8.0.tgz#7bbaf7187fe6ded3fd5be0cb6103fba9cacb9798" @@ -6539,13 +6251,6 @@ promises-aplus-tests@~2.1.0: sinon "^1.10.3" underscore "~1.8.3" -promisify-call@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/promisify-call/-/promisify-call-2.0.4.tgz#d48c2d45652ccccd52801ddecbd533a6d4bd5fba" - integrity sha1-1IwtRWUszM1SgB3ey9UzptS9X7o= - dependencies: - with-callback "^1.0.2" - protochain@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/protochain/-/protochain-1.0.5.tgz#991c407e99de264aadf8f81504b5e7faf7bfa260" @@ -6581,26 +6286,7 @@ proxy-addr@~1.1.3: forwarded "~0.1.0" ipaddr.js "1.2.0" -proxy-agent@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-3.0.1.tgz#4fb7b61b1476d0fe8e3a3384d90e2460bbded3f9" - integrity sha512-mAZexaz9ZxQhYPWfAjzlrloEjW+JHiBFryE4AJXFDTnaXfmH/FKqC1swTRKuEPbHWz02flQNXFOyDUF7zfEG6A== - dependencies: - agent-base "^4.2.0" - debug "^3.1.0" - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - lru-cache "^4.1.2" - pac-proxy-agent "^2.0.1" - proxy-from-env "^1.0.0" - socks-proxy-agent "^4.0.1" - -proxy-from-env@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" - integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= - -pseudomap@^1.0.1, pseudomap@^1.0.2: +pseudomap@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= @@ -6631,7 +6317,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@1.4.1, punycode@^1.4.1: +punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -6675,10 +6361,10 @@ q@1.4.1, q@^1.0.1, q@^1.4.1, q@~1.4.1: resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" integrity sha1-VXBbzZPF82c1MMLCy8DCs63cKG4= -q@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" - integrity sha1-3QG6ydBtMObyGa7LglPunr3DCPE= +q@^1.5.0, q@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= q@~0.9.7: version "0.9.7" @@ -6690,11 +6376,6 @@ q@~1.0.0: resolved "https://registry.yarnpkg.com/q/-/q-1.0.1.tgz#11872aeedee89268110b10a718448ffb10112a14" integrity sha1-EYcq7t7okmgRCxCnGESP+xARKhQ= -q@~1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - qjobs@^1.1.4: version "1.1.5" resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73" @@ -6712,7 +6393,7 @@ qs@6.2.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.0.tgz#3b7848c03c2dece69a9522b0fae8c4126d745f3b" integrity sha1-O3hIwDwt7OaalSKw+ujEEm10Xzs= -qs@6.5.1, qs@~6.5.1: +qs@6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== @@ -6727,11 +6408,6 @@ qs@~0.1.0: resolved "https://registry.yarnpkg.com/qs/-/qs-0.1.0.tgz#9a0d2d70d01f63d3401ea4b050822601b462ee6b" integrity sha1-mg0tcNAfY9NAHqSwUIImAbRi7ms= -qs@~6.2.0: - version "6.2.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" - integrity sha1-HPyyXBCpsrSDBT/zn138kjOQjP4= - qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" @@ -6742,6 +6418,11 @@ qs@~6.4.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" integrity sha1-E+JtKK1rD/qpExLNO/cI7TUecjM= +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + querystring-es3@~0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -6780,16 +6461,6 @@ raw-body@2.3.2: iconv-lite "0.4.19" unpipe "1.0.0" -raw-body@^2.2.0: - version "2.3.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== - dependencies: - bytes "3.0.0" - http-errors "1.6.3" - iconv-lite "0.4.23" - unpipe "1.0.0" - rc@^1.1.7: version "1.2.2" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.2.tgz#d8ce9cb57e8d64d9c7badd9876c7c34cbe3c7077" @@ -6827,17 +6498,30 @@ readable-stream@1.1, "readable-stream@>=1.1.13-1 <1.2.0-0", readable-stream@^1.0 isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@1.1.x, "readable-stream@1.x >=1.1.9": - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= +"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@^1.0.33-1, readable-stream@~1.0.0, readable-stream@~1.0.17, readable-stream@~1.0.2, readable-stream@~1.0.31: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@2, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.3.0: +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.3.0: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ== @@ -6850,17 +6534,7 @@ readable-stream@2, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stre string_decoder "~1.0.3" util-deprecate "~1.0.1" -"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@^1.0.33-1, readable-stream@~1.0.0, readable-stream@~1.0.17, readable-stream@~1.0.2, readable-stream@~1.0.31: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.1.5: +readable-stream@^2.1.5: version "2.2.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" integrity sha1-qeb+w8fdqF+LsbO6cChgRVb8gl4= @@ -6873,7 +6547,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.1.5: string_decoder "~0.10.x" util-deprecate "~1.0.1" -readable-stream@~2.0.5, readable-stream@~2.0.6: +readable-stream@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" integrity sha1-j5A0HmilPMySh4jaz80Rs265t44= @@ -6926,25 +6600,6 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" -redis-commands@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.1.tgz#81d826f45fa9c8b2011f4cd7a0fe597d241d442b" - integrity sha1-gdgm9F+pyLIBH0zXoP5ZfSQdRCs= - -redis-parser@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.6.0.tgz#52ed09dacac108f1a631c07e9b69941e7a19504b" - integrity sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs= - -redis@^2.7.1: - version "2.8.0" - resolved "https://registry.yarnpkg.com/redis/-/redis-2.8.0.tgz#202288e3f58c49f6079d97af7a10e1303ae14b02" - integrity sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A== - dependencies: - double-ended-queue "^2.1.0-0" - redis-commands "^1.2.0" - redis-parser "^2.6.0" - regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" @@ -6997,59 +6652,6 @@ replace-ext@^1.0.0: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= -request@2.75.x: - version "2.75.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.75.0.tgz#d2b8268a286da13eaa5d01adf5d18cc90f657d93" - integrity sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM= - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - bl "~1.1.2" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.0.0" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - node-uuid "~1.4.7" - oauth-sign "~0.8.1" - qs "~6.2.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - -request@2.79.0, request@^2.78.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - integrity sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4= - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - request@2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -7078,10 +6680,10 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@^2.0.0, request@^2.74.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - integrity sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw== +request@2.85.0: + version "2.85.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" + integrity sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.6.0" @@ -7106,15 +6708,31 @@ request@^2.0.0, request@^2.74.0: tunnel-agent "^0.6.0" uuid "^3.1.0" -requestretry@^1.2.2: - version "1.12.2" - resolved "https://registry.yarnpkg.com/requestretry/-/requestretry-1.12.2.tgz#13ce38a4ce4e809f3c9ec6d4ca3b7b9ba4acf26c" - integrity sha512-wDYnH4imurLs5upu31WoPaOFfEu31qhFlF7KgpYbBsmBagFmreZZo8E/XpoQ3erCP5za+72t8k8QI4wlrtwVXw== +request@^2.78.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + integrity sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4= dependencies: - extend "^3.0.0" - lodash "^4.15.0" - request "^2.74.0" - when "^3.7.7" + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" require-uncached@^1.0.2: version "1.0.3" @@ -7192,6 +6810,11 @@ rewire@~2.1.0: resolved "https://registry.yarnpkg.com/rewire/-/rewire-2.1.5.tgz#764599179cae5e393839bf3ad6e0be371ee49d81" integrity sha1-dkWZF5yuXjk4Ob861uC+Nx7knYE= +rfdc@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.2.tgz#e6e72d74f5dc39de8f538f65e00c36c18018e349" + integrity sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA== + rfile@~1.0, rfile@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rfile/-/rfile-1.0.0.tgz#59708cf90ca1e74c54c3cfc5c36fdb9810435261" @@ -7212,7 +6835,7 @@ right-pad@^1.0.1: resolved "https://registry.yarnpkg.com/right-pad/-/right-pad-1.0.1.tgz#8ca08c2cbb5b55e74dafa96bf7fd1a27d568c8d0" integrity sha1-jKCMLLtbVedNr6lr9/0aJ9VoyNA= -rimraf@2, rimraf@^2.5.1, rimraf@^2.6.0, rimraf@^2.6.1: +rimraf@2, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== @@ -7226,7 +6849,7 @@ rimraf@^2.2.8: dependencies: glob "^7.0.5" -rimraf@^2.5.2, rimraf@^2.5.4: +rimraf@^2.5.2: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" integrity sha1-wjOOxkPfeht/5cVPqG9XQopV8z0= @@ -7285,16 +6908,16 @@ safe-buffer@^5.0.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" integrity sha1-0mPKVGls2KMGtcplUekt5XkY++c= -safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== - -safe-buffer@^5.1.2: +safe-buffer@^5.1.1, safe-buffer@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -7302,7 +6925,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3": +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -7313,24 +6936,17 @@ samsam@1.1.2, samsam@~1.1: integrity sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc= sauce-connect-launcher@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/sauce-connect-launcher/-/sauce-connect-launcher-1.2.2.tgz#7346cc8fbdc443191323439b0733451f5f3521f2" - integrity sha1-c0bMj73EQxkTI0ObBzNFH181IfI= + version "1.2.4" + resolved "https://registry.yarnpkg.com/sauce-connect-launcher/-/sauce-connect-launcher-1.2.4.tgz#8d38f85242a9fbede1b2303b559f7e20c5609a1c" + integrity sha512-X2vfwulR6brUGiicXKxPm1GJ7dBEeP1II450Uv4bHGrcGOapZNgzJvn9aioea5IC5BPp/7qjKdE3xbbTBIVXMA== dependencies: adm-zip "~0.4.3" async "^2.1.2" - https-proxy-agent "~1.0.0" + https-proxy-agent "^2.2.1" lodash "^4.16.6" rimraf "^2.5.4" -saucelabs@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.4.0.tgz#b934a9af9da2874b3f40aae1fcde50a4466f5f38" - integrity sha1-uTSpr52ih0s/QKrh/N5QpEZvXzg= - dependencies: - https-proxy-agent "^1.0.0" - -saucelabs@^1.5.0: +saucelabs@^1.4.0, saucelabs@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.5.0.tgz#9405a73c360d449b232839919a86c396d379fd9d" integrity sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ== @@ -7387,11 +7003,6 @@ semver@^5.3.0, semver@^5.4.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== -semver@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== - semver@~5.0.1: version "5.0.3" resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" @@ -7514,11 +7125,6 @@ setprototypeof@1.0.3: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" integrity sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ= -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - sha.js@^2.3.6, sha.js@~2.4.4: version "2.4.8" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.8.tgz#37068c2c476b6baf402d14a49c67f597921f634f" @@ -7602,13 +7208,6 @@ sinon@^1.10.3: samsam "1.1.2" util ">=0.10.3 <1" -slack-node@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/slack-node/-/slack-node-0.2.0.tgz#de4b8dddaa8b793f61dbd2938104fdabf37dfa30" - integrity sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA= - dependencies: - requestretry "^1.2.2" - slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" @@ -7621,24 +7220,6 @@ slice-ansi@0.0.4: dependencies: readable-stream "~1.0.31" -smart-buffer@^1.0.13, smart-buffer@^1.0.4: - version "1.1.15" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" - integrity sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY= - -smart-buffer@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3" - integrity sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg== - -smtp-connection@2.12.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/smtp-connection/-/smtp-connection-2.12.0.tgz#d76ef9127cb23c2259edb1e8349c2e8d5e2d74c1" - integrity sha1-1275EnyyPCJZ7bHoNJwujV4tdME= - dependencies: - httpntlm "1.6.1" - nodemailer-shared "1.1.0" - snake-case@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f" @@ -7695,85 +7276,46 @@ socket.io-adapter@~1.1.0: resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" integrity sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs= -socket.io-client@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.0.4.tgz#0918a552406dc5e540b380dcd97afc4a64332f8e" - integrity sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44= +socket.io-client@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f" + integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ== dependencies: backo2 "1.0.2" base64-arraybuffer "0.1.5" component-bind "1.0.0" component-emitter "1.2.1" - debug "~2.6.4" - engine.io-client "~3.1.0" + debug "~3.1.0" + engine.io-client "~3.2.0" + has-binary2 "~1.0.2" has-cors "1.1.0" indexof "0.0.1" object-component "0.0.3" parseqs "0.0.5" parseuri "0.0.5" - socket.io-parser "~3.1.1" + socket.io-parser "~3.2.0" to-array "0.1.4" -socket.io-parser@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.1.2.tgz#dbc2282151fc4faebbe40aeedc0772eba619f7f2" - integrity sha1-28IoIVH8T6675Aru3Ady66YZ9/I= +socket.io-parser@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" + integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA== dependencies: component-emitter "1.2.1" - debug "~2.6.4" - has-binary2 "~1.0.2" + debug "~3.1.0" isarray "2.0.1" -socket.io@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.0.4.tgz#c1a4590ceff87ecf13c72652f046f716b29e6014" - integrity sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ= +socket.io@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980" + integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA== dependencies: - debug "~2.6.6" - engine.io "~3.1.0" + debug "~3.1.0" + engine.io "~3.2.0" + has-binary2 "~1.0.2" socket.io-adapter "~1.1.0" - socket.io-client "2.0.4" - socket.io-parser "~3.1.1" - -socks-proxy-agent@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz#2eae7cf8e2a82d34565761539a7f9718c5617659" - integrity sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA== - dependencies: - agent-base "^4.1.0" - socks "^1.1.10" - -socks-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473" - integrity sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw== - dependencies: - agent-base "~4.2.0" - socks "~2.2.0" - -socks@1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.9.tgz#628d7e4d04912435445ac0b6e459376cb3e6d691" - integrity sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE= - dependencies: - ip "^1.1.2" - smart-buffer "^1.0.4" - -socks@^1.1.10: - version "1.1.10" - resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a" - integrity sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o= - dependencies: - ip "^1.1.4" - smart-buffer "^1.0.13" - -socks@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9" - integrity sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w== - dependencies: - ip "^1.1.5" - smart-buffer "^4.0.1" + socket.io-client "2.1.1" + socket.io-parser "~3.2.0" sorted-object@^1.0.0: version "1.0.0" @@ -7844,7 +7386,7 @@ source-map@^0.1.38, source-map@~0.1.31, source-map@~0.1.7: dependencies: amdefine ">=0.0.4" -source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.6: +source-map@^0.5.3, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -7922,24 +7464,24 @@ split@0.2: dependencies: through "2" -sprintf-js@^1.0.3, sprintf-js@~1.0.2: +sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - integrity sha1-US322mKHFEMW3EwY/hzx2UBzm+M= + version "1.15.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2" + integrity sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" ecc-jsbn "~0.1.1" + getpass "^0.1.1" jsbn "~0.1.0" + safer-buffer "^2.0.2" tweetnacl "~0.14.0" stack-trace@0.0.x: @@ -7960,11 +7502,6 @@ static-extend@^0.1.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== -"statuses@>= 1.4.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - statuses@~1.3.0, statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" @@ -8054,15 +7591,22 @@ string_decoder@~1.0.3: dependencies: safe-buffer "~5.1.0" +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + stringmap@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/stringmap/-/stringmap-0.2.2.tgz#556c137b258f942b8776f5b2ef582aa069d7d1b1" integrity sha1-VWwTeyWPlCuHdvWy71gqoGnX0bE= stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg= + version "0.0.6" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" + integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA== strip-ansi@^0.3.0: version "0.3.0" @@ -8179,13 +7723,16 @@ tar-pack@^3.4.0: uid-number "^0.0.6" tar-stream@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.2.tgz#fbc6c6e83c1a19d4cb48c7d96171fc248effc7bf" - integrity sha1-+8bG6DwaGdTLSMfZYXH8JI7/x78= + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== dependencies: bl "^1.0.0" + buffer-alloc "^1.2.0" end-of-stream "^1.0.0" - readable-stream "^2.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" xtend "^4.0.0" tar@^2.2.1: @@ -8252,11 +7799,6 @@ through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1, t resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -thunkify@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/thunkify/-/thunkify-2.1.2.tgz#faa0e9d230c51acc95ca13a361ac05ca7e04553d" - integrity sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0= - tildify@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" @@ -8276,11 +7818,6 @@ timers-browserify@^1.0.1: dependencies: process "~0.11.0" -timespan@2.3.x: - version "2.3.0" - resolved "https://registry.yarnpkg.com/timespan/-/timespan-2.3.0.tgz#4902ce040bd13d845c8f59b27e9d59bad6f39929" - integrity sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk= - title-case@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.0.tgz#c68ccb4232079ded64f94b91b4941ade91391979" @@ -8315,6 +7852,11 @@ to-array@0.1.4: resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + to-iso-string@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" @@ -8345,17 +7887,10 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -tough-cookie@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" - integrity sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo= - dependencies: - punycode "^1.4.1" - -tough-cookie@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" - integrity sha1-C2GKVWW23qkL80JdBNVe3EdadWE= +tough-cookie@~2.3.0, tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA== dependencies: punycode "^1.4.1" @@ -8382,11 +7917,6 @@ tryit@^1.0.1: resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" integrity sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics= -tsscmp@~1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" - integrity sha1-fcSjOvcVgatDN9qR2FylQn69mpc= - tty-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -8504,14 +8034,6 @@ underscore-contrib@~0.3.0: dependencies: underscore "1.6.0" -underscore.string@3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db" - integrity sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s= - dependencies: - sprintf-js "^1.0.3" - util-deprecate "^1.0.2" - underscore.string@~3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.2.3.tgz#806992633665d5e5fcb4db1fb3a862eb68e9e6da" @@ -8527,11 +8049,6 @@ underscore@^1.6.0, underscore@~1.8.3: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= -underscore@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" - integrity sha1-a7rwh3UA02vjTsqlhODbn+8DUgk= - union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" @@ -8641,7 +8158,7 @@ useragent@2.2.1: lru-cache "2.2.x" tmp "0.0.x" -util-deprecate@^1.0.2, util-deprecate@~1.0.1: +util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -8663,20 +8180,10 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" - integrity sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE= - -uuid@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g== - -uws@~0.14.4: - version "0.14.5" - resolved "https://registry.yarnpkg.com/uws/-/uws-0.14.5.tgz#67aaf33c46b2a587a5f6666d00f7691328f149dc" - integrity sha1-Z6rzPEaypYel9mZtAPdpEyjxSdw= +uuid@^3.0.0, uuid@^3.1.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== v8flags@^2.0.2: version "2.0.11" @@ -8802,17 +8309,16 @@ walkdir@^0.0.11, walkdir@~0.0.7: integrity sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI= wd@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/wd/-/wd-1.4.1.tgz#6b1ab39aab1728ee276c1a2b6d7321da68b16e8c" - integrity sha512-C0wWd2X4SWWcyx5qxaixiZE4Vb07sl0yDfWHPeml8lDHSbmI9erE9BmTHIqOGoDxGgJ3/hkFmODQ7ZLKiF8+8Q== + version "1.11.0" + resolved "https://registry.yarnpkg.com/wd/-/wd-1.11.0.tgz#b610deea7f79f5a520a573c09e047e42d31433f9" + integrity sha512-h2EBfJvmsWocIjOOg5BsHh9IJKrqZDG4Az4jEZhFugEH7sOPcX6feZQ30aFuktqDI0jquarZJmNpA6V0A0Q7Mg== dependencies: - archiver "1.3.0" + archiver "2.1.1" async "2.0.1" - lodash "4.16.2" + lodash "4.17.10" mkdirp "^0.5.1" q "1.4.1" - request "2.79.0" - underscore.string "3.3.4" + request "2.85.0" vargs "0.1.0" weak-map@1.0.0: @@ -8845,11 +8351,6 @@ webdriver-manager@^12.0.6: semver "^5.3.0" xml2js "^0.4.17" -when@^3.7.7: - version "3.7.8" - resolved "https://registry.yarnpkg.com/when/-/when-3.7.8.tgz#c7130b6a7ea04693e842cdc9e7a1f2aa39a39f82" - integrity sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I= - which@^1.2.1, which@^1.2.10, which@^1.2.12, which@^1.2.9, which@~1.2.1: version "1.2.12" resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192" @@ -8886,11 +8387,6 @@ winston@^2.1.1: isstream "0.1.x" stack-trace "0.0.x" -with-callback@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/with-callback/-/with-callback-1.0.2.tgz#a09629b9a920028d721404fb435bdcff5c91bc21" - integrity sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE= - word-wrap@^1.0.3: version "1.2.1" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.1.tgz#248f459b465d179a17bc407c854d3151d07e45d8" @@ -8970,11 +8466,6 @@ xmlhttprequest-ssl@~1.5.4: resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.4.tgz#04f560915724b389088715cc0ed7813e9677bf57" integrity sha1-BPVgkVcks4kIhxXMDteBPpZ3v1c= -xregexp@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" - integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= - "xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -8995,11 +8486,6 @@ yallist@^2.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.0.0.tgz#306c543835f09ee1a4cb23b7bce9ab341c91cdd4" integrity sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ= -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" @@ -9043,12 +8529,12 @@ yeast@0.1.2: resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= -zip-stream@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.1.1.tgz#5216b48bbb4d2651f64d5c6e6f09eb4a7399d557" - integrity sha1-Uha0i7tNJlH2TVxubwnrSnOZ1Vc= +zip-stream@^1.1.0, zip-stream@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04" + integrity sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ= dependencies: archiver-utils "^1.3.0" - compress-commons "^1.1.0" + compress-commons "^1.2.0" lodash "^4.8.0" readable-stream "^2.0.0" From ab36c4b487032183833ab62656ed2dfaefb32b9e Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Thu, 25 Oct 2018 12:21:11 +0200 Subject: [PATCH 131/217] revert: fix(Angular): add workaround for Safari / Webdriver problem This reverts commit 6b915ad9db29027e0aa70634e08a8a3c5af897b8. Karma has this workaround built in since 3.1.0: https://github.com/karma-runner/karma/commit/873e4f9 --- src/Angular.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Angular.js b/src/Angular.js index a71b3cbb38f0..9edd1b56e254 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -1696,13 +1696,8 @@ function angularInit(element, bootstrap) { }); if (appElement) { if (!isAutoBootstrapAllowed) { - try { - window.console.error('AngularJS: disabling automatic bootstrap. + {% for stylesheet in doc.stylesheets %} + {$- addTag('link', {rel: 'stylesheet', href: stylesheet, type: 'text/css'}) -$} + {% endfor %} + {% for script in doc.scripts %} + {$- addTag('script', {src: script}) -$} + {% endfor %} + +