-
Notifications
You must be signed in to change notification settings - Fork 27.4k
perf($compile): replace forEach(controller) with plain loops #11084
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not a big fan of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally I often prefer Could use The other option is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am happy with |
||
var directive = controllerDirectives[controllerKey]; | ||
var locals = { | ||
$scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can just be $scope: isolateScope || scope, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so... we only want the isolated scope if this controller is for the isolated scope directive. There might be other controllers that need to be initialized with the normal scope... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But the only place that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But that doesn't mean There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doh! Sorry. Yes, you are right - I didn't notice the comparison with |
||
$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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
by adding
newIsolateScopeDirective
as a parameter, this can be moved out of the closure (or I am missing something?)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would also need access to
hasElementTranscludeDirective
. Let's not go there for now...