2015-08-03 14:10:07 -07:00
|
|
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
2015-08-19 11:26:45 -07:00
|
|
|
import {BaseException, Json, StringWrapper, isPresent, isBlank} from 'angular2/src/facade/lang';
|
2015-08-03 14:10:07 -07:00
|
|
|
import {CodegenNameUtil} from './codegen_name_util';
|
2015-08-12 16:26:21 -07:00
|
|
|
import {codify, combineGeneratedStrings, rawString} from './codegen_facade';
|
2015-08-03 14:10:07 -07:00
|
|
|
import {ProtoRecord, RecordType} from './proto_record';
|
2015-08-19 11:26:45 -07:00
|
|
|
import {BindingTarget} from './binding_record';
|
2015-08-19 10:48:53 -07:00
|
|
|
import {DirectiveRecord} from './directive_record';
|
2015-08-03 14:10:07 -07:00
|
|
|
|
2015-08-17 15:28:37 -07:00
|
|
|
/**
|
|
|
|
* This is an experimental feature. Works only in Dart.
|
|
|
|
*/
|
|
|
|
const ON_PUSH_OBSERVE = "ON_PUSH_OBSERVE";
|
|
|
|
|
2015-08-03 14:10:07 -07:00
|
|
|
/**
|
|
|
|
* Class responsible for providing change detection logic for chagne detector classes.
|
|
|
|
*/
|
|
|
|
export class CodegenLogicUtil {
|
2015-08-17 15:28:37 -07:00
|
|
|
constructor(private _names: CodegenNameUtil, private _utilName: string,
|
|
|
|
private _changeDetection: string) {}
|
2015-08-03 14:10:07 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a statement which updates the local variable representing `protoRec` with the current
|
2015-08-12 16:26:21 -07:00
|
|
|
* value of the record. Used by property bindings.
|
2015-08-03 14:10:07 -07:00
|
|
|
*/
|
2015-08-12 16:26:21 -07:00
|
|
|
genPropertyBindingEvalValue(protoRec: ProtoRecord): string {
|
|
|
|
return this.genEvalValue(protoRec, idx => this._names.getLocalName(idx),
|
|
|
|
this._names.getLocalsAccessorName());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a statement which updates the local variable representing `protoRec` with the current
|
|
|
|
* value of the record. Used by event bindings.
|
|
|
|
*/
|
|
|
|
genEventBindingEvalValue(eventRecord: any, protoRec: ProtoRecord): string {
|
|
|
|
return this.genEvalValue(protoRec, idx => this._names.getEventLocalName(eventRecord, idx),
|
|
|
|
"locals");
|
|
|
|
}
|
|
|
|
|
|
|
|
private genEvalValue(protoRec: ProtoRecord, getLocalName: Function,
|
|
|
|
localsAccessor: string): string {
|
2015-08-03 14:10:07 -07:00
|
|
|
var context = (protoRec.contextIndex == -1) ?
|
|
|
|
this._names.getDirectiveName(protoRec.directiveIndex) :
|
2015-08-12 16:26:21 -07:00
|
|
|
getLocalName(protoRec.contextIndex);
|
|
|
|
var argString = ListWrapper.map(protoRec.args, (arg) => getLocalName(arg)).join(", ");
|
2015-08-03 14:10:07 -07:00
|
|
|
|
|
|
|
var rhs: string;
|
|
|
|
switch (protoRec.mode) {
|
|
|
|
case RecordType.SELF:
|
|
|
|
rhs = context;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.CONST:
|
|
|
|
rhs = codify(protoRec.funcOrValue);
|
|
|
|
break;
|
|
|
|
|
2015-08-12 16:26:21 -07:00
|
|
|
case RecordType.PROPERTY_READ:
|
2015-08-17 15:28:37 -07:00
|
|
|
rhs = this._observe(`${context}.${protoRec.name}`, protoRec);
|
2015-08-03 14:10:07 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.SAFE_PROPERTY:
|
2015-08-17 15:28:37 -07:00
|
|
|
var read = this._observe(`${context}.${protoRec.name}`, protoRec);
|
|
|
|
rhs =
|
|
|
|
`${this._utilName}.isValueBlank(${context}) ? null : ${this._observe(read, protoRec)}`;
|
2015-08-03 14:10:07 -07:00
|
|
|
break;
|
|
|
|
|
2015-08-12 16:26:21 -07:00
|
|
|
case RecordType.PROPERTY_WRITE:
|
|
|
|
rhs = `${context}.${protoRec.name} = ${getLocalName(protoRec.args[0])}`;
|
|
|
|
break;
|
|
|
|
|
2015-08-03 14:10:07 -07:00
|
|
|
case RecordType.LOCAL:
|
2015-08-17 15:28:37 -07:00
|
|
|
rhs = this._observe(`${localsAccessor}.get(${rawString(protoRec.name)})`, protoRec);
|
2015-08-03 14:10:07 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.INVOKE_METHOD:
|
2015-08-17 15:28:37 -07:00
|
|
|
rhs = this._observe(`${context}.${protoRec.name}(${argString})`, protoRec);
|
2015-08-03 14:10:07 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.SAFE_INVOKE_METHOD:
|
2015-08-17 15:28:37 -07:00
|
|
|
var invoke = `${context}.${protoRec.name}(${argString})`;
|
2015-08-03 14:10:07 -07:00
|
|
|
rhs =
|
2015-08-17 15:28:37 -07:00
|
|
|
`${this._utilName}.isValueBlank(${context}) ? null : ${this._observe(invoke, protoRec)}`;
|
2015-08-03 14:10:07 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.INVOKE_CLOSURE:
|
|
|
|
rhs = `${context}(${argString})`;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.PRIMITIVE_OP:
|
|
|
|
rhs = `${this._utilName}.${protoRec.name}(${argString})`;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.COLLECTION_LITERAL:
|
|
|
|
rhs = `${this._utilName}.${protoRec.name}(${argString})`;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.INTERPOLATE:
|
|
|
|
rhs = this._genInterpolation(protoRec);
|
|
|
|
break;
|
|
|
|
|
2015-08-12 16:26:21 -07:00
|
|
|
case RecordType.KEYED_READ:
|
2015-08-17 15:28:37 -07:00
|
|
|
rhs = this._observe(`${context}[${getLocalName(protoRec.args[0])}]`, protoRec);
|
2015-08-12 16:26:21 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.KEYED_WRITE:
|
|
|
|
rhs = `${context}[${getLocalName(protoRec.args[0])}] = ${getLocalName(protoRec.args[1])}`;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RecordType.CHAIN:
|
|
|
|
rhs = 'null';
|
2015-08-03 14:10:07 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw new BaseException(`Unknown operation ${protoRec.mode}`);
|
|
|
|
}
|
2015-08-12 16:26:21 -07:00
|
|
|
return `${getLocalName(protoRec.selfIndex)} = ${rhs};`;
|
2015-08-03 14:10:07 -07:00
|
|
|
}
|
|
|
|
|
2015-08-17 15:28:37 -07:00
|
|
|
_observe(exp: string, rec: ProtoRecord): string {
|
|
|
|
// This is an experimental feature. Works only in Dart.
|
|
|
|
if (StringWrapper.equals(this._changeDetection, ON_PUSH_OBSERVE)) {
|
|
|
|
return `this.observe(${exp}, ${rec.selfIndex})`;
|
|
|
|
} else {
|
|
|
|
return exp;
|
|
|
|
}
|
|
|
|
}
|
2015-08-12 16:26:21 -07:00
|
|
|
|
2015-08-20 13:50:33 -07:00
|
|
|
genPropertyBindingTargets(propertyBindingTargets: BindingTarget[],
|
|
|
|
genDebugInfo: boolean): string {
|
2015-08-19 11:26:45 -07:00
|
|
|
var bs = propertyBindingTargets.map(b => {
|
|
|
|
if (isBlank(b)) return "null";
|
|
|
|
|
2015-08-20 13:50:33 -07:00
|
|
|
var debug = genDebugInfo ? codify(b.debug) : "null";
|
2015-08-19 11:26:45 -07:00
|
|
|
return `${this._utilName}.bindingTarget(${codify(b.mode)}, ${b.elementIndex}, ${codify(b.name)}, ${codify(b.unit)}, ${debug})`;
|
|
|
|
});
|
|
|
|
return `[${bs.join(", ")}]`;
|
|
|
|
}
|
|
|
|
|
|
|
|
genDirectiveIndices(directiveRecords: DirectiveRecord[]): string {
|
|
|
|
var bs = directiveRecords.map(
|
|
|
|
b =>
|
|
|
|
`${this._utilName}.directiveIndex(${b.directiveIndex.elementIndex}, ${b.directiveIndex.directiveIndex})`);
|
|
|
|
return `[${bs.join(", ")}]`;
|
|
|
|
}
|
|
|
|
|
2015-08-03 14:10:07 -07:00
|
|
|
_genInterpolation(protoRec: ProtoRecord): string {
|
|
|
|
var iVals = [];
|
|
|
|
for (var i = 0; i < protoRec.args.length; ++i) {
|
|
|
|
iVals.push(codify(protoRec.fixedArgs[i]));
|
|
|
|
iVals.push(`${this._utilName}.s(${this._names.getLocalName(protoRec.args[i])})`);
|
|
|
|
}
|
|
|
|
iVals.push(codify(protoRec.fixedArgs[protoRec.args.length]));
|
|
|
|
return combineGeneratedStrings(iVals);
|
|
|
|
}
|
2015-08-19 10:48:53 -07:00
|
|
|
|
|
|
|
genHydrateDetectors(directiveRecords: DirectiveRecord[]): string {
|
|
|
|
var res = [];
|
|
|
|
for (var i = 0; i < directiveRecords.length; ++i) {
|
|
|
|
var r = directiveRecords[i];
|
|
|
|
if (!r.isDefaultChangeDetection()) {
|
|
|
|
res.push(
|
|
|
|
`${this._names.getDetectorName(r.directiveIndex)} = this.getDetectorFor(directives, ${i});`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res.join("\n");
|
|
|
|
}
|
2015-08-03 14:10:07 -07:00
|
|
|
}
|