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

fix(re-bootstrap): Throw an error when bootstrapping a bootstrapped element #3411

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/components/angular-bootstrap/bootstrap-prettify.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location',
embedRootScope.$destroy();
});

element.data('$injector', null);
angular.bootstrap(element, modules);
}
};
Expand Down
29 changes: 29 additions & 0 deletions docs/content/error/ng/btstrpd.ngdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@ngdoc error
@name ng:btstrpd
@fullName App Already Bootstrapped with this Element
@description

Occurs when calling angular.bootstrap on an element that has already been bootstrapped.

This usually happens when you accidentally use both `ng-app` and `angular.bootstrap` to bootstrap an application.

```
<html>
...
<body ng-app="myApp">
<script>
angular.bootstrap(document.body, ['myApp']);
</script>
</body>
</html>
```

Note that for bootrapping purposes, the `<html>` element is the same as `document`, so the following will also throw an error.
```
<html>
...
<script>
angular.bootstrap(document, ['myApp']);
</script>
</html>
```
6 changes: 6 additions & 0 deletions src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,12 @@ function angularInit(element, bootstrap) {
function bootstrap(element, modules) {
var doBootstrap = function() {
element = jqLite(element);

if (element.injector()) {
var tag = (element[0] === document) ? 'document' : startingTag(element);
throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
}

modules = modules || [];
modules.unshift(['$provide', function($provide) {
$provide.value('$rootElement', element);
Expand Down
2 changes: 1 addition & 1 deletion src/jqLite.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ function JQLiteInheritedData(element, name, value) {
}

while (element.length) {
if (value = element.data(name)) return value;
if ((value = element.data(name)) !== undefined) return value;
element = element.parent();
}
}
Expand Down
26 changes: 26 additions & 0 deletions test/AngularSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,32 @@ describe('angular', function() {
/\[\$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\./
);
});


it('should complain if an element has already been bootstrapped', function () {
var element = jqLite('<div>bootstrap me!</div>');
angular.bootstrap(element);

expect(function () {
angular.bootstrap(element);
}).toThrowMatching(
/\[ng:btstrpd\] App Already Bootstrapped with this Element '<div class="?ng\-scope"?( ng\-[0-9]+="?[0-9]+"?)?>'/i
);

dealoc(element);
});


it('should complain if manually bootstrapping a document whose <html> element has already been bootstrapped', function () {
angular.bootstrap(document.getElementsByTagName('html')[0]);
expect(function () {
angular.bootstrap(document);
}).toThrowMatching(
/\[ng:btstrpd\] App Already Bootstrapped with this Element 'document'/i
);

dealoc(document);
})
});


Expand Down
14 changes: 14 additions & 0 deletions test/jqLiteSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,20 @@ describe('jqLite', function() {
dealoc(doc);
}
);

it('should return null values', function () {
var ul = jqLite('<ul><li><p><b>deep deep</b><p></li></ul>'),
li = ul.find('li'),
b = li.find('b');

ul.data('foo', 'bar');
li.data('foo', null);
expect(b.inheritedData('foo')).toBe(null);
expect(li.inheritedData('foo')).toBe(null);
expect(ul.inheritedData('foo')).toBe('bar');

dealoc(ul);
});
});


Expand Down
2 changes: 1 addition & 1 deletion test/testabilityPatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ afterEach(function() {
forEachSorted(cache, function(expando, key){
angular.forEach(expando.data, function(value, key){
count ++;
if (value.$element) {
if (value && value.$element) {
dump('LEAK', key, value.$id, sortedHtml(value.$element));
} else {
dump('LEAK', key, angular.toJson(value));
Expand Down