functionbootstrap(element, modules) {var doBootstrap = function() {// Convert the element we passed in to a jqLite element.
element = jqLite(element);
// Check to see if there is an injector setup for the element already. If there is an// injector it means this element has already been bootstrapped, so throw an error.if (element.injector()) {
var tag = (element[0] === document) ? 'document' : startingTag(element);
throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
}
// Assign modules to an empty array if it is undefined.
modules = modules || [];
// Add a function to the modules array which provides $rootElement to the// element that is being bootstrapped.
modules.unshift(['$provide', function($provide) {
$provide.value('$rootElement', element);
}]);
// Add ng to the modules array.
modules.unshift('ng');
// Create an injector instance and assign it to "injector". More on injectors later.var injector = createInjector(modules);
// Invoke scope.$apply() and inject scope, element, compile, injector and animate// as dependencies.
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
function(scope, element, compile, injector, animate) {// Behind the scenes this is just executing the anonymous function and then// running a $root.$digest() after it's finished.
scope.$apply(function() {// Setup the injector on the element we are bootstrapping.
element.data('$injector', injector);
// Compile our element and link it to the current scope.
compile(element)(scope);
});
}]
);
// Return our injector instance.return injector;
};
// ...
}

There’s a lot to digest here and a number of things that warrant investigation of their own. For this article we are going to focus on the contents of bootstrap(), but we’ll cover things like dependency injection and compilation in future posts. For now just focus on the flow of the app and that at this point we have an instance of the $injectorreturned from our doBootstrap() helper method. Now let’s dissect the rest of bootstrap().

The rest of bootstrap() either invokes doBootstrap() right away or defers bootstrapping until resumeBootstrap() is called. This allows third party tools to tie into the bootstrapping process by appending NG_DEFER_BOOTSTRAP to window.name and then calling angular.resumeBootstrap() with an array of additional modules. This is commonly used for mocking out heavy dependencies while testing.

Ready for Action

Now that our element is compiled with its dependencies and scope, we are ready for action! The element we passed in to angular.bootstrap() is no longer just a static element, it’s a dynamic Angular app that is ready for user interaction.