aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMisko Hevery2012-02-27 12:14:48 -0800
committerMisko Hevery2012-06-02 16:02:05 -0700
commit2e90cdc3d4dff966faed97d3a566e9d9c00c9794 (patch)
tree413ba0078f5decf7026791177dfcf8e3ff5f0662
parent581f93ae56ebb0086d0c0989df69a28656395006 (diff)
downloadangular.js-2e90cdc3d4dff966faed97d3a566e9d9c00c9794.tar.bz2
docs(dependency injecton): rewrite
-rw-r--r--docs/content/guide/dev_guide.di.ngdoc32
-rw-r--r--docs/content/guide/dev_guide.di.understanding_di.ngdoc193
-rw-r--r--docs/content/guide/dev_guide.di.using_di_controllers.ngdoc52
-rw-r--r--docs/content/guide/dev_guide.mvc.ngdoc2
-rw-r--r--docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc2
-rw-r--r--docs/content/guide/dev_guide.services.creating_services.ngdoc4
-rw-r--r--docs/content/guide/dev_guide.services.ngdoc4
-rw-r--r--docs/content/guide/dev_guide.services.understanding_services.ngdoc2
-rw-r--r--docs/content/guide/dev_guide.unit-testing.ngdoc2
-rw-r--r--docs/content/guide/di.ngdoc234
-rw-r--r--docs/content/guide/index.ngdoc5
-rw-r--r--src/auto/injector.js2
12 files changed, 244 insertions, 290 deletions
diff --git a/docs/content/guide/dev_guide.di.ngdoc b/docs/content/guide/dev_guide.di.ngdoc
deleted file mode 100644
index b21b05a7..00000000
--- a/docs/content/guide/dev_guide.di.ngdoc
+++ /dev/null
@@ -1,32 +0,0 @@
-@ngdoc overview
-@name Developer Guide: About Dependency Injection (DI)
-@description
-
-Dependency Injection (DI) is an object-oriented software design pattern that supports the
-decoupling and dependency management of application components.
-
-The idea behind DI is to decouple each component from all of the other components that it depends
-on to do its particular job. The way this is done in DI is by moving the responsibility for
-managing dependencies out of each individual component and into a provider component. The provider
-(or injector) component manages the life cycles and dependencies for all of the other components in
-an application.
-
-Angular has a built-in dependency management subsystem that helps to make your applications easier
-to develop, understand, and test.
-
-For more information on DI in general, see {@link http://en.wikipedia.org/wiki/Dependency_injection
-Dependency Injection} at Wikipedia, and {@link http://martinfowler.com/articles/injection.html
-Inversion of Control} by Martin Fowler, or read about DI in your favorite software design pattern
-book.
-
-
-## Related Topics
-
-* {@link dev_guide.di.understanding_di Understanding DI in Angular}
-* {@link dev_guide.services Angular Services}
-
-
-## Related API
-
-* {@link api/angular.module.ng Service API}
-* {@link api/angular.injector Angular Injector API}
diff --git a/docs/content/guide/dev_guide.di.understanding_di.ngdoc b/docs/content/guide/dev_guide.di.understanding_di.ngdoc
deleted file mode 100644
index 23b22884..00000000
--- a/docs/content/guide/dev_guide.di.understanding_di.ngdoc
+++ /dev/null
@@ -1,193 +0,0 @@
-@ngdoc overview
-@name Developer Guide: DI: Understanding DI in Angular
-@description
-
-
-While DI is widely used in statically typed languages such as Java or C++, it has not been widely
-used in JavaScript. Angular brings the benefits of DI into JavaScript apps.
-
-In angular, DI is implemented as a subsystem that manages dependencies between services,
-controllers, widgets, and filters.
-
-Services are objects that handle common tasks in web applications. Angular provides several {@link
-api/angular.module.ng built-in services}, and you can create your
-{@link dev_guide.services.creating_services own custom services}.
-
-The main job of angular's DI subsystem is to provide services to angular components that depend on
-them. The way the DI subsystem provides services is as follows: all services are registered with
-angular's {@link api/angular.module.ng service API}, and all components that depend on services
-define those dependencies as a property (`$inject`). With this information, the DI subsystem
-manages the creation of service objects and the provision of those objects to the components that
-need them, at the time they need them. The following illustration steps through the sequence of
-events:
-
-<img src="img/guide/di_sequence_final.png">
-
-In the illustration above, the dependency injection sequence proceeds as follows:
-
-1. Module "phonecat" is created and all the service providers are registered with this module.
- (the "ng" module is created by Angular behind the scenes as well)
-2. `ngApp` triggers bootstrap sequence on given element, during which angular creates injector,
-loads "phonecat" and "ng" modules and compiles the template.
-3. The `ngController` directive implicitly creates a new child scope and instantiates
-`PhoneListCtrl` controller.
-4. Injector identifies the `$http` service as `PhoneListCtrl` controller's only dependency.
-5. Injector checks its instances cache whether the `$http` service has already been instantiated.
-If not uses the provider from the available modules to construct it.
-6. Injector provides the instance of `$http` service to the `PhoneListCtrl` controller constructor.
-
-
-## How Scope Relates to DI
-
-The root scope of the application is just a service that is available for injection to any part of
-the application under the service name "$rootScope".
-
-
-## Inferring dependencies from the signature of the factory function or constructor
-
-**EXPERIMENTAL FEATURE**: This is an experimental feature. See the important note at the end of
-this section for drawbacks.
-
-We resort to `$inject` and our own annotation because there is no way in JavaScript to get a list
-of arguments. Or is there? It turns out that calling `.toString()` on a function returns the
-function declaration along with the argument names as shown below:
-
-<pre>
-function myFn(a,b){}
-expect(myFn.toString()).toEqual('function myFn(a,b){}');
-</pre>
-
-This means that angular can infer the function names after all and use that information to generate
-the `$inject` annotation automatically. Therefore the following two function definitions are
-equivalent:
-
-<pre>
-// given a user defined service
-angular.module('module1', [], function($provide) {
- $provide.factory('serviceA', ...);
-});
-
-// inject '$window', 'serviceA', curry 'name';
-function fnA($window, serviceA, name){};
-fnA.$inject = ['$window', 'serviceA'];
-
-// inject '$window', 'serviceA', curry 'name';
-function fnB($window, serviceA_, name){};
-// implies: fnB.$inject = ['$window', 'serviceA'];
-</pre>
-
-If angular does not find a `$inject` annotation on the function, then it calls the `.toString()`
-method and tries to infer what should be injected by using function argument names as dependency
-identifiers.
-
-**IMPORTANT**
-Minifiers/obfuscators change the names of function arguments and will therefore break the `$inject`
-inference. For this reason, either explicitly declare the `$inject` or do not use
-minifiers/obfuscators. In the future, we may provide a pre-processor which will scan the source
-code and insert the `$inject` into the source code so that it can be minified/obfuscated.
-
-
-### Dependency inference and variable name shadowing
-
-During inference, the injector considers argument names with leading and trailing underscores to be
-equivivalent to the name without these underscores. For example `_fooSvc_` argument name is treated
-as if it was `fooSvc`, this is useful especially in tests where variable name shadowing can cause
-some friction. This is best illustrated on examples:
-
-When testing a service, it's common to need a reference to it in every single test. This can be
-done in jasmine with DI inference like this:
-
-<pre>
-describe('fooSvc', function() {
- it('should do this thing', inject(function(fooSvc) {
- //test fooSvc
- }));
-
- it('should do that thing', inject(function(fooSvc) {
- //test fooSvc
- }));
-
- // more its
-});
-</pre>
-
-... but having to inject the service over and over gets easily tiresome.
-
-It's likely better to rewrite these tests with a use of jasmine's `beforeEach`:
-
-<pre>
-describe('fooSvc', function() {
- var fooSvc;
-
- beforeEach(inject(function(fooSvc) {
- fooSvc = fooSvc; // DOESN'T WORK! outer fooSvc is being shadowed
- }));
-
- it('should do this thing', function() {
- //test fooSvc
- });
-
- it('should do that thing', function() {
- //test fooSvc
- });
-
- // more its
-});
-</pre>
-
-This obviously won't work because `fooSvc` variable in the describe block is being shadowed by the
-`fooSvc` argument of the beforeEach function. So we have to resort to alternative solutions, like
-for example use of array notation to annotate the beforeEach fn:
-
-<pre>
-describe('fooSvc', function() {
- var fooSvc;
-
- beforeEach(inject(['fooSvc', function(fooSvc_) {
- fooSvc = fooSvc_;
- }]));
-
- it('should do this thing', function() {
- //test fooSvc
- });
-
- it('should do that thing', function() {
- //test fooSvc
- });
-});
-</pre>
-
-
-That's better, but it's still annoying, especially if you have many services to inject.
-
-To resolve this shadowing problem, the injector considers `_fooSvc_` argument names equal to
-`fooSvc`, so the test can be rewritten like this:
-
-<pre>
- describe('fooSvc', function() {
- var fooSvc;
-
- beforeEach(inject(function(_fooSvc_) {
- fooSvc = _fooSvc_;
- }));
-
- it('should do this thing', function() {
- //test fooSvc
- });
-
- it('should do that thing', function() {
- //test fooSvc
- });
-
- // more its
- });
-</pre>
-
-
-## Related Topics
-
-* {@link dev_guide.services Angular Services}
-
-## Related API
-
-* {@link api/angular.module.ng Services API}
diff --git a/docs/content/guide/dev_guide.di.using_di_controllers.ngdoc b/docs/content/guide/dev_guide.di.using_di_controllers.ngdoc
deleted file mode 100644
index 6d1ff04b..00000000
--- a/docs/content/guide/dev_guide.di.using_di_controllers.ngdoc
+++ /dev/null
@@ -1,52 +0,0 @@
-@ngdoc overview
-@name Developer Guide: DI: Using DI in Controllers
-@description
-
-The most common place to use dependency injection in angular applications is in {@link
-dev_guide.mvc.understanding_controller controllers}. Here is a simple example:
-
-<pre>
-function MyController($location){
- // do stuff with the $location service
-}
-MyController.$inject = ['$location'];
-</pre>
-
-In this example, the `MyController` constructor function takes one argument, the {@link
-api/angular.module.ng.$location $location} service. Angular is then responsible for supplying the
-instance of `$location` to the controller when the constructor is instantiated. There are two ways
-to cause controller instantiation – by configuring routes with the `$location` service, or by
-referencing the controller from the HTML template, as follows:
-
-<pre>
-<!doctype html>
-<html ng-controller="MyController" ng-app>
-<script src="http://code.angularjs.org/angular.min.js"></script>
-<body>
- ...
-</body>
-</html>
-</pre>
-
-When angular is instantiating your controller, it needs to know what services, if any, should be
-injected (passed in as arguments) into the controller. Since there is no reflection in JavaScript,
-we have to supply this information to angular in the form of an additional property on the
-controller constructor function called `$inject`. Think of it as annotations for JavaScript.
-
-<pre>
-MyController.$inject = ['$location'];
-</pre>
-
-The information in `$inject` is then used by the {@link api/angular.injector injector} to call the
-function with the correct arguments.
-
-
-## Related Topics
-
-* {@link dev_guide.di About Dependency Injection}
-* {@link dev_guide.di.understanding_di Understanding Dependency Injection in Angular}
-* {@link dev_guide.services Angular Services}
-
-## Related API
-
-* {@link api/angular.injector Angular Injector API}
diff --git a/docs/content/guide/dev_guide.mvc.ngdoc b/docs/content/guide/dev_guide.mvc.ngdoc
index c6ddc282..4555a6b2 100644
--- a/docs/content/guide/dev_guide.mvc.ngdoc
+++ b/docs/content/guide/dev_guide.mvc.ngdoc
@@ -12,7 +12,7 @@ The MVC pattern greatly summarized:
* Separate applications into distinct presentation, data, and logic components
* Encourage loose coupling between these components
-Along with {@link dev_guide.services services} and {@link dev_guide.di dependency injection}, MVC
+Along with {@link dev_guide.services services} and {@link di dependency injection}, MVC
makes angular applications better structured, easier to maintain and more testable.
The following topics explain how angular incorporates the MVC pattern into the angular way of
diff --git a/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc b/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc
index b95bdf5b..edaddf66 100644
--- a/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc
+++ b/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc
@@ -47,7 +47,7 @@ needed for a single view.
The most common way to keep controllers slim is by encapsulating work that doesn't belong to
controllers into services and then using these services in controllers via dependency injection.
-This is discussed in the {@link dev_guide.di Dependency Injection} {@link dev_guide.services
+This is discussed in the {@link di Dependency Injection} {@link dev_guide.services
Services} sections of this guide.
Do not use controllers for:
diff --git a/docs/content/guide/dev_guide.services.creating_services.ngdoc b/docs/content/guide/dev_guide.services.creating_services.ngdoc
index 4ce16a76..67471cdd 100644
--- a/docs/content/guide/dev_guide.services.creating_services.ngdoc
+++ b/docs/content/guide/dev_guide.services.creating_services.ngdoc
@@ -7,7 +7,7 @@ to write your own custom services. To do this you begin by registering a service
with a module either via the {@link api/angular.module Module#factory api} or directly
via the {@link api/angular.module.AUTO.$provide $provide} api inside of module config function.
-All angular services participate in {@link dev_guide.di dependency injection (DI)} by registering
+All angular services participate in {@link di dependency injection (DI)} by registering
themselves with Angular's DI system (injector) under a `name` (id) as well as by declaring
dependencies which need to be provided for the factory function of the registered service. The
ability to swap dependencies for mocks/stubs/dummies in tests allows for services to be highly
@@ -49,7 +49,7 @@ create this instance when called.
# Dependencies
Services can not only be depended upon, but also have its own dependencies. These can be specified
-as arguments of the factory function. {@link dev_guide.di.understanding_di Read more} about the DI
+as arguments of the factory function. {@link di.understanding_di Read more} about the DI
in Angular and the use of array notation and $inject property to make DI annotation
minification-proof.
diff --git a/docs/content/guide/dev_guide.services.ngdoc b/docs/content/guide/dev_guide.services.ngdoc
index bd000507..022f541a 100644
--- a/docs/content/guide/dev_guide.services.ngdoc
+++ b/docs/content/guide/dev_guide.services.ngdoc
@@ -4,8 +4,8 @@
Services are a feature that angular brings to client-side web apps from the server side, where
services have been commonly used for a long time. Services in angular apps are substitutable
-objects that are wired together using {@link dev_guide.di dependency injection (DI)}. Services are
-most often used with {@link dev_guide.di dependency injection}, also a key feature of angular apps.
+objects that are wired together using {@link di dependency injection (DI)}. Services are
+most often used with {@link di dependency injection}, also a key feature of angular apps.
## Related Topics
diff --git a/docs/content/guide/dev_guide.services.understanding_services.ngdoc b/docs/content/guide/dev_guide.services.understanding_services.ngdoc
index 390ced0c..d7a8a0f4 100644
--- a/docs/content/guide/dev_guide.services.understanding_services.ngdoc
+++ b/docs/content/guide/dev_guide.services.understanding_services.ngdoc
@@ -25,7 +25,7 @@ above). You can also create your own custom services.
## Related Topics
-* {@link dev_guide.di About Angular Dependency Injection}
+* {@link di About Angular Dependency Injection}
* {@link dev_guide.services.creating_services Creating Angular Services}
* {@link dev_guide.services.managing_dependencies Managing Service Dependencies}
* {@link dev_guide.services.testing_services Testing Angular Services}
diff --git a/docs/content/guide/dev_guide.unit-testing.ngdoc b/docs/content/guide/dev_guide.unit-testing.ngdoc
index 79af465b..f9e148eb 100644
--- a/docs/content/guide/dev_guide.unit-testing.ngdoc
+++ b/docs/content/guide/dev_guide.unit-testing.ngdoc
@@ -164,7 +164,7 @@ myClass.doWork();
Notice that no global variables were harmed in the writing of this test.
-Angular comes with {@link dev_guide.di dependency-injection} built in which makes the right thing
+Angular comes with {@link di dependency-injection} built in which makes the right thing
easy to do, but you still need to do it if you wish to take advantage of the testability story.
## Controllers
diff --git a/docs/content/guide/di.ngdoc b/docs/content/guide/di.ngdoc
new file mode 100644
index 00000000..d75d5b09
--- /dev/null
+++ b/docs/content/guide/di.ngdoc
@@ -0,0 +1,234 @@
+@ngdoc overview
+@name Developer Guide: Dependency Injection
+@description
+
+# Dependency Injection
+
+Dependency Injection (DI) is a software design pattern that deals with how code gets hold of its
+dependencies.
+
+For in-depth discussion about DI, see {@link http://en.wikipedia.org/wiki/Dependency_injection
+Dependency Injection} at Wikipedia, {@link http://martinfowler.com/articles/injection.html
+Inversion of Control} by Martin Fowler, or read about DI in your favorite software design pattern
+book.
+
+## DI in a nutshell
+
+There are only three ways how an object or a function can get a hold of its dependencies:
+
+ 1. The dependency can be created, typically using the `new` operator.
+
+ 2. The dependency can be looked up by referring to a global variable.
+
+ 3. The dependency can be passed in to where it is needed.
+
+
+The first two option of creating or looking up dependencies are not optimal, because they hard
+code the dependency, making it difficult, if not impossible, to modify the dependencies.
+This is especially problematic in tests, where it is often desirable to provide mock dependencies
+for test isolation.
+
+The third option is the most viable, since it removes the responsibility of locating the
+dependency from the component. The dependency is simply handed to the component.
+
+<pre>
+ function SomeClass(greeter) {
+ this.greeter = greeter
+ }
+
+ SomeClass.prototype.doSomething = function(name) {
+ this.greeter.greet(name);
+ }
+</pre>
+
+In the above example the `SomeClass` is not concerned with locating the `greeter` dependency, it
+is simply handed the `greeter` at runtime.
+
+This is desirable, but it puts the responsibility of getting hold of the dependency onto the
+code responsible for the construction of `SomeClass`.
+
+To manage the responsibility of dependency creation, each angular application has an {@link
+api/angular.injector injector}. The injector is a service locator that is responsible for
+construction and lookup of dependencies.
+
+
+Here is an example of using the injector service.
+<pre>
+ // Provide the wiring information in a module
+ angular.module('myModule', []).
+
+ // Teach the injector how to build a 'greeter'
+ // Notice that greeter itself is dependent on '$window'
+ factory('greeter', function($window) {
+ // This is a factory function, and is responsible for
+ // creating the 'greet' service.
+ return {
+ greet: function(text) {
+ $window.alert(text);
+ }
+ };
+ }).
+
+ // New injector is created from the module.
+ // (This is usually done automatically by angular bootstrap)
+ var injector = angular.injector('myModule');
+
+ // Request any dependency from the injector
+ var greeter = injector.get('greeter');
+</pre>
+
+Asking for dependencies solves the issue of hard coding, but it also means that the injector needs
+to be passed throughout the application. Passing the injector breaks the {@link
+http://en.wikipedia.org/wiki/Law_of_Demeter Law of Demeter}. To remedy this, we turn the
+dependency lookup responsibility to the injector by declaring the dependencies as in this example:
+
+<pre>
+ <!-- Given this HTML -->
+ <div ng-controller="MyController">
+ <button ng-click="sayHello()">Hello</button>
+ </div>
+</pre>
+<pre>
+ // And this controller definition
+ function MyController($scope, greeter) {
+ $scope.sayHello = function() {
+ greeter('Hello World');
+ };
+ }
+
+ // The 'ng-controller' directive does this behind the scenes
+ injector.instantiate(MyController);
+</pre>
+
+Notice that by having the `ng-controller` instantiate the class, it can satisfy all of the
+dependencies of the `MyController` without the controller ever knowing about the injector. This is
+the best outcome. The application code simply ask for the dependencies it needs, without having to
+deal with the injector. This setup does not break the Law of Demeter.
+
+# Dependency Annotation
+
+How does the injector know what service needs to be injected?
+
+The application developer needs to provide annotation information, that the injector uses in order
+to resolve the dependencies. Throughout Angular certain API functions are invoked using the
+injector, as per the API documentation. The injector needs to know what services to inject into
+the function. Below are three equivalent ways of annotating your code with service name
+information. These can be used interchangeably as you see fit and are equivalent.
+
+# Inferring Dependencies
+
+The simplest way to get hold of the dependencies, is to assume that the function parameter names
+are the names of the dependencies.
+
+<pre>
+ function MyController($scope, greeter) {
+ ...
+ }
+</pre>
+
+Given a function the injector can infer the names of the service to inject by examining the
+function declaration and extracting the parameter names. In the above example `$scope`, and
+`greeter` are two services which need to be injected into the function.
+
+While straightforward, this method will not work with JavaScript minifiers/obfuscators as they
+rename the method parameter names. This makes this way of annotating only useful for {@link
+http://www.pretotyping.org/ pretotyping}, and demo applications.
+
+# `$inject` Annotation
+
+To allow the minifers to rename the function parameters and still be able to inject right services
+the function needs to be annotate with the `$inject` property. The `$inject` property is an array
+of service names to inject.
+
+<pre>
+ var MyController = function(renamed$scope, renamedGreeter) {
+ ...
+ }
+ MyController.$inject = ['$scope', 'greeter'];
+</pre>
+
+Care must be taken that the `$inject` annotation is kept in sync with the actual arguments in the
+function declaration.
+
+This method of annotation is useful for controller declarations since it assigns the annotation
+information with the function.
+
+# Inline Annotation
+
+Sometimes using the `$inject` annotation style is not convenient such as when annotating
+directives.
+
+For example:
+<pre>
+ someModule.factory('greeter', function($window) {
+ ...;
+ });
+</pre>
+
+Results in code bloat do to the need of temporary variable:
+<pre>
+ var greeterFactory = function(renamed$window) {
+ ...;
+ };
+
+ greeterFactory.$inject = ['$window'];
+
+ someModule.factory('greeter', greeterFactory);
+</pre>
+
+For this reason the third annotation style is provided as well.
+<pre>
+ someModule.factory('greeter', ['$window', function(renamed$window) {
+ ...;
+ }]);
+</pre>
+
+Keep in mind that all of the annotation styles are equivalent and can be used anywhere in Angular
+where injection is supported.
+
+
+# Where can I use DI?
+
+DI is pervasive throughout Angular. It is typically used in controllers and factory methods.
+
+## DI in controllers
+
+Controllers are classes which are responsible for application behavior. Recommended way of
+declaring controllers is:
+
+<pre>
+ var MyController = function(dep1, dep2) {
+ ...
+ }
+ MyController.$inject = ['dep1', 'dep2'];
+
+ MyController.prototype.aMethod = function() {
+ ...
+ }
+</pre>
+
+
+## Factory methods
+
+Factory methods are responsible for creating most objects in Angular. Examples are directives,
+services, and filters. The factory methods are register with the module, and the recommended way
+of declaring factories is:
+
+<pre>
+ angualar.module('myModule', []).
+ config(['depProvider', function(depProvider){
+ ...
+ }]).
+ factory('serviceId', ['depService', function(depService) {
+ ...
+ }]).
+ directive('directiveName', ['depService', function(depService) {
+ ...
+ }]).
+ filter('filterName', ['depService', function(depService) {
+ ...
+ }]).
+ run(['depService', function(depService) {
+ ...
+ }]);
+</pre> \ No newline at end of file
diff --git a/docs/content/guide/index.ngdoc b/docs/content/guide/index.ngdoc
index d2a1ac37..377fdb97 100644
--- a/docs/content/guide/index.ngdoc
+++ b/docs/content/guide/index.ngdoc
@@ -44,7 +44,4 @@ of the following documents before returning here to the Developer Guide:
* {@link dev_guide.services.managing_dependencies Managing Service Dependencies}
* {@link dev_guide.services.testing_services Testing Angular Services}
-## {@link dev_guide.di About Dependency Injection}
-
-* {@link dev_guide.di.understanding_di Understanding DI in Angular}
-* {@link dev_guide.di.using_di_controllers Using DI in Controllers}
+## {@link di About Dependency Injection}
diff --git a/src/auto/injector.js b/src/auto/injector.js
index 49247ff4..fd664b0e 100644
--- a/src/auto/injector.js
+++ b/src/auto/injector.js
@@ -7,7 +7,7 @@
*
* @description
* Creates an injector function that can be used for retrieving services as well as for
- * dependency injection (see {@link guide/dev_guide.di dependency injection}).
+ * dependency injection (see {@link guide/di dependency injection}).
*
* @param {Array.<string|Function>} modules A list of module functions or their aliases. See