In a93f03d and d37f103 we changed the compiler and ngBind to add debugging CSS classes (i.e. ng-scope, ng-binding) in linking function. This simplified the code and made sense under the original assumptions that the debug info will be disabled by default. That is however not the case - debug info is enabled by default.
When debug info is enabled, this change improves the largetable-bp
benchmark by ~580ms, that is 30% faster.
Measuring the “create” phase, 25 loops, meantime ~1920ms -> ~1340ms.
This change does not affect performance when debug info is disabled.
`$$addScopeInfo` used to accept either DOM Node or jqLite/jQuery
wrapper. This commit simplifies the method to always require
jqLite/jQuery wrapper and thus remove the `element.data` condition which
was wrong. If `element` was a raw comment element, the `data` property
was a string (the value of the comment) and an exception was thrown.
We run unit tests in “strict” mode and thus can’t monkey-patch `window.location` nor `window.location.reload`. In order to avoid full page reload, we could pass location as argument, or another level of indirection, something like this:
```js
var ourGlobalFunkyLocation = window.location;
function reloadWithDebugInfo() {
window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;
ourGlobalFunkyLocation.reload();
}
// in the test
ourGlobalFunkyLocation = {
reload: function() {}
};
reloadWithDebugInfo();
ourGlobalFunkyLocation = window.location;
```
I don’t think any of these make sense, just so that we can test setting `window.name`. If the `reloadWithDebugInfo` function was more complicated, I would do it.
I don’t think it’s worthy to confuse production code with extra logic which purpose was only to make testing possible.
The compiler adds scope information (`ng-scope` CSS class and `$scope` data property) to elements
when the are bound to the scope. This is mostly to aid debugging tools such as Batarang. In
production this should be unnecesary and adds a performance penalty.
In the bench/apps/largetable-bp this change caused an improvement of ~100ms (7%).
This can be now disabled by calling `$compileProvider.debugInfoEnabled(false)`
in a module `config` block:
```
someModule.config(['$compileProvider', function($compileProvider) {
$compileProvider.debugInfoEnabled(false);
}]);
```
In the bench/apps/largetable-bp benchmark this change, with debug info disabled,
improved by ~120ms, that is ~10%.
Measuring the "create" phase, 25 loops, mean time ~1200ms -> ~1080ms.
The compiler and ngBind directives add binding information (`ng-binding`
CSS class and `$binding` data property) to elements when they are bound to
the scope. This is only to aid testing and debugging for tools such as
Protractor and Batarang. In production this is unnecessary and add a
performance penalty.
This can be now disabled by calling `$compileProvider.debugInfoEnabled(false)`
in a module `config` block:
```
someModule.config(['$compileProvider', function($compileProvider) {
$compileProvider.debugInfoEnabled(false);
}]);
```
In the bench/apps/largetable-bp benchmark this change, with debug info disabled,
improved by ~140ms, that is 10%.
Measuring the "create" phase, 25 loops, mean time ~1340ms -> ~1200ms.
We were storing the whole `interpolationFn` in the `$binding` data on
elements but this function was bringing a lot of closure variables with it
and so was consuming unwanted amounts of memory.
Now we are only storing the parsed interpolation expressions from the
binding (i.e. the values of `interpolationFn.expressions`).
BREAKING CHANGE:
The value of `$binding` data property on an element is always an array now
and the expressions do not include the curly braces `{{ ... }}`.
Prior to this fix when an Angular application is bootstrapped it would only
place an animation guard to prevent animations from running when the application
starts for the first two digest cycles. However, if any controllers or directives,
that are executed upon boostrap, trigger any remote code to be downloaded (via $http)
then the guard does not put that into consideration. This fix now properly addresses
that circumstance and removes the guard once all outbound HTTP requests are complete
when an Angular application is bootstrapped.
Closes#8275Closes#5262
This handy service is designed to download and cache template contents
and to throw an error when a template request fails.
BREAKING CHANGE
Angular will now throw a $compile minErr each a template fails to download
for ngView, directives and ngMessage template requests. This changes the former
behavior of silently ignoring failed HTTP requests--or when the template itself
is empty. Please ensure that all directive, ngView and ngMessage code now properly
addresses this scenario. NgInclude is uneffected from this change.
When multiple responses are received within a short window from each other, it can be wasteful to
perform full dirty-checking cycles for each individual response. In order to prevent this, it is
now possible to coalesce calls to $apply for responses which occur close together.
This behaviour is opt-in, and the default is disabled, in order to avoid breaking tests or
applications.
In order to activate coalesced apply in tests or in an application, simply perform the following
steps during configuration.
angular.module('myFancyApp', []).
config(function($httpProvider) {
$httpProvider.useApplyAsync(true);
});
OR:
angular.mock.module(function($httpProvider) {
$httpProvider.useApplyAsync(true);
});
Closes#8736Closes#7634Closes#5297
It is now possible to queue up multiple expressions to be evaluated in a single digest using
$applyAsync. The asynchronous expressions will be evaluated either 1) the next time $apply or
$rootScope.$digest is called, or 2) after after the queue flushing scheduled for the next turn
occurs (roughly ~10ms depending on browser and application).
This commit introduces a 2nd validation queue called `$asyncValidators`. Each time a value
is processed by the validation pipeline, if all synchronous `$validators` succeed, the value
is then passed through the `$asyncValidators` validation queue. These validators should return
a promise. Rejection of a validation promise indicates a failed validation.
With this commit, ngModel will now handle parsing first and then validation
afterwards once the parsing is successful. If any parser along the way returns
`undefined` then ngModel will break the chain of parsing and register a
a parser error represented by the type of input that is being collected
(e.g. number, date, datetime, url, etc...). If a parser fails for a standard
text input field then an error of `parse` will be placed on `model.$error`.
BREAKING CHANGE
Any parser code from before that returned an `undefined` value
(or nothing at all) will now cause a parser failure. When this occurs
none of the validators present in `$validators` will run until the parser
error is gone.
we now store both the object type and the id as the hashkey and return it for all objects.
for primitives we still have to do string concatination because we can't use expandos on them to
store the hashkey
The HTML5 spec allows to use seconds for `input[time]` and `input[datetime-local]`,
even though they are not displayed by all browsers.
Related to #8447.
Angular used to always use the browser timezone when parsing
`input[date]`, `input[time]`, … The timezone can now be changed
to `UTC` via `ngModelOptions`.
Closes#8447.
BREAKING CHANGE:
According to the HTML5 spec `input[time]` should create dates
based on the year 1970 (used to be based on the year 1900).
Related to #8447.
Angular used to always use the browser timezone for
`dateFilter`. An additional parameter was added to allow to use
`UTC` timezone instead.
Related to #8447.
In some cases, the type of Error thrown by minErr is meaningful, such as in $q where a TypeError
is sometimes required. This fix allows providing an error constructor as the second argument to
minErr, which will be used to construct the error that gets returned by the factory function.
When transition-delay and animation-delay were used to drive the staggering
animation the result was unpredictable at times due to the browser not being
able to register the generated delay styles in time. This caused a hard to
track down bug that didn't have a solid solution when styles were being used.
This fix ensures that stagger delays are handled by the $timeout service.
Closes#7228Closes#7547Closes#8297Closes#8547
BREAKING CHANGE
If any stagger code consisted of having BOTH transition staggers and delay staggers
together then that will not work the same way. Angular will now instead choose
the highest stagger delay value and set the timeout to wait for that before
applying the active CSS class.
The $animate service (both the service inside of ng and ngAnimate) now
makes use of promises instead of callback functions.
BREAKING CHANGE
Both the API for the cancallation method and the done callback for
$animate animations is different. Instead of using a callback function
for each of the $animate animation methods, a promise is used instead.
```js
//before
$animate.enter(element, container, null, callbackFn);
//after
$animate.enter(element, container).then(callbackFn);
```
The animation can now be cancelled via `$animate.cancel(promise)`.
```js
//before
var cancelFn = $animate.enter(element, container);
cancelFn(); //cancels the animation
//after
var promise = $animate.enter(element, container);
$animate.cancel(promise); //cancels the animation
```
All class-based animation methods (addClass, removeClass and setClass) on $animate
are now processed after the next digest occurs. This fix prevents any sequencing
errors from occuring from excessive calls to $animate.addClass, $animate.remoteClass
or $animate.setClass.
BREAKING CHANGE
$animate.addClass, $animate.removeClass and $animate.setClass will no longer start the animation
right after being called in the directive code. The animation will only commence once a digest
has passed. This means that all animation-related testing code requires an extra digest to kick
off the animation.
```js
//before this fix
$animate.addClass(element, 'super');
expect(element).toHaveClass('super');
//now
$animate.addClass(element, 'super');
$rootScope.$digest();
expect(element).toHaveClass('super');
```
$animate will also tally the amount of times classes are added and removed and only animate
the left over classes once the digest kicks in. This means that for any directive code that
adds and removes the same CSS class on the same element then this may result in no animation
being triggered at all.
```js
$animate.addClass(element, 'klass');
$animate.removeClass(element, 'klass');
$rootScope.$digest();
//nothing happens...
```
createInternalInjector does not specify the formal parameter `strictDi`, and instead uses the binding
from the parent function's formal parameters, making this parameter unnecessary.
Closes#8771
Also changes the wording to include the word "escaped" and "escape", which may help users find the
information they're looking for via searching. (ノ◕ヮ◕)ノ*:・゚✧
Closes#8770
11f5aeeee9 changed the compiler to use 'EA' as a 'restrict'
value if not specified in the directive object, and the directive guide needed some slight
changes to address this.
Closes#8769