Skip to content

Commit

Permalink
refactor($compile): remove preAssignBindingsEnabled leftovers
Browse files Browse the repository at this point in the history
Now that we don't need to support `preAssignBindingsEnabled` (removed in angular#15782), complexity introduced in `$controller` by angular#7645 can be removed.
  • Loading branch information
thorn0 committed May 26, 2018
1 parent 5262039 commit 6b9a0fc
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 127 deletions.
11 changes: 6 additions & 5 deletions src/auto/injector.js
Original file line number Diff line number Diff line change
Expand Up @@ -938,14 +938,15 @@ function createInjector(modulesToLoad, strictDi) {
fn = fn[fn.length - 1];
}

if (!isClass(fn)) {
// http://jsperf.com/angularjs-invoke-apply-vs-switch
// #5388
return fn.apply(self, args);
} else {
if (isClass(fn)) {
// This code path was used by $controller previously and is not really needed any more.
args.unshift(null);
return new (Function.prototype.bind.apply(fn, args))();
}

// http://jsperf.com/angularjs-invoke-apply-vs-switch
// #5388
return fn.apply(self, args);
}


Expand Down
130 changes: 57 additions & 73 deletions src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2788,10 +2788,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
};
}

if (controllerDirectives) {
elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective);
}

if (newIsolateScopeDirective) {
// Initialize isolate scope bindings for new isolate scope directive.
compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
Expand All @@ -2807,53 +2803,69 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
}

// Initialize bindToController bindings
for (var name in elementControllers) {
var controllerDirective = controllerDirectives[name];
var controller = elementControllers[name];
var bindings = controllerDirective.$$bindings.bindToController;
if (controllerDirectives) {
elementControllers = createMap();
for (var name in controllerDirectives) {
var directive = controllerDirectives[name];
var locals = {
$scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
$element: $element,
$attrs: attrs,
$transclude: transcludeFn
};

controller.instance = controller();
$element.data('$' + controllerDirective.name + 'Controller', controller.instance);
controller.bindingInfo =
initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
}
var controllerConstructor = directive.controller;
if (controllerConstructor === '@') {
controllerConstructor = attrs[name];
}

// Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy
forEach(controllerDirectives, function(controllerDirective, name) {
var require = controllerDirective.require;
if (controllerDirective.bindToController && !isArray(require) && isObject(require)) {
extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers));
var instance = $controller(controllerConstructor, locals, false, directive.controllerAs);

$element.data('$' + directive.name + 'Controller', instance);

// Initialize bindToController bindings
var bindings = directive.$$bindings.bindToController;
var bindingInfo = initializeDirectiveBindings(controllerScope, attrs, instance, bindings, directive);

elementControllers[name] = { instance: instance, bindingInfo: bindingInfo };
}
});

// Handle the init and destroy lifecycle hooks on all controllers that have them
forEach(elementControllers, function(controller) {
var controllerInstance = controller.instance;
if (isFunction(controllerInstance.$onChanges)) {
try {
controllerInstance.$onChanges(controller.bindingInfo.initialChanges);
} catch (e) {
$exceptionHandler(e);
// Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy
forEach(controllerDirectives, function(controllerDirective, name) {
var require = controllerDirective.require;
if (controllerDirective.bindToController && !isArray(require) && isObject(require)) {
extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers));
}
}
if (isFunction(controllerInstance.$onInit)) {
try {
controllerInstance.$onInit();
} catch (e) {
$exceptionHandler(e);
});

// Handle the init and destroy lifecycle hooks on all controllers that have them
forEach(elementControllers, function(controller) {
var controllerInstance = controller.instance;
if (isFunction(controllerInstance.$onChanges)) {
try {
controllerInstance.$onChanges(controller.bindingInfo.initialChanges);
} catch (e) {
$exceptionHandler(e);
}
}
}
if (isFunction(controllerInstance.$doCheck)) {
controllerScope.$watch(function() { controllerInstance.$doCheck(); });
controllerInstance.$doCheck();
}
if (isFunction(controllerInstance.$onDestroy)) {
controllerScope.$on('$destroy', function callOnDestroyHook() {
controllerInstance.$onDestroy();
});
}
});
if (isFunction(controllerInstance.$onInit)) {
try {
controllerInstance.$onInit();
} catch (e) {
$exceptionHandler(e);
}
}
if (isFunction(controllerInstance.$doCheck)) {
controllerScope.$watch(function() { controllerInstance.$doCheck(); });
controllerInstance.$doCheck();
}
if (isFunction(controllerInstance.$onDestroy)) {
controllerScope.$on('$destroy', function callOnDestroyHook() {
controllerInstance.$onDestroy();
});
}
});
}

// PRELINKING
for (i = 0, ii = preLinkFns.length; i < ii; i++) {
Expand Down Expand Up @@ -2981,34 +2993,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return value || null;
}

function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective) {
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.
// In this case .data will not attach any data.
// 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;
$element.data('$' + directive.name + 'Controller', controllerInstance.instance);
}
return elementControllers;
}

// Depending upon the context in which a directive finds itself it might need to have a new isolated
// or child scope created. For instance:
// * if the directive has been pulled into a template because another directive with a higher priority
Expand Down
43 changes: 2 additions & 41 deletions src/ng/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,12 @@ function $ControllerProvider() {
* It's just a simple call to {@link auto.$injector $injector}, but extracted into
* a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
*/
return function $controller(expression, locals, later, ident) {
return function $controller(expression, locals, _ignored, ident) {
// PRIVATE API:
// param `later` --- indicates that the controller's constructor is invoked at a later time.
// If true, $controller will allocate the object with the correct
// prototype chain, but will not invoke the controller until a returned
// callback is invoked.
// param `_ignored` --- not used, kept for compatibility with the $controller decorator in ngMock
// param `ident` --- An optional label which overrides the label parsed from the controller
// expression, if any.
var instance, match, constructor, identifier;
later = later === true;
if (ident && isString(ident)) {
identifier = ident;
}
Expand All @@ -116,41 +112,6 @@ function $ControllerProvider() {
assertArgFn(expression, constructor, true);
}

if (later) {
// Instantiate controller later:
// This machinery is used to create an instance of the object before calling the
// controller's constructor itself.
//
// This allows properties to be added to the controller before the constructor is
// invoked. Primarily, this is used for isolate scope bindings in $compile.
//
// This feature is not intended for use by applications, and is thus not documented
// publicly.
// Object creation: http://jsperf.com/create-constructor/2
var controllerPrototype = (isArray(expression) ?
expression[expression.length - 1] : expression).prototype;
instance = Object.create(controllerPrototype || null);

if (identifier) {
addIdentifier(locals, identifier, instance, constructor || expression.name);
}

return extend(function $controllerInit() {
var result = $injector.invoke(expression, instance, locals, constructor);
if (result !== instance && (isObject(result) || isFunction(result))) {
instance = result;
if (identifier) {
// If result changed, re-assign controllerAs value to scope.
addIdentifier(locals, identifier, instance, constructor || expression.name);
}
}
return instance;
}, {
instance: instance,
identifier: identifier
});
}

instance = $injector.instantiate(expression, locals, constructor);

if (identifier) {
Expand Down
12 changes: 4 additions & 8 deletions src/ngMock/angular-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -2332,14 +2332,10 @@ angular.mock.$RootElementProvider = function() {
*/
function createControllerDecorator() {
angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
return function(expression, locals, later, ident) {
if (later && typeof later === 'object') {
var instantiate = $delegate(expression, locals, true, ident);
var instance = instantiate();
angular.extend(instance, later);
return instance;
}
return $delegate(expression, locals, later, ident);
return function(expression, locals, bindings, ident) {
var instance = $delegate(expression, locals, false, ident);
angular.extend(instance, bindings);
return instance;
};
}];

Expand Down

0 comments on commit 6b9a0fc

Please sign in to comment.