(scope, attrs, destination, bindings, directive)
| 9499 | // Set up $watches for isolate scope and controller bindings. This process |
| 9500 | // only occurs for isolate scopes and new scopes with controllerAs. |
| 9501 | function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) { |
| 9502 | var removeWatchCollection = []; |
| 9503 | forEach(bindings, function(definition, scopeName) { |
| 9504 | var attrName = definition.attrName, |
| 9505 | optional = definition.optional, |
| 9506 | mode = definition.mode, // @, =, or & |
| 9507 | lastValue, |
| 9508 | parentGet, parentSet, compare, removeWatch; |
| 9509 | |
| 9510 | switch (mode) { |
| 9511 | |
| 9512 | case '@': |
| 9513 | if (!optional && !hasOwnProperty.call(attrs, attrName)) { |
| 9514 | destination[scopeName] = attrs[attrName] = void 0; |
| 9515 | } |
| 9516 | attrs.$observe(attrName, function(value) { |
| 9517 | if (isString(value)) { |
| 9518 | destination[scopeName] = value; |
| 9519 | } |
| 9520 | }); |
| 9521 | attrs.$$observers[attrName].$$scope = scope; |
| 9522 | lastValue = attrs[attrName]; |
| 9523 | if (isString(lastValue)) { |
| 9524 | // If the attribute has been provided then we trigger an interpolation to ensure |
| 9525 | // the value is there for use in the link fn |
| 9526 | destination[scopeName] = $interpolate(lastValue)(scope); |
| 9527 | } else if (isBoolean(lastValue)) { |
| 9528 | // If the attributes is one of the BOOLEAN_ATTR then Angular will have converted |
| 9529 | // the value to boolean rather than a string, so we special case this situation |
| 9530 | destination[scopeName] = lastValue; |
| 9531 | } |
| 9532 | break; |
| 9533 | |
| 9534 | case '=': |
| 9535 | if (!hasOwnProperty.call(attrs, attrName)) { |
| 9536 | if (optional) break; |
| 9537 | attrs[attrName] = void 0; |
| 9538 | } |
| 9539 | if (optional && !attrs[attrName]) break; |
| 9540 | |
| 9541 | parentGet = $parse(attrs[attrName]); |
| 9542 | if (parentGet.literal) { |
| 9543 | compare = equals; |
| 9544 | } else { |
| 9545 | compare = function(a, b) { return a === b || (a !== a && b !== b); }; |
| 9546 | } |
| 9547 | parentSet = parentGet.assign || function() { |
| 9548 | // reset the change, or we will throw this exception on every $digest |
| 9549 | lastValue = destination[scopeName] = parentGet(scope); |
| 9550 | throw $compileMinErr('nonassign', |
| 9551 | "Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!", |
| 9552 | attrs[attrName], attrName, directive.name); |
| 9553 | }; |
| 9554 | lastValue = destination[scopeName] = parentGet(scope); |
| 9555 | var parentValueWatch = function parentValueWatch(parentValue) { |
| 9556 | if (!compare(parentValue, destination[scopeName])) { |
| 9557 | // we are out of sync and need to copy |
| 9558 | if (!compare(parentValue, lastValue)) { |
no test coverage detected