scratch

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 124  →  ?path2? @ 125
/bower_components/angular/angular.js
@@ -1,13 +1,63 @@
/**
* @license AngularJS v1.6.3
* @license AngularJS v1.6.5
* (c) 2010-2017 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window) {'use strict';
 
/* exported
minErrConfig,
errorHandlingConfig,
isValidObjectMaxDepth
*/
 
var minErrConfig = {
objectMaxDepth: 5
};
 
/**
* @ngdoc function
* @name angular.errorHandlingConfig
* @module ng
* @kind function
*
* @description
* Configure several aspects of error handling in AngularJS if used as a setter or return the
* current configuration if used as a getter. The following options are supported:
*
* - **objectMaxDepth**: The maximum depth to which objects are traversed when stringified for error messages.
*
* Omitted or undefined options will leave the corresponding configuration values unchanged.
*
* @param {Object=} config - The configuration object. May only contain the options that need to be
* updated. Supported keys:
*
* * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a
* non-positive or non-numeric value, removes the max depth limit.
* Default: 5
*/
function errorHandlingConfig(config) {
if (isObject(config)) {
if (isDefined(config.objectMaxDepth)) {
minErrConfig.objectMaxDepth = isValidObjectMaxDepth(config.objectMaxDepth) ? config.objectMaxDepth : NaN;
}
} else {
return minErrConfig;
}
}
 
/**
* @private
* @param {Number} maxDepth
* @return {boolean}
*/
function isValidObjectMaxDepth(maxDepth) {
return isNumber(maxDepth) && maxDepth > 0;
}
 
/**
* @description
*
* This object provides a utility for producing rich Error messages within
* Angular. It can be called as follows:
*
@@ -56,7 +106,7 @@
return match;
});
 
message += '\nhttp://errors.angularjs.org/1.6.3/' +
message += '\nhttp://errors.angularjs.org/1.6.5/' +
(module ? module + '/' : '') + code;
 
for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -112,6 +162,7 @@
isNumber,
isNumberNaN,
isDate,
isError,
isArray,
isFunction,
isRegExp,
@@ -129,6 +180,7 @@
includes,
arrayRemove,
copy,
simpleCompare,
equals,
csp,
jq,
@@ -195,51 +247,7 @@
 
var hasOwnProperty = Object.prototype.hasOwnProperty;
 
var minErrConfig = {
objectMaxDepth: 5
};
 
/**
* @ngdoc function
* @name angular.errorHandlingConfig
* @module ng
* @kind function
*
* @description
* Configure several aspects of error handling in AngularJS if used as a setter or return the
* current configuration if used as a getter. The following options are supported:
*
* - **objectMaxDepth**: The maximum depth to which objects are traversed when stringified for error messages.
*
* Omitted or undefined options will leave the corresponding configuration values unchanged.
*
* @param {Object=} config - The configuration object. May only contain the options that need to be
* updated. Supported keys:
*
* * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a
* non-positive or non-numeric value, removes the max depth limit.
* Default: 5
*/
function errorHandlingConfig(config) {
if (isObject(config)) {
if (isDefined(config.objectMaxDepth)) {
minErrConfig.objectMaxDepth = isValidObjectMaxDepth(config.objectMaxDepth) ? config.objectMaxDepth : NaN;
}
} else {
return minErrConfig;
}
}
 
/**
* @private
* @param {Number} maxDepth
* @return {boolean}
*/
function isValidObjectMaxDepth(maxDepth) {
return isNumber(maxDepth) && maxDepth > 0;
}
 
/**
* @ngdoc function
* @name angular.lowercase
* @module ng
@@ -546,6 +554,20 @@
* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source
* objects, performing a deep copy.
*
* @deprecated
* sinceVersion="1.6.5"
* This function is deprecated, but will not be removed in the 1.x lifecycle.
* There are edge cases (see {@link angular.merge#known-issues known issues}) that are not
* supported by this function. We suggest
* using [lodash's merge()](https://lodash.com/docs/4.17.4#merge) instead.
*
* @knownIssue
* This is a list of (known) object types that are not handled correctly by this function:
* - [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob)
* - [`MediaStream`](https://developer.mozilla.org/docs/Web/API/MediaStream)
* - [`CanvasGradient`](https://developer.mozilla.org/docs/Web/API/CanvasGradient)
* - AngularJS {@link $rootScope.Scope scopes};
*
* @param {Object} dst Destination object.
* @param {...Object} src Source object(s).
* @returns {Object} Reference to `dst`.
@@ -756,6 +778,24 @@
var isArray = Array.isArray;
 
/**
* @description
* Determines if a reference is an `Error`.
* Loosely based on https://www.npmjs.com/package/iserror
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is an `Error`.
*/
function isError(value) {
var tag = toString.call(value);
switch (tag) {
case '[object Error]': return true;
case '[object Exception]': return true;
case '[object DOMException]': return true;
default: return value instanceof Error;
}
}
 
/**
* @ngdoc function
* @name angular.isFunction
* @module ng
@@ -1107,6 +1147,10 @@
}
 
 
// eslint-disable-next-line no-self-compare
function simpleCompare(a, b) { return a === b || (a !== a && b !== b); }
 
 
/**
* @ngdoc function
* @name angular.equals
@@ -1187,7 +1231,7 @@
}
} else if (isDate(o1)) {
if (!isDate(o2)) return false;
return equals(o1.getTime(), o2.getTime());
return simpleCompare(o1.getTime(), o2.getTime());
} else if (isRegExp(o1)) {
if (!isRegExp(o2)) return false;
return o1.toString() === o2.toString();
@@ -1431,7 +1475,7 @@
 
var ALL_COLONS = /:/g;
function timezoneToOffset(timezone, fallback) {
// Support: IE 9-11 only, Edge 13-14+
// Support: IE 9-11 only, Edge 13-15+
// IE/Edge do not "understand" colon (`:`) in timezone
timezone = timezone.replace(ALL_COLONS, '');
var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
@@ -1458,12 +1502,7 @@
* @returns {string} Returns the string representation of the element.
*/
function startingTag(element) {
element = jqLite(element).clone();
try {
// turns out IE does not let you set .html() on elements which
// are not allowed to have children. So we just ignore it.
element.empty();
} catch (e) { /* empty */ }
element = jqLite(element).clone().empty();
var elemHtml = jqLite('<div>').append(element).html();
try {
return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
@@ -1601,6 +1640,7 @@
var script = document.currentScript;
 
if (!script) {
// Support: IE 9-11 only
// IE does not have `document.currentScript`
return true;
}
@@ -2592,7 +2632,7 @@
return dst || src;
}
 
/* global toDebugString: true */
/* exported toDebugString */
 
function serializeObject(obj, maxDepth) {
var seen = [];
@@ -2601,7 +2641,9 @@
// and a very deep object can cause a performance issue, so we copy the object
// based on this specific depth and then stringify it.
if (isValidObjectMaxDepth(maxDepth)) {
obj = copy(obj, null, maxDepth);
// This file is also included in `angular-loader`, so `copy()` might not always be available in
// the closure. Therefore, it is lazily retrieved as `angular.copy()` when needed.
obj = angular.copy(obj, null, maxDepth);
}
return JSON.stringify(obj, function(key, val) {
val = toJsonReplacer(key, val);
@@ -2742,11 +2784,11 @@
var version = {
// These placeholder strings will be replaced by grunt's `build` task.
// They need to be double- or single-quoted.
full: '1.6.3',
full: '1.6.5',
major: 1,
minor: 6,
dot: 3,
codeName: 'scriptalicious-bootstrapping'
dot: 5,
codeName: 'toffee-salinization'
};
 
 
@@ -2892,7 +2934,7 @@
});
}
])
.info({ angularVersion: '1.6.3' });
.info({ angularVersion: '1.6.5' });
}
 
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -3096,12 +3138,6 @@
return false;
}
 
function jqLiteCleanData(nodes) {
for (var i = 0, ii = nodes.length; i < ii; i++) {
jqLiteRemoveData(nodes[i]);
}
}
 
function jqLiteBuildFragment(html, context) {
var tmp, tag, wrap,
fragment = context.createDocumentFragment(),
@@ -3204,13 +3240,10 @@
}
 
function jqLiteDealoc(element, onlyDescendants) {
if (!onlyDescendants) jqLiteRemoveData(element);
if (!onlyDescendants && jqLiteAcceptsData(element)) jqLite.cleanData([element]);
 
if (element.querySelectorAll) {
var descendants = element.querySelectorAll('*');
for (var i = 0, l = descendants.length; i < l; i++) {
jqLiteRemoveData(descendants[i]);
}
jqLite.cleanData(element.querySelectorAll('*'));
}
}
 
@@ -3508,7 +3541,11 @@
data: jqLiteData,
removeData: jqLiteRemoveData,
hasData: jqLiteHasData,
cleanData: jqLiteCleanData
cleanData: function jqLiteCleanData(nodes) {
for (var i = 0, ii = nodes.length; i < ii; i++) {
jqLiteRemoveData(nodes[i]);
}
}
}, function(fn, name) {
JQLite[name] = fn;
});
@@ -5486,6 +5523,7 @@
var $AnimateProvider = ['$provide', /** @this */ function($provide) {
var provider = this;
var classNameFilter = null;
var customFilter = null;
 
this.$$registeredAnimations = Object.create(null);
 
@@ -5540,6 +5578,51 @@
 
/**
* @ngdoc method
* @name $animateProvider#customFilter
*
* @description
* Sets and/or returns the custom filter function that is used to "filter" animations, i.e.
* determine if an animation is allowed or not. When no filter is specified (the default), no
* animation will be blocked. Setting the `customFilter` value will only allow animations for
* which the filter function's return value is truthy.
*
* This allows to easily create arbitrarily complex rules for filtering animations, such as
* allowing specific events only, or enabling animations on specific subtrees of the DOM, etc.
* Filtering animations can also boost performance for low-powered devices, as well as
* applications containing a lot of structural operations.
*
* <div class="alert alert-success">
* **Best Practice:**
* Keep the filtering function as lean as possible, because it will be called for each DOM
* action (e.g. insertion, removal, class change) performed by "animation-aware" directives.
* See {@link guide/animations#which-directives-support-animations- here} for a list of built-in
* directives that support animations.
* Performing computationally expensive or time-consuming operations on each call of the
* filtering function can make your animations sluggish.
* </div>
*
* **Note:** If present, `customFilter` will be checked before
* {@link $animateProvider#classNameFilter classNameFilter}.
*
* @param {Function=} filterFn - The filter function which will be used to filter all animations.
* If a falsy value is returned, no animation will be performed. The function will be called
* with the following arguments:
* - **node** `{DOMElement}` - The DOM element to be animated.
* - **event** `{String}` - The name of the animation event (e.g. `enter`, `leave`, `addClass`
* etc).
* - **options** `{Object}` - A collection of options/styles used for the animation.
* @return {Function} The current filter function or `null` if there is none set.
*/
this.customFilter = function(filterFn) {
if (arguments.length === 1) {
customFilter = isFunction(filterFn) ? filterFn : null;
}
 
return customFilter;
};
 
/**
* @ngdoc method
* @name $animateProvider#classNameFilter
*
* @description
@@ -5549,6 +5632,11 @@
* When setting the `classNameFilter` value, animations will only be performed on elements
* that successfully match the filter expression. This in turn can boost performance
* for low-powered devices as well as applications containing a lot of structural operations.
*
* **Note:** If present, `classNameFilter` will be checked after
* {@link $animateProvider#customFilter customFilter}. If `customFilter` is present and returns
* false, `classNameFilter` will not be checked.
*
* @param {RegExp=} expression The className expression which will be checked against all animations
* @return {RegExp} The current CSS className expression value. If null then there is no expression value
*/
@@ -7369,9 +7457,9 @@
* initialized.
*
* <div class="alert alert-warning">
* **Deprecation warning:** although bindings for non-ES6 class controllers are currently
* bound to `this` before the controller constructor is called, this use is now deprecated. Please place initialization
* code that relies upon bindings inside a `$onInit` method on the controller, instead.
* **Deprecation warning:** if `$compileProcvider.preAssignBindingsEnabled(true)` was called, bindings for non-ES6 class
* controllers are bound to `this` before the controller constructor is called but this use is now deprecated. Please
* place initialization code that relies upon bindings inside a `$onInit` method on the controller, instead.
* </div>
*
* It is also possible to set `bindToController` to an object hash with the same format as the `scope` property.
@@ -8138,7 +8226,8 @@
* @ngdoc method
* @name $compileProvider#component
* @module ng
* @param {string} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`)
* @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`),
* or an object map of components where the keys are the names and the values are the component definition objects.
* @param {Object} options Component definition object (a simplified
* {@link ng.$compile#directive-definition-object directive definition object}),
* with the following properties (all optional):
@@ -8221,6 +8310,11 @@
* See also {@link ng.$compileProvider#directive $compileProvider.directive()}.
*/
this.component = function registerComponent(name, options) {
if (!isString(name)) {
forEach(name, reverseParams(bind(this, registerComponent)));
return this;
}
 
var controller = options.controller || function() {};
 
function factory($injector) {
@@ -8384,7 +8478,14 @@
*
* If disabled (false), the compiler calls the constructor first before assigning bindings.
*
* The default value is true in Angular 1.5.x but will switch to false in Angular 1.6.x.
* The default value is false.
*
* @deprecated
* sinceVersion="1.6.0"
* removeVersion="1.7.0"
*
* This method and the option to assign the bindings before calling the controller's constructor
* will be removed in v1.7.0.
*/
var preAssignBindingsEnabled = false;
this.preAssignBindingsEnabled = function(enabled) {
@@ -10149,7 +10250,7 @@
}
linkQueue = null;
}).catch(function(error) {
if (error instanceof Error) {
if (isError(error)) {
$exceptionHandler(error);
}
});
@@ -10474,8 +10575,7 @@
if (parentGet.literal) {
compare = equals;
} else {
// eslint-disable-next-line no-self-compare
compare = function simpleCompare(a, b) { return a === b || (a !== a && b !== b); };
compare = simpleCompare;
}
parentSet = parentGet.assign || function() {
// reset the change, or we will throw this exception on every $digest
@@ -10550,9 +10650,7 @@
});
 
function recordChanges(key, currentValue, previousValue) {
if (isFunction(destination.$onChanges) && currentValue !== previousValue &&
// eslint-disable-next-line no-self-compare
(currentValue === currentValue || previousValue === previousValue)) {
if (isFunction(destination.$onChanges) && !simpleCompare(currentValue, previousValue)) {
// If we have not already scheduled the top level onChangesQueue handler then do so now
if (!onChangesQueue) {
scope.$$postDigest(flushOnChangesQueue);
@@ -11167,7 +11265,12 @@
if (tempData) {
var contentType = headers('Content-Type');
if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
data = fromJson(tempData);
try {
data = fromJson(tempData);
} catch (e) {
throw $httpMinErr('baddata', 'Data must be a valid JSON object. Received: "{0}". ' +
'Parse error: "{1}"', data, e);
}
}
}
}
@@ -11290,12 +11393,6 @@
* {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of HTTP responses
* by default. See {@link $http#caching $http Caching} for more information.
*
* - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
* Defaults value is `'XSRF-TOKEN'`.
*
* - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
* XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
*
* - **`defaults.headers`** - {Object} - Default headers for all $http requests.
* Refer to {@link ng.$http#setting-http-headers $http} for documentation on
* setting default headers.
@@ -11304,6 +11401,9 @@
* - **`defaults.headers.put`**
* - **`defaults.headers.patch`**
*
* - **`defaults.jsonpCallbackParam`** - `{string}` - the name of the query parameter that passes the name of the
* callback in a JSONP request. The value of this parameter will be replaced with the expression generated by the
* {@link $jsonpCallbacks} service. Defaults to `'callback'`.
*
* - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function
* used to the prepare string representation of request parameters (specified as an object).
@@ -11310,10 +11410,30 @@
* If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
* Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
*
* - **`defaults.jsonpCallbackParam`** - `{string}` - the name of the query parameter that passes the name of the
* callback in a JSONP request. The value of this parameter will be replaced with the expression generated by the
* {@link $jsonpCallbacks} service. Defaults to `'callback'`.
* - **`defaults.transformRequest`** -
* `{Array<function(data, headersGetter)>|function(data, headersGetter)}` -
* An array of functions (or a single function) which are applied to the request data.
* By default, this is an array with one request transformation function:
*
* - If the `data` property of the request configuration object contains an object, serialize it
* into JSON format.
*
* - **`defaults.transformResponse`** -
* `{Array<function(data, headersGetter, status)>|function(data, headersGetter, status)}` -
* An array of functions (or a single function) which are applied to the response data. By default,
* this is an array which applies one response transformation function that does two things:
*
* - If XSRF prefix is detected, strip it
* (see {@link ng.$http#security-considerations Security Considerations in the $http docs}).
* - If the `Content-Type` is `application/json` or the response looks like JSON,
* deserialize it using a JSON parser.
*
* - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
* Defaults value is `'XSRF-TOKEN'`.
*
* - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
* XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
*
**/
var defaults = this.defaults = {
// transform incoming response data
@@ -11576,15 +11696,18 @@
*
* Angular provides the following default transformations:
*
* Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):
* Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`) is
* an array with one function that does the following:
*
* - If the `data` property of the request configuration object contains an object, serialize it
* into JSON format.
*
* Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):
* Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`) is
* an array with one function that does the following:
*
* - If XSRF prefix is detected, strip it (see Security Considerations section below).
* - If JSON response is detected, deserialize it using a JSON parser.
* - If the `Content-Type` is `application/json` or the response looks like JSON,
* deserialize it using a JSON parser.
*
*
* ### Overriding the Default Transformations Per Request
@@ -13072,7 +13195,7 @@
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
* @param {...*=} Pass additional parameters to the executed function.
* @returns {promise} A promise which will be notified on each iteration.
* @returns {promise} A promise which will be notified on each iteration. It will resolve once all iterations of the interval complete.
*
* @example
* <example module="intervalExample" name="interval-service">
@@ -13221,7 +13344,7 @@
interval.cancel = function(promise) {
if (promise && promise.$$intervalId in intervals) {
// Interval cancels should not report as unhandled promise.
intervals[promise.$$intervalId].promise.catch(noop);
markQExceptionHandled(intervals[promise.$$intervalId].promise);
intervals[promise.$$intervalId].reject('canceled');
$window.clearInterval(promise.$$intervalId);
delete intervals[promise.$$intervalId];
@@ -14363,6 +14486,14 @@
*
* The main purpose of this service is to simplify debugging and troubleshooting.
*
* To reveal the location of the calls to `$log` in the JavaScript console,
* you can "blackbox" the AngularJS source in your browser:
*
* [Mozilla description of blackboxing](https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Black_box_a_source).
* [Chrome description of blackboxing](https://developer.chrome.com/devtools/docs/blackboxing).
*
* Note: Not all browsers support blackboxing.
*
* The default is to log `debug` messages. You can use
* {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
*
@@ -14484,7 +14615,7 @@
};
 
function formatError(arg) {
if (arg instanceof Error) {
if (isError(arg)) {
if (arg.stack && formatStackTrace) {
arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
? 'Error: ' + arg.message + '\n' + arg.stack
@@ -14498,29 +14629,17 @@
 
function consoleLog(type) {
var console = $window.console || {},
logFn = console[type] || console.log || noop,
hasApply = false;
logFn = console[type] || console.log || noop;
 
// Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
// The reason behind this is that console.log has type "object" in IE8...
try {
hasApply = !!logFn.apply;
} catch (e) { /* empty */ }
 
if (hasApply) {
return function() {
var args = [];
forEach(arguments, function(arg) {
args.push(formatError(arg));
});
return logFn.apply(console, args);
};
}
 
// we are IE which either doesn't have window.console => this is noop and we do nothing,
// or we are IE where console.log doesn't have apply so we log at least first 2 args
return function(arg1, arg2) {
logFn(arg1, arg2 == null ? '' : arg2);
return function() {
var args = [];
forEach(arguments, function(arg) {
args.push(formatError(arg));
});
// Support: IE 9 only
// console methods don't inherit from Function.prototype in IE 9 so we can't
// call `logFn.apply(console, args)` directly.
return Function.prototype.apply.call(logFn, console, args);
};
}
}];
@@ -15148,15 +15267,47 @@
return !fn.$stateful;
}
 
function findConstantAndWatchExpressions(ast, $filter) {
var PURITY_ABSOLUTE = 1;
var PURITY_RELATIVE = 2;
 
// Detect nodes which could depend on non-shallow state of objects
function isPure(node, parentIsPure) {
switch (node.type) {
// Computed members might invoke a stateful toString()
case AST.MemberExpression:
if (node.computed) {
return false;
}
break;
 
// Unary always convert to primative
case AST.UnaryExpression:
return PURITY_ABSOLUTE;
 
// The binary + operator can invoke a stateful toString().
case AST.BinaryExpression:
return node.operator !== '+' ? PURITY_ABSOLUTE : false;
 
// Functions / filters probably read state from within objects
case AST.CallExpression:
return false;
}
 
return (undefined === parentIsPure) ? PURITY_RELATIVE : parentIsPure;
}
 
function findConstantAndWatchExpressions(ast, $filter, parentIsPure) {
var allConstants;
var argsToWatch;
var isStatelessFilter;
 
var astIsPure = ast.isPure = isPure(ast, parentIsPure);
 
switch (ast.type) {
case AST.Program:
allConstants = true;
forEach(ast.body, function(expr) {
findConstantAndWatchExpressions(expr.expression, $filter);
findConstantAndWatchExpressions(expr.expression, $filter, astIsPure);
allConstants = allConstants && expr.expression.constant;
});
ast.constant = allConstants;
@@ -15166,26 +15317,26 @@
ast.toWatch = [];
break;
case AST.UnaryExpression:
findConstantAndWatchExpressions(ast.argument, $filter);
findConstantAndWatchExpressions(ast.argument, $filter, astIsPure);
ast.constant = ast.argument.constant;
ast.toWatch = ast.argument.toWatch;
break;
case AST.BinaryExpression:
findConstantAndWatchExpressions(ast.left, $filter);
findConstantAndWatchExpressions(ast.right, $filter);
findConstantAndWatchExpressions(ast.left, $filter, astIsPure);
findConstantAndWatchExpressions(ast.right, $filter, astIsPure);
ast.constant = ast.left.constant && ast.right.constant;
ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch);
break;
case AST.LogicalExpression:
findConstantAndWatchExpressions(ast.left, $filter);
findConstantAndWatchExpressions(ast.right, $filter);
findConstantAndWatchExpressions(ast.left, $filter, astIsPure);
findConstantAndWatchExpressions(ast.right, $filter, astIsPure);
ast.constant = ast.left.constant && ast.right.constant;
ast.toWatch = ast.constant ? [] : [ast];
break;
case AST.ConditionalExpression:
findConstantAndWatchExpressions(ast.test, $filter);
findConstantAndWatchExpressions(ast.alternate, $filter);
findConstantAndWatchExpressions(ast.consequent, $filter);
findConstantAndWatchExpressions(ast.test, $filter, astIsPure);
findConstantAndWatchExpressions(ast.alternate, $filter, astIsPure);
findConstantAndWatchExpressions(ast.consequent, $filter, astIsPure);
ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant;
ast.toWatch = ast.constant ? [] : [ast];
break;
@@ -15194,9 +15345,9 @@
ast.toWatch = [ast];
break;
case AST.MemberExpression:
findConstantAndWatchExpressions(ast.object, $filter);
findConstantAndWatchExpressions(ast.object, $filter, astIsPure);
if (ast.computed) {
findConstantAndWatchExpressions(ast.property, $filter);
findConstantAndWatchExpressions(ast.property, $filter, astIsPure);
}
ast.constant = ast.object.constant && (!ast.computed || ast.property.constant);
ast.toWatch = [ast];
@@ -15206,7 +15357,7 @@
allConstants = isStatelessFilter;
argsToWatch = [];
forEach(ast.arguments, function(expr) {
findConstantAndWatchExpressions(expr, $filter);
findConstantAndWatchExpressions(expr, $filter, astIsPure);
allConstants = allConstants && expr.constant;
if (!expr.constant) {
argsToWatch.push.apply(argsToWatch, expr.toWatch);
@@ -15216,8 +15367,8 @@
ast.toWatch = isStatelessFilter ? argsToWatch : [ast];
break;
case AST.AssignmentExpression:
findConstantAndWatchExpressions(ast.left, $filter);
findConstantAndWatchExpressions(ast.right, $filter);
findConstantAndWatchExpressions(ast.left, $filter, astIsPure);
findConstantAndWatchExpressions(ast.right, $filter, astIsPure);
ast.constant = ast.left.constant && ast.right.constant;
ast.toWatch = [ast];
break;
@@ -15225,7 +15376,7 @@
allConstants = true;
argsToWatch = [];
forEach(ast.elements, function(expr) {
findConstantAndWatchExpressions(expr, $filter);
findConstantAndWatchExpressions(expr, $filter, astIsPure);
allConstants = allConstants && expr.constant;
if (!expr.constant) {
argsToWatch.push.apply(argsToWatch, expr.toWatch);
@@ -15238,13 +15389,13 @@
allConstants = true;
argsToWatch = [];
forEach(ast.properties, function(property) {
findConstantAndWatchExpressions(property.value, $filter);
findConstantAndWatchExpressions(property.value, $filter, astIsPure);
allConstants = allConstants && property.value.constant && !property.computed;
if (!property.value.constant) {
argsToWatch.push.apply(argsToWatch, property.value.toWatch);
}
if (property.computed) {
findConstantAndWatchExpressions(property.key, $filter);
findConstantAndWatchExpressions(property.key, $filter, astIsPure);
if (!property.key.constant) {
argsToWatch.push.apply(argsToWatch, property.key.toWatch);
}
@@ -15295,15 +15446,13 @@
return ast.constant;
}
 
function ASTCompiler(astBuilder, $filter) {
this.astBuilder = astBuilder;
function ASTCompiler($filter) {
this.$filter = $filter;
}
 
ASTCompiler.prototype = {
compile: function(expression) {
compile: function(ast) {
var self = this;
var ast = this.astBuilder.ast(expression);
this.state = {
nextId: 0,
filters: {},
@@ -15331,7 +15480,7 @@
var intoId = self.nextId();
self.recurse(watch, intoId);
self.return_(intoId);
self.state.inputs.push(fnKey);
self.state.inputs.push({name: fnKey, isPure: watch.isPure});
watch.watchId = key;
});
this.state.computing = 'fn';
@@ -15358,8 +15507,6 @@
ifDefined,
plusFn);
this.state = this.stage = undefined;
fn.literal = isLiteral(ast);
fn.constant = isConstant(ast);
return fn;
},
 
@@ -15369,13 +15516,16 @@
 
watchFns: function() {
var result = [];
var fns = this.state.inputs;
var inputs = this.state.inputs;
var self = this;
forEach(fns, function(name) {
result.push('var ' + name + '=' + self.generateFunction(name, 's'));
forEach(inputs, function(input) {
result.push('var ' + input.name + '=' + self.generateFunction(input.name, 's'));
if (input.isPure) {
result.push(input.name, '.isPure=' + JSON.stringify(input.isPure) + ';');
}
});
if (fns.length) {
result.push('fn.inputs=[' + fns.join(',') + '];');
if (inputs.length) {
result.push('fn.inputs=[' + inputs.map(function(i) { return i.name; }).join(',') + '];');
}
return result.join('');
},
@@ -15762,15 +15912,13 @@
};
 
 
function ASTInterpreter(astBuilder, $filter) {
this.astBuilder = astBuilder;
function ASTInterpreter($filter) {
this.$filter = $filter;
}
 
ASTInterpreter.prototype = {
compile: function(expression) {
compile: function(ast) {
var self = this;
var ast = this.astBuilder.ast(expression);
findConstantAndWatchExpressions(ast, self.$filter);
var assignable;
var assign;
@@ -15783,6 +15931,7 @@
inputs = [];
forEach(toWatch, function(watch, key) {
var input = self.recurse(watch);
input.isPure = watch.isPure;
watch.input = input;
inputs.push(input);
watch.watchId = key;
@@ -15809,8 +15958,6 @@
if (inputs) {
fn.inputs = inputs;
}
fn.literal = isLiteral(ast);
fn.constant = isConstant(ast);
return fn;
},
 
@@ -16139,20 +16286,21 @@
/**
* @constructor
*/
var Parser = function Parser(lexer, $filter, options) {
this.lexer = lexer;
this.$filter = $filter;
this.options = options;
function Parser(lexer, $filter, options) {
this.ast = new AST(lexer, options);
this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) :
new ASTCompiler(this.ast, $filter);
};
this.astCompiler = options.csp ? new ASTInterpreter($filter) :
new ASTCompiler($filter);
}
 
Parser.prototype = {
constructor: Parser,
 
parse: function(text) {
return this.astCompiler.compile(text);
var ast = this.ast.ast(text);
var fn = this.astCompiler.compile(ast);
fn.literal = isLiteral(ast);
fn.constant = isConstant(ast);
return fn;
}
};
 
@@ -16321,7 +16469,7 @@
return newValue === oldValueOfValue;
}
 
if (typeof newValue === 'object' && !compareObjectIdentity) {
if (typeof newValue === 'object') {
 
// attempt to convert the value to a primitive type
// TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
@@ -16328,7 +16476,7 @@
// be cheaply dirty-checked
newValue = getValueOf(newValue);
 
if (typeof newValue === 'object') {
if (typeof newValue === 'object' && !compareObjectIdentity) {
// objects/arrays are not supported - deep-watching them would be too expensive
return false;
}
@@ -16350,7 +16498,7 @@
inputExpressions = inputExpressions[0];
return scope.$watch(function expressionInputWatch(scope) {
var newInputValue = inputExpressions(scope);
if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf, parsedExpression.literal)) {
if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf, inputExpressions.isPure)) {
lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);
oldInputValueOf = newInputValue && getValueOf(newInputValue);
}
@@ -16370,7 +16518,7 @@
 
for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
var newInputValue = inputExpressions[i](scope);
if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i], parsedExpression.literal))) {
if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i], inputExpressions[i].isPure))) {
oldInputValues[i] = newInputValue;
oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
}
@@ -16468,17 +16616,26 @@
 
// Propagate $$watchDelegates other then inputsWatchDelegate
useInputs = !parsedExpression.inputs;
if (parsedExpression.$$watchDelegate &&
parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
fn.$$watchDelegate = parsedExpression.$$watchDelegate;
if (watchDelegate && watchDelegate !== inputsWatchDelegate) {
fn.$$watchDelegate = watchDelegate;
fn.inputs = parsedExpression.inputs;
} else if (!interceptorFn.$stateful) {
// If there is an interceptor, but no watchDelegate then treat the interceptor like
// we treat filters - it is assumed to be a pure function unless flagged with $stateful
// Treat interceptor like filters - assume non-stateful by default and use the inputsWatchDelegate
fn.$$watchDelegate = inputsWatchDelegate;
fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
}
 
if (fn.inputs) {
fn.inputs = fn.inputs.map(function(e) {
// Remove the isPure flag of inputs when it is not absolute because they are now wrapped in a
// potentially non-pure interceptor function.
if (e.isPure === PURITY_RELATIVE) {
return function depurifier(s) { return e(s); };
}
return e;
});
}
 
return fn;
}
}];
@@ -16764,7 +16921,7 @@
* @param {function(function)} nextTick Function for executing functions in the next turn.
* @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
* debugging purposes.
@ param {=boolean} errorOnUnhandledRejections Whether an error should be generated on unhandled
* @param {boolean=} errorOnUnhandledRejections Whether an error should be generated on unhandled
* promises rejections.
* @returns {object} Promise manager.
*/
@@ -16835,7 +16992,7 @@
state.pending = undefined;
try {
for (var i = 0, ii = pending.length; i < ii; ++i) {
state.pur = true;
markQStateExceptionHandled(state);
promise = pending[i][0];
fn = pending[i][state.status];
try {
@@ -16862,10 +17019,10 @@
// eslint-disable-next-line no-unmodified-loop-condition
while (!queueSize && checkQueue.length) {
var toCheck = checkQueue.shift();
if (!toCheck.pur) {
toCheck.pur = true;
if (!isStateExceptionHandled(toCheck)) {
markQStateExceptionHandled(toCheck);
var errorMessage = 'Possibly unhandled rejection: ' + toDebugString(toCheck.value);
if (toCheck.value instanceof Error) {
if (isError(toCheck.value)) {
exceptionHandler(toCheck.value, errorMessage);
} else {
exceptionHandler(errorMessage);
@@ -16875,7 +17032,7 @@
}
 
function scheduleProcessQueue(state) {
if (errorOnUnhandledRejections && !state.pending && state.status === 2 && !state.pur) {
if (errorOnUnhandledRejections && !state.pending && state.status === 2 && !isStateExceptionHandled(state)) {
if (queueSize === 0 && checkQueue.length === 0) {
nextTick(processChecks);
}
@@ -17156,6 +17313,16 @@
return $Q;
}
 
function isStateExceptionHandled(state) {
return !!state.pur;
}
function markQStateExceptionHandled(state) {
state.pur = true;
}
function markQExceptionHandled(q) {
markQStateExceptionHandled(q.$$state);
}
 
/** @this */
function $$RAFProvider() { //rAF
this.$get = ['$window', '$timeout', function($window, $timeout) {
@@ -17636,6 +17803,12 @@
* values are examined for changes on every call to `$digest`.
* - The `listener` is called whenever any expression in the `watchExpressions` array changes.
*
* `$watchGroup` is more performant than watching each expression individually, and should be
* used when the listener does not need to know which expression has changed.
* If the listener needs to know which expression has changed,
* {@link ng.$rootScope.Scope#$watch $watch()} or
* {@link ng.$rootScope.Scope#$watchCollection $watchCollection()} should be used.
*
* @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually
* watched using {@link ng.$rootScope.Scope#$watch $watch()}
*
@@ -17644,7 +17817,34 @@
* The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching
* those of `watchExpression`
* and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching
* those of `watchExpression`
* those of `watchExpression`.
*
* Note that `newValues` and `oldValues` reflect the differences in each **individual**
* expression, and not the difference of the values between each call of the listener.
* That means the difference between `newValues` and `oldValues` cannot be used to determine
* which expression has changed / remained stable:
*
* ```js
*
* $scope.$watchGroup(['v1', 'v2'], function(newValues, oldValues) {
* console.log(newValues, oldValues);
* });
*
* // newValues, oldValues initially
* // [undefined, undefined], [undefined, undefined]
*
* $scope.v1 = 'a';
* $scope.v2 = 'a';
*
* // ['a', 'a'], [undefined, undefined]
*
* $scope.v2 = 'b'
*
* // v1 hasn't changed since it became `'a'`, therefore its oldValue is still `undefined`
* // ['a', 'b'], [undefined, 'a']
*
* ```
*
* The `scope` refers to the current scope.
* @returns {function()} Returns a de-registration function for all listeners.
*/
@@ -18687,12 +18887,21 @@
var $sceMinErr = minErr('$sce');
 
var SCE_CONTEXTS = {
// HTML is used when there's HTML rendered (e.g. ng-bind-html, iframe srcdoc binding).
HTML: 'html',
 
// Style statements or stylesheets. Currently unused in AngularJS.
CSS: 'css',
 
// An URL used in a context where it does not refer to a resource that loads code. Currently
// unused in AngularJS.
URL: 'url',
// RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
// url. (e.g. ng-include, script src, templateUrl)
 
// RESOURCE_URL is a subtype of URL used where the referred-to resource could be interpreted as
// code. (e.g. ng-include, script src binding, templateUrl)
RESOURCE_URL: 'resourceUrl',
 
// Script. Currently unused in AngularJS.
JS: 'js'
};
 
@@ -18754,6 +18963,16 @@
* `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
* Contextual Escaping (SCE)} services to AngularJS.
*
* For an overview of this service and the functionnality it provides in AngularJS, see the main
* page for {@link ng.$sce SCE}. The current page is targeted for developers who need to alter how
* SCE works in their application, which shouldn't be needed in most cases.
*
* <div class="alert alert-danger">
* AngularJS strongly relies on contextual escaping for the security of bindings: disabling or
* modifying this might cause cross site scripting (XSS) vulnerabilities. For libraries owners,
* changes to this service will also influence users, so be extra careful and document your changes.
* </div>
*
* Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
* the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is
* because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
@@ -18779,11 +18998,15 @@
* @description
*
* The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
* $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure
* that the URLs used for sourcing Angular templates are safe. Refer {@link
* ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
* {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
* $sceDelegate service}, used as a delegate for {@link ng.$sce Strict Contextual Escaping (SCE)}.
*
* The `$sceDelegateProvider` allows one to get/set the whitelists and blacklists used to ensure
* that the URLs used for sourcing AngularJS templates and other script-running URLs are safe (all
* places that use the `$sce.RESOURCE_URL` context). See
* {@link ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist}
* and
* {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist},
*
* For the general details about this service in Angular, read the main page for {@link ng.$sce
* Strict Contextual Escaping (SCE)}.
*
@@ -18811,6 +19034,13 @@
* ]);
* });
* ```
* Note that an empty whitelist will block every resource URL from being loaded, and will require
* you to manually mark each one as trusted with `$sce.trustAsResourceUrl`. However, templates
* requested by {@link ng.$templateRequest $templateRequest} that are present in
* {@link ng.$templateCache $templateCache} will not go through this check. If you have a mechanism
* to populate your templates in that cache at config time, then it is a good idea to remove 'self'
* from that whitelist. This helps to mitigate the security impact of certain types of issues, like
* for instance attacker-controlled `ng-includes`.
*/
 
function $SceDelegateProvider() {
@@ -18826,23 +19056,23 @@
* @kind function
*
* @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
* provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored.
* provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored.
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* allowed in this array.
*
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* allowed in this array.
* @return {Array} The currently set whitelist array.
*
* <div class="alert alert-warning">
* **Note:** an empty whitelist array will block all URLs!
* </div>
* @description
* Sets/Gets the whitelist of trusted resource URLs.
*
* @return {Array} the currently set whitelist array.
*
* The **default value** when no whitelist has been explicitly set is `['self']` allowing only
* same origin resource requests.
*
* @description
* Sets/Gets the whitelist of trusted resource URLs.
* <div class="alert alert-warning">
* **Note:** the default whitelist of 'self' is not recommended if your app shares its origin
* with other apps! It is a good idea to limit it to only your application's directory.
* </div>
*/
this.resourceUrlWhitelist = function(value) {
if (arguments.length) {
@@ -18857,25 +19087,23 @@
* @kind function
*
* @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
* provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored.
* provided. This must be an array or null. A snapshot of this array is used so further
* changes to the array are ignored.</p><p>
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* allowed in this array.</p><p>
* The typical usage for the blacklist is to **block
* [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
* these would otherwise be trusted but actually return content from the redirected domain.
* </p><p>
* Finally, **the blacklist overrides the whitelist** and has the final say.
*
* Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
* allowed in this array.
* @return {Array} The currently set blacklist array.
*
* The typical usage for the blacklist is to **block
* [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
* these would otherwise be trusted but actually return content from the redirected domain.
* @description
* Sets/Gets the blacklist of trusted resource URLs.
*
* Finally, **the blacklist overrides the whitelist** and has the final say.
*
* @return {Array} the currently set blacklist array.
*
* The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
* is no blacklist.)
*
* @description
* Sets/Gets the blacklist of trusted resource URLs.
*/
 
this.resourceUrlBlacklist = function(value) {
@@ -18959,17 +19187,24 @@
* @name $sceDelegate#trustAs
*
* @description
* Returns an object that is trusted by angular for use in specified strict
* contextual escaping contexts (such as ng-bind-html, ng-include, any src
* attribute interpolation, any dom event binding attribute interpolation
* such as for onclick, etc.) that uses the provided value.
* See {@link ng.$sce $sce} for enabling strict contextual escaping.
* Returns a trusted representation of the parameter for the specified context. This trusted
* object will later on be used as-is, without any security check, by bindings or directives
* that require this security context.
* For instance, marking a string as trusted for the `$sce.HTML` context will entirely bypass
* the potential `$sanitize` call in corresponding `$sce.HTML` bindings or directives, such as
* `ng-bind-html`. Note that in most cases you won't need to call this function: if you have the
* sanitizer loaded, passing the value itself will render all the HTML that does not pose a
* security risk.
*
* @param {string} type The kind of context in which this value is safe for use. e.g. url,
* resourceUrl, html, js and css.
* @param {*} value The value that that should be considered trusted/safe.
* @returns {*} A value that can be used to stand in for the provided `value` in places
* where Angular expects a $sce.trustAs() return value.
* See {@link ng.$sceDelegate#getTrusted getTrusted} for the function that will consume those
* trusted values, and {@link ng.$sce $sce} for general documentation about strict contextual
* escaping.
*
* @param {string} type The context in which this value is safe for use, e.g. `$sce.URL`,
* `$sce.RESOURCE_URL`, `$sce.HTML`, `$sce.JS` or `$sce.CSS`.
*
* @param {*} value The value that should be considered trusted.
* @return {*} A trusted representation of value, that can be used in the given context.
*/
function trustAs(type, trustedValue) {
var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
@@ -19001,11 +19236,11 @@
* ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
*
* If the passed parameter is not a value that had been returned by {@link
* ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
* ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, it must be returned as-is.
*
* @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
* call or anything else.
* @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
* call or anything else.
* @return {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
* `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns
* `value` unchanged.
*/
@@ -19022,20 +19257,21 @@
* @name $sceDelegate#getTrusted
*
* @description
* Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and
* returns the originally supplied value if the queried context type is a supertype of the
* created type. If this condition isn't satisfied, throws an exception.
* Takes any input, and either returns a value that's safe to use in the specified context, or
* throws an exception.
*
* <div class="alert alert-danger">
* Disabling auto-escaping is extremely dangerous, it usually creates a Cross Site Scripting
* (XSS) vulnerability in your application.
* </div>
* In practice, there are several cases. When given a string, this function runs checks
* and sanitization to make it safe without prior assumptions. When given the result of a {@link
* ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call, it returns the originally supplied
* value if that value's context is valid for this call's context. Finally, this function can
* also throw when there is no way to turn `maybeTrusted` in a safe value (e.g., no sanitization
* is available or possible.)
*
* @param {string} type The kind of context in which this value is to be used.
* @param {string} type The context in which this value is to be used (such as `$sce.HTML`).
* @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
* `$sceDelegate.trustAs`} call.
* @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
* `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
* `$sceDelegate.trustAs`} call, or anything else (which will not be considered trusted.)
* @return {*} A version of the value that's safe to use in the given context, or throws an
* exception if this is impossible.
*/
function getTrusted(type, maybeTrusted) {
if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') {
@@ -19042,13 +19278,17 @@
return maybeTrusted;
}
var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
// If maybeTrusted is a trusted class instance or subclass instance, then unwrap and return
// as-is.
if (constructor && maybeTrusted instanceof constructor) {
return maybeTrusted.$$unwrapTrustedValue();
}
// If we get here, then we may only take one of two actions.
// 1. sanitize the value for the requested type, or
// 2. throw an exception.
// Otherwise, if we get here, then we may either make it safe, or throw an exception. This
// depends on the context: some are sanitizatible (HTML), some use whitelists (RESOURCE_URL),
// some are impossible to do (JS). This step isn't implemented for CSS and URL, as AngularJS
// has no corresponding sinks.
if (type === SCE_CONTEXTS.RESOURCE_URL) {
// RESOURCE_URL uses a whitelist.
if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
return maybeTrusted;
} else {
@@ -19057,8 +19297,10 @@
maybeTrusted.toString());
}
} else if (type === SCE_CONTEXTS.HTML) {
// htmlSanitizer throws its own error when no sanitizer is available.
return htmlSanitizer(maybeTrusted);
}
// Default error when the $sce service has no way to make the input safe.
throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
}
 
@@ -19094,22 +19336,28 @@
*
* # Strict Contextual Escaping
*
* Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
* contexts to result in a value that is marked as safe to use for that context. One example of
* such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer
* to these contexts as privileged or SCE contexts.
* Strict Contextual Escaping (SCE) is a mode in which AngularJS constrains bindings to only render
* trusted values. Its goal is to assist in writing code in a way that (a) is secure by default, and
* (b) makes auditing for security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
*
* As of version 1.2, Angular ships with SCE enabled by default.
* ## Overview
*
* Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow
* one to execute arbitrary javascript by the use of the expression() syntax. Refer
* <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
* You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
* to the top of your HTML document.
* To systematically block XSS security bugs, AngularJS treats all values as untrusted by default in
* HTML or sensitive URL bindings. When binding untrusted values, AngularJS will automatically
* run security checks on them (sanitizations, whitelists, depending on context), or throw when it
* cannot guarantee the security of the result. That behavior depends strongly on contexts: HTML
* can be sanitized, but template URLs cannot, for instance.
*
* SCE assists in writing code in a way that (a) is secure by default and (b) makes auditing for
* security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
* To illustrate this, consider the `ng-bind-html` directive. It renders its value directly as HTML:
* we call that the *context*. When given an untrusted input, AngularJS will attempt to sanitize it
* before rendering if a sanitizer is available, and throw otherwise. To bypass sanitization and
* render the input as-is, you will need to mark it as trusted for that context before attempting
* to bind it.
*
* As of version 1.2, AngularJS ships with SCE enabled by default.
*
* ## In practice
*
* Here's an example of a binding in a privileged context:
*
* ```
@@ -19118,10 +19366,10 @@
* ```
*
* Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
* disabled, this application allows the user to render arbitrary HTML into the DIV.
* In a more realistic example, one may be rendering user comments, blog articles, etc. via
* bindings. (HTML is just one example of a context where rendering user controlled input creates
* security vulnerabilities.)
* disabled, this application allows the user to render arbitrary HTML into the DIV, which would
* be an XSS security bug. In a more realistic example, one may be rendering user comments, blog
* articles, etc. via bindings. (HTML is just one example of a context where rendering user
* controlled input creates security vulnerabilities.)
*
* For the case of HTML, you might use a library, either on the client side, or on the server side,
* to sanitize unsafe HTML before binding to the value and rendering it in the document.
@@ -19131,25 +19379,29 @@
* ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
* properties/fields and forgot to update the binding to the sanitized value?
*
* To be secure by default, you want to ensure that any such bindings are disallowed unless you can
* determine that something explicitly says it's safe to use a value for binding in that
* context. You can then audit your code (a simple grep would do) to ensure that this is only done
* for those values that you can easily tell are safe - because they were received from your server,
* sanitized by your library, etc. You can organize your codebase to help with this - perhaps
* allowing only the files in a specific directory to do this. Ensuring that the internal API
* exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
* To be secure by default, AngularJS makes sure bindings go through that sanitization, or
* any similar validation process, unless there's a good reason to trust the given value in this
* context. That trust is formalized with a function call. This means that as a developer, you
* can assume all untrusted bindings are safe. Then, to audit your code for binding security issues,
* you just need to ensure the values you mark as trusted indeed are safe - because they were
* received from your server, sanitized by your library, etc. You can organize your codebase to
* help with this - perhaps allowing only the files in a specific directory to do this.
* Ensuring that the internal API exposed by that code doesn't markup arbitrary values as safe then
* becomes a more manageable task.
*
* In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}
* (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to
* obtain values that will be accepted by SCE / privileged contexts.
* build the trusted versions of your values.
*
*
* ## How does it work?
*
* In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
* $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link
* ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
* {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
* $sce.getTrusted(context, value)} rather than to the value directly. Think of this function as
* a way to enforce the required security context in your data sink. Directives use {@link
* ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs
* the {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals. Also,
* when binding without directives, AngularJS will understand the context of your bindings
* automatically.
*
* As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
* ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
@@ -19190,12 +19442,13 @@
* It's important to remember that SCE only applies to interpolation expressions.
*
* If your expressions are constant literals, they're automatically trusted and you don't need to
* call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
* `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works.
* call `$sce.trustAs` on them (e.g.
* `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works. The `$sceDelegate` will
* also use the `$sanitize` service if it is available when binding untrusted values to
* `$sce.HTML` context. AngularJS provides an implementation in `angular-sanitize.js`, and if you
* wish to use it, you will also need to depend on the {@link ngSanitize `ngSanitize`} module in
* your application.
*
* Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
* through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.
*
* The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
* templates in `ng-include` from your application's domain without having to even know about SCE.
* It blocks loading templates from other domains or loading templates over http from an https
@@ -19212,12 +19465,18 @@
*
* | Context | Notes |
* |---------------------|----------------|
* | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
* | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
* | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
* | `$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`, `VIDEO`, `AUDIO`, `SOURCE`, and `TRACK` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
* | `$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. |
* | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered, and the {@link ngSanitize.$sanitize $sanitize} service is available (implemented by the {@link ngSanitize ngSanitize} module) this will sanitize the value instead of throwing an error. |
* | `$sce.CSS` | For CSS that's safe to source into the application. Currently, no bindings require this context. Feel free to use it in your own directives. |
* | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=`, `<img src=`, and some others sanitize their urls and don't constitute an SCE context.) |
* | `$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`, `VIDEO`, `AUDIO`, `SOURCE`, and `TRACK` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does (it's not just the URL that matters, but also what is at the end of it), and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
* | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently, no bindings require this context. Feel free to use it in your own directives. |
*
*
* Be aware that `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
* through {@link ng.$sce#getTrusted $sce.getTrusted}. There's no CSS-, URL-, or JS-context bindings
* in AngularJS currently, so their corresponding `$sce.trustAs` functions aren't useful yet. This
* might evolve.
*
* ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
*
* Each element in these arrays must be one of the following:
@@ -19335,7 +19594,8 @@
* for little coding overhead. It will be much harder to take an SCE disabled application and
* either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE
* for cases where you have a lot of existing code that was written before SCE was introduced and
* you're migrating them a module at a time.
* you're migrating them a module at a time. Also do note that this is an app-wide setting, so if
* you are writing a library, you will cause security bugs applications using it.
*
* That said, here's how you can completely disable SCE:
*
@@ -19342,7 +19602,7 @@
* ```
* angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
* // Completely disable SCE. For demonstration purposes only!
* // Do not use in new projects.
* // Do not use in new projects or libraries.
* $sceProvider.enabled(false);
* });
* ```
@@ -19357,8 +19617,8 @@
* @name $sceProvider#enabled
* @kind function
*
* @param {boolean=} value If provided, then enables/disables SCE.
* @return {boolean} true if SCE is enabled, false otherwise.
* @param {boolean=} value If provided, then enables/disables SCE application-wide.
* @return {boolean} True if SCE is enabled, false otherwise.
*
* @description
* Enables/disables SCE and returns the current value.
@@ -19412,9 +19672,9 @@
* getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
* will also succeed.
*
* Inheritance happens to capture this in a natural way. In some future, we
* may not use inheritance anymore. That is OK because no code outside of
* sce.js and sceSpecs.js would need to be aware of this detail.
* Inheritance happens to capture this in a natural way. In some future, we may not use
* inheritance anymore. That is OK because no code outside of sce.js and sceSpecs.js would need to
* be aware of this detail.
*/
 
this.$get = ['$parse', '$sceDelegate', function(
@@ -19436,8 +19696,8 @@
* @name $sce#isEnabled
* @kind function
*
* @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
* have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
* @return {Boolean} True if SCE is enabled, false otherwise. If you want to set the value, you
* have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
*
* @description
* Returns a boolean indicating if SCE is enabled.
@@ -19464,14 +19724,14 @@
* wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
* *result*)}
*
* @param {string} type The kind of SCE context in which this result will be used.
* @param {string} type The SCE context in which this result will be used.
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
* @return {function(context, locals)} A function which represents the compiled expression:
*
* * `context` – `{object}` – an object against which any expressions embedded in the strings
* are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values in
* `context`.
* * `context` – `{object}` – an object against which any expressions embedded in the
* strings are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values
* in `context`.
*/
sce.parseAs = function sceParseAs(type, expr) {
var parsed = $parse(expr);
@@ -19489,18 +19749,18 @@
* @name $sce#trustAs
*
* @description
* Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,
* returns an object that is trusted by angular for use in specified strict contextual
* escaping contexts (such as ng-bind-html, ng-include, any src attribute
* interpolation, any dom event binding attribute interpolation such as for onclick, etc.)
* that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual
* escaping.
* Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such, returns a
* wrapped object that represents your value, and the trust you have in its safety for the given
* context. AngularJS can then use that value as-is in bindings of the specified secure context.
* This is used in bindings for `ng-bind-html`, `ng-include`, and most `src` attribute
* interpolations. See {@link ng.$sce $sce} for strict contextual escaping.
*
* @param {string} type The kind of context in which this value is safe for use. e.g. url,
* resourceUrl, html, js and css.
* @param {*} value The value that that should be considered trusted/safe.
* @returns {*} A value that can be used to stand in for the provided `value` in places
* where Angular expects a $sce.trustAs() return value.
* @param {string} type The context in which this value is safe for use, e.g. `$sce.URL`,
* `$sce.RESOURCE_URL`, `$sce.HTML`, `$sce.JS` or `$sce.CSS`.
*
* @param {*} value The value that that should be considered trusted.
* @return {*} A wrapped version of value that can be used as a trusted variant of your `value`
* in the context you specified.
*/
 
/**
@@ -19511,15 +19771,27 @@
* Shorthand method. `$sce.trustAsHtml(value)` →
* {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
*
* @param {*} value The value to trustAs.
* @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
* $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives
* only accept expressions that are either literal constants or are the
* return value of {@link ng.$sce#trustAs $sce.trustAs}.)
* @param {*} value The value to mark as trusted for `$sce.HTML` context.
* @return {*} A wrapped version of value that can be used as a trusted variant of your `value`
* in `$sce.HTML` context (like `ng-bind-html`).
*/
 
/**
* @ngdoc method
* @name $sce#trustAsCss
*
* @description
* Shorthand method. `$sce.trustAsCss(value)` →
* {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.CSS, value)`}
*
* @param {*} value The value to mark as trusted for `$sce.CSS` context.
* @return {*} A wrapped version of value that can be used as a trusted variant
* of your `value` in `$sce.CSS` context. This context is currently unused, so there are
* almost no reasons to use this function so far.
*/
 
/**
* @ngdoc method
* @name $sce#trustAsUrl
*
* @description
@@ -19526,11 +19798,10 @@
* Shorthand method. `$sce.trustAsUrl(value)` →
* {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
*
* @param {*} value The value to trustAs.
* @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
* $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives
* only accept expressions that are either literal constants or are the
* return value of {@link ng.$sce#trustAs $sce.trustAs}.)
* @param {*} value The value to mark as trusted for `$sce.URL` context.
* @return {*} A wrapped version of value that can be used as a trusted variant of your `value`
* in `$sce.URL` context. That context is currently unused, so there are almost no reasons
* to use this function so far.
*/
 
/**
@@ -19541,11 +19812,10 @@
* Shorthand method. `$sce.trustAsResourceUrl(value)` →
* {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
*
* @param {*} value The value to trustAs.
* @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
* $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives
* only accept expressions that are either literal constants or are the return
* value of {@link ng.$sce#trustAs $sce.trustAs}.)
* @param {*} value The value to mark as trusted for `$sce.RESOURCE_URL` context.
* @return {*} A wrapped version of value that can be used as a trusted variant of your `value`
* in `$sce.RESOURCE_URL` context (template URLs in `ng-include`, most `src` attribute
* bindings, ...)
*/
 
/**
@@ -19556,11 +19826,10 @@
* Shorthand method. `$sce.trustAsJs(value)` →
* {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
*
* @param {*} value The value to trustAs.
* @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
* $sce.getTrustedJs(value)} to obtain the original value. (privileged directives
* only accept expressions that are either literal constants or are the
* return value of {@link ng.$sce#trustAs $sce.trustAs}.)
* @param {*} value The value to mark as trusted for `$sce.JS` context.
* @return {*} A wrapped version of value that can be used as a trusted variant of your `value`
* in `$sce.JS` context. That context is currently unused, so there are almost no reasons to
* use this function so far.
*/
 
/**
@@ -19569,16 +19838,17 @@
*
* @description
* Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,
* takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
* originally supplied value if the queried context type is a supertype of the created type.
* If this condition isn't satisfied, throws an exception.
* takes any input, and either returns a value that's safe to use in the specified context,
* or throws an exception. This function is aware of trusted values created by the `trustAs`
* function and its shorthands, and when contexts are appropriate, returns the unwrapped value
* as-is. Finally, this function can also throw when there is no way to turn `maybeTrusted` in a
* safe value (e.g., no sanitization is available or possible.)
*
* @param {string} type The kind of context in which this value is to be used.
* @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
* call.
* @returns {*} The value the was originally provided to
* {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
* Otherwise, throws an exception.
* @param {string} type The context in which this value is to be used.
* @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs
* `$sce.trustAs`} call, or anything else (which will not be considered trusted.)
* @return {*} A version of the value that's safe to use in the given context, or throws an
* exception if this is impossible.
*/
 
/**
@@ -19590,7 +19860,7 @@
* {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
*
* @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
* @return {*} The return value of `$sce.getTrusted($sce.HTML, value)`
*/
 
/**
@@ -19602,7 +19872,7 @@
* {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
*
* @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
* @return {*} The return value of `$sce.getTrusted($sce.CSS, value)`
*/
 
/**
@@ -19614,7 +19884,7 @@
* {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
*
* @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
* @return {*} The return value of `$sce.getTrusted($sce.URL, value)`
*/
 
/**
@@ -19626,7 +19896,7 @@
* {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
*
* @param {*} value The value to pass to `$sceDelegate.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
* @return {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
*/
 
/**
@@ -19638,7 +19908,7 @@
* {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
*
* @param {*} value The value to pass to `$sce.getTrusted`.
* @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
* @return {*} The return value of `$sce.getTrusted($sce.JS, value)`
*/
 
/**
@@ -19650,12 +19920,12 @@
* {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
* @return {function(context, locals)} A function which represents the compiled expression:
*
* * `context` – `{object}` – an object against which any expressions embedded in the strings
* are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values in
* `context`.
* * `context` – `{object}` – an object against which any expressions embedded in the
* strings are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values
* in `context`.
*/
 
/**
@@ -19667,12 +19937,12 @@
* {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
* @return {function(context, locals)} A function which represents the compiled expression:
*
* * `context` – `{object}` – an object against which any expressions embedded in the strings
* are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values in
* `context`.
* * `context` – `{object}` – an object against which any expressions embedded in the
* strings are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values
* in `context`.
*/
 
/**
@@ -19684,12 +19954,12 @@
* {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
* @return {function(context, locals)} A function which represents the compiled expression:
*
* * `context` – `{object}` – an object against which any expressions embedded in the strings
* are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values in
* `context`.
* * `context` – `{object}` – an object against which any expressions embedded in the
* strings are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values
* in `context`.
*/
 
/**
@@ -19701,12 +19971,12 @@
* {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
* @return {function(context, locals)} A function which represents the compiled expression:
*
* * `context` – `{object}` – an object against which any expressions embedded in the strings
* are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values in
* `context`.
* * `context` – `{object}` – an object against which any expressions embedded in the
* strings are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values
* in `context`.
*/
 
/**
@@ -19718,12 +19988,12 @@
* {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}
*
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
* @return {function(context, locals)} A function which represents the compiled expression:
*
* * `context` – `{object}` – an object against which any expressions embedded in the strings
* are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values in
* `context`.
* * `context` – `{object}` – an object against which any expressions embedded in the
* strings are evaluated against (typically a scope object).
* * `locals` – `{object=}` – local variables context object, useful for overriding values
* in `context`.
*/
 
// Shorthand delegations.
@@ -20149,7 +20419,7 @@
timeout.cancel = function(promise) {
if (promise && promise.$$timeoutId in deferreds) {
// Timeout cancels should not report an unhandled promise.
deferreds[promise.$$timeoutId].promise.catch(noop);
markQExceptionHandled(deferreds[promise.$$timeoutId].promise);
deferreds[promise.$$timeoutId].reject('canceled');
delete deferreds[promise.$$timeoutId];
return $browser.defer.cancel(promise.$$timeoutId);
@@ -20583,8 +20853,9 @@
* The final result is an array of those elements that the predicate returned true for.
*
* @param {function(actual, expected)|true|false} [comparator] Comparator which is used in
* determining if the expected value (from the filter expression) and actual value (from
* the object in the array) should be considered a match.
* determining if values retrieved using `expression` (when it is not a function) should be
* considered a match based on the expected value (from the filter expression) and actual
* value (from the object in the array).
*
* Can be one of:
*
@@ -21279,7 +21550,7 @@
GGGG: longEraGetter
};
 
var DATE_FORMATS_SPLIT = /((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
var DATE_FORMATS_SPLIT = /((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))([\s\S]*)/,
NUMBER_STRING = /^-?\d+$/;
 
/**
@@ -21338,6 +21609,8 @@
* `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
* (e.g. `"h 'o''clock'"`).
*
* Any other characters in the `format` string will be output as-is.
*
* @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
* number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
* shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
@@ -21500,6 +21773,9 @@
* @kind function
* @description
* Converts string to lowercase.
*
* See the {@link ng.uppercase uppercase filter documentation} for a functionally identical example.
*
* @see angular.lowercase
*/
var lowercaseFilter = valueFn(lowercase);
@@ -21511,7 +21787,23 @@
* @kind function
* @description
* Converts string to uppercase.
* @see angular.uppercase
* @example
<example module="uppercaseFilterExample" name="filter-uppercase">
<file name="index.html">
<script>
angular.module('uppercaseFilterExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.title = 'This is a title';
}]);
</script>
<div ng-controller="ExampleController">
<!-- This title should be formatted normally -->
<h1>{{title}}</h1>
<!-- This title should be capitalized -->
<h1>{{title | uppercase}}</h1>
</div>
</file>
</example>
*/
var uppercaseFilter = valueFn(uppercase);
 
@@ -21700,6 +21992,9 @@
* dummy predicate that returns the item's index as `value`.
* (If you are using a custom comparator, make sure it can handle this predicate as well.)
*
* If a custom comparator still can't distinguish between two items, then they will be sorted based
* on their index using the built-in comparator.
*
* Finally, in an attempt to simplify things, if a predicate returns an object as the extracted
* value for an item, `orderBy` will try to convert that object to a primitive value, before passing
* it to the comparator. The following rules govern the conversion:
@@ -22246,7 +22541,7 @@
}
}
 
return compare(v1.tieBreaker, v2.tieBreaker) * descending;
return (compare(v1.tieBreaker, v2.tieBreaker) || defaultCompare(v1.tieBreaker, v2.tieBreaker)) * descending;
}
};
 
@@ -22849,17 +23144,23 @@
* @property {boolean} $dirty True if user has already interacted with the form.
* @property {boolean} $valid True if all of the containing forms and controls are valid.
* @property {boolean} $invalid True if at least one containing control or form is invalid.
* @property {boolean} $pending True if at least one containing control or form is pending.
* @property {boolean} $submitted True if user has submitted the form even if its invalid.
*
* @property {Object} $error Is an object hash, containing references to controls or
* forms with failing validators, where:
* @property {Object} $pending An object hash, containing references to controls or forms with
* pending validators, where:
*
* - keys are validations tokens (error names).
* - values are arrays of controls or forms that have a pending validator for the given error name.
*
* See {@link form.FormController#$error $error} for a list of built-in validation tokens.
*
* @property {Object} $error An object hash, containing references to controls or forms with failing
* validators, where:
*
* - keys are validation tokens (error names),
* - values are arrays of controls or forms that have a failing validator for given error name.
* - values are arrays of controls or forms that have a failing validator for the given error name.
*
* Built-in validation tokens:
*
* - `email`
* - `max`
* - `maxlength`
@@ -23105,9 +23406,24 @@
* @name form.FormController#$setValidity
*
* @description
* Sets the validity of a form control.
* Change the validity state of the form, and notify the parent form (if any).
*
* This method will also propagate to parent forms.
* Application developers will rarely need to call this method directly. It is used internally, by
* {@link ngModel.NgModelController#$setValidity NgModelController.$setValidity()}, to propagate a
* control's validity state to the parent `FormController`.
*
* @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be
* assigned to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` (for
* unfulfilled `$asyncValidators`), so that it is available for data-binding. The
* `validationErrorKey` should be in camelCase and will get converted into dash-case for
* class name. Example: `myError` will result in `ng-valid-my-error` and
* `ng-invalid-my-error` classes and can be bound to as `{{ someForm.$error.myError }}`.
* @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending
* (undefined), or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
* Skipped is used by AngularJS when validators do not run because of parse errors and when
* `$asyncValidators` do not run because any of the `$validators` failed.
* @param {NgModelController | FormController} controller - The controller whose validity state is
* triggering the change.
*/
addSetValidityMethod({
clazz: FormController,
@@ -28297,7 +28613,9 @@
 
this.$$currentValidationRunId = 0;
 
this.$$scope = $scope;
// https://github.com/angular/angular.js/issues/15833
// Prevent `$$scope` from being iterated over by `copy` when NgModelController is deep watched
Object.defineProperty(this, '$$scope', {value: $scope});
this.$$attr = $attr;
this.$$element = $element;
this.$$animate = $animate;
@@ -28906,8 +29224,8 @@
// -> scope value did not change since the last digest as
// ng-change executes in apply phase
// 4. view should be changed back to 'a'
ctrl.$$scope.$watch(function ngModelWatch() {
var modelValue = ctrl.$$ngModelGet(ctrl.$$scope);
ctrl.$$scope.$watch(function ngModelWatch(scope) {
var modelValue = ctrl.$$ngModelGet(scope);
 
// if scope model value and ngModel value are out of sync
// TODO(perf): why not move this to the action fn?
@@ -28956,7 +29274,7 @@
* (for unfulfilled `$asyncValidators`), so that it is available for data-binding.
* The `validationErrorKey` should be in camelCase and will get converted into dash-case
* for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
* class and can be bound to as `{{someForm.someControl.$error.myError}}` .
* classes and can be bound to as `{{ someForm.someControl.$error.myError }}`.
* @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
* or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
* Skipped is used by Angular when validators do not run because of parse errors and
@@ -30031,7 +30349,8 @@
}
 
 
// we can't just jqLite('<option>') since jqLite is not smart enough
// Support: IE 9 only
// We can't just jqLite('<option>') since jqLite is not smart enough
// to create it in <select> and IE barfs otherwise.
var optionTemplate = window.document.createElement('option'),
optGroupTemplate = window.document.createElement('optgroup');
@@ -30052,6 +30371,9 @@
}
}
 
// The empty option will be compiled and rendered before we first generate the options
selectElement.empty();
 
var providedEmptyOption = !!selectCtrl.emptyOption;
 
var unknownOption = jqLite(optionTemplate.cloneNode(false));
@@ -30073,12 +30395,15 @@
if (!multiple) {
 
selectCtrl.writeValue = function writeNgOptionsValue(value) {
var selectedOption = options.selectValueMap[selectElement.val()];
// The options might not be defined yet when ngModel tries to render
if (!options) return;
 
var selectedOption = selectElement[0].options[selectElement[0].selectedIndex];
var option = options.getOptionFromViewValue(value);
 
// Make sure to remove the selected attribute from the previously selected option
// Otherwise, screen readers might get confused
if (selectedOption) selectedOption.element.removeAttribute('selected');
if (selectedOption) selectedOption.removeAttribute('selected');
 
if (option) {
// Don't update the option when it is already selected.
@@ -30088,7 +30413,6 @@
 
if (selectElement[0].value !== option.selectValue) {
selectCtrl.removeUnknownOption();
selectCtrl.unselectEmptyOption();
 
selectElement[0].value = option.selectValue;
option.element.selected = true;
@@ -30096,14 +30420,7 @@
 
option.element.setAttribute('selected', 'selected');
} else {
 
if (providedEmptyOption) {
selectCtrl.selectEmptyOption();
} else if (selectCtrl.unknownOption.parent().length) {
selectCtrl.updateUnknownOption(value);
} else {
selectCtrl.renderUnknownOption(value);
}
selectCtrl.selectUnknownOrEmptyOption(value);
}
};
 
@@ -30132,9 +30449,11 @@
} else {
 
selectCtrl.writeValue = function writeNgOptionsMultiple(values) {
// The options might not be defined yet when ngModel tries to render
if (!options) return;
 
// Only set `<option>.selected` if necessary, in order to prevent some browsers from
// scrolling to `<option>` elements that are outside the `<select>` element's viewport.
 
var selectedOptions = values && values.map(getAndUpdateSelectedOption) || [];
 
options.items.forEach(function(option) {
@@ -30176,13 +30495,11 @@
 
if (providedEmptyOption) {
 
// we need to remove it before calling selectElement.empty() because otherwise IE will
// remove the label from the element. wtf?
selectCtrl.emptyOption.remove();
 
// compile the element since there might be bindings in it
$compile(selectCtrl.emptyOption)(scope);
 
selectElement.prepend(selectCtrl.emptyOption);
 
if (selectCtrl.emptyOption[0].nodeType === NODE_TYPE_COMMENT) {
// This means the empty option has currently no actual DOM node, probably because
// it has been modified by a transclusion directive.
@@ -30200,8 +30517,12 @@
ngModelCtrl.$render();
 
optionEl.on('$destroy', function() {
var needsRerender = selectCtrl.$isEmptyOptionSelected();
 
selectCtrl.hasEmptyOption = false;
selectCtrl.emptyOption = undefined;
 
if (needsRerender) ngModelCtrl.$render();
});
}
};
@@ -30214,12 +30535,6 @@
 
}
 
selectElement.empty();
 
// We need to do this here to ensure that the options object is defined
// when we first hit it in writeNgOptionsValue
updateOptions();
 
// We will re-render the option elements if the option values or labels change
scope.$watchCollection(ngOptions.getWatchables, updateOptions);
 
@@ -30243,7 +30558,8 @@
function updateOptionElement(option, element) {
option.element = element;
element.disabled = option.disabled;
// NOTE: The label must be set before the value, otherwise IE10/11/EDGE create unresponsive
// Support: IE 11 only, Edge 12-13 only
// NOTE: The label must be set before the value, otherwise IE 11 & Edge create unresponsive
// selects in certain circumstances when multiple selects are next to each other and display
// the option list in listbox style, i.e. the select is [multiple], or specifies a [size].
// See https://github.com/angular/angular.js/issues/11314 for more info.
@@ -30279,11 +30595,6 @@
 
var groupElementMap = {};
 
// Ensure that the empty option is always there if it was explicitly provided
if (providedEmptyOption) {
selectElement.prepend(selectCtrl.emptyOption);
}
 
options.items.forEach(function addOption(option) {
var groupElement;
 
@@ -30328,7 +30639,6 @@
ngModelCtrl.$render();
}
}
 
}
}
 
@@ -31016,7 +31326,7 @@
// Store a list of elements from previous run. This is a hash where key is the item from the
// iterator, and the value is objects with following properties.
// - scope: bound scope
// - element: previous element.
// - clone: previous element.
// - index: position
//
// We are using no-proto object so that we don't need to guard against inherited props via
@@ -32119,7 +32429,7 @@
var noopNgModelController = { $setViewValue: noop, $render: noop };
 
function setOptionSelectedStatus(optionEl, value) {
optionEl.prop('selected', value); // needed for IE
optionEl.prop('selected', value);
/**
* When unselecting an option, setting the property to null / false should be enough
* However, screenreaders might react to the selected attribute instead, see
@@ -32133,10 +32443,120 @@
/**
* @ngdoc type
* @name select.SelectController
*
* @description
* The controller for the `<select>` directive. This provides support for reading
* and writing the selected value(s) of the control and also coordinates dynamically
* added `<option>` elements, perhaps by an `ngRepeat` directive.
* The controller for the {@link ng.select select} directive. The controller exposes
* a few utility methods that can be used to augment the behavior of a regular or an
* {@link ng.ngOptions ngOptions} select element.
*
* @example
* ### Set a custom error when the unknown option is selected
*
* This example sets a custom error "unknownValue" on the ngModelController
* when the select element's unknown option is selected, i.e. when the model is set to a value
* that is not matched by any option.
*
* <example name="select-unknown-value-error" module="staticSelect">
* <file name="index.html">
* <div ng-controller="ExampleController">
* <form name="myForm">
* <label for="testSelect"> Single select: </label><br>
* <select name="testSelect" ng-model="selected" unknown-value-error>
* <option value="option-1">Option 1</option>
* <option value="option-2">Option 2</option>
* </select><br>
* <span ng-if="myForm.testSelect.$error.unknownValue">Error: The current model doesn't match any option</span>
*
* <button ng-click="forceUnknownOption()">Force unknown option</button><br>
* </form>
* </div>
* </file>
* <file name="app.js">
* angular.module('staticSelect', [])
* .controller('ExampleController', ['$scope', function($scope) {
* $scope.selected = null;
*
* $scope.forceUnknownOption = function() {
* $scope.selected = 'nonsense';
* };
* }])
* .directive('unknownValueError', function() {
* return {
* require: ['ngModel', 'select'],
* link: function(scope, element, attrs, ctrls) {
* var ngModelCtrl = ctrls[0];
* var selectCtrl = ctrls[1];
*
* ngModelCtrl.$validators.unknownValue = function(modelValue, viewValue) {
* if (selectCtrl.$isUnknownOptionSelected()) {
* return false;
* }
*
* return true;
* };
* }
*
* };
* });
* </file>
*</example>
*
*
* @example
* ### Set the "required" error when the unknown option is selected.
*
* By default, the "required" error on the ngModelController is only set on a required select
* when the empty option is selected. This example adds a custom directive that also sets the
* error when the unknown option is selected.
*
* <example name="select-unknown-value-required" module="staticSelect">
* <file name="index.html">
* <div ng-controller="ExampleController">
* <form name="myForm">
* <label for="testSelect"> Select: </label><br>
* <select name="testSelect" ng-model="selected" unknown-value-required>
* <option value="option-1">Option 1</option>
* <option value="option-2">Option 2</option>
* </select><br>
* <span ng-if="myForm.testSelect.$error.required">Error: Please select a value</span><br>
*
* <button ng-click="forceUnknownOption()">Force unknown option</button><br>
* </form>
* </div>
* </file>
* <file name="app.js">
* angular.module('staticSelect', [])
* .controller('ExampleController', ['$scope', function($scope) {
* $scope.selected = null;
*
* $scope.forceUnknownOption = function() {
* $scope.selected = 'nonsense';
* };
* }])
* .directive('unknownValueRequired', function() {
* return {
* priority: 1, // This directive must run after the required directive has added its validator
* require: ['ngModel', 'select'],
* link: function(scope, element, attrs, ctrls) {
* var ngModelCtrl = ctrls[0];
* var selectCtrl = ctrls[1];
*
* var originalRequiredValidator = ngModelCtrl.$validators.required;
*
* ngModelCtrl.$validators.required = function() {
* if (attrs.required && selectCtrl.$isUnknownOptionSelected()) {
* return false;
* }
*
* return originalRequiredValidator.apply(this, arguments);
* };
* }
* };
* });
* </file>
*</example>
*
*
*/
var SelectController =
['$element', '$scope', /** @this */ function($element, $scope) {
@@ -32154,15 +32574,18 @@
// does not match any of the options. When it is rendered the value of the unknown
// option is '? XXX ?' where XXX is the hashKey of the value that is not known.
//
// Support: IE 9 only
// We can't just jqLite('<option>') since jqLite is not smart enough
// to create it in <select> and IE barfs otherwise.
self.unknownOption = jqLite(window.document.createElement('option'));
 
// The empty option is an option with the value '' that te application developer can
// provide inside the select. When the model changes to a value that doesn't match an option,
// it is selected - so if an empty option is provided, no unknown option is generated.
// However, the empty option is not removed when the model matches an option. It is always selectable
// and indicates that a "null" selection has been made.
// The empty option is an option with the value '' that the application developer can
// provide inside the select. It is always selectable and indicates that a "null" selection has
// been made by the user.
// If the select has an empty option, and the model of the select is set to "undefined" or "null",
// the empty option is selected.
// If the model is set to a different unmatched value, the unknown option is rendered and
// selected, i.e both are present, because a "null" selection and an unknown value are different.
self.hasEmptyOption = false;
self.emptyOption = undefined;
 
@@ -32198,7 +32621,7 @@
 
self.unselectEmptyOption = function() {
if (self.hasEmptyOption) {
self.emptyOption.removeAttr('selected');
setOptionSelectedStatus(self.emptyOption, false);
}
};
 
@@ -32240,14 +32663,7 @@
var selectedOption = $element[0].options[$element[0].selectedIndex];
setOptionSelectedStatus(jqLite(selectedOption), true);
} else {
if (value == null && self.emptyOption) {
self.removeUnknownOption();
self.selectEmptyOption();
} else if (self.unknownOption.parent().length) {
self.updateUnknownOption(value);
} else {
self.renderUnknownOption(value);
}
self.selectUnknownOrEmptyOption(value);
}
};
 
@@ -32290,7 +32706,60 @@
return !!optionsMap.get(value);
};
 
/**
* @ngdoc method
* @name select.SelectController#$hasEmptyOption
*
* @description
*
* Returns `true` if the select element currently has an empty option
* element, i.e. an option that signifies that the select is empty / the selection is null.
*
*/
self.$hasEmptyOption = function() {
return self.hasEmptyOption;
};
 
/**
* @ngdoc method
* @name select.SelectController#$isUnknownOptionSelected
*
* @description
*
* Returns `true` if the select element's unknown option is selected. The unknown option is added
* and automatically selected whenever the select model doesn't match any option.
*
*/
self.$isUnknownOptionSelected = function() {
// Presence of the unknown option means it is selected
return $element[0].options[0] === self.unknownOption[0];
};
 
/**
* @ngdoc method
* @name select.SelectController#$isEmptyOptionSelected
*
* @description
*
* Returns `true` if the select element has an empty option and this empty option is currently
* selected. Returns `false` if the select element has no empty option or it is not selected.
*
*/
self.$isEmptyOptionSelected = function() {
return self.hasEmptyOption && $element[0].options[$element[0].selectedIndex] === self.emptyOption[0];
};
 
self.selectUnknownOrEmptyOption = function(value) {
if (value == null && self.emptyOption) {
self.removeUnknownOption();
self.selectEmptyOption();
} else if (self.unknownOption.parent().length) {
self.updateUnknownOption(value);
} else {
self.renderUnknownOption(value);
}
};
 
var renderScheduled = false;
function scheduleRender() {
if (renderScheduled) return;
@@ -32438,6 +32907,9 @@
* the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.
* Value and textContent can be interpolated.
*
* The {@link select.SelectController select controller} exposes utility functions that can be used
* to manipulate the select's behavior.
*
* ## Matching model and option values
*
* In general, the match between the model and an option is evaluated by strictly comparing the model
@@ -32490,6 +32962,19 @@
* @param {string=} ngAttrSize sets the size of the select element dynamically. Uses the
* {@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
*
@@ -32734,10 +33219,11 @@
includes(value, selectCtrl.selectValueMap[option.value]));
var currentlySelected = option.selected;
 
// IE and Edge, adding options to the selection via shift+click/UP/DOWN,
// Support: IE 9-11 only, Edge 12-15+
// In IE and Edge adding options to the selection via shift+click/UP/DOWN
// will de-select already selected options if "selected" on those options was set
// more than once (i.e. when the options were already selected)
// So we only modify the selected property if neccessary.
// So we only modify the selected property if necessary.
// Note: this behavior cannot be replicated via unit tests because it only shows in the
// actual user interface.
if (shouldBeSelected !== currentlySelected) {