aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Minar2011-01-04 00:46:25 -0800
committerIgor Minar2011-01-04 16:40:41 -0800
commit3ea5941f0e51c57f55071a85f2033c23c99847c0 (patch)
tree74b8b20178e96f13c5f3550740e35dcb68642a8a
parentd0270d92568e1b7c762b42a0ee0712b65d9acc5c (diff)
downloadangular.js-3ea5941f0e51c57f55071a85f2033c23c99847c0.tar.bz2
removing support for 'eager-published' services
-rw-r--r--CHANGELOG.md33
-rw-r--r--src/Injector.js6
-rw-r--r--src/services.js13
-rw-r--r--src/validators.js10
-rw-r--r--src/widgets.js2
-rw-r--r--test/BinderTest.js16
-rw-r--r--test/InjectorSpec.js16
-rw-r--r--test/ValidatorsTest.js2
-rw-r--r--test/servicesSpec.js46
9 files changed, 83 insertions, 61 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9227eb5..ed9d4fb5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,12 +1,39 @@
# <angular/> 0.9.9 time-shift (in-progress) #
+### Performance
+- $location and $cookies services are now lazily initialized to avoid the polling overhead when
+ not needed.
+
### Breaking changes
- - Many of the services are now lazy created instead of 'eager-publish'. You can get these
- services back into the root scope by adding ng:init="$location = $inject('$location')"
- in your view. The services effected are:
+ - Support for 'eager-published' services was removed. This change was done to make explicit
+ dependency declaration always required in order to allow making relatively expensive services
+ lazily initialized (e.g. $cookie, $location), as well as remove 'magic' and reduce unnecessary
+ scope namespace pollution.
+
+ Complete list of affected services:
+
- $location
- $route
- $cookies
+ - $window
+ - $document
+ - $exceptionHandler
+ - $invalidWidgets
+
+ To temporarily preserve the 'eager-published' status for these services, you may use `ng:init`
+ (e.g. `ng:init="$location = $inject('$location'), ...`) in the view or more correctly create
+ a service like this:
+
+ angular.service('published-svc-shim', function() {
+ this.$location = this.$inject('$location');
+ this.$route = this.$inject('$route');
+ this.$cookies = this.$inject('$cookies');
+ this.$window = this.$inject('$window');
+ this.$document = this.$inject('$document');
+ this.$exceptionHandler = this.$inject('$exceptionHandler');
+ this.$invalidWidgets = this.$inject('$invalidWidgets');
+ }, {$creation: 'eager'});
+
# <angular/> 0.9.8 astral-projection (2010-12-23) #
diff --git a/src/Injector.js b/src/Injector.js
index 6fc466b9..c819d4f0 100644
--- a/src/Injector.js
+++ b/src/Injector.js
@@ -58,9 +58,9 @@ function createInjector(providerScope, providers, cache) {
creation = provider.$creation;
if (creation == 'eager') {
inject(name);
- }
- if (creation == 'eager-published') {
- setter(value, name, inject(name));
+ } else {
+ if (isDefined(creation))
+ throw "Unknown $creation value '" + creation + "' for service " + name;
}
});
} else {
diff --git a/src/services.js b/src/services.js
index 5356d612..e77baf38 100644
--- a/src/services.js
+++ b/src/services.js
@@ -1,8 +1,7 @@
var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
HASH_MATCH = /^([^\?]*)?(\?([^\?]*))?$/,
DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp':21},
- EAGER = 'eager',
- EAGER_PUBLISHED = EAGER + '-published';
+ EAGER = 'eager';
function angularServiceInject(name, fn, inject, eager) {
angularService(name, fn, {$inject:inject, $creation:eager});
@@ -26,7 +25,7 @@ function angularServiceInject(name, fn, inject, eager) {
<input ng:init="greeting='Hello World!'" type="text" name="greeting" />
<button ng:click="$window.alert(greeting)">ALERT</button>
*/
-angularServiceInject("$window", bind(window, identity, window), [], EAGER_PUBLISHED);
+angularServiceInject("$window", bind(window, identity, window), [], EAGER);
/**
* @workInProgress
@@ -39,7 +38,7 @@ angularServiceInject("$window", bind(window, identity, window), [], EAGER_PUBLIS
*/
angularServiceInject("$document", function(window){
return jqLite(window.document);
-}, ['$window'], EAGER_PUBLISHED);
+}, ['$window'], EAGER);
/**
* @workInProgress
@@ -382,7 +381,7 @@ angularServiceInject("$log", function($window){
return logFn;
}
}
-}, ['$window'], EAGER_PUBLISHED);
+}, ['$window'], EAGER);
/**
* @workInProgress
@@ -406,7 +405,7 @@ angularServiceInject('$exceptionHandler', function($log){
return function(e) {
$log.error(e);
};
-}, ['$log'], EAGER_PUBLISHED);
+}, ['$log'], EAGER);
/**
* @workInProgress
@@ -531,7 +530,7 @@ angularServiceInject("$invalidWidgets", function(){
}
return invalidWidgets;
-}, [], EAGER_PUBLISHED);
+}, [], EAGER);
diff --git a/src/validators.js b/src/validators.js
index 8e288882..b55db341 100644
--- a/src/validators.js
+++ b/src/validators.js
@@ -382,10 +382,12 @@ extend(angularValidator, {
cache.current = input;
- var inputState = cache.inputs[input];
+ var inputState = cache.inputs[input],
+ $invalidWidgets = scope.$inject('$invalidWidgets');
+
if (!inputState) {
cache.inputs[input] = inputState = { inFlight: true };
- scope.$invalidWidgets.markInvalid(scope.$element);
+ $invalidWidgets.markInvalid(scope.$element);
element.addClass('ng-input-indicator-wait');
asynchronousFn(input, function(error, data) {
inputState.response = data;
@@ -393,14 +395,14 @@ extend(angularValidator, {
inputState.inFlight = false;
if (cache.current == input) {
element.removeClass('ng-input-indicator-wait');
- scope.$invalidWidgets.markValid(element);
+ $invalidWidgets.markValid(element);
}
element.data($$validate)();
scope.$root.$eval();
});
} else if (inputState.inFlight) {
// request in flight, mark widget invalid, but don't show it to user
- scope.$invalidWidgets.markInvalid(scope.$element);
+ $invalidWidgets.markInvalid(scope.$element);
} else {
(updateFn||noop)(inputState.response);
}
diff --git a/src/widgets.js b/src/widgets.js
index 532627eb..a09ee29d 100644
--- a/src/widgets.js
+++ b/src/widgets.js
@@ -271,7 +271,7 @@ function valueAccessor(scope, element) {
formatterName = element.attr('ng:format') || NOOP,
formatter = angularFormatter(formatterName),
format, parse, lastError, required,
- invalidWidgets = scope.$invalidWidgets || {markValid:noop, markInvalid:noop};
+ invalidWidgets = scope.$inject('$invalidWidgets') || {markValid:noop, markInvalid:noop};
if (!validator) throw "Validator named '" + validatorName + "' not found.";
if (!formatter) throw "Formatter named '" + formatterName + "' not found.";
format = formatter.format;
diff --git a/test/BinderTest.js b/test/BinderTest.js
index 58081f25..c5c81ee9 100644
--- a/test/BinderTest.js
+++ b/test/BinderTest.js
@@ -515,38 +515,38 @@ BinderTest.prototype.testValidateForm = function() {
var items = [{}, {}];
c.scope.$set("items", items);
c.scope.$eval();
- assertEquals(3, c.scope.$get("$invalidWidgets.length"));
+ assertEquals(3, c.scope.$inject('$invalidWidgets').length);
c.scope.$set('name', '');
c.scope.$eval();
- assertEquals(3, c.scope.$get("$invalidWidgets.length"));
+ assertEquals(3, c.scope.$inject('$invalidWidgets').length);
c.scope.$set('name', ' ');
c.scope.$eval();
- assertEquals(3, c.scope.$get("$invalidWidgets.length"));
+ assertEquals(3, c.scope.$inject('$invalidWidgets').length);
c.scope.$set('name', 'abc');
c.scope.$eval();
- assertEquals(2, c.scope.$get("$invalidWidgets.length"));
+ assertEquals(2, c.scope.$inject('$invalidWidgets').length);
items[0].name = 'abc';
c.scope.$eval();
- assertEquals(1, c.scope.$get("$invalidWidgets.length"));
+ assertEquals(1, c.scope.$inject('$invalidWidgets').length);
items[1].name = 'abc';
c.scope.$eval();
- assertEquals(0, c.scope.$get("$invalidWidgets.length"));
+ assertEquals(0, c.scope.$inject('$invalidWidgets').length);
};
BinderTest.prototype.testValidateOnlyVisibleItems = function(){
var c = this.compile('<div><input name="name" ng:required><input ng:show="show" name="name" ng:required></div>', undefined, jqLite(document.body));
c.scope.$set("show", true);
c.scope.$eval();
- assertEquals(2, c.scope.$get("$invalidWidgets.length"));
+ assertEquals(2, c.scope.$inject('$invalidWidgets').length);
c.scope.$set("show", false);
c.scope.$eval();
- assertEquals(1, c.scope.$invalidWidgets.visible());
+ assertEquals(1, c.scope.$inject('$invalidWidgets').visible());
};
BinderTest.prototype.testDeleteAttributeIfEvaluatesFalse = function() {
diff --git a/test/InjectorSpec.js b/test/InjectorSpec.js
index ba0f27f7..275d98ff 100644
--- a/test/InjectorSpec.js
+++ b/test/InjectorSpec.js
@@ -53,19 +53,9 @@ describe('injector', function(){
it('should autostart eager services', function(){
var log = '';
- providers('eager', function(){log += 'eager;';}, {$creation: 'eager'});
+ providers('eager', function(){log += 'eager;'; return 'foo'}, {$creation: 'eager'});
inject();
expect(log).toEqual('eager;');
- expect(scope.eager).not.toBeDefined();
+ expect(inject('eager')).toBe('foo');
});
-
-
- it('should return a list of published objects', function(){
- var log = '';
- providers('eager', function(){log += 'eager;'; return 'pub'; }, {$creation: 'eager-published'});
- inject();
- expect(log).toEqual('eager;');
- expect(scope.eager).toEqual('pub');
-
- });
-}); \ No newline at end of file
+});
diff --git a/test/ValidatorsTest.js b/test/ValidatorsTest.js
index f740c7b2..d6df7184 100644
--- a/test/ValidatorsTest.js
+++ b/test/ValidatorsTest.js
@@ -128,7 +128,7 @@ describe('Validator:asynchronous', function(){
it("should not make second request to same value", function(){
asynchronous.call(self, "kai", function(v,f){value=v; fn=f;});
expect(value).toEqual('kai');
- expect(self.$invalidWidgets[0]).toEqual(self.$element);
+ expect(self.$inject('$invalidWidgets')[0]).toEqual(self.$element);
var spy = jasmine.createSpy();
asynchronous.call(self, "kai", spy);
diff --git a/test/servicesSpec.js b/test/servicesSpec.js
index 014acae4..e7bf39cb 100644
--- a/test/servicesSpec.js
+++ b/test/servicesSpec.js
@@ -24,7 +24,7 @@ describe("service", function(){
it("should inject $window", function(){
- expect(scope.$window).toEqual(window);
+ expect(scope.$inject('$window')).toEqual(window);
});
xit('should add stylesheets', function(){
@@ -44,11 +44,12 @@ describe("service", function(){
function warn(){ logger+= 'warn;'; }
function info(){ logger+= 'info;'; }
function error(){ logger+= 'error;'; }
- var scope = createScope({}, angularService, {$window: {console:{log:log, warn:warn, info:info, error:error}}, $document:[{cookie:''}]});
- scope.$log.log();
- scope.$log.warn();
- scope.$log.info();
- scope.$log.error();
+ var scope = createScope({}, angularService, {$window: {console:{log:log, warn:warn, info:info, error:error}}, $document:[{cookie:''}]}),
+ $log = scope.$inject('$log');
+ $log.log();
+ $log.warn();
+ $log.info();
+ $log.error();
expect(logger).toEqual('log;warn;info;error;');
});
@@ -56,19 +57,21 @@ describe("service", function(){
var logger = "";
function log(){ logger+= 'log;'; }
var scope = createScope({}, angularService, {$window: {console:{log:log}}, $document:[{cookie:''}]});
- scope.$log.log();
- scope.$log.warn();
- scope.$log.info();
- scope.$log.error();
+ var $log = scope.$inject('$log');
+ $log.log();
+ $log.warn();
+ $log.info();
+ $log.error();
expect(logger).toEqual('log;log;log;log;');
});
it('should use noop if no console', function(){
- var scope = createScope({}, angularService, {$window: {}, $document:[{cookie:''}]});
- scope.$log.log();
- scope.$log.warn();
- scope.$log.info();
- scope.$log.error();
+ var scope = createScope({}, angularService, {$window: {}, $document:[{cookie:''}]}),
+ $log = scope.$inject('$log');
+ $log.log();
+ $log.warn();
+ $log.info();
+ $log.error();
});
describe('Error', function(){
@@ -112,7 +115,7 @@ describe("service", function(){
it('should log errors', function(){
var error = '';
$log.error = function(m) { error += m; };
- scope.$exceptionHandler('myError');
+ scope.$inject('$exceptionHandler')('myError');
expect(error).toEqual('myError');
});
});
@@ -263,25 +266,26 @@ describe("service", function(){
scope = compile('<input name="price" ng:required ng:validate="number"></input>');
jqLite(document.body).append(scope.$element);
scope.$init();
- expect(scope.$invalidWidgets.length).toEqual(1);
+ var $invalidWidgets = scope.$inject('$invalidWidgets');
+ expect($invalidWidgets.length).toEqual(1);
scope.price = 123;
scope.$eval();
- expect(scope.$invalidWidgets.length).toEqual(0);
+ expect($invalidWidgets.length).toEqual(0);
scope.$element.remove();
scope.price = 'abc';
scope.$eval();
- expect(scope.$invalidWidgets.length).toEqual(0);
+ expect($invalidWidgets.length).toEqual(0);
jqLite(document.body).append(scope.$element);
scope.price = 'abcd'; //force revalidation, maybe this should be done automatically?
scope.$eval();
- expect(scope.$invalidWidgets.length).toEqual(1);
+ expect($invalidWidgets.length).toEqual(1);
jqLite(document.body).html('');
scope.$eval();
- expect(scope.$invalidWidgets.length).toEqual(0);
+ expect($invalidWidgets.length).toEqual(0);
});
});