From 77615b0a3e396fc18eff147682d1fe434d5d169a Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Mon, 16 Feb 2015 23:05:43 -0800 Subject: [PATCH] perf($compile): replace forEach(controller) with plain loops --- src/ng/compile.js | 70 +++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 69d9d778b330..f97c780d7061 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1671,7 +1671,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (!directive.templateUrl && directive.controller) { directiveValue = directive.controller; - controllerDirectives = controllerDirectives || {}; + controllerDirectives = controllerDirectives || createMap(); assertNoDuplicate("'" + directiveName + "' controller", controllerDirectives[directiveName], directive, $compileNode); controllerDirectives[directiveName] = directive; @@ -1877,6 +1877,36 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return value || null; } + function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) { + var elementControllers = createMap(); + for (var controllerKey in controllerDirectives) { + var directive = controllerDirectives[controllerKey]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; + + var controller = directive.controller; + if (controller == '@') { + controller = attrs[directive.name]; + } + + var controllerInstance = $controller(controller, locals, true, directive.controllerAs); + + // For directives with element transclusion the element is a comment, + // but jQuery .data doesn't support attaching data to comment nodes as it's hard to + // clean up (http://bugs.jquery.com/ticket/8335). + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + if (!hasElementTranscludeDirective) { + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } + } + return elementControllers; + } function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn, thisLinkFn) { @@ -1903,32 +1933,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } if (controllerDirectives) { - elementControllers = {}; - forEach(controllerDirectives, function(directive) { - var locals = { - $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, - $element: $element, - $attrs: attrs, - $transclude: transcludeFn - }, controllerInstance; - - controller = directive.controller; - if (controller == '@') { - controller = attrs[directive.name]; - } - - controllerInstance = $controller(controller, locals, true, directive.controllerAs); - - // For directives with element transclusion the element is a comment, - // but jQuery .data doesn't support attaching data to comment nodes as it's hard to - // clean up (http://bugs.jquery.com/ticket/8335). - // Instead, we save the controllers for the element in a local hash and attach to .data - // later, once we have the actual element. - elementControllers[directive.name] = controllerInstance; - if (!hasElementTranscludeDirective) { - $element.data('$' + directive.name + 'Controller', controllerInstance.instance); - } - }); + elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope); } if (newIsolateScopeDirective) { @@ -1958,17 +1963,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { bindings, scopeDirective); } } - forEach(elementControllers, function(controller) { - var result = controller(); - if (result !== controller.instance && + for (i in elementControllers) { + controller = elementControllers[i]; + var controllerResult = controller(); + if (controllerResult !== controller.instance && controller === controllerForBindings) { // Remove and re-install bindToController bindings thisLinkFn.$$destroyBindings(); thisLinkFn.$$destroyBindings = - initializeDirectiveBindings(scope, attrs, result, + initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective); } - }); + } } // PRELINKING