angularjs-rails 1.5.5 → 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.5.5
2
+ * @license AngularJS v1.5.6
3
3
  * (c) 2010-2016 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.5.5
2
+ * @license AngularJS v1.5.6
3
3
  * (c) 2010-2016 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -57,7 +57,7 @@ function minErr(module, ErrorConstructor) {
57
57
  return match;
58
58
  });
59
59
 
60
- message += '\nhttp://errors.angularjs.org/1.5.5/' +
60
+ message += '\nhttp://errors.angularjs.org/1.5.6/' +
61
61
  (module ? module + '/' : '') + code;
62
62
 
63
63
  for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -516,12 +516,22 @@ noop.$inject = [];
516
516
  * functional style.
517
517
  *
518
518
  ```js
519
- function transformer(transformationFn, value) {
520
- return (transformationFn || angular.identity)(value);
521
- };
519
+ function transformer(transformationFn, value) {
520
+ return (transformationFn || angular.identity)(value);
521
+ };
522
+
523
+ // E.g.
524
+ function getResult(fn, input) {
525
+ return (fn || angular.identity)(input);
526
+ };
527
+
528
+ getResult(function(n) { return n * 2; }, 21); // returns 42
529
+ getResult(null, 21); // returns 21
530
+ getResult(undefined, 21); // returns 21
522
531
  ```
523
- * @param {*} value to be returned.
524
- * @returns {*} the value passed in.
532
+ *
533
+ * @param {*} value to be returned.
534
+ * @returns {*} the value passed in.
525
535
  */
526
536
  function identity($) {return $;}
527
537
  identity.$inject = [];
@@ -766,8 +776,8 @@ var escapeForRegexp = function(s) {
766
776
  */
767
777
  function isElement(node) {
768
778
  return !!(node &&
769
- (node.nodeName // we are a direct element
770
- || (node.prop && node.attr && node.find))); // we have an on and find method part of jQuery API
779
+ (node.nodeName // We are a direct element.
780
+ || (node.prop && node.attr && node.find))); // We have an on and find method part of jQuery API.
771
781
  }
772
782
 
773
783
  /**
@@ -1257,7 +1267,7 @@ function bind(self, fn) {
1257
1267
  : fn.call(self);
1258
1268
  };
1259
1269
  } else {
1260
- // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
1270
+ // In IE, native methods are not functions so they cannot be bound (note: they don't need to be).
1261
1271
  return fn;
1262
1272
  }
1263
1273
  }
@@ -1294,6 +1304,27 @@ function toJsonReplacer(key, value) {
1294
1304
  * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
1295
1305
  * If set to an integer, the JSON output will contain that many spaces per indentation.
1296
1306
  * @returns {string|undefined} JSON-ified string representing `obj`.
1307
+ * @knownIssue
1308
+ *
1309
+ * The Safari browser throws a `RangeError` instead of returning `null` when it tries to stringify a `Date`
1310
+ * object with an invalid date value. The only reliable way to prevent this is to monkeypatch the
1311
+ * `Date.prototype.toJSON` method as follows:
1312
+ *
1313
+ * ```
1314
+ * var _DatetoJSON = Date.prototype.toJSON;
1315
+ * Date.prototype.toJSON = function() {
1316
+ * try {
1317
+ * return _DatetoJSON.call(this);
1318
+ * } catch(e) {
1319
+ * if (e instanceof RangeError) {
1320
+ * return null;
1321
+ * }
1322
+ * throw e;
1323
+ * }
1324
+ * };
1325
+ * ```
1326
+ *
1327
+ * See https://github.com/angular/angular.js/pull/14221 for more information.
1297
1328
  */
1298
1329
  function toJson(obj, pretty) {
1299
1330
  if (isUndefined(obj)) return undefined;
@@ -1384,7 +1415,7 @@ function tryDecodeURIComponent(value) {
1384
1415
  try {
1385
1416
  return decodeURIComponent(value);
1386
1417
  } catch (e) {
1387
- // Ignore any invalid uri component
1418
+ // Ignore any invalid uri component.
1388
1419
  }
1389
1420
  }
1390
1421
 
@@ -1629,7 +1660,7 @@ function angularInit(element, bootstrap) {
1629
1660
  module,
1630
1661
  config = {};
1631
1662
 
1632
- // The element `element` has priority over any other element
1663
+ // The element `element` has priority over any other element.
1633
1664
  forEach(ngAttrPrefixes, function(prefix) {
1634
1665
  var name = prefix + 'app';
1635
1666
 
@@ -1723,7 +1754,7 @@ function bootstrap(element, modules, config) {
1723
1754
 
1724
1755
  if (element.injector()) {
1725
1756
  var tag = (element[0] === window.document) ? 'document' : startingTag(element);
1726
- //Encode angle brackets to prevent input from being sanitized to empty string #8683
1757
+ // Encode angle brackets to prevent input from being sanitized to empty string #8683.
1727
1758
  throw ngMinErr(
1728
1759
  'btstrpd',
1729
1760
  "App already bootstrapped with this element '{0}'",
@@ -2479,11 +2510,11 @@ function toDebugString(obj) {
2479
2510
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2480
2511
  */
2481
2512
  var version = {
2482
- full: '1.5.5', // all of these placeholder strings will be replaced by grunt's
2513
+ full: '1.5.6', // all of these placeholder strings will be replaced by grunt's
2483
2514
  major: 1, // package task
2484
2515
  minor: 5,
2485
- dot: 5,
2486
- codeName: 'material-conspiration'
2516
+ dot: 6,
2517
+ codeName: 'arrow-stringification'
2487
2518
  };
2488
2519
 
2489
2520
 
@@ -2710,8 +2741,8 @@ function publishExternalAPI(angular) {
2710
2741
  * - [`removeData()`](http://api.jquery.com/removeData/)
2711
2742
  * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
2712
2743
  * - [`text()`](http://api.jquery.com/text/)
2713
- * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
2714
- * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
2744
+ * - [`toggleClass()`](http://api.jquery.com/toggleClass/) - Does not support a function as first argument
2745
+ * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers
2715
2746
  * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
2716
2747
  * - [`val()`](http://api.jquery.com/val/)
2717
2748
  * - [`wrap()`](http://api.jquery.com/wrap/)
@@ -3871,8 +3902,16 @@ var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
3871
3902
  var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
3872
3903
  var $injectorMinErr = minErr('$injector');
3873
3904
 
3905
+ function stringifyFn(fn) {
3906
+ // Support: Chrome 50-51 only
3907
+ // Creating a new string by adding `' '` at the end, to hack around some bug in Chrome v50/51
3908
+ // (See https://github.com/angular/angular.js/issues/14487.)
3909
+ // TODO (gkalpak): Remove workaround when Chrome v52 is released
3910
+ return Function.prototype.toString.call(fn) + ' ';
3911
+ }
3912
+
3874
3913
  function extractArgs(fn) {
3875
- var fnText = Function.prototype.toString.call(fn).replace(STRIP_COMMENTS, ''),
3914
+ var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''),
3876
3915
  args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
3877
3916
  return args;
3878
3917
  }
@@ -4140,18 +4179,20 @@ function annotate(fn, strictDi, name) {
4140
4179
  * these cases the {@link auto.$provide $provide} service has additional helper methods to register
4141
4180
  * services without specifying a provider.
4142
4181
  *
4143
- * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
4182
+ * * {@link auto.$provide#provider provider(name, provider)} - registers a **service provider** with the
4144
4183
  * {@link auto.$injector $injector}
4145
- * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
4184
+ * * {@link auto.$provide#constant constant(name, obj)} - registers a value/object that can be accessed by
4146
4185
  * providers and services.
4147
- * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
4186
+ * * {@link auto.$provide#value value(name, obj)} - registers a value/object that can only be accessed by
4148
4187
  * services, not providers.
4149
- * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
4188
+ * * {@link auto.$provide#factory factory(name, fn)} - registers a service **factory function**
4150
4189
  * that will be wrapped in a **service provider** object, whose `$get` property will contain the
4151
4190
  * given factory function.
4152
- * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
4191
+ * * {@link auto.$provide#service service(name, Fn)} - registers a **constructor function**
4153
4192
  * that will be wrapped in a **service provider** object, whose `$get` property will instantiate
4154
4193
  * a new object using the given constructor function.
4194
+ * * {@link auto.$provide#decorator decorator(name, decorFn)} - registers a **decorator function** that
4195
+ * will be able to modify or replace the implementation of another service.
4155
4196
  *
4156
4197
  * See the individual methods for more information and examples.
4157
4198
  */
@@ -4408,18 +4449,20 @@ function annotate(fn, strictDi, name) {
4408
4449
  * @name $provide#decorator
4409
4450
  * @description
4410
4451
  *
4411
- * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
4452
+ * Register a **decorator function** with the {@link auto.$injector $injector}. A decorator function
4412
4453
  * intercepts the creation of a service, allowing it to override or modify the behavior of the
4413
- * service. The object returned by the decorator may be the original service, or a new service
4414
- * object which replaces or wraps and delegates to the original service.
4454
+ * service. The return value of the decorator function may be the original service, or a new service
4455
+ * that replaces (or wraps and delegates to) the original service.
4456
+ *
4457
+ * You can find out more about using decorators in the {@link guide/decorators} guide.
4415
4458
  *
4416
4459
  * @param {string} name The name of the service to decorate.
4417
4460
  * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
4418
- * instantiated and should return the decorated service instance. The function is called using
4461
+ * provided and should return the decorated service instance. The function is called using
4419
4462
  * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
4420
4463
  * Local injection arguments:
4421
4464
  *
4422
- * * `$delegate` - The original service instance, which can be monkey patched, configured,
4465
+ * * `$delegate` - The original service instance, which can be replaced, monkey patched, configured,
4423
4466
  * decorated or delegated to.
4424
4467
  *
4425
4468
  * @example
@@ -4645,7 +4688,7 @@ function createInjector(modulesToLoad, strictDi) {
4645
4688
  // Workaround for MS Edge.
4646
4689
  // Check https://connect.microsoft.com/IE/Feedback/Details/2211653
4647
4690
  return typeof func === 'function'
4648
- && /^(?:class\s|constructor\()/.test(Function.prototype.toString.call(func));
4691
+ && /^(?:class\s|constructor\()/.test(stringifyFn(func));
4649
4692
  }
4650
4693
 
4651
4694
  function invoke(fn, self, locals, serviceName) {
@@ -4736,7 +4779,7 @@ function $AnchorScrollProvider() {
4736
4779
  * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
4737
4780
  * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
4738
4781
  * in the
4739
- * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#the-indicated-part-of-the-document).
4782
+ * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#an-indicated-part-of-the-document).
4740
4783
  *
4741
4784
  * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
4742
4785
  * match any anchor whenever it changes. This can be disabled by calling
@@ -5974,7 +6017,7 @@ function Browser(window, document, $log, $sniffer) {
5974
6017
  // Do the assignment again so that those two variables are referentially identical.
5975
6018
  lastHistoryState = cachedState;
5976
6019
  } else {
5977
- if (!sameBase || pendingLocation) {
6020
+ if (!sameBase) {
5978
6021
  pendingLocation = url;
5979
6022
  }
5980
6023
  if (replace) {
@@ -5988,6 +6031,9 @@ function Browser(window, document, $log, $sniffer) {
5988
6031
  pendingLocation = url;
5989
6032
  }
5990
6033
  }
6034
+ if (pendingLocation) {
6035
+ pendingLocation = url;
6036
+ }
5991
6037
  return self;
5992
6038
  // getter
5993
6039
  } else {
@@ -6904,8 +6950,9 @@ function $TemplateCacheProvider() {
6904
6950
  * If the `require` property is an object and `bindToController` is truthy, then the required controllers are
6905
6951
  * bound to the controller using the keys of the `require` property. This binding occurs after all the controllers
6906
6952
  * have been constructed but before `$onInit` is called.
6953
+ * If the name of the required controller is the same as the local name (the key), the name can be
6954
+ * omitted. For example, `{parentDir: '^^'}` is equivalent to `{parentDir: '^^parentDir'}`.
6907
6955
  * See the {@link $compileProvider#component} helper for an example of how this can be used.
6908
- *
6909
6956
  * If no such required directive(s) can be found, or if the directive does not have a controller, then an error is
6910
6957
  * raised (unless no link function is specified and the required controllers are not being bound to the directive
6911
6958
  * controller, in which case error checking is skipped). The name can be prefixed with:
@@ -7534,6 +7581,20 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7534
7581
  }
7535
7582
  }
7536
7583
 
7584
+ function getDirectiveRequire(directive) {
7585
+ var require = directive.require || (directive.controller && directive.name);
7586
+
7587
+ if (!isArray(require) && isObject(require)) {
7588
+ forEach(require, function(value, key) {
7589
+ var match = value.match(REQUIRE_PREFIX_REGEXP);
7590
+ var name = value.substring(match[0].length);
7591
+ if (!name) require[key] = match[0] + key;
7592
+ });
7593
+ }
7594
+
7595
+ return require;
7596
+ }
7597
+
7537
7598
  /**
7538
7599
  * @ngdoc method
7539
7600
  * @name $compileProvider#directive
@@ -7570,7 +7631,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
7570
7631
  directive.priority = directive.priority || 0;
7571
7632
  directive.index = index;
7572
7633
  directive.name = directive.name || name;
7573
- directive.require = directive.require || (directive.controller && directive.name);
7634
+ directive.require = getDirectiveRequire(directive);
7574
7635
  directive.restrict = directive.restrict || 'EA';
7575
7636
  directive.$$moduleName = directiveFactory.$$moduleName;
7576
7637
  directives.push(directive);
@@ -8027,7 +8088,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8027
8088
  (nodeName === 'img' && key === 'src')) {
8028
8089
  // sanitize a[href] and img[src] values
8029
8090
  this[key] = value = $$sanitizeUri(value, key === 'src');
8030
- } else if (nodeName === 'img' && key === 'srcset') {
8091
+ } else if (nodeName === 'img' && key === 'srcset' && isDefined(value)) {
8031
8092
  // sanitize img[srcset] values
8032
8093
  var result = "";
8033
8094
 
@@ -8186,7 +8247,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8186
8247
  compile.$$createComment = function(directiveName, comment) {
8187
8248
  var content = '';
8188
8249
  if (debugInfoEnabled) {
8189
- content = ' ' + (directiveName || '') + ': ' + (comment || '') + ' ';
8250
+ content = ' ' + (directiveName || '') + ': ';
8251
+ if (comment) content += comment + ' ';
8190
8252
  }
8191
8253
  return window.document.createComment(content);
8192
8254
  };
@@ -8918,10 +8980,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
8918
8980
  } else if (directive.compile) {
8919
8981
  try {
8920
8982
  linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
8983
+ var context = directive.$$originalDirective || directive;
8921
8984
  if (isFunction(linkFn)) {
8922
- addLinkFns(null, linkFn, attrStart, attrEnd);
8985
+ addLinkFns(null, bind(context, linkFn), attrStart, attrEnd);
8923
8986
  } else if (linkFn) {
8924
- addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
8987
+ addLinkFns(bind(context, linkFn.pre), bind(context, linkFn.post), attrStart, attrEnd);
8925
8988
  }
8926
8989
  } catch (e) {
8927
8990
  $exceptionHandler(e, startingTag($compileNode));
@@ -9790,14 +9853,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
9790
9853
 
9791
9854
  parentGet = $parse(attrs[attrName]);
9792
9855
 
9793
- destination[scopeName] = parentGet(scope);
9856
+ var initialValue = destination[scopeName] = parentGet(scope);
9794
9857
  initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);
9795
9858
 
9796
9859
  removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) {
9797
- if (newValue === oldValue) {
9798
- // If the new and old values are identical then this is the first time the watch has been triggered
9799
- // So instead we use the current value on the destination as the old value
9800
- oldValue = destination[scopeName];
9860
+ if (oldValue === newValue) {
9861
+ if (oldValue === initialValue) return;
9862
+ oldValue = initialValue;
9801
9863
  }
9802
9864
  recordChanges(scopeName, newValue, oldValue);
9803
9865
  destination[scopeName] = newValue;
@@ -10700,10 +10762,13 @@ function $HttpProvider() {
10700
10762
  * - **config** – `{Object}` – The configuration object that was used to generate the request.
10701
10763
  * - **statusText** – `{string}` – HTTP status text of the response.
10702
10764
  *
10703
- * A response status code between 200 and 299 is considered a success status and
10704
- * will result in the success callback being called. Note that if the response is a redirect,
10705
- * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
10706
- * called for such responses.
10765
+ * A response status code between 200 and 299 is considered a success status and will result in
10766
+ * the success callback being called. Any response status code outside of that range is
10767
+ * considered an error status and will result in the error callback being called.
10768
+ * Also, status codes less than -1 are normalized to zero. -1 usually means the request was
10769
+ * aborted, e.g. using a `config.timeout`.
10770
+ * Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning
10771
+ * that the outcome (success or error) will be determined by the final response status code.
10707
10772
  *
10708
10773
  *
10709
10774
  * ## Shortcut methods
@@ -12033,6 +12098,30 @@ function $InterpolateProvider() {
12033
12098
  * </file>
12034
12099
  * </example>
12035
12100
  *
12101
+ * @knownIssue
12102
+ * It is currently not possible for an interpolated expression to contain the interpolation end
12103
+ * symbol. For example, `{{ '}}' }}` will be incorrectly interpreted as `{{ ' }}` + `' }}`, i.e.
12104
+ * an interpolated expression consisting of a single-quote (`'`) and the `' }}` string.
12105
+ *
12106
+ * @knownIssue
12107
+ * All directives and components must use the standard `{{` `}}` interpolation symbols
12108
+ * in their templates. If you change the application interpolation symbols the {@link $compile}
12109
+ * service will attempt to denormalize the standard symbols to the custom symbols.
12110
+ * The denormalization process is not clever enough to know not to replace instances of the standard
12111
+ * symbols where they would not normally be treated as interpolation symbols. For example in the following
12112
+ * code snippet the closing braces of the literal object will get incorrectly denormalized:
12113
+ *
12114
+ * ```
12115
+ * <div data-context='{"context":{"id":3,"type":"page"}}">
12116
+ * ```
12117
+ *
12118
+ * The workaround is to ensure that such instances are separated by whitespace:
12119
+ * ```
12120
+ * <div data-context='{"context":{"id":3,"type":"page"} }">
12121
+ * ```
12122
+ *
12123
+ * See https://github.com/angular/angular.js/pull/14610#issuecomment-219401099 for more information.
12124
+ *
12036
12125
  * @param {string} text The text with markup to interpolate.
12037
12126
  * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
12038
12127
  * embedded expression in order to return an interpolation function. Strings with no
@@ -12455,17 +12544,20 @@ function parseAppUrl(relativeUrl, locationObj) {
12455
12544
  }
12456
12545
  }
12457
12546
 
12547
+ function startsWith(haystack, needle) {
12548
+ return haystack.lastIndexOf(needle, 0) === 0;
12549
+ }
12458
12550
 
12459
12551
  /**
12460
12552
  *
12461
- * @param {string} begin
12462
- * @param {string} whole
12463
- * @returns {string} returns text from whole after begin or undefined if it does not begin with
12464
- * expected string.
12553
+ * @param {string} base
12554
+ * @param {string} url
12555
+ * @returns {string} returns text from `url` after `base` or `undefined` if it does not begin with
12556
+ * the expected string.
12465
12557
  */
12466
- function beginsWith(begin, whole) {
12467
- if (whole.indexOf(begin) === 0) {
12468
- return whole.substr(begin.length);
12558
+ function stripBaseUrl(base, url) {
12559
+ if (startsWith(url, base)) {
12560
+ return url.substr(base.length);
12469
12561
  }
12470
12562
  }
12471
12563
 
@@ -12511,7 +12603,7 @@ function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
12511
12603
  * @private
12512
12604
  */
12513
12605
  this.$$parse = function(url) {
12514
- var pathUrl = beginsWith(appBaseNoFile, url);
12606
+ var pathUrl = stripBaseUrl(appBaseNoFile, url);
12515
12607
  if (!isString(pathUrl)) {
12516
12608
  throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
12517
12609
  appBaseNoFile);
@@ -12548,14 +12640,14 @@ function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
12548
12640
  var appUrl, prevAppUrl;
12549
12641
  var rewrittenUrl;
12550
12642
 
12551
- if (isDefined(appUrl = beginsWith(appBase, url))) {
12643
+ if (isDefined(appUrl = stripBaseUrl(appBase, url))) {
12552
12644
  prevAppUrl = appUrl;
12553
- if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) {
12554
- rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
12645
+ if (isDefined(appUrl = stripBaseUrl(basePrefix, appUrl))) {
12646
+ rewrittenUrl = appBaseNoFile + (stripBaseUrl('/', appUrl) || appUrl);
12555
12647
  } else {
12556
12648
  rewrittenUrl = appBase + prevAppUrl;
12557
12649
  }
12558
- } else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) {
12650
+ } else if (isDefined(appUrl = stripBaseUrl(appBaseNoFile, url))) {
12559
12651
  rewrittenUrl = appBaseNoFile + appUrl;
12560
12652
  } else if (appBaseNoFile == url + '/') {
12561
12653
  rewrittenUrl = appBaseNoFile;
@@ -12589,14 +12681,14 @@ function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
12589
12681
  * @private
12590
12682
  */
12591
12683
  this.$$parse = function(url) {
12592
- var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
12684
+ var withoutBaseUrl = stripBaseUrl(appBase, url) || stripBaseUrl(appBaseNoFile, url);
12593
12685
  var withoutHashUrl;
12594
12686
 
12595
12687
  if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
12596
12688
 
12597
12689
  // The rest of the url starts with a hash so we have
12598
12690
  // got either a hashbang path or a plain hash fragment
12599
- withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
12691
+ withoutHashUrl = stripBaseUrl(hashPrefix, withoutBaseUrl);
12600
12692
  if (isUndefined(withoutHashUrl)) {
12601
12693
  // There was no hashbang prefix so we just have a hash fragment
12602
12694
  withoutHashUrl = withoutBaseUrl;
@@ -12644,7 +12736,7 @@ function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
12644
12736
  var firstPathSegmentMatch;
12645
12737
 
12646
12738
  //Get the relative path from the input URL.
12647
- if (url.indexOf(base) === 0) {
12739
+ if (startsWith(url, base)) {
12648
12740
  url = url.replace(base, '');
12649
12741
  }
12650
12742
 
@@ -12707,7 +12799,7 @@ function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
12707
12799
 
12708
12800
  if (appBase == stripHash(url)) {
12709
12801
  rewrittenUrl = url;
12710
- } else if ((appUrl = beginsWith(appBaseNoFile, url))) {
12802
+ } else if ((appUrl = stripBaseUrl(appBaseNoFile, url))) {
12711
12803
  rewrittenUrl = appBase + hashPrefix + appUrl;
12712
12804
  } else if (appBaseNoFile === url + '/') {
12713
12805
  rewrittenUrl = appBaseNoFile;
@@ -12889,7 +12981,7 @@ var locationPrototype = {
12889
12981
  * ```
12890
12982
  *
12891
12983
  * @param {(string|number)=} path New path
12892
- * @return {string} path
12984
+ * @return {(string|object)} path if called with no parameters, or `$location` if called with a parameter
12893
12985
  */
12894
12986
  path: locationGetterSetter('$$path', function(path) {
12895
12987
  path = path !== null ? path.toString() : '';
@@ -13315,7 +13407,7 @@ function $LocationProvider() {
13315
13407
  // update $location when $browser url changes
13316
13408
  $browser.onUrlChange(function(newUrl, newState) {
13317
13409
 
13318
- if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
13410
+ if (isUndefined(stripBaseUrl(appBaseNoFile, newUrl))) {
13319
13411
  // If we are navigating outside of the app then force a reload
13320
13412
  $window.location.href = newUrl;
13321
13413
  return;
@@ -14151,13 +14243,28 @@ AST.prototype = {
14151
14243
  property = {type: AST.Property, kind: 'init'};
14152
14244
  if (this.peek().constant) {
14153
14245
  property.key = this.constant();
14246
+ property.computed = false;
14247
+ this.consume(':');
14248
+ property.value = this.expression();
14154
14249
  } else if (this.peek().identifier) {
14155
14250
  property.key = this.identifier();
14251
+ property.computed = false;
14252
+ if (this.peek(':')) {
14253
+ this.consume(':');
14254
+ property.value = this.expression();
14255
+ } else {
14256
+ property.value = property.key;
14257
+ }
14258
+ } else if (this.peek('[')) {
14259
+ this.consume('[');
14260
+ property.key = this.expression();
14261
+ this.consume(']');
14262
+ property.computed = true;
14263
+ this.consume(':');
14264
+ property.value = this.expression();
14156
14265
  } else {
14157
14266
  this.throwError("invalid key", this.peek());
14158
14267
  }
14159
- this.consume(':');
14160
- property.value = this.expression();
14161
14268
  properties.push(property);
14162
14269
  } while (this.expect(','));
14163
14270
  }
@@ -14326,7 +14433,7 @@ function findConstantAndWatchExpressions(ast, $filter) {
14326
14433
  argsToWatch = [];
14327
14434
  forEach(ast.properties, function(property) {
14328
14435
  findConstantAndWatchExpressions(property.value, $filter);
14329
- allConstants = allConstants && property.value.constant;
14436
+ allConstants = allConstants && property.value.constant && !property.computed;
14330
14437
  if (!property.value.constant) {
14331
14438
  argsToWatch.push.apply(argsToWatch, property.value.toWatch);
14332
14439
  }
@@ -14498,7 +14605,7 @@ ASTCompiler.prototype = {
14498
14605
  },
14499
14606
 
14500
14607
  recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
14501
- var left, right, self = this, args, expression;
14608
+ var left, right, self = this, args, expression, computed;
14502
14609
  recursionFn = recursionFn || noop;
14503
14610
  if (!skipWatchIdCheck && isDefined(ast.watchId)) {
14504
14611
  intoId = intoId || this.nextId();
@@ -14695,17 +14802,41 @@ ASTCompiler.prototype = {
14695
14802
  break;
14696
14803
  case AST.ObjectExpression:
14697
14804
  args = [];
14805
+ computed = false;
14698
14806
  forEach(ast.properties, function(property) {
14699
- self.recurse(property.value, self.nextId(), undefined, function(expr) {
14700
- args.push(self.escape(
14701
- property.key.type === AST.Identifier ? property.key.name :
14702
- ('' + property.key.value)) +
14703
- ':' + expr);
14704
- });
14807
+ if (property.computed) {
14808
+ computed = true;
14809
+ }
14705
14810
  });
14706
- expression = '{' + args.join(',') + '}';
14707
- this.assign(intoId, expression);
14708
- recursionFn(expression);
14811
+ if (computed) {
14812
+ intoId = intoId || this.nextId();
14813
+ this.assign(intoId, '{}');
14814
+ forEach(ast.properties, function(property) {
14815
+ if (property.computed) {
14816
+ left = self.nextId();
14817
+ self.recurse(property.key, left);
14818
+ } else {
14819
+ left = property.key.type === AST.Identifier ?
14820
+ property.key.name :
14821
+ ('' + property.key.value);
14822
+ }
14823
+ right = self.nextId();
14824
+ self.recurse(property.value, right);
14825
+ self.assign(self.member(intoId, left, property.computed), right);
14826
+ });
14827
+ } else {
14828
+ forEach(ast.properties, function(property) {
14829
+ self.recurse(property.value, ast.constant ? undefined : self.nextId(), undefined, function(expr) {
14830
+ args.push(self.escape(
14831
+ property.key.type === AST.Identifier ? property.key.name :
14832
+ ('' + property.key.value)) +
14833
+ ':' + expr);
14834
+ });
14835
+ });
14836
+ expression = '{' + args.join(',') + '}';
14837
+ this.assign(intoId, expression);
14838
+ }
14839
+ recursionFn(intoId || expression);
14709
14840
  break;
14710
14841
  case AST.ThisExpression:
14711
14842
  this.assign(intoId, 's');
@@ -15031,16 +15162,28 @@ ASTInterpreter.prototype = {
15031
15162
  case AST.ObjectExpression:
15032
15163
  args = [];
15033
15164
  forEach(ast.properties, function(property) {
15034
- args.push({key: property.key.type === AST.Identifier ?
15035
- property.key.name :
15036
- ('' + property.key.value),
15037
- value: self.recurse(property.value)
15038
- });
15165
+ if (property.computed) {
15166
+ args.push({key: self.recurse(property.key),
15167
+ computed: true,
15168
+ value: self.recurse(property.value)
15169
+ });
15170
+ } else {
15171
+ args.push({key: property.key.type === AST.Identifier ?
15172
+ property.key.name :
15173
+ ('' + property.key.value),
15174
+ computed: false,
15175
+ value: self.recurse(property.value)
15176
+ });
15177
+ }
15039
15178
  });
15040
15179
  return function(scope, locals, assign, inputs) {
15041
15180
  var value = {};
15042
15181
  for (var i = 0; i < args.length; ++i) {
15043
- value[args[i].key] = args[i].value(scope, locals, assign, inputs);
15182
+ if (args[i].computed) {
15183
+ value[args[i].key(scope, locals, assign, inputs)] = args[i].value(scope, locals, assign, inputs);
15184
+ } else {
15185
+ value[args[i].key] = args[i].value(scope, locals, assign, inputs);
15186
+ }
15044
15187
  }
15045
15188
  return context ? {value: value} : value;
15046
15189
  };
@@ -17039,15 +17182,19 @@ function $RootScopeProvider() {
17039
17182
  dirty = false;
17040
17183
  current = target;
17041
17184
 
17042
- while (asyncQueue.length) {
17185
+ // It's safe for asyncQueuePosition to be a local variable here because this loop can't
17186
+ // be reentered recursively. Calling $digest from a function passed to $applyAsync would
17187
+ // lead to a '$digest already in progress' error.
17188
+ for (var asyncQueuePosition = 0; asyncQueuePosition < asyncQueue.length; asyncQueuePosition++) {
17043
17189
  try {
17044
- asyncTask = asyncQueue.shift();
17190
+ asyncTask = asyncQueue[asyncQueuePosition];
17045
17191
  asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
17046
17192
  } catch (e) {
17047
17193
  $exceptionHandler(e);
17048
17194
  }
17049
17195
  lastDirtyWatch = null;
17050
17196
  }
17197
+ asyncQueue.length = 0;
17051
17198
 
17052
17199
  traverseScopesLoop:
17053
17200
  do { // "traverse the scopes" loop
@@ -17118,13 +17265,15 @@ function $RootScopeProvider() {
17118
17265
 
17119
17266
  clearPhase();
17120
17267
 
17121
- while (postDigestQueue.length) {
17268
+ // postDigestQueuePosition isn't local here because this loop can be reentered recursively.
17269
+ while (postDigestQueuePosition < postDigestQueue.length) {
17122
17270
  try {
17123
- postDigestQueue.shift()();
17271
+ postDigestQueue[postDigestQueuePosition++]();
17124
17272
  } catch (e) {
17125
17273
  $exceptionHandler(e);
17126
17274
  }
17127
17275
  }
17276
+ postDigestQueue.length = postDigestQueuePosition = 0;
17128
17277
  },
17129
17278
 
17130
17279
 
@@ -17579,6 +17728,8 @@ function $RootScopeProvider() {
17579
17728
  var postDigestQueue = $rootScope.$$postDigestQueue = [];
17580
17729
  var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];
17581
17730
 
17731
+ var postDigestQueuePosition = 0;
17732
+
17582
17733
  return $rootScope;
17583
17734
 
17584
17735
 
@@ -18147,7 +18298,7 @@ function $SceDelegateProvider() {
18147
18298
  * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
18148
18299
  * to the top of your HTML document.
18149
18300
  *
18150
- * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
18301
+ * SCE assists in writing code in a way that (a) is secure by default and (b) makes auditing for
18151
18302
  * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
18152
18303
  *
18153
18304
  * Here's an example of a binding in a privileged context:
@@ -18824,7 +18975,7 @@ function $SnifferProvider() {
18824
18975
  for (var prop in bodyStyle) {
18825
18976
  if (match = vendorRegex.exec(prop)) {
18826
18977
  vendorPrefix = match[0];
18827
- vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
18978
+ vendorPrefix = vendorPrefix[0].toUpperCase() + vendorPrefix.substr(1);
18828
18979
  break;
18829
18980
  }
18830
18981
  }
@@ -18947,7 +19098,7 @@ function $TemplateRequestProvider() {
18947
19098
  // are included in there. This also makes Angular accept any script
18948
19099
  // directive, no matter its name. However, we still need to unwrap trusted
18949
19100
  // types.
18950
- if (!isString(tpl) || !$templateCache.get(tpl)) {
19101
+ if (!isString(tpl) || isUndefined($templateCache.get(tpl))) {
18951
19102
  tpl = $sce.getTrustedResourceUrl(tpl);
18952
19103
  }
18953
19104
 
@@ -20129,7 +20280,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
20129
20280
 
20130
20281
  // extract decimals digits
20131
20282
  if (integerLen > 0) {
20132
- decimals = digits.splice(integerLen);
20283
+ decimals = digits.splice(integerLen, digits.length);
20133
20284
  } else {
20134
20285
  decimals = digits;
20135
20286
  digits = [0];
@@ -20138,10 +20289,10 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
20138
20289
  // format the integer digits with grouping separators
20139
20290
  var groups = [];
20140
20291
  if (digits.length >= pattern.lgSize) {
20141
- groups.unshift(digits.splice(-pattern.lgSize).join(''));
20292
+ groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(''));
20142
20293
  }
20143
20294
  while (digits.length > pattern.gSize) {
20144
- groups.unshift(digits.splice(-pattern.gSize).join(''));
20295
+ groups.unshift(digits.splice(-pattern.gSize, digits.length).join(''));
20145
20296
  }
20146
20297
  if (digits.length) {
20147
20298
  groups.unshift(digits.join(''));
@@ -22080,11 +22231,11 @@ var inputType = {
22080
22231
  <span class="error" ng-show="myForm.input.$error.pattern">
22081
22232
  Single word only!</span>
22082
22233
  </div>
22083
- <tt>text = {{example.text}}</tt><br/>
22084
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
22085
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
22086
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
22087
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
22234
+ <code>text = {{example.text}}</code><br/>
22235
+ <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br/>
22236
+ <code>myForm.input.$error = {{myForm.input.$error}}</code><br/>
22237
+ <code>myForm.$valid = {{myForm.$valid}}</code><br/>
22238
+ <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br/>
22088
22239
  </form>
22089
22240
  </file>
22090
22241
  <file name="protractor.js" type="protractor">
@@ -23963,8 +24114,9 @@ var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse,
23963
24114
  restrict: 'A',
23964
24115
  compile: function ngBindHtmlCompile(tElement, tAttrs) {
23965
24116
  var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
23966
- var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
23967
- return (value || '').toString();
24117
+ var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function sceValueOf(val) {
24118
+ // Unwrap the value to compare the actual inner safe value, not the wrapper object.
24119
+ return $sce.valueOf(val);
23968
24120
  });
23969
24121
  $compile.$$addBindingClass(tElement);
23970
24122
 
@@ -23972,9 +24124,9 @@ var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse,
23972
24124
  $compile.$$addBindingInfo(element, attr.ngBindHtml);
23973
24125
 
23974
24126
  scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
23975
- // we re-evaluate the expr because we want a TrustedValueHolderType
23976
- // for $sce, not a string
23977
- element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
24127
+ // The watched value is the unwrapped value. To avoid re-escaping, use the direct getter.
24128
+ var value = ngBindHtmlGetter(scope);
24129
+ element.html($sce.getTrustedHtml(value) || '');
23978
24130
  });
23979
24131
  };
23980
24132
  }
@@ -24127,7 +24279,9 @@ function classDirective(name, selector) {
24127
24279
  }
24128
24280
 
24129
24281
  function ngClassWatchAction(newVal) {
24130
- if (selector === true || scope.$index % 2 === selector) {
24282
+ // jshint bitwise: false
24283
+ if (selector === true || (scope.$index & 1) === selector) {
24284
+ // jshint bitwise: true
24131
24285
  var newClasses = arrayClasses(newVal || []);
24132
24286
  if (!oldVal) {
24133
24287
  addClasses(newClasses);
@@ -30353,6 +30507,7 @@ var styleDirective = valueFn({
30353
30507
  /**
30354
30508
  * @ngdoc directive
30355
30509
  * @name ngRequired
30510
+ * @restrict A
30356
30511
  *
30357
30512
  * @description
30358
30513
  *