perf($compile): move $$isolateBinding creation to directive factory instead of on each link

This commit is contained in:
Jason Bedard
2014-08-14 21:11:33 -07:00
committed by Jeff Cross
parent 9314719d1e
commit 56f09f0b44
3 changed files with 52 additions and 21 deletions

View File

@@ -574,6 +574,31 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// 'on' and be composed of only English letters.
var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
function parseIsolateBindings(scope, directiveName) {
var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
var bindings = {};
forEach(scope, function(definition, scopeName) {
var match = definition.match(LOCAL_REGEXP);
if (!match) {
throw $compileMinErr('iscp',
"Invalid isolate scope definition for directive '{0}'." +
" Definition: {... {1}: '{2}' ...}",
directiveName, scopeName, definition);
}
bindings[scopeName] = {
attrName: match[3] || scopeName,
mode: match[1],
optional: match[2] === '?'
};
});
return bindings;
}
/**
* @ngdoc method
* @name $compileProvider#directive
@@ -611,6 +636,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
directive.name = directive.name || name;
directive.require = directive.require || (directive.controller && directive.name);
directive.restrict = directive.restrict || 'EA';
if (isObject(directive.scope)) {
directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name);
}
directives.push(directive);
} catch (e) {
$exceptionHandler(e);
@@ -1657,16 +1685,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
newIsolateScopeDirective.bindToController === true) {
isolateBindingContext = isolateScopeController.instance;
}
forEach(newIsolateScopeDirective.scope, function(definition, scopeName) {
var match = definition.match(LOCAL_REGEXP) || [],
attrName = match[3] || scopeName,
optional = (match[2] == '?'),
mode = match[1], // @, =, or &
forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) {
var attrName = definition.attrName,
optional = definition.optional,
mode = definition.mode, // @, =, or &
lastValue,
parentGet, parentSet, compare;
isolateScope.$$isolateBindings[scopeName] = mode + attrName;
switch (mode) {
case '@':
@@ -1721,12 +1747,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return parentGet(scope, locals);
};
break;
default:
throw $compileMinErr('iscp',
"Invalid isolate scope definition for directive '{0}'." +
" Definition: {... {1}: '{2}' ...}",
newIsolateScopeDirective.name, scopeName, definition);
}
});
}

View File

@@ -134,7 +134,7 @@ function $RootScopeProvider(){
this.$$postDigestQueue = [];
this.$$listeners = {};
this.$$listenerCount = {};
this.$$isolateBindings = {};
this.$$isolateBindings = null;
this.$$applyAsyncQueue = [];
}

View File

@@ -3507,14 +3507,25 @@ describe('$compile', function() {
expect(typeof componentScope.$$isolateBindings).toBe('object');
expect(componentScope.$$isolateBindings.attr).toBe('@attr');
expect(componentScope.$$isolateBindings.attrAlias).toBe('@attr');
expect(componentScope.$$isolateBindings.ref).toBe('=ref');
expect(componentScope.$$isolateBindings.refAlias).toBe('=ref');
expect(componentScope.$$isolateBindings.reference).toBe('=reference');
expect(componentScope.$$isolateBindings.expr).toBe('&expr');
expect(componentScope.$$isolateBindings.exprAlias).toBe('&expr');
expect(componentScope.$$isolateBindings.attr.mode).toBe('@');
expect(componentScope.$$isolateBindings.attr.attrName).toBe('attr');
expect(componentScope.$$isolateBindings.attrAlias.attrName).toBe('attr');
expect(componentScope.$$isolateBindings.ref.mode).toBe('=');
expect(componentScope.$$isolateBindings.ref.attrName).toBe('ref');
expect(componentScope.$$isolateBindings.refAlias.attrName).toBe('ref');
expect(componentScope.$$isolateBindings.reference.mode).toBe('=');
expect(componentScope.$$isolateBindings.reference.attrName).toBe('reference');
expect(componentScope.$$isolateBindings.expr.mode).toBe('&');
expect(componentScope.$$isolateBindings.expr.attrName).toBe('expr');
expect(componentScope.$$isolateBindings.exprAlias.attrName).toBe('expr');
var firstComponentScope = componentScope,
first$$isolateBindings = componentScope.$$isolateBindings;
dealoc(element);
compile('<div><span my-component>');
expect(componentScope).not.toBe(firstComponentScope);
expect(componentScope.$$isolateBindings).toBe(first$$isolateBindings);
}));