Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 3ee744c

Browse files
committed
fix(re-bootstrap): Throw an error when bootstrapping a bootstrapped element.
Nothing would prevent a user from accidentally calling angular.bootstrap on an element that had already been bootstrapped. If this was done, odd behavior could manifest in an application, causing different scopes to update the same DOM, and causing debugger confusion. This fix adds a check inside of angular.bootstrap to check if the passed-in element already has an injector, and if so, will throw an error.
1 parent 94ec84e commit 3ee744c

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

docs/content/error/ng/btstrpd.ngdoc

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
@ngdoc error
2+
@name ng:btstrpd
3+
@fullName App Already Bootstrapped with this Element
4+
@description
5+
6+
Occurs when calling angular.bootstrap on an element that has already been bootstrapped.
7+
8+
This usually happens when you accidentally use both `ng-app` and `angular.bootstrap` to bootstrap an application.
9+
10+
```
11+
<html>
12+
...
13+
<body ng-app="myApp">
14+
<script>
15+
angular.bootstrap(document.body, ['myApp']);
16+
</script>
17+
</body>
18+
</html>
19+
```
20+
21+
Note that for bootrapping purposes, the `<html>` element is the same as `document`, so the following will also throw an error.
22+
```
23+
<html>
24+
...
25+
<script>
26+
angular.bootstrap(document, ['myApp']);
27+
</script>
28+
</html>
29+
```

src/Angular.js

+6
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,12 @@ function angularInit(element, bootstrap) {
10491049
function bootstrap(element, modules) {
10501050
var doBootstrap = function() {
10511051
element = jqLite(element);
1052+
1053+
if (element.injector()) {
1054+
var tag = (element[0] === document) ? 'document' : startingTag(element);
1055+
throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
1056+
}
1057+
10521058
modules = modules || [];
10531059
modules.unshift(['$provide', function($provide) {
10541060
$provide.value('$rootElement', element);

test/AngularSpec.js

+26
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,32 @@ describe('angular', function() {
656656
/\[\$injector:modulerr] Failed to instantiate module doesntexist due to:\n.*\[\$injector:nomod] Module 'doesntexist' is not available! You either misspelled the module name or forgot to load it\./
657657
);
658658
});
659+
660+
661+
it('should complain if an element has already been bootstrapped', function () {
662+
var element = jqLite('<div>bootstrap me!</div>');
663+
angular.bootstrap(element);
664+
665+
expect(function () {
666+
angular.bootstrap(element);
667+
}).toThrowMatching(
668+
/\[ng:btstrpd\] App Already Bootstrapped with this Element '<div class="?ng\-scope"?( ng\-[0-9]+="?[0-9]+"?)?>'/i
669+
);
670+
671+
dealoc(element);
672+
});
673+
674+
675+
it('should complain if manually bootstrapping a document whose <html> element has already been bootstrapped', function () {
676+
angular.bootstrap(document.getElementsByTagName('html')[0]);
677+
expect(function () {
678+
angular.bootstrap(document);
679+
}).toThrowMatching(
680+
/\[ng:btstrpd\] App Already Bootstrapped with this Element 'document'/i
681+
);
682+
683+
dealoc(document);
684+
})
659685
});
660686

661687

0 commit comments

Comments
 (0)