Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a2ac5f53a | |||
| 21deaf637a | |||
| 72e15a3a83 | |||
| 174cb4a8c8 | |||
| 33f769b0a1 | |||
| c8abf20558 | |||
| 6dbb183e75 | |||
| bc4844d3b2 | |||
| 708f8b47de | |||
| 5518126d42 | |||
| 5fe73fdc3a | |||
| 394c496bf2 | |||
| 8e1aeba715 | |||
| 0e6e7eb477 | |||
| 183f636816 | |||
| 5f8ed63f2a | |||
| e4f3c94e31 | |||
| 1e5cbcbd93 | |||
| dcf3ec160f | |||
| a7beb5b6d3 | |||
| 1d3b65adc2 | |||
| d528644fe3 | |||
| 6f1bcfc14e | |||
| 996914c6b0 | |||
| fff048d099 | |||
| dcb0da8225 | |||
| b664e20d12 | |||
| 3d68b95028 | |||
| 163aca336d |
+245
-21
@@ -1,3 +1,130 @@
|
||||
<a name="1.6.1"></a>
|
||||
# 1.6.1 promise-rectification (2016-12-23)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
- **$q:** Add traceback to unhandled promise rejections
|
||||
([174cb4](https://github.com/angular/angular.js/commit/174cb4a8c81e25581da5b452c2bb43b0fa377a9b)
|
||||
[#14631](https://github.com/angular/angular.js/issues/14631))
|
||||
- **$$cookieReader:** correctly handle forbidden access to `document.cookie`
|
||||
([33f769](https://github.com/angular/angular.js/commit/33f769b0a1214055c16fb59adad4897bf53d62bf)
|
||||
[#15523](https://github.com/angular/angular.js/issues/15523))
|
||||
- **ngOptions:** do not unset the `selected` property unless necessary
|
||||
([bc4844](https://github.com/angular/angular.js/commit/bc4844d3b297d80aecef89aa1b32615024decedc)
|
||||
[#15477](https://github.com/angular/angular.js/issues/15477))
|
||||
- **ngModelOptions:** work correctly when on the template of `replace` directives
|
||||
([5f8ed6](https://github.com/angular/angular.js/commit/5f8ed63f2ab02ffb9c21bf9c29d27c851d162e26)
|
||||
[#15492](https://github.com/angular/angular.js/issues/15492))
|
||||
- **ngClassOdd/Even:** add/remove the correct classes when expression/`$index` change simultaneously
|
||||
([d52864](https://github.com/angular/angular.js/commit/d528644fe3e9ffd43999e7fc67806059f9e1083e))
|
||||
- **jqLite:** silently ignore `after()` if element has no parent
|
||||
([3d68b9](https://github.com/angular/angular.js/commit/3d68b9502848ff6714ef89bfb95b8e70ae34eff6)
|
||||
[#15331](https://github.com/angular/angular.js/issues/15331),
|
||||
[#15475](https://github.com/angular/angular.js/issues/15475))
|
||||
- **$rootScope:** when adding/removing watchers during $digest
|
||||
([163aca](https://github.com/angular/angular.js/commit/163aca336d7586a45255787af41b14b2a12361dd)
|
||||
[#15422](https://github.com/angular/angular.js/issues/15422))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
- **ngClass:** avoid unnecessary `.data()` accesses, deep-watching and copies
|
||||
([1d3b65](https://github.com/angular/angular.js/commit/1d3b65adc2c22ff662159ef910089cf10d1edb7b)
|
||||
[#14404](https://github.com/angular/angular.js/issues/14404))
|
||||
|
||||
|
||||
|
||||
<a name="1.5.10"></a>
|
||||
# 1.5.10 asynchronous-synchronization (2016-12-15)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
- **$compile:**
|
||||
- don't throw tplrt error when there is whitespace around a top-level comment
|
||||
([12752f](https://github.com/angular/angular.js/commit/12752f66ac425ab38a5ee574a4bfbf3516adc42c)
|
||||
[#15108](https://github.com/angular/angular.js/issues/15108))
|
||||
- clean up `@`-binding observers when re-assigning bindings
|
||||
([f3cb6e](https://github.com/angular/angular.js/commit/f3cb6e309aa1f676e5951ac745fa886d3581c2f4)
|
||||
[#15268](https://github.com/angular/angular.js/issues/15268))
|
||||
- set attribute value even if `ngAttr*` contains no interpolation
|
||||
([229799](https://github.com/angular/angular.js/commit/22979904fb754c59e9f6ee5d8763e3b8de0e18c2)
|
||||
[#15133](https://github.com/angular/angular.js/issues/15133))
|
||||
- `bindToController` should work without `controllerAs`
|
||||
([944989](https://github.com/angular/angular.js/commit/9449893763a4fd95ee8ff78b53c6966a874ec9ae)
|
||||
[#15088](https://github.com/angular/angular.js/issues/15088))
|
||||
- do not overwrite values set in `$onInit()` for `<`-bound literals
|
||||
([07e1ba](https://github.com/angular/angular.js/commit/07e1ba365fb5e8a049be732bd7b62f71e0aa1672)
|
||||
[#15118](https://github.com/angular/angular.js/issues/15118))
|
||||
- avoid calling `$onChanges()` twice for `NaN` initial values
|
||||
([0cf5be](https://github.com/angular/angular.js/commit/0cf5be52642f7e9d81a708b3005042eac6492572))
|
||||
- **$location:** prevent infinite digest with IDN urls in Edge
|
||||
([4bf892](https://github.com/angular/angular.js/commit/4bf89218130d434771089fdfe643490b8d2ee259)
|
||||
[#15217](https://github.com/angular/angular.js/issues/15217))
|
||||
- **$rootScope:** correctly handle adding/removing watchers during `$digest`
|
||||
([a9708d](https://github.com/angular/angular.js/commit/a9708de84b50f06eacda33834d5bbdfc97c97f37)
|
||||
[#15422](https://github.com/angular/angular.js/issues/15422))
|
||||
- **$sce:** fix `adjustMatcher` to replace multiple `*` and `**`
|
||||
([78eecb](https://github.com/angular/angular.js/commit/78eecb43dbb0500358d333aea8955bd0646a7790))
|
||||
- **jqLite:** silently ignore `after()` if element has no parent
|
||||
([77ed85](https://github.com/angular/angular.js/commit/77ed85bcd3be057a5a79231565ac7accc6d644c6)
|
||||
[#15331](https://github.com/angular/angular.js/issues/15331))
|
||||
- **input[radio]:** use non-strict comparison for checkedness
|
||||
([593a50](https://github.com/angular/angular.js/commit/593a5034841b3b7661d3bcbdd06b7a9d0876fd34))
|
||||
- **select, ngOptions:**
|
||||
- let `ngValue` take precedence over option text with multiple interpolations
|
||||
([5b7ec8](https://github.com/angular/angular.js/commit/5b7ec8c84e88ee08aacaf9404853eda0016093f5)
|
||||
[#15413](https://github.com/angular/angular.js/issues/15413))
|
||||
- don't add comment nodes as empty options
|
||||
([1d29c9](https://github.com/angular/angular.js/commit/1d29c91c3429de96e4103533752700d1266741be)
|
||||
[#15454](https://github.com/angular/angular.js/issues/15454))
|
||||
- **ngClassOdd/Even:** add/remove the correct classes when expression/`$index` change simultaneously
|
||||
([e3d020](https://github.com/angular/angular.js/commit/e3d02070ab8a02c818dcc5114db6fba9d3f385d6))
|
||||
- **$sanitize:** reduce stack height in IE <= 11
|
||||
([862dc2](https://github.com/angular/angular.js/commit/862dc2532f8126a4a71fd3d957884ba6f11f591c)
|
||||
[#14928](https://github.com/angular/angular.js/issues/14928))
|
||||
- **ngMock/$controller:** respect `$compileProvider.preAssignBindingsEnabled()`
|
||||
([75c83f](https://github.com/angular/angular.js/commit/75c83ff3195931859a099f7a95bf81d32abf2eb3))
|
||||
|
||||
|
||||
## New Features
|
||||
- **bootstrap:** do not bootstrap from unknown schemes with a different origin
|
||||
([bdeb33](https://github.com/angular/angular.js/commit/bdeb3392a8719131ab2b993f2a881c43a2860f92)
|
||||
[#15428](https://github.com/angular/angular.js/issues/15428))
|
||||
- **$anchorScroll:** convert numeric hash targets to string
|
||||
([a52640](https://github.com/angular/angular.js/commit/a5264090b66ad0cf9a93de84bb7b307868c0edef)
|
||||
[#14680](https://github.com/angular/angular.js/issues/14680))
|
||||
- **$compile:**
|
||||
- add `preAssignBindingsEnabled` option
|
||||
([f86576](https://github.com/angular/angular.js/commit/f86576def44005f180a66e3aa12d6cc73c1ac72c))
|
||||
- throw error when directive name or factory function is invalid
|
||||
([5c9399](https://github.com/angular/angular.js/commit/5c9399d18ae5cd79e6cf6fc4377d66df00f6fcc7)
|
||||
[#15056](https://github.com/angular/angular.js/issues/15056))
|
||||
- **$controller:** throw when requested controller is not registered
|
||||
([9ae793](https://github.com/angular/angular.js/commit/9ae793d8a69afe84370b601e07fc375fc18a576a)
|
||||
[#14980](https://github.com/angular/angular.js/issues/14980))
|
||||
- **$location:** add support for selectively rewriting links based on attribute
|
||||
([a4a222](https://github.com/angular/angular.js/commit/a4a22266f127d3b9a6818e6f4754f048e253f693))
|
||||
- **$resource:** pass `status`/`statusText` to success callbacks
|
||||
([a8da25](https://github.com/angular/angular.js/commit/a8da25c74d2c1f6265f0fafd95bf72c981d9d678)
|
||||
[#8341](https://github.com/angular/angular.js/issues/8841)
|
||||
[#8841](https://github.com/angular/angular.js/issues/8841))
|
||||
- **ngSwitch:** allow multiple case matches via optional attribute `ngSwitchWhenSeparator`
|
||||
([0e1651](https://github.com/angular/angular.js/commit/0e1651bfd28ba73ebd0e4943d85af48c4506e02c)
|
||||
[#3410](https://github.com/angular/angular.js/issues/3410)
|
||||
[#3516](https://github.com/angular/angular.js/issues/3516))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
- **all:** don't trigger digests after enter/leave of structural directives
|
||||
([c57779](https://github.com/angular/angular.js/commit/c57779d8725493c5853dceda0105dafd5c0e3a7c)
|
||||
[#15322](https://github.com/angular/angular.js/issues/15322))
|
||||
- **$compile:** validate `directive.restrict` property on directive init
|
||||
([31d464](https://github.com/angular/angular.js/commit/31d464feef38b1cc950da6c8dccd0f194ebfc68b))
|
||||
- **ngOptions:** avoid calls to `element.value`
|
||||
([e269ad](https://github.com/angular/angular.js/commit/e269ad1244bc50fee9218f7c18fab3e9ab063aab))
|
||||
- **jqLite:** move bind/unbind definitions out of the loop
|
||||
([7717b9](https://github.com/angular/angular.js/commit/7717b96e950a5916a5f12fd611c73d3b06a8d717))
|
||||
|
||||
|
||||
<a name="1.6.0"></a>
|
||||
# 1.6.0 rainbow-tsunami (2016-12-08)
|
||||
|
||||
@@ -8,9 +135,15 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
- **ngModelOptions:** allow options to be inherited from ancestor `ngModelOptions`
|
||||
([296cfc](https://github.com/angular/angular.js/commit/296cfce40c25e9438bfa46a0eb27240707a10ffa),
|
||||
[#10922](https://github.com/angular/angular.js/issues/10922))
|
||||
- **$compile:** set `preAssignBindingsEnabled` to false by default
|
||||
([bcd0d4](https://github.com/angular/angular.js/commit/bcd0d4d896d0dfdd988ff4f849c1d40366125858),
|
||||
[#15352](https://github.com/angular/angular.js/issues/15352))
|
||||
- **$compile:**
|
||||
- add `preAssignBindingsEnabled` option
|
||||
([dfb8cf](https://github.com/angular/angular.js/commit/dfb8cf6402678206132e5bc603764d21e0f986ef))
|
||||
- set `preAssignBindingsEnabled` to false by default
|
||||
([bcd0d4](https://github.com/angular/angular.js/commit/bcd0d4d896d0dfdd988ff4f849c1d40366125858),
|
||||
[#15352](https://github.com/angular/angular.js/issues/15352))
|
||||
- throw error when directive name or factory function is invalid
|
||||
([53a3bf](https://github.com/angular/angular.js/commit/53a3bf6634600c3aeff092eacc35edf399b27aec)
|
||||
[#15056](https://github.com/angular/angular.js/issues/15056))
|
||||
- **jqLite:**
|
||||
- implement `jqLite(f)` as an alias to `jqLite(document).ready(f)`
|
||||
([369fb7](https://github.com/angular/angular.js/commit/369fb7f4f73664bcdab0350701552d8bef6f605e))
|
||||
@@ -38,6 +171,9 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
- JSONP requests now require a trusted resource URL
|
||||
([6476af](https://github.com/angular/angular.js/commit/6476af83cd0418c84e034a955b12a842794385c4),
|
||||
[#11352](https://github.com/angular/angular.js/issues/11352))
|
||||
- **$anchorScroll:** convert numeric hash targets to string
|
||||
([9062ba](https://github.com/angular/angular.js/commit/9062bae05c002934fe7bfd76043dcc3de9acfde6)
|
||||
[#14680](https://github.com/angular/angular.js/issues/14680))
|
||||
- **select:** support values of any type added with `ngValue`
|
||||
([f02b70](https://github.com/angular/angular.js/commit/f02b707b5e4a5ffd1e1a20d910754cfabfc19622),
|
||||
[#9842](https://github.com/angular/angular.js/issues/9842))
|
||||
@@ -51,6 +187,10 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
[#10597](https://github.com/angular/angular.js/issues/10597))
|
||||
- allow `ngTrim` to work for `input[type=radio]`
|
||||
([47724b](https://github.com/angular/angular.js/commit/47724baffe050269385b3481e9a9cf4ab3944b4b))
|
||||
- **ngSwitch:** allow multiple case matches via optional attribute `ngSwitchWhenSeparator`
|
||||
([0b221](https://github.com/angular/angular.js/commit/0b22173000596bf4b78f6a90083b994d46164d79)
|
||||
[#3410](https://github.com/angular/angular.js/issues/3410)
|
||||
[#3516](https://github.com/angular/angular.js/issues/3516))
|
||||
- **$interpolate:** use custom `toString()` function if present
|
||||
([a5fd2e](https://github.com/angular/angular.js/commit/a5fd2e4c0376676fa317e09a8d8be4966b82cbfe),
|
||||
[#7317](https://github.com/angular/angular.js/issues/7317),
|
||||
@@ -66,18 +206,30 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
([c9dffd](https://github.com/angular/angular.js/commit/c9dffde1cb167660120753181cb6d01dc1d1b3d0),
|
||||
[#13653](https://github.com/angular/angular.js/issues/13653),
|
||||
[#7992](https://github.com/angular/angular.js/issues/7992))
|
||||
- **$location:** default hashPrefix to `'!'`
|
||||
([aa077e](https://github.com/angular/angular.js/commit/aa077e81129c740041438688dff2e8d20c3d7b52),
|
||||
[#13812](https://github.com/angular/angular.js/issues/13812))
|
||||
- **$resource:** pass `status`/`statusText` to success callbacks
|
||||
([e3a378](https://github.com/angular/angular.js/commit/e3a378e7a329f60f6b48517f83a4f4c9efecb056)
|
||||
[#8341](https://github.com/angular/angular.js/issues/8841)
|
||||
[#8841](https://github.com/angular/angular.js/issues/8841))
|
||||
- **$location:**
|
||||
- default hashPrefix to `'!'`
|
||||
([aa077e](https://github.com/angular/angular.js/commit/aa077e81129c740041438688dff2e8d20c3d7b52)
|
||||
[#13812](https://github.com/angular/angular.js/issues/13812))
|
||||
- add support for selectively rewriting links based on attribute
|
||||
([3d686a](https://github.com/angular/angular.js/commit/3d686a988dc4373da094cff6905e5b0d8da6afa4))
|
||||
- **$controller:** throw when requested controller is not registered
|
||||
([eacfe4](https://github.com/angular/angular.js/commit/eacfe4148eb97e550117ed7fd3c37b58537a9f64)
|
||||
[#14980](https://github.com/angular/angular.js/issues/14980))
|
||||
|
||||
|
||||
|
||||
## Security Related
|
||||
- Please read the [Sandbox Removal Blog Post](http://angularjs.blogspot.com/2016/09/angular-16-expression-sandbox-removal.html).
|
||||
- **bootstrap:** explicitly whitelist URL schemes for bootstrap. (#15427)
|
||||
([7f1b8b](https://github.com/angular/angular.js/commit/7f1b8bdfe1043871c5ead2ec602efc41e0de5e53))
|
||||
- **bootstrap:**
|
||||
- explicitly whitelist URL schemes for bootstrap.
|
||||
([7f1b8b](https://github.com/angular/angular.js/commit/7f1b8bdfe1043871c5ead2ec602efc41e0de5e53))
|
||||
- do not bootstrap from unknown schemes with a different origin
|
||||
([465d17](https://github.com/angular/angular.js/commit/465d1734559ca4a7f4aa24387060f88fcc53ecb1))
|
||||
([465d17](https://github.com/angular/angular.js/commit/465d1734559ca4a7f4aa24387060f88fcc53ecb1)
|
||||
[#15428](https://github.com/angular/angular.js/issues/15428))
|
||||
- **$compile:**
|
||||
- secure `link[href]` as a `RESOURCE_URL`s in `$sce`
|
||||
([04cad4](https://github.com/angular/angular.js/commit/04cad41d26ebaf44b5ee0c29a152d61f235f3efa),
|
||||
@@ -87,14 +239,18 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
- **$sce:** fix `adjustMatcher` to replace multiple '*' and '**' (#7897)
|
||||
- **$sce:** fix `adjustMatcher` to replace multiple `*` and `**`
|
||||
([991a2b](https://github.com/angular/angular.js/commit/991a2b30e00aed1d312e29555e356a795f9e3d62))
|
||||
- **ngModelOptions:** handle debounce of `updateOn` triggers that are not in debounce list
|
||||
([789790](https://github.com/angular/angular.js/commit/789790feee4d6c5b1f5d5b18ecb0ccf6edd36fb3))
|
||||
- **ngMock/$controller:** respect `$compileProvider.preAssignBindingsEnabled()`
|
||||
([7d9a79](https://github.com/angular/angular.js/commit/7d9a791c6a8c80d29d6c84afa287c81f2a307439))
|
||||
- **$location:** throw if the path starts with double (back)slashes
|
||||
([4aa953](https://github.com/angular/angular.js/commit/4aa9534b0fea732d6492a2863c3ee7e077c8d004))
|
||||
- **$location:**
|
||||
- prevent infinite digest with IDN URLs in Edge
|
||||
([705afc](https://github.com/angular/angular.js/commit/705afcd160c8428133b36f2cd63db305dc52f2d7)
|
||||
[#15217](https://github.com/angular/angular.js/issues/15217))
|
||||
- throw if the path starts with double (back)slashes
|
||||
([4aa953](https://github.com/angular/angular.js/commit/4aa9534b0fea732d6492a2863c3ee7e077c8d004))
|
||||
- **core:** do not auto-bootstrap when loaded from an extension.
|
||||
([0ff10e](https://github.com/angular/angular.js/commit/0ff10e1b56c6b7c4ac465e35c96a5886e294bac5))
|
||||
- **input[radio]:** use strict comparison when evaluating checked-ness
|
||||
@@ -124,6 +280,20 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
- don't throw tplrt error when there is a whitespace around a top-level comment
|
||||
([76d3da](https://github.com/angular/angular.js/commit/76d3dafdeaf2f343d094b5a34ffb74adf64bb284),
|
||||
[#15108](https://github.com/angular/angular.js/issues/15108))
|
||||
- clean up `@`-binding observers when re-assigning bindings
|
||||
([586e2a](https://github.com/angular/angular.js/commit/586e2acb269016a0fee66ac33f4a385f631afad0)
|
||||
[#15268](https://github.com/angular/angular.js/issues/15268))
|
||||
- set attribute value even if `ngAttr*` contains no interpolation
|
||||
([3fe3da](https://github.com/angular/angular.js/commit/3fe3da8794571a1479d884be26a621f06cdb7842)
|
||||
[#15133](https://github.com/angular/angular.js/issues/15133))
|
||||
- `bindToController` should work without `controllerAs`
|
||||
([16dcce](https://github.com/angular/angular.js/commit/16dccea8873b06285d4ec6eb3bb8e96ccbd3b64e)
|
||||
[#15088](https://github.com/angular/angular.js/issues/15088))
|
||||
- do not overwrite values set in `$onInit()` for `<`-bound literals
|
||||
([a1bdff](https://github.com/angular/angular.js/commit/a1bdffa12f82e838dee5492956b380df7e54cdf9)
|
||||
[#15118](https://github.com/angular/angular.js/issues/15118))
|
||||
- avoid calling `$onChanges()` twice for `NaN` initial values
|
||||
([7d7efb](https://github.com/angular/angular.js/commit/7d7efbf545c8c07713eb45301660dcfca4121445))
|
||||
- disallow linking the same element more than once
|
||||
([1e1fbc](https://github.com/angular/angular.js/commit/1e1fbc75f5e20e8541f517a5cf6f30f8f2eed53f))
|
||||
- correctly merge consecutive text nodes on IE11
|
||||
@@ -136,14 +306,14 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
[#5513](https://github.com/angular/angular.js/issues/5513),
|
||||
[#5597](https://github.com/angular/angular.js/issues/5597))
|
||||
- move check for interpolation of on-event attributes to compile time
|
||||
([b89c21](https://github.com/angular/angular.js/commit/b89c2181a9a165e06c027390164e08635ec449f4),
|
||||
[#13267](https://github.com/angular/angular.js/issues/13267))
|
||||
([b89c21](https://github.com/angular/angular.js/commit/b89c2181a9a165e06c027390164e08635ec449f4),
|
||||
[#13267](https://github.com/angular/angular.js/issues/13267))
|
||||
- **select, ngOptions, ngValue:**
|
||||
- don't add comment nodes as empty options
|
||||
([245b27](https://github.com/angular/angular.js/commit/245b27101aad129061585252b73652054319ca82),
|
||||
[#15454](https://github.com/angular/angular.js/issues/15454))
|
||||
- do not throw when removing the element (e.g. via `ngIf`)
|
||||
([7a667c](https://github.com/angular/angular.js/commit/7a667c77e36f2b1738425a9cfb52d48bb9d8220f))
|
||||
([7a667c](https://github.com/angular/angular.js/commit/7a667c77e36f2b1738425a9cfb52d48bb9d8220f))
|
||||
- add/remove selected attribute for selected/unselected options
|
||||
([c75698](https://github.com/angular/angular.js/commit/c75698df55f5a026bcd7fcecbb9d4ff0bc3ebc3e))
|
||||
- don't register options when select has no ngModel
|
||||
@@ -158,7 +328,7 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
([e6afca](https://github.com/angular/angular.js/commit/e6afca00c9061a3e13b570796ca3ab428c1723a1),
|
||||
[#14031](https://github.com/angular/angular.js/issues/14031))
|
||||
- **$resource:**
|
||||
- **$resource:** allow params in `hostname` (except for IPv6 addresses)
|
||||
- allow params in `hostname` (except for IPv6 addresses)
|
||||
([752b1e](https://github.com/angular/angular.js/commit/752b1e69b7a8e9c0b908f1980e9c738888f3647c),
|
||||
[#14542](https://github.com/angular/angular.js/issues/14542))
|
||||
- fulfill promise with the correct value on error
|
||||
@@ -202,6 +372,9 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
- **loader:** `module.decorator` order of operations is now irrelevant
|
||||
([6a2ebd](https://github.com/angular/angular.js/commit/6a2ebdba5df27e789e3cb10f11eedf90f7b9b97e),
|
||||
[#12382](https://github.com/angular/angular.js/issues/12382))
|
||||
- **$sanitize:** reduce stack height in IE <= 11
|
||||
([45129c](https://github.com/angular/angular.js/commit/45129cfd06104bd89f469dded9ccbaf20894bd76)
|
||||
[#14928](https://github.com/angular/angular.js/issues/14928))
|
||||
- **ngAnimate:** make svg elements work with `classNameFilter`
|
||||
([81bf7e](https://github.com/angular/angular.js/commit/81bf7ed73ee67f9eb997da869c52839449ca02b3))
|
||||
|
||||
@@ -221,8 +394,11 @@ consolidating all the changes shown in the previous 1.6.0 release candidates.**
|
||||
([d71dc2](https://github.com/angular/angular.js/commit/d71dc2f5afec230711351e9f160873a41eb60597))
|
||||
- **injector:** cache the results of the native class detection check
|
||||
([5ceb5d](https://github.com/angular/angular.js/commit/5ceb5dbfa6d9b6d15232a1f5c767b2f431325948))
|
||||
- **$compile:** use strict comparison for `controller === '@'`
|
||||
([bbd3db](https://github.com/angular/angular.js/commit/bbd3db14f857aab996ad129f2f15ca6348e9fd9f))
|
||||
- **$compile:**
|
||||
- use strict comparison for `controller === '@'`
|
||||
([bbd3db](https://github.com/angular/angular.js/commit/bbd3db14f857aab996ad129f2f15ca6348e9fd9f))
|
||||
- validate `directive.restrict` property on directive init
|
||||
([11f273](https://github.com/angular/angular.js/commit/11f2731f72e932615e8ce15e6a73f4ac808cc7e7))
|
||||
- **$parse:**
|
||||
- Inline constants
|
||||
([bd7d5f](https://github.com/angular/angular.js/commit/bd7d5f6345439aa2d1da708ffee20b4c565131d4))
|
||||
@@ -1595,6 +1771,7 @@ Please read the [Sandbox Removal Blog Post](http://angularjs.blogspot.com/2016/0
|
||||
- **ngModel:** treat synchronous validators as boolean always ([7bc71a](https://github.com/angular/angular.js/commit/7bc71adc63bb6bb609b44dd2d3ea8fb0cd3f300b) [#14734](https://github.com/angular/angular.js/issues/14734))
|
||||
- **$q:** treat thrown errors as regular rejections ([e13eea](https://github.com/angular/angular.js/commit/e13eeabd7e34a78becec06cfbe72c23f2dcb85f9) [#3174](https://github.com/angular/angular.js/issues/3174) [#15213](https://github.com/angular/angular.js/issues/15213))
|
||||
- **ngTransclude:** use fallback content if only whitespace is provided ([32aa7e](https://github.com/angular/angular.js/commit/32aa7e7395527624119e3917c54ee43b4d219301) [#15077](https://github.com/angular/angular.js/issues/15077))
|
||||
- **$location:** prevent infinite digest with IDN URLs in Edge ([705afc](https://github.com/angular/angular.js/commit/705afcd160c8428133b36f2cd63db305dc52f2d7) [#15217](https://github.com/angular/angular.js/issues/15217))
|
||||
- **$compile:**
|
||||
- don't throw tplrt error when there is a whitespace around a top-level comment ([76d3da](https://github.com/angular/angular.js/commit/76d3dafdeaf2f343d094b5a34ffb74adf64bb284) [#15108](https://github.com/angular/angular.js/issues/15108))
|
||||
- disallow linking the same element more than once ([1e1fbc](https://github.com/angular/angular.js/commit/1e1fbc75f5e20e8541f517a5cf6f30f8f2eed53f))
|
||||
@@ -1604,6 +1781,20 @@ Please read the [Sandbox Removal Blog Post](http://angularjs.blogspot.com/2016/0
|
||||
- don't add leading white-space in attributes for a specific merge case ([305ba1](https://github.com/angular/angular.js/commit/305ba1a3fb3529cb3fdf04c12ac03fbb4f634456))
|
||||
- don't trim white-space in attributes ([97bbf8](https://github.com/angular/angular.js/commit/97bbf86a1979d099802f0d631c17c54b87563b40) [#5513](https://github.com/angular/angular.js/issues/5513) [#5597](https://github.com/angular/angular.js/issues/5597))
|
||||
- move check for interpolation of on-event attributes to compile time ([b89c21](https://github.com/angular/angular.js/commit/b89c2181a9a165e06c027390164e08635ec449f4) [#13267](https://github.com/angular/angular.js/issues/13267))
|
||||
- clean up `@`-binding observers when re-assigning bindings
|
||||
([586e2a](https://github.com/angular/angular.js/commit/586e2acb269016a0fee66ac33f4a385f631afad0)
|
||||
[#15268](https://github.com/angular/angular.js/issues/15268))
|
||||
- set attribute value even if `ngAttr*` contains no interpolation
|
||||
([3fe3da](https://github.com/angular/angular.js/commit/3fe3da8794571a1479d884be26a621f06cdb7842)
|
||||
[#15133](https://github.com/angular/angular.js/issues/15133))
|
||||
- `bindToController` should work without `controllerAs`
|
||||
([16dcce](https://github.com/angular/angular.js/commit/16dccea8873b06285d4ec6eb3bb8e96ccbd3b64e)
|
||||
[#15088](https://github.com/angular/angular.js/issues/15088))
|
||||
- do not overwrite values set in `$onInit()` for `<`-bound literals
|
||||
([a1bdff](https://github.com/angular/angular.js/commit/a1bdffa12f82e838dee5492956b380df7e54cdf9)
|
||||
[#15118](https://github.com/angular/angular.js/issues/15118))
|
||||
- avoid calling `$onChanges()` twice for `NaN` initial values
|
||||
([7d7efb](https://github.com/angular/angular.js/commit/7d7efbf545c8c07713eb45301660dcfca4121445))
|
||||
- **select:**
|
||||
- add/remove selected attribute for selected/unselected options ([c75698](https://github.com/angular/angular.js/commit/c75698df55f5a026bcd7fcecbb9d4ff0bc3ebc3e))
|
||||
- don't register options when select has no ngModel ([e8c2e1](https://github.com/angular/angular.js/commit/e8c2e119758e58e18fe43932d09a8ff9f506aa9d))
|
||||
@@ -1627,6 +1818,9 @@ Please read the [Sandbox Removal Blog Post](http://angularjs.blogspot.com/2016/0
|
||||
- **ngMock/$httpBackend:** fail if a url is provided but is `undefined` ([7551b8](https://github.com/angular/angular.js/commit/7551b8975a91ee286cc2cf4af5e78f924533575e) [#8442](https://github.com/angular/angular.js/issues/8442) [#10934](https://github.com/angular/angular.js/issues/10934))
|
||||
- **$route:** don't process route change controllers and templates for `redirectTo` routes ([7f4b35](https://github.com/angular/angular.js/commit/7f4b356c2bebb87f0c26b57a20415b004b20bcd1) [#3332](https://github.com/angular/angular.js/issues/3332))
|
||||
- **loader:** `module.decorator` order of operations is now irrelevant ([6a2ebd](https://github.com/angular/angular.js/commit/6a2ebdba5df27e789e3cb10f11eedf90f7b9b97e) [#12382](https://github.com/angular/angular.js/issues/12382))
|
||||
- **$sanitize:** reduce stack height in IE <= 11
|
||||
([45129c](https://github.com/angular/angular.js/commit/45129cfd06104bd89f469dded9ccbaf20894bd76)
|
||||
[#14928](https://github.com/angular/angular.js/issues/14928))
|
||||
- **ngAnimate:** make svg elements work with `classNameFilter` ([81bf7e](https://github.com/angular/angular.js/commit/81bf7ed73ee67f9eb997da869c52839449ca02b3))
|
||||
|
||||
|
||||
@@ -1637,21 +1831,46 @@ Please read the [Sandbox Removal Blog Post](http://angularjs.blogspot.com/2016/0
|
||||
- don't remove a boolean attribute for `.attr(attrName, '')` ([3faf45](https://github.com/angular/angular.js/commit/3faf4505732758165083c9d21de71fa9b6983f4a))
|
||||
- remove the attribute for `.attr(attribute, null)` ([4e3624](https://github.com/angular/angular.js/commit/4e3624552284d0e725bf6262b2e468cd2c7682fa))
|
||||
- return `[]` for `.val()` on `<select multiple>` with no selection ([d882fd](https://github.com/angular/angular.js/commit/d882fde2e532216e7cf424495db1ccb5be1789f8))
|
||||
- **$compile:**
|
||||
- add `preAssignBindingsEnabled` option
|
||||
([dfb8cf](https://github.com/angular/angular.js/commit/dfb8cf6402678206132e5bc603764d21e0f986ef))
|
||||
- throw error when directive name or factory function is invalid
|
||||
([53a3bf](https://github.com/angular/angular.js/commit/53a3bf6634600c3aeff092eacc35edf399b27aec)
|
||||
[#15056](https://github.com/angular/angular.js/issues/15056))
|
||||
- **$http:**
|
||||
- remove deprecated callback methods: `success()/error()` ([b54a39](https://github.com/angular/angular.js/commit/b54a39e2029005e0572fbd2ac0e8f6a4e5d69014))
|
||||
- JSONP callback must be specified by `jsonpCallbackParam` config ([fb6634](https://github.com/angular/angular.js/commit/fb663418710736161a6b5da49c345e92edf58dcb) [#15161](https://github.com/angular/angular.js/issues/15161) [#11352](https://github.com/angular/angular.js/issues/11352))
|
||||
- JSONP requests now require a trusted resource URL ([6476af](https://github.com/angular/angular.js/commit/6476af83cd0418c84e034a955b12a842794385c4) [#11352](https://github.com/angular/angular.js/issues/11352))
|
||||
- **$anchorScroll:** convert numeric hash targets to string
|
||||
([9062ba](https://github.com/angular/angular.js/commit/9062bae05c002934fe7bfd76043dcc3de9acfde6)
|
||||
[#14680](https://github.com/angular/angular.js/issues/14680))
|
||||
- **ngModelOptions:** allow options to be inherited from ancestor `ngModelOptions` ([87a2ff](https://github.com/angular/angular.js/commit/87a2ff76af5d0a9268d8eb84db5755077d27c84c) [#10922](https://github.com/angular/angular.js/issues/10922))
|
||||
- **input:**
|
||||
- add support for binding to `input[type=range]` ([913016](https://github.com/angular/angular.js/commit/9130166767c4792c5d32d08a918fc7becf32c9a6) [#5892](https://github.com/angular/angular.js/issues/5892) [#14870](https://github.com/angular/angular.js/issues/14870))
|
||||
- add support for `step` to `input[type=number]` ([e1da4be](https://github.com/angular/angular.js/commit/e1da4bed8e291003d485a8ad346ab80bed8ae2e3) [#10597](https://github.com/angular/angular.js/issues/10597))
|
||||
- allow `ngTrim` to work for `input[type=radio]` ([47724b](https://github.com/angular/angular.js/commit/47724baffe050269385b3481e9a9cf4ab3944b4b))
|
||||
- **ngSwitch:** allow multiple case matches via optional attribute `ngSwitchWhenSeparator`
|
||||
([0b221](https://github.com/angular/angular.js/commit/0b22173000596bf4b78f6a90083b994d46164d79)
|
||||
[#3410](https://github.com/angular/angular.js/issues/3410)
|
||||
[#3516](https://github.com/angular/angular.js/issues/3516))
|
||||
- **ngRoute:** allow `ngView` to be included in an asynchronously loaded template ([c13c66](https://github.com/angular/angular.js/commit/c13c666728c1a1485ef18e92d7cb35118ce39609) [#1213](https://github.com/angular/angular.js/issues/1213))
|
||||
- **select:** support values of any type added with `ngValue` ([f02b70](https://github.com/angular/angular.js/commit/f02b707b5e4a5ffd1e1a20d910754cfabfc19622) [#9842](https://github.com/angular/angular.js/issues/9842))
|
||||
- **$interpolate:** use custom `toString()` function if present ([a5fd2e](https://github.com/angular/angular.js/commit/a5fd2e4c0376676fa317e09a8d8be4966b82cbfe) [#7317](https://github.com/angular/angular.js/issues/7317) [#11406](https://github.com/angular/angular.js/issues/11406))
|
||||
- **$route:** implement `resolveRedirectTo` ([e98656](https://github.com/angular/angular.js/commit/e9865654b39c71be71034c38581a8c7bd16bc716) [#5150](https://github.com/angular/angular.js/issues/5150))
|
||||
- **$q:** report promises with non rejection callback ([c9dffd](https://github.com/angular/angular.js/commit/c9dffde1cb167660120753181cb6d01dc1d1b3d0) [#13653](https://github.com/angular/angular.js/issues/13653) [#7992](https://github.com/angular/angular.js/issues/7992))
|
||||
- **$location:** default hashPrefix to `'!'` ([aa077e](https://github.com/angular/angular.js/commit/aa077e81129c740041438688dff2e8d20c3d7b52) [#13812](https://github.com/angular/angular.js/issues/13812))
|
||||
- **$resource:** pass `status`/`statusText` to success callbacks
|
||||
([e3a378](https://github.com/angular/angular.js/commit/e3a378e7a329f60f6b48517f83a4f4c9efecb056)
|
||||
[#8341](https://github.com/angular/angular.js/issues/8841)
|
||||
[#8841](https://github.com/angular/angular.js/issues/8841))
|
||||
- **$location:**
|
||||
- default hashPrefix to `'!'`
|
||||
([aa077e](https://github.com/angular/angular.js/commit/aa077e81129c740041438688dff2e8d20c3d7b52)
|
||||
[#13812](https://github.com/angular/angular.js/issues/13812))
|
||||
- add support for selectively rewriting links based on attribute
|
||||
([3d686a](https://github.com/angular/angular.js/commit/3d686a988dc4373da094cff6905e5b0d8da6afa4))
|
||||
- **$controller:** throw when requested controller is not registered
|
||||
([eacfe4](https://github.com/angular/angular.js/commit/eacfe4148eb97e550117ed7fd3c37b58537a9f64)
|
||||
[#14980](https://github.com/angular/angular.js/issues/14980))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
@@ -1660,7 +1879,11 @@ Please read the [Sandbox Removal Blog Post](http://angularjs.blogspot.com/2016/0
|
||||
- **$animate:** listen for document visibility changes ([d71dc2](https://github.com/angular/angular.js/commit/d71dc2f5afec230711351e9f160873a41eb60597))
|
||||
- **injector:** cache the results of the native class detection check ([5ceb5d](https://github.com/angular/angular.js/commit/5ceb5dbfa6d9b6d15232a1f5c767b2f431325948))
|
||||
- **$parse:** Inline constants ([bd7d5f](https://github.com/angular/angular.js/commit/bd7d5f6345439aa2d1da708ffee20b4c565131d4))
|
||||
- **$compile:** use strict comparison for `controller === '@'` ([bbd3db](https://github.com/angular/angular.js/commit/bbd3db14f857aab996ad129f2f15ca6348e9fd9f))
|
||||
- **$compile:**
|
||||
- use strict comparison for `controller === '@'`
|
||||
([bbd3db](https://github.com/angular/angular.js/commit/bbd3db14f857aab996ad129f2f15ca6348e9fd9f))
|
||||
- validate `directive.restrict` property on directive init
|
||||
([11f273](https://github.com/angular/angular.js/commit/11f2731f72e932615e8ce15e6a73f4ac808cc7e7))
|
||||
- **$parse:** remove Angular expression sandbox ([1547c7](https://github.com/angular/angular.js/commit/1547c751aa48efe7dbefef701c3df5983b04aa2e) [#15094](https://github.com/angular/angular.js/issues/15094))
|
||||
|
||||
|
||||
@@ -4273,6 +4496,7 @@ support asynchronous loading of resources.)
|
||||
|
||||
- **$compile:** Lazily compile the `transclude` function
|
||||
([652b83eb](https://github.com/angular/angular.js/commit/652b83eb226131d131a44453520a569202aa4aac))
|
||||
See https://github.com/angular/angular.js/issues/14343#issuecomment-229037252 for more information.
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
@@ -14710,7 +14934,7 @@ with the `$route` service
|
||||
|
||||
### Docs
|
||||
- rewrite of several major portions of angular.service.*, angular.Array.*, angular.Object.* docs
|
||||
- added support for [sitemap]((http://docs.angularjs.org/sitemap.xml) to make the docs indexable by
|
||||
- added support for [sitemap](http://docs.angularjs.org/sitemap.xml) to make the docs indexable by
|
||||
search crawlers
|
||||
- transition of Developer Guide docs from the wiki into docs.angularjs.org
|
||||
- lots of improvements related to formatting of the content of docs.anguarjs.org
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
'use strict';
|
||||
|
||||
var app = angular.module('ngClassBenchmark', []);
|
||||
|
||||
app.controller('DataController', function DataController($scope) {
|
||||
|
||||
this.init = function() {
|
||||
this.numberOfTodos = 1000;
|
||||
this.implementation = 'tableOptimized';
|
||||
this.completedPeriodicity = 3;
|
||||
this.importantPeriodicity = 13;
|
||||
this.urgentPeriodicity = 29;
|
||||
|
||||
this.createTodos(100);
|
||||
this.setTodosValuesWithSeed(0);
|
||||
};
|
||||
|
||||
this.clearTodos = function() {
|
||||
this.todos = null;
|
||||
};
|
||||
|
||||
this.createTodos = function(count) {
|
||||
var i;
|
||||
this.todos = [];
|
||||
for (i = 0; i < count; i++) {
|
||||
this.todos.push({
|
||||
id: i + 1,
|
||||
completed: false,
|
||||
important: false,
|
||||
urgent: false
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.setTodosValuesWithSeed = function(offset) {
|
||||
var i, todo;
|
||||
for (i = 0; i < this.todos.length; i++) {
|
||||
todo = this.todos[i];
|
||||
todo.completed = 0 === (i + offset) % this.completedPeriodicity;
|
||||
todo.important = 0 === (i + offset) % this.importantPeriodicity;
|
||||
todo.urgent = 0 === (i + offset) % this.urgentPeriodicity;
|
||||
}
|
||||
};
|
||||
|
||||
this.init();
|
||||
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'setup',
|
||||
fn: function() {
|
||||
$scope.$apply();
|
||||
this.clearTodos();
|
||||
this.createTodos(this.numberOfTodos);
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'create',
|
||||
fn: function() {
|
||||
// initialize data for first time that will construct the DOM
|
||||
this.setTodosValuesWithSeed(0);
|
||||
$scope.$apply();
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: '$apply',
|
||||
fn: function() {
|
||||
$scope.$apply();
|
||||
}
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'update',
|
||||
fn: function() {
|
||||
// move everything but completed
|
||||
this.setTodosValuesWithSeed(3);
|
||||
$scope.$apply();
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'unclass',
|
||||
fn: function() {
|
||||
// remove all classes
|
||||
this.setTodosValuesWithSeed(NaN);
|
||||
$scope.$apply();
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'class',
|
||||
fn: function() {
|
||||
// add all classes as the initial state
|
||||
this.setTodosValuesWithSeed(0);
|
||||
$scope.$apply();
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'destroy',
|
||||
fn: function() {
|
||||
this.clearTodos();
|
||||
$scope.$apply();
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/* eslint-env node */
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
scripts: [{
|
||||
id: 'angular',
|
||||
src: '/build/angular.js'
|
||||
},
|
||||
{
|
||||
src: 'app.js'
|
||||
}]
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,177 @@
|
||||
<style>
|
||||
.gold {
|
||||
background: gold;
|
||||
}
|
||||
.silver {
|
||||
background: silver;
|
||||
}
|
||||
.table tbody tr > td.success {
|
||||
background-color: #dff0d8;
|
||||
}
|
||||
|
||||
.table tbody tr > td.error {
|
||||
background-color: #f2dede;
|
||||
}
|
||||
|
||||
.table tbody tr > td.warning {
|
||||
background-color: #fcf8e3;
|
||||
}
|
||||
|
||||
.table tbody tr > td.info {
|
||||
background-color: #d9edf7;
|
||||
}
|
||||
.completed {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.important {
|
||||
font-weight: bold;
|
||||
}
|
||||
.urgent {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
<div ng-app="ngClassBenchmark" ng-cloak class="container-fluid">
|
||||
<div ng-controller="DataController as benchmark" class="row">
|
||||
<div class="col-lg-12">
|
||||
|
||||
<div class="well">
|
||||
<h3>Parameters</h3>
|
||||
|
||||
<br>
|
||||
<p>
|
||||
<label>Number of todos</label><br>
|
||||
<input type="number" ng-model="benchmark.numberOfTodos">
|
||||
</p>
|
||||
|
||||
<br>
|
||||
<p>
|
||||
<label>Implementation</label><br>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input ng-model="benchmark.implementation" value="tableOptimized"
|
||||
type="radio" name="implementation">
|
||||
Table optimized <br>
|
||||
<code>ng-class="todo.completed && 'success'"</code>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input ng-model="benchmark.implementation" value="table"
|
||||
type="radio" name="implementation">
|
||||
Table <br>
|
||||
<code>ng-class="{success: todo.completed}"</code>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input ng-model="benchmark.implementation" value="list"
|
||||
type="radio" name="implementation">
|
||||
List <br>
|
||||
<code>ng-class="{completed: todo.completed, urgent: todo.urgent, important: todo.important"}</code>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input ng-model="benchmark.implementation" value="singleOptimized"
|
||||
type="radio" name="implementation">
|
||||
Single ngClass optimized <br>
|
||||
<code>
|
||||
ng-class="{'panel-success': !!benchmark.todos, 'panel-danger': !benchmark.todos}"
|
||||
</code>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input ng-model="benchmark.implementation" value="single"
|
||||
type="radio" name="implementation">
|
||||
Single ngClass <br>
|
||||
<code>
|
||||
ng-class="{'panel-success': benchmark.todos, 'panel-danger': !benchmark.todos}"
|
||||
</code>
|
||||
</label>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<h3>Example</h3>
|
||||
<div ng-switch="benchmark.implementation">
|
||||
|
||||
<table ng-switch-when="tableOptimized" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>todo #id</th>
|
||||
<th>completed?</th>
|
||||
<th>urgent?</th>
|
||||
<th>important?</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="todo in benchmark.todos track by todo.id"
|
||||
ng-class="todo.completed && 'active'"
|
||||
ng-class-even="todo.completed && todo.important && 'gold'"
|
||||
ng-class-odd="todo.completed && todo.important && 'silver'"
|
||||
>
|
||||
<td>#{{todo.id}}</td>
|
||||
<td>{{todo.completed}}</td>
|
||||
<td ng-class="todo.urgent && 'danger'">{{todo.urgent}}</td>
|
||||
<td ng-class="todo.important && 'success'">{{todo.important}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table ng-switch-when="table" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>todo #id</th>
|
||||
<th>completed?</th>
|
||||
<th>urgent?</th>
|
||||
<th>important?</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="todo in benchmark.todos track by todo.id"
|
||||
ng-class="{active: todo.completed}"
|
||||
ng-class-even="{gold: todo.completed && todo.important}"
|
||||
ng-class-odd="{silver: todo.completed && todo.important}"
|
||||
>
|
||||
<td>#{{todo.id}}</td>
|
||||
<td>{{todo.completed}}</td>
|
||||
<td ng-class="{danger: todo.urgent}">{{todo.urgent}}</td>
|
||||
<td ng-class="{success: todo.important}">{{todo.important}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<ul ng-switch-when="list">
|
||||
<li ng-repeat="todo in benchmark.todos track by todo.id"
|
||||
ng-class="{
|
||||
completed: todo.completed,
|
||||
urgent: todo.urgent,
|
||||
important: todo.important
|
||||
}">#{{todo.id}}</li>
|
||||
</ul>
|
||||
|
||||
<div ng-switch-when="singleOptimized"
|
||||
class="panel"
|
||||
ng-class="{'panel-success': !!benchmark.todos, 'panel-danger': !benchmark.todos}">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Information</h3>
|
||||
</div>
|
||||
<div class="panel-body"> The title is green because there are todos... </div>
|
||||
</div>
|
||||
|
||||
<div ng-switch-when="single"
|
||||
class="panel"
|
||||
ng-class="{'panel-success': benchmark.todos, 'panel-danger': !benchmark.todos}">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Information</h3>
|
||||
</div>
|
||||
<div class="panel-body"> The title is green because there are todos... </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br><br><br>
|
||||
@@ -159,10 +159,11 @@ angular.module('examples', [])
|
||||
|
||||
};
|
||||
|
||||
// Initialize the example data, so it's ready when clicking the open button.
|
||||
// Otherwise pop-up blockers will prevent a new window from opening
|
||||
ctrl.prepareExampleData(ctrl.example.path);
|
||||
|
||||
ctrl.$onInit = function() {
|
||||
// Initialize the example data, so it's ready when clicking the open button.
|
||||
// Otherwise pop-up blockers will prevent a new window from opening
|
||||
ctrl.prepareExampleData(ctrl.example.path);
|
||||
};
|
||||
}]
|
||||
};
|
||||
}])
|
||||
|
||||
@@ -119,7 +119,8 @@ You can find a larger list of Angular external libraries at [ngmodules.org](http
|
||||
### Books
|
||||
* [AngularJS Directives](http://www.amazon.com/AngularJS-Directives-Alex-Vanston/dp/1783280336) by Alex Vanston
|
||||
* [AngularJS Essentials (Free eBook)](https://www.packtpub.com/packt/free-ebook/angularjs-essentials) by Rodrigo Branas
|
||||
* [AngularJS : Novice to Ninja](http://www.amazon.in/AngularJS-Novice-Ninja-Sandeep-Panda/dp/0992279453) by Sandeep Panda
|
||||
* [AngularJS in Action](https://www.manning.com/books/angularjs-in-action) by Lukas Ruebbelke
|
||||
* [AngularJS: Novice to Ninja](http://www.amazon.in/AngularJS-Novice-Ninja-Sandeep-Panda/dp/0992279453) by Sandeep Panda
|
||||
* [AngularJS UI Development](http://www.amazon.com/AngularJS-UI-Development-Amit-Ghart-ebook/dp/B00OXVAK7A) by Amit Gharat and Matthias Nehlsen
|
||||
* [AngularJS: Up and Running](http://www.amazon.com/AngularJS-Running-Enhanced-Productivity-Structured/dp/1491901942) by Brad Green and Shyam Seshadri
|
||||
* [Developing an AngularJS Edge](http://www.amazon.com/Developing-AngularJS-Edge-Christopher-Hiller-ebook/dp/B00CJLFF8K) by Christopher Hiller
|
||||
|
||||
@@ -28,8 +28,8 @@ for other directives to augment its behavior.
|
||||
<form novalidate class="simple-form">
|
||||
<label>Name: <input type="text" ng-model="user.name" /></label><br />
|
||||
<label>E-mail: <input type="email" ng-model="user.email" /></label><br />
|
||||
Gender: <label><input type="radio" ng-model="user.gender" value="male" />male</label>
|
||||
<label><input type="radio" ng-model="user.gender" value="female" />female</label><br />
|
||||
Best Editor: <label><input type="radio" ng-model="user.preference" value="vi" />vi</label>
|
||||
<label><input type="radio" ng-model="user.preference" value="emacs" />emacs</label><br />
|
||||
<input type="button" ng-click="reset()" value="Reset" />
|
||||
<input type="submit" ng-click="update(user)" value="Save" />
|
||||
</form>
|
||||
|
||||
@@ -88,7 +88,8 @@ commits for more info.
|
||||
|
||||
- **jqLite** is more aligned to jQuery 3, which required the following changes
|
||||
(see [details](guide/migration#migrate1.5to1.6-ng-misc-jqLite) below):
|
||||
- Keys passed to `.data()` and `.css()` are now camelCased in the same as jQuery does it.
|
||||
- Keys passed to `.data()` and `.css()` are now camelCased in the same way as the jQuery methods
|
||||
do.
|
||||
- Setting boolean attributes to empty string no longer removes the attribute.
|
||||
- Calling `.val()` on a multiple select will always return an array, even if no option is
|
||||
selected.
|
||||
|
||||
@@ -194,7 +194,7 @@ angular.module('phonecatApp', [
|
||||
```
|
||||
|
||||
Now, in addition to the core services and directives, we can also configure the `$route` service
|
||||
(using it's provider) for our application. In order to be able to quickly locate the configuration
|
||||
(using its provider) for our application. In order to be able to quickly locate the configuration
|
||||
code, we put it into a separate file and used the `.config` suffix.
|
||||
|
||||
<br />
|
||||
|
||||
@@ -173,7 +173,10 @@ angular.module('phoneList', ['core.phone']);
|
||||
**`app/phone-detail/phone-detail.module.js`:**
|
||||
|
||||
```js
|
||||
angular.module('phoneDetail', ['core.phone']);
|
||||
angular.module('phoneDetail', [
|
||||
'ngRoute',
|
||||
'core.phone'
|
||||
]);
|
||||
```
|
||||
|
||||
<br />
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "angularjs",
|
||||
"license": "MIT",
|
||||
"branchVersion": "^1.5.8",
|
||||
"branchVersion": "^1.6.0",
|
||||
"branchPattern": "1.6.*",
|
||||
"distTag": "latest",
|
||||
"repository": {
|
||||
@@ -26,7 +26,7 @@
|
||||
"browserstacktunnel-wrapper": "^1.4.2",
|
||||
"canonical-path": "0.0.2",
|
||||
"changez": "^2.1.1",
|
||||
"changez-angular": "^2.1.0",
|
||||
"changez-angular": "^2.1.2",
|
||||
"cheerio": "^0.17.0",
|
||||
"commitizen": "^2.3.0",
|
||||
"cross-spawn": "^4.0.0",
|
||||
|
||||
+8
-5
@@ -979,12 +979,15 @@ forEach({
|
||||
|
||||
after: function(element, newElement) {
|
||||
var index = element, parent = element.parentNode;
|
||||
newElement = new JQLite(newElement);
|
||||
|
||||
for (var i = 0, ii = newElement.length; i < ii; i++) {
|
||||
var node = newElement[i];
|
||||
parent.insertBefore(node, index.nextSibling);
|
||||
index = node;
|
||||
if (parent) {
|
||||
newElement = new JQLite(newElement);
|
||||
|
||||
for (var i = 0, ii = newElement.length; i < ii; i++) {
|
||||
var node = newElement[i];
|
||||
parent.insertBefore(node, index.nextSibling);
|
||||
index = node;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -14,6 +14,14 @@ function $$CookieReader($document) {
|
||||
var lastCookies = {};
|
||||
var lastCookieString = '';
|
||||
|
||||
function safeGetCookie(rawDocument) {
|
||||
try {
|
||||
return rawDocument.cookie || '';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function safeDecodeURIComponent(str) {
|
||||
try {
|
||||
return decodeURIComponent(str);
|
||||
@@ -24,7 +32,7 @@ function $$CookieReader($document) {
|
||||
|
||||
return function() {
|
||||
var cookieArray, cookie, i, index, name;
|
||||
var currentCookieString = rawDocument.cookie || '';
|
||||
var currentCookieString = safeGetCookie(rawDocument);
|
||||
|
||||
if (currentCookieString !== lastCookieString) {
|
||||
lastCookieString = currentCookieString;
|
||||
|
||||
+144
-95
@@ -8,51 +8,71 @@
|
||||
|
||||
function classDirective(name, selector) {
|
||||
name = 'ngClass' + name;
|
||||
return ['$animate', function($animate) {
|
||||
var indexWatchExpression;
|
||||
|
||||
return ['$parse', function($parse) {
|
||||
return {
|
||||
restrict: 'AC',
|
||||
link: function(scope, element, attr) {
|
||||
var oldVal;
|
||||
var expression = attr[name].trim();
|
||||
var isOneTime = (expression.charAt(0) === ':') && (expression.charAt(1) === ':');
|
||||
|
||||
scope.$watch(attr[name], ngClassWatchAction, true);
|
||||
var watchInterceptor = isOneTime ? toFlatValue : toClassString;
|
||||
var watchExpression = $parse(expression, watchInterceptor);
|
||||
var watchAction = isOneTime ? ngClassOneTimeWatchAction : ngClassWatchAction;
|
||||
|
||||
attr.$observe('class', function(value) {
|
||||
ngClassWatchAction(scope.$eval(attr[name]));
|
||||
});
|
||||
var classCounts = element.data('$classCounts');
|
||||
var oldModulo = true;
|
||||
var oldClassString;
|
||||
|
||||
|
||||
if (name !== 'ngClass') {
|
||||
scope.$watch('$index', function($index, old$index) {
|
||||
/* eslint-disable no-bitwise */
|
||||
var mod = $index & 1;
|
||||
if (mod !== (old$index & 1)) {
|
||||
var classes = arrayClasses(scope.$eval(attr[name]));
|
||||
if (mod === selector) {
|
||||
addClasses(classes);
|
||||
} else {
|
||||
removeClasses(classes);
|
||||
}
|
||||
}
|
||||
/* eslint-enable */
|
||||
});
|
||||
}
|
||||
|
||||
function addClasses(classes) {
|
||||
var newClasses = digestClassCounts(classes, 1);
|
||||
attr.$addClass(newClasses);
|
||||
}
|
||||
|
||||
function removeClasses(classes) {
|
||||
var newClasses = digestClassCounts(classes, -1);
|
||||
attr.$removeClass(newClasses);
|
||||
}
|
||||
|
||||
function digestClassCounts(classes, count) {
|
||||
if (!classCounts) {
|
||||
// Use createMap() to prevent class assumptions involving property
|
||||
// names in Object.prototype
|
||||
var classCounts = element.data('$classCounts') || createMap();
|
||||
classCounts = createMap();
|
||||
element.data('$classCounts', classCounts);
|
||||
}
|
||||
|
||||
if (name !== 'ngClass') {
|
||||
if (!indexWatchExpression) {
|
||||
indexWatchExpression = $parse('$index', function moduloTwo($index) {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return $index & 1;
|
||||
});
|
||||
}
|
||||
|
||||
scope.$watch(indexWatchExpression, ngClassIndexWatchAction);
|
||||
}
|
||||
|
||||
scope.$watch(watchExpression, watchAction, isOneTime);
|
||||
|
||||
function addClasses(classString) {
|
||||
classString = digestClassCounts(split(classString), 1);
|
||||
attr.$addClass(classString);
|
||||
}
|
||||
|
||||
function removeClasses(classString) {
|
||||
classString = digestClassCounts(split(classString), -1);
|
||||
attr.$removeClass(classString);
|
||||
}
|
||||
|
||||
function updateClasses(oldClassString, newClassString) {
|
||||
var oldClassArray = split(oldClassString);
|
||||
var newClassArray = split(newClassString);
|
||||
|
||||
var toRemoveArray = arrayDifference(oldClassArray, newClassArray);
|
||||
var toAddArray = arrayDifference(newClassArray, oldClassArray);
|
||||
|
||||
var toRemoveString = digestClassCounts(toRemoveArray, -1);
|
||||
var toAddString = digestClassCounts(toAddArray, 1);
|
||||
|
||||
attr.$addClass(toAddString);
|
||||
attr.$removeClass(toRemoveString);
|
||||
}
|
||||
|
||||
function digestClassCounts(classArray, count) {
|
||||
var classesToUpdate = [];
|
||||
forEach(classes, function(className) {
|
||||
|
||||
forEach(classArray, function(className) {
|
||||
if (count > 0 || classCounts[className]) {
|
||||
classCounts[className] = (classCounts[className] || 0) + count;
|
||||
if (classCounts[className] === +(count > 0)) {
|
||||
@@ -60,77 +80,106 @@ function classDirective(name, selector) {
|
||||
}
|
||||
}
|
||||
});
|
||||
element.data('$classCounts', classCounts);
|
||||
|
||||
return classesToUpdate.join(' ');
|
||||
}
|
||||
|
||||
function updateClasses(oldClasses, newClasses) {
|
||||
var toAdd = arrayDifference(newClasses, oldClasses);
|
||||
var toRemove = arrayDifference(oldClasses, newClasses);
|
||||
toAdd = digestClassCounts(toAdd, 1);
|
||||
toRemove = digestClassCounts(toRemove, -1);
|
||||
if (toAdd && toAdd.length) {
|
||||
$animate.addClass(element, toAdd);
|
||||
function ngClassIndexWatchAction(newModulo) {
|
||||
// This watch-action should run before the `ngClass[OneTime]WatchAction()`, thus it
|
||||
// adds/removes `oldClassString`. If the `ngClass` expression has changed as well, the
|
||||
// `ngClass[OneTime]WatchAction()` will update the classes.
|
||||
if (newModulo === selector) {
|
||||
addClasses(oldClassString);
|
||||
} else {
|
||||
removeClasses(oldClassString);
|
||||
}
|
||||
if (toRemove && toRemove.length) {
|
||||
$animate.removeClass(element, toRemove);
|
||||
|
||||
oldModulo = newModulo;
|
||||
}
|
||||
|
||||
function ngClassOneTimeWatchAction(newClassValue) {
|
||||
var newClassString = toClassString(newClassValue);
|
||||
|
||||
if (newClassString !== oldClassString) {
|
||||
ngClassWatchAction(newClassString);
|
||||
}
|
||||
}
|
||||
|
||||
function ngClassWatchAction(newVal) {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
if (selector === true || (scope.$index & 1) === selector) {
|
||||
var newClasses = arrayClasses(newVal || []);
|
||||
if (!oldVal) {
|
||||
addClasses(newClasses);
|
||||
} else if (!equals(newVal,oldVal)) {
|
||||
var oldClasses = arrayClasses(oldVal);
|
||||
updateClasses(oldClasses, newClasses);
|
||||
}
|
||||
}
|
||||
if (isArray(newVal)) {
|
||||
oldVal = newVal.map(function(v) { return shallowCopy(v); });
|
||||
} else {
|
||||
oldVal = shallowCopy(newVal);
|
||||
function ngClassWatchAction(newClassString) {
|
||||
if (oldModulo === selector) {
|
||||
updateClasses(oldClassString, newClassString);
|
||||
}
|
||||
|
||||
oldClassString = newClassString;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function arrayDifference(tokens1, tokens2) {
|
||||
var values = [];
|
||||
|
||||
outer:
|
||||
for (var i = 0; i < tokens1.length; i++) {
|
||||
var token = tokens1[i];
|
||||
for (var j = 0; j < tokens2.length; j++) {
|
||||
if (token === tokens2[j]) continue outer;
|
||||
}
|
||||
values.push(token);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
function arrayClasses(classVal) {
|
||||
var classes = [];
|
||||
if (isArray(classVal)) {
|
||||
forEach(classVal, function(v) {
|
||||
classes = classes.concat(arrayClasses(v));
|
||||
});
|
||||
return classes;
|
||||
} else if (isString(classVal)) {
|
||||
return classVal.split(' ');
|
||||
} else if (isObject(classVal)) {
|
||||
forEach(classVal, function(v, k) {
|
||||
if (v) {
|
||||
classes = classes.concat(k.split(' '));
|
||||
}
|
||||
});
|
||||
return classes;
|
||||
}
|
||||
return classVal;
|
||||
}
|
||||
}];
|
||||
|
||||
// Helpers
|
||||
function arrayDifference(tokens1, tokens2) {
|
||||
if (!tokens1 || !tokens1.length) return [];
|
||||
if (!tokens2 || !tokens2.length) return tokens1;
|
||||
|
||||
var values = [];
|
||||
|
||||
outer:
|
||||
for (var i = 0; i < tokens1.length; i++) {
|
||||
var token = tokens1[i];
|
||||
for (var j = 0; j < tokens2.length; j++) {
|
||||
if (token === tokens2[j]) continue outer;
|
||||
}
|
||||
values.push(token);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function split(classString) {
|
||||
return classString && classString.split(' ');
|
||||
}
|
||||
|
||||
function toClassString(classValue) {
|
||||
var classString = classValue;
|
||||
|
||||
if (isArray(classValue)) {
|
||||
classString = classValue.map(toClassString).join(' ');
|
||||
} else if (isObject(classValue)) {
|
||||
classString = Object.keys(classValue).
|
||||
filter(function(key) { return classValue[key]; }).
|
||||
join(' ');
|
||||
}
|
||||
|
||||
return classString;
|
||||
}
|
||||
|
||||
function toFlatValue(classValue) {
|
||||
var flatValue = classValue;
|
||||
|
||||
if (isArray(classValue)) {
|
||||
flatValue = classValue.map(toFlatValue);
|
||||
} else if (isObject(classValue)) {
|
||||
var hasUndefined = false;
|
||||
|
||||
flatValue = Object.keys(classValue).filter(function(key) {
|
||||
var value = classValue[key];
|
||||
|
||||
if (!hasUndefined && isUndefined(value)) {
|
||||
hasUndefined = true;
|
||||
}
|
||||
|
||||
return value;
|
||||
});
|
||||
|
||||
if (hasUndefined) {
|
||||
// Prevent the `oneTimeLiteralWatchInterceptor` from unregistering
|
||||
// the watcher, by including at least one `undefined` value.
|
||||
flatValue.push(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
return flatValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -331,19 +331,27 @@ defaultModelOptions = new ModelOptions({
|
||||
*
|
||||
*/
|
||||
var ngModelOptionsDirective = function() {
|
||||
NgModelOptionsController.$inject = ['$attrs', '$scope'];
|
||||
function NgModelOptionsController($attrs, $scope) {
|
||||
this.$$attrs = $attrs;
|
||||
this.$$scope = $scope;
|
||||
}
|
||||
NgModelOptionsController.prototype = {
|
||||
$onInit: function() {
|
||||
var parentOptions = this.parentCtrl ? this.parentCtrl.$options : defaultModelOptions;
|
||||
var modelOptionsDefinition = this.$$scope.$eval(this.$$attrs.ngModelOptions);
|
||||
|
||||
this.$options = parentOptions.createChild(modelOptionsDefinition);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
// ngModelOptions needs to run before ngModel and input directives
|
||||
priority: 10,
|
||||
require: ['ngModelOptions', '?^^ngModelOptions'],
|
||||
controller: function NgModelOptionsController() {},
|
||||
link: {
|
||||
pre: function ngModelOptionsPreLinkFn(scope, element, attrs, ctrls) {
|
||||
var optionsCtrl = ctrls[0];
|
||||
var parentOptions = ctrls[1] ? ctrls[1].$options : defaultModelOptions;
|
||||
optionsCtrl.$options = parentOptions.createChild(scope.$eval(attrs.ngModelOptions));
|
||||
}
|
||||
}
|
||||
require: {parentCtrl: '?^^ngModelOptions'},
|
||||
bindToController: true,
|
||||
controller: NgModelOptionsController
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -505,17 +505,17 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
|
||||
|
||||
} else {
|
||||
|
||||
selectCtrl.writeValue = function writeNgOptionsMultiple(value) {
|
||||
options.items.forEach(function(option) {
|
||||
option.element.selected = false;
|
||||
});
|
||||
selectCtrl.writeValue = function writeNgOptionsMultiple(values) {
|
||||
// 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.
|
||||
|
||||
if (value) {
|
||||
value.forEach(function(item) {
|
||||
var option = options.getOptionFromViewValue(item);
|
||||
if (option) option.element.selected = true;
|
||||
});
|
||||
}
|
||||
var selectedOptions = values && values.map(getAndUpdateSelectedOption) || [];
|
||||
|
||||
options.items.forEach(function(option) {
|
||||
if (option.element.selected && !includes(selectedOptions, option)) {
|
||||
option.element.selected = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -605,6 +605,14 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
|
||||
updateOptionElement(option, optionElement);
|
||||
}
|
||||
|
||||
function getAndUpdateSelectedOption(viewValue) {
|
||||
var option = options.getOptionFromViewValue(viewValue);
|
||||
var element = option && option.element;
|
||||
|
||||
if (element && !element.selected) element.selected = true;
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
function updateOptionElement(option, element) {
|
||||
option.element = element;
|
||||
|
||||
+2
-1
@@ -33,7 +33,8 @@ function $IntervalProvider() {
|
||||
* appropriate moment. See the example below for more details on how and when to do this.
|
||||
* </div>
|
||||
*
|
||||
* @param {function()} fn A function that should be called repeatedly.
|
||||
* @param {function()} fn A function that should be called repeatedly. If no additional arguments
|
||||
* are passed (see below), the function is called with the current iteration count.
|
||||
* @param {number} delay Number of milliseconds between each function call.
|
||||
* @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
|
||||
* indefinitely.
|
||||
|
||||
+6
-1
@@ -239,6 +239,7 @@ function $QProvider() {
|
||||
*
|
||||
* @description
|
||||
* Retrieves or overrides whether to generate an error when a rejected promise is not handled.
|
||||
* This feature is enabled by default.
|
||||
*
|
||||
* @param {boolean=} value Whether to generate an error when a rejected promise is not handled.
|
||||
* @returns {boolean|ng.$qProvider} Current value when called without a new value or self for
|
||||
@@ -380,7 +381,11 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
|
||||
if (!toCheck.pur) {
|
||||
toCheck.pur = true;
|
||||
var errorMessage = 'Possibly unhandled rejection: ' + toDebugString(toCheck.value);
|
||||
exceptionHandler(errorMessage);
|
||||
if (toCheck.value instanceof Error) {
|
||||
exceptionHandler(toCheck.value, errorMessage);
|
||||
} else {
|
||||
exceptionHandler(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-5
@@ -416,15 +416,21 @@ function $RootScopeProvider() {
|
||||
|
||||
if (!array) {
|
||||
array = scope.$$watchers = [];
|
||||
array.$$digestWatchIndex = -1;
|
||||
}
|
||||
// we use unshift since we use a while loop in $digest for speed.
|
||||
// the while loop reads in reverse order.
|
||||
array.unshift(watcher);
|
||||
array.$$digestWatchIndex++;
|
||||
incrementWatchersCount(this, 1);
|
||||
|
||||
return function deregisterWatch() {
|
||||
if (arrayRemove(array, watcher) >= 0) {
|
||||
var index = arrayRemove(array, watcher);
|
||||
if (index >= 0) {
|
||||
incrementWatchersCount(scope, -1);
|
||||
if (index < array.$$digestWatchIndex) {
|
||||
array.$$digestWatchIndex--;
|
||||
}
|
||||
}
|
||||
lastDirtyWatch = null;
|
||||
};
|
||||
@@ -757,7 +763,6 @@ function $RootScopeProvider() {
|
||||
$digest: function() {
|
||||
var watch, value, last, fn, get,
|
||||
watchers,
|
||||
length,
|
||||
dirty, ttl = TTL,
|
||||
next, current, target = this,
|
||||
watchLog = [],
|
||||
@@ -798,10 +803,10 @@ function $RootScopeProvider() {
|
||||
do { // "traverse the scopes" loop
|
||||
if ((watchers = current.$$watchers)) {
|
||||
// process our watches
|
||||
length = watchers.length;
|
||||
while (length--) {
|
||||
watchers.$$digestWatchIndex = watchers.length;
|
||||
while (watchers.$$digestWatchIndex--) {
|
||||
try {
|
||||
watch = watchers[length];
|
||||
watch = watchers[watchers.$$digestWatchIndex];
|
||||
// Most common watches are on primitives, in which case we can short
|
||||
// circuit it with === operator, only when === fails do we use .equals
|
||||
if (watch) {
|
||||
|
||||
@@ -629,10 +629,8 @@ angular.module('ngMessages', [], function initAngularHelpers() {
|
||||
* @scope
|
||||
*
|
||||
* @description
|
||||
* `ngMessageExp` is a directive with the purpose to show and hide a particular message.
|
||||
* For `ngMessageExp` to operate, a parent `ngMessages` directive on a parent DOM element
|
||||
* must be situated since it determines which messages are visible based on the state
|
||||
* of the provided key/value map that `ngMessages` listens on.
|
||||
* `ngMessageExp` is the same as {@link directive:ngMessage `ngMessage`}, but instead of a static
|
||||
* value, it accepts an expression to be evaluated for the message key.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
|
||||
@@ -391,8 +391,7 @@ function generateInputCompilerHelper(helper) {
|
||||
};
|
||||
|
||||
helper.changeInputValueTo = function(value) {
|
||||
helper.inputElm.val(value);
|
||||
browserTrigger(helper.inputElm, $sniffer.hasEvent('input') ? 'input' : 'change');
|
||||
helper.changeGivenInputTo(helper.inputElm, value);
|
||||
};
|
||||
|
||||
helper.changeGivenInputTo = function(inputElm, value) {
|
||||
|
||||
@@ -2182,6 +2182,14 @@ describe('jqLite', function() {
|
||||
span.after('abc');
|
||||
expect(root.html().toLowerCase()).toEqual('<span></span>abc');
|
||||
});
|
||||
|
||||
|
||||
it('should not throw when the element has no parent', function() {
|
||||
var span = jqLite('<span></span>');
|
||||
expect(function() { span.after('abc'); }).not.toThrow();
|
||||
expect(span.length).toBe(1);
|
||||
expect(span[0].outerHTML).toBe('<span></span>');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
+118
-86
@@ -3,103 +3,135 @@
|
||||
describe('$$cookieReader', function() {
|
||||
var $$cookieReader, document;
|
||||
|
||||
function deleteAllCookies() {
|
||||
var cookies = document.cookie.split(';');
|
||||
var path = window.location.pathname;
|
||||
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var cookie = cookies[i];
|
||||
var eqPos = cookie.indexOf('=');
|
||||
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
|
||||
var parts = path.split('/');
|
||||
while (parts.length) {
|
||||
document.cookie = name + '=;path=' + (parts.join('/') || '/') + ';expires=Thu, 01 Jan 1970 00:00:00 GMT';
|
||||
parts.pop();
|
||||
describe('with access to `document.cookie`', function() {
|
||||
|
||||
function deleteAllCookies() {
|
||||
var cookies = document.cookie.split(';');
|
||||
var path = window.location.pathname;
|
||||
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var cookie = cookies[i];
|
||||
var eqPos = cookie.indexOf('=');
|
||||
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
|
||||
var parts = path.split('/');
|
||||
while (parts.length) {
|
||||
document.cookie = name + '=;path=' + (parts.join('/') || '/') + ';expires=Thu, 01 Jan 1970 00:00:00 GMT';
|
||||
parts.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
document = window.document;
|
||||
deleteAllCookies();
|
||||
expect(document.cookie).toEqual('');
|
||||
beforeEach(function() {
|
||||
document = window.document;
|
||||
deleteAllCookies();
|
||||
expect(document.cookie).toEqual('');
|
||||
|
||||
inject(function(_$$cookieReader_) {
|
||||
inject(function(_$$cookieReader_) {
|
||||
$$cookieReader = _$$cookieReader_;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
deleteAllCookies();
|
||||
expect(document.cookie).toEqual('');
|
||||
});
|
||||
|
||||
|
||||
describe('get via $$cookieReader()[cookieName]', function() {
|
||||
|
||||
it('should return undefined for nonexistent cookie', function() {
|
||||
expect($$cookieReader().nonexistent).not.toBeDefined();
|
||||
});
|
||||
|
||||
|
||||
it('should return a value for an existing cookie', function() {
|
||||
document.cookie = 'foo=bar=baz;path=/';
|
||||
expect($$cookieReader().foo).toEqual('bar=baz');
|
||||
});
|
||||
|
||||
|
||||
it('should return the the first value provided for a cookie', function() {
|
||||
// For a cookie that has different values that differ by path, the
|
||||
// value for the most specific path appears first. $$cookieReader()
|
||||
// should provide that value for the cookie.
|
||||
document.cookie = 'foo="first"; foo="second"';
|
||||
expect($$cookieReader()['foo']).toBe('"first"');
|
||||
});
|
||||
|
||||
|
||||
it('should decode cookie values that were encoded by puts', function() {
|
||||
document.cookie = 'cookie2%3Dbar%3Bbaz=val%3Due;path=/';
|
||||
expect($$cookieReader()['cookie2=bar;baz']).toEqual('val=ue');
|
||||
});
|
||||
|
||||
|
||||
it('should preserve leading & trailing spaces in names and values', function() {
|
||||
document.cookie = '%20cookie%20name%20=%20cookie%20value%20';
|
||||
expect($$cookieReader()[' cookie name ']).toEqual(' cookie value ');
|
||||
expect($$cookieReader()['cookie name']).not.toBeDefined();
|
||||
});
|
||||
|
||||
|
||||
it('should decode special characters in cookie values', function() {
|
||||
document.cookie = 'cookie_name=cookie_value_%E2%82%AC';
|
||||
expect($$cookieReader()['cookie_name']).toEqual('cookie_value_€');
|
||||
});
|
||||
|
||||
|
||||
it('should not decode cookie values that do not appear to be encoded', function() {
|
||||
// see #9211 - sometimes cookies contain a value that causes decodeURIComponent to throw
|
||||
document.cookie = 'cookie_name=cookie_value_%XX';
|
||||
expect($$cookieReader()['cookie_name']).toEqual('cookie_value_%XX');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('getAll via $$cookieReader()', function() {
|
||||
|
||||
it('should return cookies as hash', function() {
|
||||
document.cookie = 'foo1=bar1;path=/';
|
||||
document.cookie = 'foo2=bar2;path=/';
|
||||
expect($$cookieReader()).toEqual({'foo1':'bar1', 'foo2':'bar2'});
|
||||
});
|
||||
|
||||
|
||||
it('should return empty hash if no cookies exist', function() {
|
||||
expect($$cookieReader()).toEqual({});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should initialize cookie cache with existing cookies', function() {
|
||||
document.cookie = 'existingCookie=existingValue;path=/';
|
||||
expect($$cookieReader()).toEqual({'existingCookie':'existingValue'});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('without access to `document.cookie`', function() {
|
||||
var cookieSpy;
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
cookieSpy = jasmine.createSpy('cookie').and.throwError('Can\'t touch this!');
|
||||
document = Object.create({}, {'cookie': {get: cookieSpy}});
|
||||
|
||||
$provide.value('$document', [document]);
|
||||
}));
|
||||
|
||||
beforeEach(inject(function(_$$cookieReader_) {
|
||||
$$cookieReader = _$$cookieReader_;
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
afterEach(function() {
|
||||
deleteAllCookies();
|
||||
expect(document.cookie).toEqual('');
|
||||
});
|
||||
|
||||
|
||||
describe('get via $$cookieReader()[cookieName]', function() {
|
||||
|
||||
it('should return undefined for nonexistent cookie', function() {
|
||||
expect($$cookieReader().nonexistent).not.toBeDefined();
|
||||
});
|
||||
|
||||
|
||||
it('should return a value for an existing cookie', function() {
|
||||
document.cookie = 'foo=bar=baz;path=/';
|
||||
expect($$cookieReader().foo).toEqual('bar=baz');
|
||||
});
|
||||
|
||||
it('should return the the first value provided for a cookie', function() {
|
||||
// For a cookie that has different values that differ by path, the
|
||||
// value for the most specific path appears first. $$cookieReader()
|
||||
// should provide that value for the cookie.
|
||||
document.cookie = 'foo="first"; foo="second"';
|
||||
expect($$cookieReader()['foo']).toBe('"first"');
|
||||
});
|
||||
|
||||
it('should decode cookie values that were encoded by puts', function() {
|
||||
document.cookie = 'cookie2%3Dbar%3Bbaz=val%3Due;path=/';
|
||||
expect($$cookieReader()['cookie2=bar;baz']).toEqual('val=ue');
|
||||
});
|
||||
|
||||
|
||||
it('should preserve leading & trailing spaces in names and values', function() {
|
||||
document.cookie = '%20cookie%20name%20=%20cookie%20value%20';
|
||||
expect($$cookieReader()[' cookie name ']).toEqual(' cookie value ');
|
||||
expect($$cookieReader()['cookie name']).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should decode special characters in cookie values', function() {
|
||||
document.cookie = 'cookie_name=cookie_value_%E2%82%AC';
|
||||
expect($$cookieReader()['cookie_name']).toEqual('cookie_value_€');
|
||||
});
|
||||
|
||||
it('should not decode cookie values that do not appear to be encoded', function() {
|
||||
// see #9211 - sometimes cookies contain a value that causes decodeURIComponent to throw
|
||||
document.cookie = 'cookie_name=cookie_value_%XX';
|
||||
expect($$cookieReader()['cookie_name']).toEqual('cookie_value_%XX');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('getAll via $$cookieReader()', function() {
|
||||
|
||||
it('should return cookies as hash', function() {
|
||||
document.cookie = 'foo1=bar1;path=/';
|
||||
document.cookie = 'foo2=bar2;path=/';
|
||||
expect($$cookieReader()).toEqual({'foo1':'bar1', 'foo2':'bar2'});
|
||||
});
|
||||
|
||||
|
||||
it('should return empty hash if no cookies exist', function() {
|
||||
it('should return an empty object', function() {
|
||||
expect($$cookieReader()).toEqual({});
|
||||
expect(cookieSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should initialize cookie cache with existing cookies', function() {
|
||||
document.cookie = 'existingCookie=existingValue;path=/';
|
||||
expect($$cookieReader()).toEqual({'existingCookie':'existingValue'});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -244,21 +244,34 @@ describe('ngClass', function() {
|
||||
}));
|
||||
|
||||
|
||||
it('should allow ngClassOdd/Even on the same element with overlapping classes', inject(function($rootScope, $compile, $animate) {
|
||||
var className;
|
||||
|
||||
element = $compile('<ul><li ng-repeat="i in [0,1,2]" ng-class-odd="\'same odd\'" ng-class-even="\'same even\'"></li><ul>')($rootScope);
|
||||
it('should allow ngClassOdd/Even on the same element with overlapping classes',
|
||||
inject(function($compile, $rootScope) {
|
||||
element = $compile(
|
||||
'<ul>' +
|
||||
'<li ng-repeat="i in [0,1,2]" ' +
|
||||
'ng-class-odd="\'same odd\'" ' +
|
||||
'ng-class-even="\'same even\'">' +
|
||||
'</li>' +
|
||||
'<ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
var e1 = jqLite(element[0].childNodes[1]);
|
||||
var e2 = jqLite(element[0].childNodes[5]);
|
||||
expect(e1.hasClass('same')).toBeTruthy();
|
||||
expect(e1.hasClass('odd')).toBeTruthy();
|
||||
expect(e2.hasClass('same')).toBeTruthy();
|
||||
expect(e2.hasClass('odd')).toBeTruthy();
|
||||
|
||||
var e1 = element.children().eq(0);
|
||||
var e2 = element.children().eq(1);
|
||||
var e3 = element.children().eq(2);
|
||||
|
||||
expect(e1).toHaveClass('same');
|
||||
expect(e1).toHaveClass('odd');
|
||||
expect(e1).not.toHaveClass('even');
|
||||
expect(e2).toHaveClass('same');
|
||||
expect(e2).not.toHaveClass('odd');
|
||||
expect(e2).toHaveClass('even');
|
||||
expect(e3).toHaveClass('same');
|
||||
expect(e3).toHaveClass('odd');
|
||||
expect(e3).not.toHaveClass('even');
|
||||
})
|
||||
);
|
||||
|
||||
it('should allow ngClass with overlapping classes', inject(function($rootScope, $compile, $animate) {
|
||||
it('should allow ngClass with overlapping classes', inject(function($rootScope, $compile) {
|
||||
element = $compile('<div ng-class="{\'same yes\': test, \'same no\': !test}"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
@@ -266,9 +279,7 @@ describe('ngClass', function() {
|
||||
expect(element).not.toHaveClass('yes');
|
||||
expect(element).toHaveClass('no');
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.test = true;
|
||||
});
|
||||
$rootScope.$apply('test = true');
|
||||
|
||||
expect(element).toHaveClass('same');
|
||||
expect(element).toHaveClass('yes');
|
||||
@@ -299,38 +310,79 @@ describe('ngClass', function() {
|
||||
expect(e2.hasClass('D')).toBeFalsy();
|
||||
}));
|
||||
|
||||
it('should reapply ngClass when interpolated class attribute changes',
|
||||
inject(function($compile, $rootScope) {
|
||||
element = $compile(
|
||||
'<div>' +
|
||||
'<div class="one {{two}} three" ng-class="{five: five}"></div>' +
|
||||
'<div class="one {{two}} three {{four}}" ng-class="{five: five}"></div>' +
|
||||
'</div>')($rootScope);
|
||||
var e1 = element.children().eq(0);
|
||||
var e2 = element.children().eq(1);
|
||||
|
||||
it('should reapply ngClass when interpolated class attribute changes', inject(function($rootScope, $compile) {
|
||||
element = $compile('<div class="one {{cls}} three" ng-class="{four: four}"></div>')($rootScope);
|
||||
$rootScope.$apply('two = "two"; five = true');
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.cls = 'two';
|
||||
$rootScope.four = true;
|
||||
});
|
||||
expect(element).toHaveClass('one');
|
||||
expect(element).toHaveClass('two'); // interpolated
|
||||
expect(element).toHaveClass('three');
|
||||
expect(element).toHaveClass('four');
|
||||
expect(e1).toHaveClass('one');
|
||||
expect(e1).toHaveClass('two');
|
||||
expect(e1).toHaveClass('three');
|
||||
expect(e1).not.toHaveClass('four');
|
||||
expect(e1).toHaveClass('five');
|
||||
expect(e2).toHaveClass('one');
|
||||
expect(e2).toHaveClass('two');
|
||||
expect(e2).toHaveClass('three');
|
||||
expect(e2).not.toHaveClass('four');
|
||||
expect(e2).toHaveClass('five');
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.cls = 'too';
|
||||
});
|
||||
expect(element).toHaveClass('one');
|
||||
expect(element).toHaveClass('too'); // interpolated
|
||||
expect(element).toHaveClass('three');
|
||||
expect(element).toHaveClass('four'); // should still be there
|
||||
expect(element.hasClass('two')).toBeFalsy();
|
||||
$rootScope.$apply('two = "another-two"');
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.cls = 'to';
|
||||
});
|
||||
expect(element).toHaveClass('one');
|
||||
expect(element).toHaveClass('to'); // interpolated
|
||||
expect(element).toHaveClass('three');
|
||||
expect(element).toHaveClass('four'); // should still be there
|
||||
expect(element.hasClass('two')).toBeFalsy();
|
||||
expect(element.hasClass('too')).toBeFalsy();
|
||||
}));
|
||||
expect(e1).toHaveClass('one');
|
||||
expect(e1).not.toHaveClass('two');
|
||||
expect(e1).toHaveClass('another-two');
|
||||
expect(e1).toHaveClass('three');
|
||||
expect(e1).not.toHaveClass('four');
|
||||
expect(e1).toHaveClass('five');
|
||||
expect(e2).toHaveClass('one');
|
||||
expect(e2).not.toHaveClass('two');
|
||||
expect(e2).toHaveClass('another-two');
|
||||
expect(e2).toHaveClass('three');
|
||||
expect(e2).not.toHaveClass('four');
|
||||
expect(e2).toHaveClass('five');
|
||||
|
||||
$rootScope.$apply('two = "two-more"; four = "four"');
|
||||
|
||||
expect(e1).toHaveClass('one');
|
||||
expect(e1).not.toHaveClass('two');
|
||||
expect(e1).not.toHaveClass('another-two');
|
||||
expect(e1).toHaveClass('two-more');
|
||||
expect(e1).toHaveClass('three');
|
||||
expect(e1).not.toHaveClass('four');
|
||||
expect(e1).toHaveClass('five');
|
||||
expect(e2).toHaveClass('one');
|
||||
expect(e2).not.toHaveClass('two');
|
||||
expect(e2).not.toHaveClass('another-two');
|
||||
expect(e2).toHaveClass('two-more');
|
||||
expect(e2).toHaveClass('three');
|
||||
expect(e2).toHaveClass('four');
|
||||
expect(e2).toHaveClass('five');
|
||||
|
||||
$rootScope.$apply('five = false');
|
||||
|
||||
expect(e1).toHaveClass('one');
|
||||
expect(e1).not.toHaveClass('two');
|
||||
expect(e1).not.toHaveClass('another-two');
|
||||
expect(e1).toHaveClass('two-more');
|
||||
expect(e1).toHaveClass('three');
|
||||
expect(e1).not.toHaveClass('four');
|
||||
expect(e1).not.toHaveClass('five');
|
||||
expect(e2).toHaveClass('one');
|
||||
expect(e2).not.toHaveClass('two');
|
||||
expect(e2).not.toHaveClass('another-two');
|
||||
expect(e2).toHaveClass('two-more');
|
||||
expect(e2).toHaveClass('three');
|
||||
expect(e2).toHaveClass('four');
|
||||
expect(e2).not.toHaveClass('five');
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
it('should not mess up class value due to observing an interpolated class attribute', inject(function($rootScope, $compile) {
|
||||
@@ -409,6 +461,47 @@ describe('ngClass', function() {
|
||||
expect(e2.hasClass('odd')).toBeFalsy();
|
||||
}));
|
||||
|
||||
|
||||
it('should add/remove the correct classes when the expression and `$index` change simultaneously',
|
||||
inject(function($compile, $rootScope) {
|
||||
element = $compile(
|
||||
'<div>' +
|
||||
'<div ng-class-odd="foo"></div>' +
|
||||
'<div ng-class-even="foo"></div>' +
|
||||
'</div>')($rootScope);
|
||||
var odd = element.children().eq(0);
|
||||
var even = element.children().eq(1);
|
||||
|
||||
$rootScope.$apply('$index = 0; foo = "class1"');
|
||||
|
||||
expect(odd).toHaveClass('class1');
|
||||
expect(odd).not.toHaveClass('class2');
|
||||
expect(even).not.toHaveClass('class1');
|
||||
expect(even).not.toHaveClass('class2');
|
||||
|
||||
$rootScope.$apply('$index = 1; foo = "class2"');
|
||||
|
||||
expect(odd).not.toHaveClass('class1');
|
||||
expect(odd).not.toHaveClass('class2');
|
||||
expect(even).not.toHaveClass('class1');
|
||||
expect(even).toHaveClass('class2');
|
||||
|
||||
$rootScope.$apply('foo = "class1"');
|
||||
|
||||
expect(odd).not.toHaveClass('class1');
|
||||
expect(odd).not.toHaveClass('class2');
|
||||
expect(even).toHaveClass('class1');
|
||||
expect(even).not.toHaveClass('class2');
|
||||
|
||||
$rootScope.$apply('$index = 2');
|
||||
|
||||
expect(odd).toHaveClass('class1');
|
||||
expect(odd).not.toHaveClass('class2');
|
||||
expect(even).not.toHaveClass('class1');
|
||||
expect(even).not.toHaveClass('class2');
|
||||
})
|
||||
);
|
||||
|
||||
it('should support mixed array/object variable with a mutating object',
|
||||
inject(function($rootScope, $compile) {
|
||||
element = $compile('<div ng-class="classVar"></div>')($rootScope);
|
||||
@@ -424,6 +517,125 @@ describe('ngClass', function() {
|
||||
})
|
||||
);
|
||||
|
||||
it('should do value stabilization as expected when one-time binding',
|
||||
inject(function($rootScope, $compile) {
|
||||
element = $compile('<div ng-class="::className"></div>')($rootScope);
|
||||
|
||||
$rootScope.$apply('className = "foo"');
|
||||
expect(element).toHaveClass('foo');
|
||||
|
||||
$rootScope.$apply('className = "bar"');
|
||||
expect(element).toHaveClass('foo');
|
||||
})
|
||||
);
|
||||
|
||||
it('should remove the watcher when static array one-time binding',
|
||||
inject(function($rootScope, $compile) {
|
||||
element = $compile('<div ng-class="::[className]"></div>')($rootScope);
|
||||
|
||||
$rootScope.$apply('className = "foo"');
|
||||
expect(element).toHaveClass('foo');
|
||||
|
||||
$rootScope.$apply('className = "bar"');
|
||||
expect(element).toHaveClass('foo');
|
||||
expect(element).not.toHaveClass('bar');
|
||||
})
|
||||
);
|
||||
|
||||
it('should remove the watcher when static map one-time binding',
|
||||
inject(function($rootScope, $compile) {
|
||||
element = $compile('<div ng-class="::{foo: fooPresent}"></div>')($rootScope);
|
||||
|
||||
$rootScope.$apply('fooPresent = true');
|
||||
expect(element).toHaveClass('foo');
|
||||
|
||||
$rootScope.$apply('fooPresent = false');
|
||||
expect(element).toHaveClass('foo');
|
||||
})
|
||||
);
|
||||
|
||||
it('should track changes of mutating object inside an array',
|
||||
inject(function($rootScope, $compile) {
|
||||
$rootScope.classVar = [{orange: true}];
|
||||
element = $compile('<div ng-class="classVar"></div>')($rootScope);
|
||||
|
||||
$rootScope.$digest();
|
||||
expect(element).toHaveClass('orange');
|
||||
|
||||
$rootScope.$apply('classVar[0].orange = false');
|
||||
expect(element).not.toHaveClass('orange');
|
||||
})
|
||||
);
|
||||
|
||||
describe('large objects', function() {
|
||||
var getProp;
|
||||
var veryLargeObj;
|
||||
|
||||
beforeEach(function() {
|
||||
getProp = jasmine.createSpy('getProp');
|
||||
veryLargeObj = {};
|
||||
|
||||
Object.defineProperty(veryLargeObj, 'prop', {
|
||||
get: getProp,
|
||||
enumerable: true
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be copied when using an expression', inject(function($compile, $rootScope) {
|
||||
element = $compile('<div ng-class="fooClass"></div>')($rootScope);
|
||||
$rootScope.fooClass = {foo: veryLargeObj};
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element).toHaveClass('foo');
|
||||
expect(getProp).not.toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should not be copied when using a literal', inject(function($compile, $rootScope) {
|
||||
element = $compile('<div ng-class="{foo: veryLargeObj}"></div>')($rootScope);
|
||||
$rootScope.veryLargeObj = veryLargeObj;
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element).toHaveClass('foo');
|
||||
expect(getProp).not.toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should not be copied when inside an array', inject(function($compile, $rootScope) {
|
||||
element = $compile('<div ng-class="[{foo: veryLargeObj}]"></div>')($rootScope);
|
||||
$rootScope.veryLargeObj = veryLargeObj;
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element).toHaveClass('foo');
|
||||
expect(getProp).not.toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should not be copied when using one-time binding', inject(function($compile, $rootScope) {
|
||||
element = $compile('<div ng-class="::{foo: veryLargeObj, bar: bar}"></div>')($rootScope);
|
||||
$rootScope.veryLargeObj = veryLargeObj;
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element).toHaveClass('foo');
|
||||
expect(element).not.toHaveClass('bar');
|
||||
expect(getProp).not.toHaveBeenCalled();
|
||||
|
||||
$rootScope.$apply('veryLargeObj.bar = "bar"');
|
||||
|
||||
expect(element).toHaveClass('foo');
|
||||
expect(element).not.toHaveClass('bar');
|
||||
expect(getProp).not.toHaveBeenCalled();
|
||||
|
||||
$rootScope.$apply('bar = "bar"');
|
||||
|
||||
expect(element).toHaveClass('foo');
|
||||
expect(element).toHaveClass('bar');
|
||||
expect(getProp).not.toHaveBeenCalled();
|
||||
|
||||
$rootScope.$apply('veryLargeObj.bar = "qux"');
|
||||
|
||||
expect(element).toHaveClass('foo');
|
||||
expect(element).toHaveClass('bar');
|
||||
expect(getProp).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('ngClass animations', function() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2827,6 +2827,7 @@ describe('ngOptions', function() {
|
||||
expect(scope.selected).toEqual(['0']);
|
||||
});
|
||||
|
||||
|
||||
it('should deselect all options when model is emptied', function() {
|
||||
createMultiSelect();
|
||||
scope.$apply(function() {
|
||||
@@ -2841,6 +2842,86 @@ describe('ngOptions', function() {
|
||||
|
||||
expect(element.find('option')[0].selected).toEqual(false);
|
||||
});
|
||||
|
||||
|
||||
it('should not re-set the `selected` property if it already has the correct value', function() {
|
||||
scope.values = [{name: 'A'}, {name: 'B'}];
|
||||
createMultiSelect();
|
||||
|
||||
var options = element.find('option');
|
||||
var optionsSetSelected = [];
|
||||
var _selected = [];
|
||||
|
||||
// Set up spies
|
||||
forEach(options, function(option, i) {
|
||||
optionsSetSelected[i] = jasmine.createSpy('optionSetSelected' + i);
|
||||
_selected[i] = option.selected;
|
||||
Object.defineProperty(option, 'selected', {
|
||||
get: function() { return _selected[i]; },
|
||||
set: optionsSetSelected[i].and.callFake(function(value) { _selected[i] = value; })
|
||||
});
|
||||
});
|
||||
|
||||
// Select `optionA`
|
||||
scope.$apply('selected = [values[0]]');
|
||||
|
||||
expect(optionsSetSelected[0]).toHaveBeenCalledOnceWith(true);
|
||||
expect(optionsSetSelected[1]).not.toHaveBeenCalled();
|
||||
expect(options[0].selected).toBe(true);
|
||||
expect(options[1].selected).toBe(false);
|
||||
optionsSetSelected[0].calls.reset();
|
||||
optionsSetSelected[1].calls.reset();
|
||||
|
||||
// Select `optionB` (`optionA` remains selected)
|
||||
scope.$apply('selected.push(values[1])');
|
||||
|
||||
expect(optionsSetSelected[0]).not.toHaveBeenCalled();
|
||||
expect(optionsSetSelected[1]).toHaveBeenCalledOnceWith(true);
|
||||
expect(options[0].selected).toBe(true);
|
||||
expect(options[1].selected).toBe(true);
|
||||
optionsSetSelected[0].calls.reset();
|
||||
optionsSetSelected[1].calls.reset();
|
||||
|
||||
// Unselect `optionA` (`optionB` remains selected)
|
||||
scope.$apply('selected.shift()');
|
||||
|
||||
expect(optionsSetSelected[0]).toHaveBeenCalledOnceWith(false);
|
||||
expect(optionsSetSelected[1]).not.toHaveBeenCalled();
|
||||
expect(options[0].selected).toBe(false);
|
||||
expect(options[1].selected).toBe(true);
|
||||
optionsSetSelected[0].calls.reset();
|
||||
optionsSetSelected[1].calls.reset();
|
||||
|
||||
// Reselect `optionA` (`optionB` remains selected)
|
||||
scope.$apply('selected.push(values[0])');
|
||||
|
||||
expect(optionsSetSelected[0]).toHaveBeenCalledOnceWith(true);
|
||||
expect(optionsSetSelected[1]).not.toHaveBeenCalled();
|
||||
expect(options[0].selected).toBe(true);
|
||||
expect(options[1].selected).toBe(true);
|
||||
optionsSetSelected[0].calls.reset();
|
||||
optionsSetSelected[1].calls.reset();
|
||||
|
||||
// Unselect `optionB` (`optionA` remains selected)
|
||||
scope.$apply('selected.shift()');
|
||||
|
||||
expect(optionsSetSelected[0]).not.toHaveBeenCalled();
|
||||
expect(optionsSetSelected[1]).toHaveBeenCalledOnceWith(false);
|
||||
expect(options[0].selected).toBe(true);
|
||||
expect(options[1].selected).toBe(false);
|
||||
optionsSetSelected[0].calls.reset();
|
||||
optionsSetSelected[1].calls.reset();
|
||||
|
||||
// Unselect `optionA`
|
||||
scope.$apply('selected.length = 0');
|
||||
|
||||
expect(optionsSetSelected[0]).toHaveBeenCalledOnceWith(false);
|
||||
expect(optionsSetSelected[1]).not.toHaveBeenCalled();
|
||||
expect(options[0].selected).toBe(false);
|
||||
expect(options[1].selected).toBe(false);
|
||||
optionsSetSelected[0].calls.reset();
|
||||
optionsSetSelected[1].calls.reset();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
+90
-39
@@ -181,16 +181,14 @@ describe('q', function() {
|
||||
};
|
||||
|
||||
|
||||
function exceptionHandler(reason) {
|
||||
exceptionHandlerCalls.push(reason);
|
||||
function exceptionHandler(exception, reason) {
|
||||
if (typeof reason === 'undefined') {
|
||||
exceptionHandlerCalls.push({ reason: exception });
|
||||
} else {
|
||||
exceptionHandlerCalls.push({ reason: reason, exception: exception });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function exceptionHandlerStr() {
|
||||
return exceptionHandlerCalls.join('; ');
|
||||
}
|
||||
|
||||
|
||||
beforeEach(function() {
|
||||
q = qFactory(mockNextTick.nextTick, exceptionHandler, true);
|
||||
q_no_error = qFactory(mockNextTick.nextTick, exceptionHandler, false);
|
||||
@@ -2167,45 +2165,98 @@ describe('q', function() {
|
||||
|
||||
|
||||
describe('when exceptionHandler is called', function() {
|
||||
it('should log an unhandled rejected promise', function() {
|
||||
var defer = q.defer();
|
||||
defer.reject('foo');
|
||||
mockNextTick.flush();
|
||||
expect(exceptionHandlerStr()).toBe('Possibly unhandled rejection: foo');
|
||||
});
|
||||
function CustomError() { }
|
||||
CustomError.prototype = Object.create(Error.prototype);
|
||||
|
||||
var errorEg = new Error('Fail');
|
||||
var errorStr = toDebugString(errorEg);
|
||||
|
||||
var customError = new CustomError('Custom');
|
||||
var customErrorStr = toDebugString(customError);
|
||||
|
||||
var nonErrorObj = { isATest: 'this is' };
|
||||
var nonErrorObjStr = toDebugString(nonErrorObj);
|
||||
|
||||
var fixtures = [
|
||||
{
|
||||
type: 'Error object',
|
||||
value: errorEg,
|
||||
expected: {
|
||||
exception: errorEg,
|
||||
reason: 'Possibly unhandled rejection: ' + errorStr
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'custom Error object',
|
||||
value: customError,
|
||||
expected: {
|
||||
exception: customError,
|
||||
reason: 'Possibly unhandled rejection: ' + customErrorStr
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'non-Error object',
|
||||
value: nonErrorObj,
|
||||
expected: {
|
||||
reason: 'Possibly unhandled rejection: ' + nonErrorObjStr
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'string primitive',
|
||||
value: 'foo',
|
||||
expected: {
|
||||
reason: 'Possibly unhandled rejection: foo'
|
||||
}
|
||||
}
|
||||
];
|
||||
forEach(fixtures, function(fixture) {
|
||||
var type = fixture.type;
|
||||
var value = fixture.value;
|
||||
var expected = fixture.expected;
|
||||
|
||||
describe('with ' + type, function() {
|
||||
|
||||
it('should log an unhandled rejected promise', function() {
|
||||
var defer = q.defer();
|
||||
defer.reject(value);
|
||||
mockNextTick.flush();
|
||||
expect(exceptionHandlerCalls).toEqual([expected]);
|
||||
});
|
||||
|
||||
|
||||
it('should not log an unhandled rejected promise if disabled', function() {
|
||||
var defer = q_no_error.defer();
|
||||
defer.reject('foo');
|
||||
expect(exceptionHandlerStr()).toBe('');
|
||||
});
|
||||
it('should not log an unhandled rejected promise if disabled', function() {
|
||||
var defer = q_no_error.defer();
|
||||
defer.reject(value);
|
||||
expect(exceptionHandlerCalls).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should log a handled rejected promise on a promise without rejection callbacks', function() {
|
||||
var defer = q.defer();
|
||||
defer.promise.then(noop);
|
||||
defer.reject('foo');
|
||||
mockNextTick.flush();
|
||||
expect(exceptionHandlerStr()).toBe('Possibly unhandled rejection: foo');
|
||||
});
|
||||
it('should log a handled rejected promise on a promise without rejection callbacks', function() {
|
||||
var defer = q.defer();
|
||||
defer.promise.then(noop);
|
||||
defer.reject(value);
|
||||
mockNextTick.flush();
|
||||
expect(exceptionHandlerCalls).toEqual([expected]);
|
||||
});
|
||||
|
||||
|
||||
it('should not log a handled rejected promise', function() {
|
||||
var defer = q.defer();
|
||||
defer.promise.catch(noop);
|
||||
defer.reject('foo');
|
||||
mockNextTick.flush();
|
||||
expect(exceptionHandlerStr()).toBe('');
|
||||
});
|
||||
it('should not log a handled rejected promise', function() {
|
||||
var defer = q.defer();
|
||||
defer.promise.catch(noop);
|
||||
defer.reject(value);
|
||||
mockNextTick.flush();
|
||||
expect(exceptionHandlerCalls).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should not log a handled rejected promise that is handled in a future tick', function() {
|
||||
var defer = q.defer();
|
||||
defer.promise.catch(noop);
|
||||
defer.resolve(q.reject('foo'));
|
||||
mockNextTick.flush();
|
||||
expect(exceptionHandlerStr()).toBe('');
|
||||
it('should not log a handled rejected promise that is handled in a future tick', function() {
|
||||
var defer = q.defer();
|
||||
defer.promise.catch(noop);
|
||||
defer.resolve(q.reject(value));
|
||||
mockNextTick.flush();
|
||||
expect(exceptionHandlerCalls).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -498,6 +498,78 @@ describe('Scope', function() {
|
||||
expect(watch2).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
|
||||
it('should not skip watchers when adding new watchers during digest',
|
||||
inject(function($rootScope) {
|
||||
var log = [];
|
||||
|
||||
var watchFn1 = function() { log.push(1); };
|
||||
var watchFn2 = function() { log.push(2); };
|
||||
var watchFn3 = function() { log.push(3); };
|
||||
var addWatcherOnce = function(newValue, oldValue) {
|
||||
if (newValue === oldValue) {
|
||||
$rootScope.$watch(watchFn3);
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.$watch(watchFn1, addWatcherOnce);
|
||||
$rootScope.$watch(watchFn2);
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(log).toEqual([1, 2, 3, 1, 2, 3]);
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
it('should not run the current watcher twice when removing a watcher during digest',
|
||||
inject(function($rootScope) {
|
||||
var log = [];
|
||||
var removeWatcher3;
|
||||
|
||||
var watchFn3 = function() { log.push(3); };
|
||||
var watchFn2 = function() { log.push(2); };
|
||||
var watchFn1 = function() { log.push(1); };
|
||||
var removeWatcherOnce = function(newValue, oldValue) {
|
||||
if (newValue === oldValue) {
|
||||
removeWatcher3();
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.$watch(watchFn1, removeWatcherOnce);
|
||||
$rootScope.$watch(watchFn2);
|
||||
removeWatcher3 = $rootScope.$watch(watchFn3);
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(log).toEqual([1, 2, 1, 2]);
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
it('should not skip watchers when removing itself during digest',
|
||||
inject(function($rootScope) {
|
||||
var log = [];
|
||||
var removeWatcher1;
|
||||
|
||||
var watchFn3 = function() { log.push(3); };
|
||||
var watchFn2 = function() { log.push(2); };
|
||||
var watchFn1 = function() { log.push(1); };
|
||||
var removeItself = function() {
|
||||
removeWatcher1();
|
||||
};
|
||||
|
||||
removeWatcher1 = $rootScope.$watch(watchFn1, removeItself);
|
||||
$rootScope.$watch(watchFn2);
|
||||
$rootScope.$watch(watchFn3);
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(log).toEqual([1, 2, 3, 2, 3]);
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
it('should not infinitely digest when current value is NaN', inject(function($rootScope) {
|
||||
$rootScope.$watch(function() { return NaN;});
|
||||
|
||||
@@ -598,7 +670,7 @@ describe('Scope', function() {
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(log).toEqual(['watch1', 'watchAction1', 'watch1', 'watch3', 'watchAction3',
|
||||
expect(log).toEqual(['watch1', 'watchAction1', 'watch3', 'watchAction3',
|
||||
'watch1', 'watch3']);
|
||||
scope.$destroy();
|
||||
log.reset();
|
||||
@@ -895,8 +967,7 @@ describe('Scope', function() {
|
||||
$rootScope.$watch(log.fn('w5'), log.fn('w5action'));
|
||||
});
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual(['w1', 'w2', 'w3', 'w4', 'w4action',
|
||||
'w1', 'w2', 'w3', 'w4', 'w5', 'w5action',
|
||||
expect(log).toEqual(['w1', 'w2', 'w3', 'w4', 'w4action', 'w5', 'w5action',
|
||||
'w1', 'w2', 'w3', 'w4', 'w5']);
|
||||
}));
|
||||
|
||||
|
||||
@@ -947,9 +947,9 @@ change-case@3.0.0:
|
||||
upper-case "^1.1.1"
|
||||
upper-case-first "^1.1.0"
|
||||
|
||||
changez-angular@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/changez-angular/-/changez-angular-2.1.0.tgz#927f7f5b7227eadabed79e1b2c0924c83984f7a3"
|
||||
changez-angular@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/changez-angular/-/changez-angular-2.1.2.tgz#9f32fc5439a949eee426087dd5d108bc4bf6de23"
|
||||
dependencies:
|
||||
changez "^2.1.0"
|
||||
nunjucks-date "^1.2.0"
|
||||
@@ -2468,7 +2468,16 @@ glob@7.0.5, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@~7.0.0:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^4.0.5, glob@^4.3.1, glob@~4.3.0:
|
||||
glob@^4.0.5, glob@~4.0.2:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-4.0.6.tgz#695c50bdd4e2fb5c5d370b091f388d3707e291a7"
|
||||
dependencies:
|
||||
graceful-fs "^3.0.2"
|
||||
inherits "2"
|
||||
minimatch "^1.0.0"
|
||||
once "^1.3.0"
|
||||
|
||||
glob@^4.3.1, glob@~4.3.0:
|
||||
version "4.3.5"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-4.3.5.tgz#80fbb08ca540f238acce5d11d1e9bc41e75173d3"
|
||||
dependencies:
|
||||
@@ -2516,15 +2525,6 @@ glob@~3.1.21:
|
||||
inherits "1"
|
||||
minimatch "~0.2.11"
|
||||
|
||||
glob@~4.0.2:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-4.0.6.tgz#695c50bdd4e2fb5c5d370b091f388d3707e291a7"
|
||||
dependencies:
|
||||
graceful-fs "^3.0.2"
|
||||
inherits "2"
|
||||
minimatch "^1.0.0"
|
||||
once "^1.3.0"
|
||||
|
||||
global-modules@^0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d"
|
||||
@@ -3939,11 +3939,11 @@ lodash@3.10.1, lodash@^3.10.1, lodash@^3.8.0, lodash@~3.10.1:
|
||||
version "3.10.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
|
||||
|
||||
lodash@4.15.0, lodash@^4.0.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.7.0, lodash@^4.8.0:
|
||||
lodash@4.15.0, lodash@^4.0.0, lodash@^4.13.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.7.0, lodash@^4.8.0:
|
||||
version "4.15.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.15.0.tgz#3162391d8f0140aa22cf8f6b3c34d6b7f63d3aa9"
|
||||
|
||||
lodash@4.16.2:
|
||||
lodash@4.16.2, lodash@^4.14.0:
|
||||
version "4.16.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652"
|
||||
|
||||
@@ -4963,18 +4963,18 @@ pump@^0.3.5:
|
||||
end-of-stream "~1.0.0"
|
||||
once "~1.2.0"
|
||||
|
||||
punycode@1.3.2:
|
||||
punycode@1.3.2, punycode@>=0.2.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
||||
|
||||
punycode@>=0.2.0, punycode@~1.2.3:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.2.4.tgz#54008ac972aec74175def9cba6df7fa9d3918740"
|
||||
|
||||
punycode@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||
|
||||
punycode@~1.2.3:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.2.4.tgz#54008ac972aec74175def9cba6df7fa9d3918740"
|
||||
|
||||
q-io@^1.10.9, q-io@~1.13.2:
|
||||
version "1.13.2"
|
||||
resolved "https://registry.yarnpkg.com/q-io/-/q-io-1.13.2.tgz#eea130d481ddb5e1aa1bc5a66855f7391d06f003"
|
||||
@@ -5104,7 +5104,7 @@ read@~1.0.4:
|
||||
dependencies:
|
||||
mute-stream "~0.0.4"
|
||||
|
||||
readable-stream@1.1, "readable-stream@>=1.1.13-1 <1.2.0-0", readable-stream@^1.0.27-1, readable-stream@^1.0.33-1, readable-stream@^1.1.13, readable-stream@^1.1.13-1, readable-stream@~1.1.8, readable-stream@~1.1.9:
|
||||
readable-stream@1.1, "readable-stream@>=1.1.13-1 <1.2.0-0", readable-stream@^1.0.27-1, readable-stream@^1.1.13, readable-stream@^1.1.13-1, readable-stream@~1.1.8, readable-stream@~1.1.9:
|
||||
version "1.1.13"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e"
|
||||
dependencies:
|
||||
@@ -5113,7 +5113,7 @@ readable-stream@1.1, "readable-stream@>=1.1.13-1 <1.2.0-0", readable-stream@^1.0
|
||||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0.0, readable-stream@~1.0.17, readable-stream@~1.0.2, readable-stream@~1.0.26, readable-stream@~1.0.31:
|
||||
"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@^1.0.33-1, readable-stream@~1.0.0, readable-stream@~1.0.17, readable-stream@~1.0.2, readable-stream@~1.0.26, readable-stream@~1.0.31:
|
||||
version "1.0.34"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user