angularjs-rails 1.5.5 → 1.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  *