From 528cedaa0cff894c6123526ef511b06f52b2f2f9 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 15 Jul 2015 12:34:46 +0100 Subject: [PATCH 01/86] docs(CHANGELOG): Remove redundant items from 1.4.3 changes The update to the change log for the 1.4.3 release accidentally included a number of changes from previous releases. --- CHANGELOG.md | 88 ---------------------------------------------------- 1 file changed, 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76115091ad74..02a788921e62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,99 +7,11 @@ - **$animateCss:** ensure animations execute if only a keyframeStyle is provided ([97d79eec](https://github.com/angular/angular.js/commit/97d79eec80092f5fae3336c23aa881a72436de55), [#12124](https://github.com/angular/angular.js/issues/12124), [#12340](https://github.com/angular/angular.js/issues/12340)) -- **$browser:** prevent infinite digest if changing hash when there is no hashPrefix - ([f81ff3be](https://github.com/angular/angular.js/commit/f81ff3beb0c9d19d494c5878086fb57476442b8b), - [#10423](https://github.com/angular/angular.js/issues/10423), [#12145](https://github.com/angular/angular.js/issues/12145)) -- **$compile:** - - throw error when requestng new and isolate scopes (async) - ([6333d65b](https://github.com/angular/angular.js/commit/6333d65b76e0796cfbab8a2953af0c8014dba2e1), - [#12215](https://github.com/angular/angular.js/issues/12215), [#12217](https://github.com/angular/angular.js/issues/12217)) - - do not write @-bound properties if attribute is not present - ([8a1eb162](https://github.com/angular/angular.js/commit/8a1eb1625c080445ce1e519762e1f2d4fd842b72), - [#12151](https://github.com/angular/angular.js/issues/12151), [#12144](https://github.com/angular/angular.js/issues/12144)) - - workaround for IE11 MutationObserver - ([f3b1d0b7](https://github.com/angular/angular.js/commit/f3b1d0b723298a5f8ea21d0704405649cce1b5fc), - [#11781](https://github.com/angular/angular.js/issues/11781)) - - exception when using "watch" as isolated scope binding variable in Firefox - ([a6339d30](https://github.com/angular/angular.js/commit/a6339d30d1379689da5eec9647a953f64821f8b0), - [#11627](https://github.com/angular/angular.js/issues/11627)) -- **$location:** - - allow navigating outside the original base URL - ([6903b5ec](https://github.com/angular/angular.js/commit/6903b5ec4c04ed6b7c80ef7d638c48639ccdc4bb), - [#11302](https://github.com/angular/angular.js/issues/11302), [#4776](https://github.com/angular/angular.js/issues/4776)) - - do not get caught in infinite digest in IE9 - ([91b60226](https://github.com/angular/angular.js/commit/91b602263b96b6fce1331208462e18eb647f4d60), - [#11439](https://github.com/angular/angular.js/issues/11439), [#11675](https://github.com/angular/angular.js/issues/11675), [#11935](https://github.com/angular/angular.js/issues/11935), [#12083](https://github.com/angular/angular.js/issues/12083)) -- **$parse:** - - set null reference properties to `undefined` - ([71fc3f4f](https://github.com/angular/angular.js/commit/71fc3f4fa0cd12eff335d57efed7c033554749f4), - [#12099](https://github.com/angular/angular.js/issues/12099)) - - set null reference properties to `undefined` - ([d19504a1](https://github.com/angular/angular.js/commit/d19504a179355d7801d59a8db0285a1322e04601), - [#11959](https://github.com/angular/angular.js/issues/11959)) -- **$sanitize:** dont not remove tab index property - ([799353c7](https://github.com/angular/angular.js/commit/799353c75de28e6fbf52dac6e0721e85b578575a), - [#8371](https://github.com/angular/angular.js/issues/8371), [#5853](https://github.com/angular/angular.js/issues/5853)) -- **compile:** assign ctrl return values correctly for multiple directives - ([8caf1802](https://github.com/angular/angular.js/commit/8caf1802e0e93389dec626ef35e04a302aa6c39d), - [#12029](https://github.com/angular/angular.js/issues/12029), [#12036](https://github.com/angular/angular.js/issues/12036)) -- **copy:** do not copy the same object twice - ([0e622f7b](https://github.com/angular/angular.js/commit/0e622f7b5bc3d5d0ab0fbc1a1bc69404bd7216d5)) -- **forms:** parse exponential notation in numberInputType parser - ([ebd0fbba](https://github.com/angular/angular.js/commit/ebd0fbba8ff90bee0cd016d574643d56a7f81ed0), - [#12121](https://github.com/angular/angular.js/issues/12121), [#12122](https://github.com/angular/angular.js/issues/12122)) -- **linky:** allow case insensitive scheme detection - ([8dc09e6d](https://github.com/angular/angular.js/commit/8dc09e6dabb84c2c611cdc9e40adfac989648200), - [#12073](https://github.com/angular/angular.js/issues/12073), [#12073](https://github.com/angular/angular.js/issues/12073)) - **loader:** define isFunction ([9ea52d81](https://github.com/angular/angular.js/commit/9ea52d818bcd2fb3ea8ccc85bf47f9fd5af68843)) -- **merge:** treat dates as atomic values instead of objects. - ([6cbbd966](https://github.com/angular/angular.js/commit/6cbbd966479448591f819cbf904e0a3b757613dc), - [#11720](https://github.com/angular/angular.js/issues/11720), [#11720](https://github.com/angular/angular.js/issues/11720)) - **ngAnimate:** ensure that orphaned elements do not throw errors when animated ([e4aeae0c](https://github.com/angular/angular.js/commit/e4aeae0c7303b94135e6df20e6c5e25f2aa0f586), [#11975](https://github.com/angular/angular.js/issues/11975), [#12338](https://github.com/angular/angular.js/issues/12338)) -- **ngAria:** - - update `aria-valuemin/max` when `min/max` change - ([ebaa0f59](https://github.com/angular/angular.js/commit/ebaa0f598501702ae64d59ada0ae492eaf0e2db6), - [#11770](https://github.com/angular/angular.js/issues/11770), [#11774](https://github.com/angular/angular.js/issues/11774)) - - ensure boolean values for aria-hidden and aria-disabled - ([59273354](https://github.com/angular/angular.js/commit/59273354b57dd8d1ad2cd2f4740ffa8923e480f9), - [#11365](https://github.com/angular/angular.js/issues/11365)) -- **ngModel:** form validation when there is an Object.prototype enumerable value - ([0934b76b](https://github.com/angular/angular.js/commit/0934b76b72cec86093414834ac4cb7f0946b651d), - [#12066](https://github.com/angular/angular.js/issues/12066)) -- **ngOptions:** - - only watch numeric properties of an array - ([14638f4a](https://github.com/angular/angular.js/commit/14638f4a60053b085565e597fc74bd31cf0d372b)) - - do not watch properties starting with $ - ([34a6da24](https://github.com/angular/angular.js/commit/34a6da24c17356d4ffc70aec3f621a140a9a61ab), - [#11930](https://github.com/angular/angular.js/issues/11930), [#12010](https://github.com/angular/angular.js/issues/12010)) - - use reference check only when not using trackBy - ([d7dc14dc](https://github.com/angular/angular.js/commit/d7dc14dc0cdeb9c187d227e19acc8aca7df9d740), - [#11936](https://github.com/angular/angular.js/issues/11936), [#11996](https://github.com/angular/angular.js/issues/11996)) -- **orderBy:** ensure correct ordering with arrays of objects and no predicate - ([48e1f560](https://github.com/angular/angular.js/commit/48e1f5605edd32a63318fd78f5165c7d1f1a20f9), - [#11866](https://github.com/angular/angular.js/issues/11866), [#11312](https://github.com/angular/angular.js/issues/11312), [#4282](https://github.com/angular/angular.js/issues/4282)) - - -## Features - -- **$compile:** show module name during multidir error - ([351fe4b7](https://github.com/angular/angular.js/commit/351fe4b79c50a45a11af2fcd2aa7b6fd3b70058d), - [#11775](https://github.com/angular/angular.js/issues/11775)) -- **$q:** $q.resolve as an alias for $q.when - ([3ef52980](https://github.com/angular/angular.js/commit/3ef529806fef28b41ca4af86a330f39a95699cf6), - [#11944](https://github.com/angular/angular.js/issues/11944), [#11987](https://github.com/angular/angular.js/issues/11987)) -- **ngAria:** add option to disable role=button - ([1f5e42e8](https://github.com/angular/angular.js/commit/1f5e42e8821217026ef36a46d36f84d7cd32830a), - [#11580](https://github.com/angular/angular.js/issues/11580), [#12234](https://github.com/angular/angular.js/issues/12234)) - - -## Performance Improvements - -- **$compile:** avoid jquery data calls when there is no data - ([9efb0d5e](https://github.com/angular/angular.js/commit/9efb0d5ee961b57c8fc144a3138a15955e4010e2)) From 1f4aa471931d4b24155a64ba023defa3d68cf507 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 15 Jul 2015 13:52:56 +0100 Subject: [PATCH 02/86] docs(migration): clarify non-numeric matching Closes #12350 --- docs/content/guide/migration.ngdoc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/content/guide/migration.ngdoc b/docs/content/guide/migration.ngdoc index f76d0ab21455..a77534fc2856 100644 --- a/docs/content/guide/migration.ngdoc +++ b/docs/content/guide/migration.ngdoc @@ -194,8 +194,9 @@ in which the properties were defined. Due to [7fda214c](https://github.com/angular/angular.js/commit/7fda214c4f65a6a06b25cf5d5aff013a364e9cef), the `select` directive will now use strict comparison of the `ngModel` scope value against `option` -values to determine which option is selected. This means `Number` scope values will not be matched -against numeric option strings. +values to determine which option is selected. This means non-string scope values (such as `Number` or `Boolean`) +will not be matched against equivalent option strings (such as the strings `"123"`, `"true"` or `"false"`). + In Angular 1.3.x, setting `scope.x = 200` would select the option with the value 200 in the following `select`: ``` @@ -206,7 +207,8 @@ In Angular 1.3.x, setting `scope.x = 200` would select the option with the value ``` In Angular 1.4.x, the 'unknown option' will be selected. -To remedy this, you can simply initialize the model as a string: `scope.x = '200'`, or if you want to + +To remedy this, you can initialize the model as a string: `scope.x = '200'`, or if you want to keep the model as a `Number`, you can do the conversion via `$formatters` and `$parsers` on `ngModel`: ```js @@ -248,7 +250,7 @@ is marked as optional and the attribute is not specified, no function will be ad Due to [62d514b](https://github.com/angular/angular.js/commit/62d514b06937cc7dd86e973ea11165c88343b42d), returning an object from a controller constructor function will now override the scope. Views that use the -controllerAs method will no longer get the this reference, but the returned object. +controllerAs method will no longer get the this reference, but the returned object. ## Cookies (`ngCookies`) From 618356e481fcfeac74bfc9086332e25062fd8133 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Wed, 15 Jul 2015 22:52:21 +0100 Subject: [PATCH 03/86] fix(ngCsp): allow CSP to be configurable There are two different features in Angular that can break CSP rules: use of `eval` to execute a string as JavaScript and dynamic injection of CSS style rules into the DOM. This change allows us to configure which of these features should be turned off to allow a more fine grained set of CSP rules to be supported. Closes #11933 Closes #8459 Closes #12346 --- lib/grunt/utils.js | 2 +- src/Angular.js | 31 +++++++++++++---- src/AngularPublic.js | 1 - src/ng/directive/ngCsp.js | 64 +++++++++++++++++++++++++--------- src/ng/parse.js | 7 ++-- test/AngularSpec.js | 72 ++++++++++++++++++++++++++++----------- test/ng/snifferSpec.js | 7 ++-- 7 files changed, 134 insertions(+), 50 deletions(-) diff --git a/lib/grunt/utils.js b/lib/grunt/utils.js index 5c194378bad2..204db413ecf2 100644 --- a/lib/grunt/utils.js +++ b/lib/grunt/utils.js @@ -116,7 +116,7 @@ module.exports = { .replace(/\\/g, '\\\\') .replace(/'/g, "\\'") .replace(/\r?\n/g, '\\n'); - js = "!window.angular.$$csp() && window.angular.element(document.head).prepend('');"; + js = "!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('');"; state.js.push(js); return state; diff --git a/src/Angular.js b/src/Angular.js index e66b9938a9a3..9d351a869bb0 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -984,22 +984,39 @@ function equals(o1, o2) { } var csp = function() { - if (isDefined(csp.isActive_)) return csp.isActive_; + if (!isDefined(csp.rules)) { - var active = !!(document.querySelector('[ng-csp]') || - document.querySelector('[data-ng-csp]')); - if (!active) { + var ngCspElement = (document.querySelector('[ng-csp]') || + document.querySelector('[data-ng-csp]')); + + if (ngCspElement) { + var ngCspAttribute = ngCspElement.getAttribute('ng-csp') || + ngCspElement.getAttribute('data-ng-csp'); + csp.rules = { + noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1), + noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1) + }; + } else { + csp.rules = { + noUnsafeEval: noUnsafeEval(), + noInlineStyle: false + }; + } + } + + return csp.rules; + + function noUnsafeEval() { try { /* jshint -W031, -W054 */ new Function(''); /* jshint +W031, +W054 */ + return false; } catch (e) { - active = true; + return true; } } - - return (csp.isActive_ = active); }; /** diff --git a/src/AngularPublic.js b/src/AngularPublic.js index dff1ce015ae1..9afb79c16d6a 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -20,7 +20,6 @@ ngClassDirective, ngClassEvenDirective, ngClassOddDirective, - ngCspDirective, ngCloakDirective, ngControllerDirective, ngFormDirective, diff --git a/src/ng/directive/ngCsp.js b/src/ng/directive/ngCsp.js index 974d2e9305fb..378333b4a854 100644 --- a/src/ng/directive/ngCsp.js +++ b/src/ng/directive/ngCsp.js @@ -6,27 +6,29 @@ * * @element html * @description - * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support. + * + * Angular has some features that can break certain + * [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) rules. + * + * If you intend to implement these rules then you must tell Angular not to use these features. * * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps. * - * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things). - * For Angular to be CSP compatible there are only two things that we need to do differently: * - * - don't use `Function` constructor to generate optimized value getters - * - don't inject custom stylesheet into the document + * The following rules affect Angular: * - * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp` - * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will - * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will - * be raised. + * * `unsafe-eval`: this rule forbids apps to use `eval` or `Function(string)` generated functions + * (among other things). Angular makes use of this in the {@link $parse} service to provide a 30% + * increase in the speed of evaluating Angular expressions. * - * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically - * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}). - * To make those directives work in CSP mode, include the `angular-csp.css` manually. + * * `unsafe-inline`: this rule forbids apps from inject custom styles into the document. Angular + * makes use of this to include some CSS rules (e.g. {@link ngCloak} and {@link ngHide}). + * To make these directives work when a CSP rule is blocking inline styles, you must link to the + * `angular-csp.css` in your HTML manually. * - * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This - * autodetection however triggers a CSP error to be logged in the console: + * If you do not provide `ngCsp` then Angular tries to autodetect if CSP is blocking unsafe-eval + * and automatically deactivates this feature in the {@link $parse} service. This autodetection, + * however, triggers a CSP error to be logged in the console: * * ``` * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of @@ -35,11 +37,39 @@ * ``` * * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp` - * directive on the root element of the application or on the `angular.js` script tag, whichever - * appears first in the html document. + * directive on an element of the HTML document that appears before the `