parent
92a5876f51
commit
61341b2791
|
@ -113,6 +113,11 @@ let bindingIndex: number;
|
||||||
*/
|
*/
|
||||||
let cleanup: any[]|null;
|
let cleanup: any[]|null;
|
||||||
|
|
||||||
|
const enum BindingDirection {
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swap the current state with a new state.
|
* Swap the current state with a new state.
|
||||||
*
|
*
|
||||||
|
@ -581,12 +586,11 @@ export function listener(eventName: string, listener: EventListener, useCapture
|
||||||
if (tNode.outputs === undefined) {
|
if (tNode.outputs === undefined) {
|
||||||
// if we create TNode here, inputs must be undefined so we know they still need to be
|
// if we create TNode here, inputs must be undefined so we know they still need to be
|
||||||
// checked
|
// checked
|
||||||
tNode.outputs = null;
|
tNode.outputs = generatePropertyAliases(node.flags, BindingDirection.Output);
|
||||||
tNode = generatePropertyAliases(node.flags, tNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const outputs = tNode.outputs;
|
const outputs = tNode.outputs;
|
||||||
let outputData: (number | string)[]|undefined;
|
let outputData: PropertyAliasValue|undefined;
|
||||||
if (outputs && (outputData = outputs[eventName])) {
|
if (outputs && (outputData = outputs[eventName])) {
|
||||||
createOutput(outputData, listener);
|
createOutput(outputData, listener);
|
||||||
}
|
}
|
||||||
|
@ -596,7 +600,7 @@ export function listener(eventName: string, listener: EventListener, useCapture
|
||||||
* Iterates through the outputs associated with a particular event name and subscribes to
|
* Iterates through the outputs associated with a particular event name and subscribes to
|
||||||
* each output.
|
* each output.
|
||||||
*/
|
*/
|
||||||
function createOutput(outputs: (number | string)[], listener: Function): void {
|
function createOutput(outputs: PropertyAliasValue, listener: Function): void {
|
||||||
for (let i = 0; i < outputs.length; i += 2) {
|
for (let i = 0; i < outputs.length; i += 2) {
|
||||||
ngDevMode && assertDataInRange(outputs[i] as number);
|
ngDevMode && assertDataInRange(outputs[i] as number);
|
||||||
const subscription = data[outputs[i] as number][outputs[i | 1]].subscribe(listener);
|
const subscription = data[outputs[i] as number][outputs[i | 1]].subscribe(listener);
|
||||||
|
@ -658,18 +662,16 @@ export function elementAttribute(index: number, attrName: string, value: any): v
|
||||||
export function elementProperty<T>(index: number, propName: string, value: T | NO_CHANGE): void {
|
export function elementProperty<T>(index: number, propName: string, value: T | NO_CHANGE): void {
|
||||||
if (value === NO_CHANGE) return;
|
if (value === NO_CHANGE) return;
|
||||||
const node = data[index] as LElementNode;
|
const node = data[index] as LElementNode;
|
||||||
|
const tNode = node.tNode !;
|
||||||
let tNode: TNode|null = node.tNode !;
|
|
||||||
// if tNode.inputs is undefined, a listener has created outputs, but inputs haven't
|
// if tNode.inputs is undefined, a listener has created outputs, but inputs haven't
|
||||||
// yet been checked
|
// yet been checked
|
||||||
if (tNode.inputs === undefined) {
|
if (tNode.inputs === undefined) {
|
||||||
// mark inputs as checked
|
// mark inputs as checked
|
||||||
tNode.inputs = null;
|
tNode.inputs = generatePropertyAliases(node.flags, BindingDirection.Input);
|
||||||
tNode = generatePropertyAliases(node.flags, tNode, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputData = tNode.inputs;
|
const inputData = tNode.inputs;
|
||||||
let dataValue: PropertyAliasValue|null;
|
let dataValue: PropertyAliasValue|undefined;
|
||||||
if (inputData && (dataValue = inputData[propName])) {
|
if (inputData && (dataValue = inputData[propName])) {
|
||||||
setInputsForProperty(dataValue, value);
|
setInputsForProperty(dataValue, value);
|
||||||
} else {
|
} else {
|
||||||
|
@ -707,7 +709,7 @@ function createTNode(
|
||||||
* Given a list of directive indices and minified input names, sets the
|
* Given a list of directive indices and minified input names, sets the
|
||||||
* input properties on the corresponding directives.
|
* input properties on the corresponding directives.
|
||||||
*/
|
*/
|
||||||
function setInputsForProperty(inputs: (number | string)[], value: any): void {
|
function setInputsForProperty(inputs: PropertyAliasValue, value: any): void {
|
||||||
for (let i = 0; i < inputs.length; i += 2) {
|
for (let i = 0; i < inputs.length; i += 2) {
|
||||||
ngDevMode && assertDataInRange(inputs[i] as number);
|
ngDevMode && assertDataInRange(inputs[i] as number);
|
||||||
data[inputs[i] as number][inputs[i | 1]] = value;
|
data[inputs[i] as number][inputs[i | 1]] = value;
|
||||||
|
@ -715,33 +717,37 @@ function setInputsForProperty(inputs: (number | string)[], value: any): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function consolidates all the inputs or outputs defined by directives
|
* Consolidates all inputs or outputs of all directives on this logical node.
|
||||||
* on this node into one object and stores it in tData so it can
|
|
||||||
* be shared between all templates of this type.
|
|
||||||
*
|
*
|
||||||
* @param index Index where data should be stored in tData
|
* @param number lNodeFlags logical node flags
|
||||||
|
* @param Direction direction whether to consider inputs or outputs
|
||||||
|
* @returns PropertyAliases|null aggregate of all properties if any, `null` otherwise
|
||||||
*/
|
*/
|
||||||
function generatePropertyAliases(flags: number, tNode: TNode, isInputData = false): TNode {
|
function generatePropertyAliases(lNodeFlags: number, direction: BindingDirection): PropertyAliases|
|
||||||
const start = flags >> LNodeFlags.INDX_SHIFT;
|
null {
|
||||||
const size = (flags & LNodeFlags.SIZE_MASK) >> LNodeFlags.SIZE_SHIFT;
|
const size = (lNodeFlags & LNodeFlags.SIZE_MASK) >> LNodeFlags.SIZE_SHIFT;
|
||||||
|
let propStore: PropertyAliases|null = null;
|
||||||
|
|
||||||
|
if (size > 0) {
|
||||||
|
const start = lNodeFlags >> LNodeFlags.INDX_SHIFT;
|
||||||
|
const isInput = direction === BindingDirection.Input;
|
||||||
|
|
||||||
for (let i = start, ii = start + size; i < ii; i++) {
|
for (let i = start, ii = start + size; i < ii; i++) {
|
||||||
const directiveDef: DirectiveDef<any> = tData ![i] as DirectiveDef<any>;
|
const directiveDef = tData ![i] as DirectiveDef<any>;
|
||||||
const propertyAliasMap: {[publicName: string]: string} =
|
const propertyAliasMap: {[publicName: string]: string} =
|
||||||
isInputData ? directiveDef.inputs : directiveDef.outputs;
|
isInput ? directiveDef.inputs : directiveDef.outputs;
|
||||||
for (let publicName in propertyAliasMap) {
|
for (let publicName in propertyAliasMap) {
|
||||||
if (propertyAliasMap.hasOwnProperty(publicName)) {
|
if (propertyAliasMap.hasOwnProperty(publicName)) {
|
||||||
|
propStore = propStore || {};
|
||||||
const internalName = propertyAliasMap[publicName];
|
const internalName = propertyAliasMap[publicName];
|
||||||
const staticDirData: PropertyAliases = isInputData ?
|
const hasProperty = propStore.hasOwnProperty(publicName);
|
||||||
(tNode.inputs || (tNode.inputs = {})) :
|
hasProperty ? propStore[publicName].push(i, internalName) :
|
||||||
(tNode.outputs || (tNode.outputs = {}));
|
(propStore[publicName] = [i, internalName]);
|
||||||
const hasProperty: boolean = staticDirData.hasOwnProperty(publicName);
|
|
||||||
hasProperty ? staticDirData[publicName].push(i, internalName) :
|
|
||||||
(staticDirData[publicName] = [i, internalName]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tNode;
|
}
|
||||||
|
return propStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -801,7 +807,6 @@ export function elementStyle<T>(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
//// Text
|
//// Text
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
|
|
@ -253,16 +253,23 @@ export interface TNode {
|
||||||
*/
|
*/
|
||||||
localNames: (string|number)[]|null;
|
localNames: (string|number)[]|null;
|
||||||
|
|
||||||
/**
|
/** Information about input properties that need to be set once from attribute data. */
|
||||||
* This property contains information about input properties that
|
|
||||||
* need to be set once from attribute data.
|
|
||||||
*/
|
|
||||||
initialInputs: InitialInputData|null|undefined;
|
initialInputs: InitialInputData|null|undefined;
|
||||||
|
|
||||||
/** Input data for all directives on this node. */
|
/**
|
||||||
|
* Input data for all directives on this node.
|
||||||
|
*
|
||||||
|
* - `undefined` means that the prop has not been initialized yet,
|
||||||
|
* - `null` means that the prop has been initialized but no inputs have been found.
|
||||||
|
*/
|
||||||
inputs: PropertyAliases|null|undefined;
|
inputs: PropertyAliases|null|undefined;
|
||||||
|
|
||||||
/** Output data for all directives on this node. */
|
/**
|
||||||
|
* Output data for all directives on this node.
|
||||||
|
*
|
||||||
|
* - `undefined` means that the prop has not been initialized yet,
|
||||||
|
* - `null` means that the prop has been initialized but no outputs have been found.
|
||||||
|
*/
|
||||||
outputs: PropertyAliases|null|undefined;
|
outputs: PropertyAliases|null|undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -298,11 +305,10 @@ export type PropertyAliases = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value in PropertyAliases.
|
* Store the runtime input or output names for all the directives.
|
||||||
*
|
*
|
||||||
* In each array:
|
* - Even indices: directive index
|
||||||
* Even indices: directive index
|
* - Odd indices: minified / internal name
|
||||||
* Odd indices: minified / internal name
|
|
||||||
*
|
*
|
||||||
* e.g. [0, 'change-minified']
|
* e.g. [0, 'change-minified']
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue