refactor(change_detect): Abstract name logic into NameRegistry
Create `NameRegistry`, responsible for understanding how names are generated for change detector fields and variables. Use `NameRegistry` for both JS Jit & Dart pre-generated detectors. Making progress on #3248
This commit is contained in:
parent
23cd385f20
commit
0906ee8a4e
@ -6,6 +6,7 @@ import {ChangeDetectionUtil} from './change_detection_util';
|
|||||||
import {DirectiveIndex, DirectiveRecord} from './directive_record';
|
import {DirectiveIndex, DirectiveRecord} from './directive_record';
|
||||||
|
|
||||||
import {ProtoRecord, RecordType} from './proto_record';
|
import {ProtoRecord, RecordType} from './proto_record';
|
||||||
|
import {CodegenNameUtil, sanitizeName} from './codegen_name_util';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,7 +24,6 @@ var DISPATCHER_ACCESSOR = "this.dispatcher";
|
|||||||
var PIPES_ACCESSOR = "this.pipes";
|
var PIPES_ACCESSOR = "this.pipes";
|
||||||
var PROTOS_ACCESSOR = "this.protos";
|
var PROTOS_ACCESSOR = "this.protos";
|
||||||
var DIRECTIVES_ACCESSOR = "this.directiveRecords";
|
var DIRECTIVES_ACCESSOR = "this.directiveRecords";
|
||||||
var CONTEXT_ACCESSOR = "this.context";
|
|
||||||
var IS_CHANGED_LOCAL = "isChanged";
|
var IS_CHANGED_LOCAL = "isChanged";
|
||||||
var CHANGES_LOCAL = "changes";
|
var CHANGES_LOCAL = "changes";
|
||||||
var LOCALS_ACCESSOR = "this.locals";
|
var LOCALS_ACCESSOR = "this.locals";
|
||||||
@ -31,41 +31,16 @@ var MODE_ACCESSOR = "this.mode";
|
|||||||
var CURRENT_PROTO = "this.currentProto";
|
var CURRENT_PROTO = "this.currentProto";
|
||||||
var ALREADY_CHECKED_ACCESSOR = "this.alreadyChecked";
|
var ALREADY_CHECKED_ACCESSOR = "this.alreadyChecked";
|
||||||
|
|
||||||
|
|
||||||
export class ChangeDetectorJITGenerator {
|
export class ChangeDetectorJITGenerator {
|
||||||
_localNames: List<string>;
|
_names: CodegenNameUtil;
|
||||||
_changeNames: List<string>;
|
|
||||||
_fieldNames: List<string>;
|
|
||||||
_pipeNames: List<string>;
|
|
||||||
|
|
||||||
constructor(public id: string, public changeDetectionStrategy: string,
|
constructor(public id: string, public changeDetectionStrategy: string,
|
||||||
public records: List<ProtoRecord>, public directiveRecords: List<any>) {
|
public records: List<ProtoRecord>, public directiveRecords: List<any>) {
|
||||||
this._localNames = this._getLocalNames(records);
|
this._names = new CodegenNameUtil(this.records, this.directiveRecords, 'this._', UTIL);
|
||||||
this._changeNames = this._getChangeNames(this._localNames);
|
|
||||||
this._fieldNames = this._getFieldNames(this._localNames);
|
|
||||||
this._pipeNames = this._getPipeNames(this._localNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getLocalNames(records: List<ProtoRecord>): List<string> {
|
|
||||||
var index = 0;
|
|
||||||
var names = records.map((r) => { return _sanitizeName(`${r.name}${index++}`); });
|
|
||||||
return ["context"].concat(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getChangeNames(_localNames: List<string>): List<string> {
|
|
||||||
return _localNames.map((n) => `change_${n}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getFieldNames(_localNames: List<string>): List<string> {
|
|
||||||
return _localNames.map((n) => `this.${n}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getPipeNames(_localNames: List<string>): List<string> {
|
|
||||||
return _localNames.map((n) => `this.${n}_pipe`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generate(): Function {
|
generate(): Function {
|
||||||
var typeName = _sanitizeName(`ChangeDetector_${this.id}`);
|
var typeName = sanitizeName(`ChangeDetector_${this.id}`);
|
||||||
var classDefinition = `
|
var classDefinition = `
|
||||||
var ${typeName} = function ${typeName}(dispatcher, protos, directiveRecords) {
|
var ${typeName} = function ${typeName}(dispatcher, protos, directiveRecords) {
|
||||||
${ABSTRACT_CHANGE_DETECTOR}.call(this, ${JSON.stringify(this.id)}, dispatcher);
|
${ABSTRACT_CHANGE_DETECTOR}.call(this, ${JSON.stringify(this.id)}, dispatcher);
|
||||||
@ -75,7 +50,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
${CURRENT_PROTO} = null;
|
${CURRENT_PROTO} = null;
|
||||||
${PIPES_ACCESSOR} = null;
|
${PIPES_ACCESSOR} = null;
|
||||||
${ALREADY_CHECKED_ACCESSOR} = false;
|
${ALREADY_CHECKED_ACCESSOR} = false;
|
||||||
${this._genFieldDefinitions()}
|
${this._names.genDehydrateFields()}
|
||||||
}
|
}
|
||||||
|
|
||||||
${typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype);
|
${typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype);
|
||||||
@ -94,12 +69,11 @@ export class ChangeDetectorJITGenerator {
|
|||||||
${typeName}.prototype.__detectChangesInRecords = function(throwOnChange) {
|
${typeName}.prototype.__detectChangesInRecords = function(throwOnChange) {
|
||||||
${CURRENT_PROTO} = null;
|
${CURRENT_PROTO} = null;
|
||||||
|
|
||||||
${this._genLocalDefinitions()}
|
${this._names.genInitLocals()}
|
||||||
${this._genChangeDefinitions()}
|
|
||||||
var ${IS_CHANGED_LOCAL} = false;
|
var ${IS_CHANGED_LOCAL} = false;
|
||||||
var ${CHANGES_LOCAL} = null;
|
var ${CHANGES_LOCAL} = null;
|
||||||
|
|
||||||
context = ${CONTEXT_ACCESSOR};
|
context = ${this._names.getContextName()};
|
||||||
|
|
||||||
${this.records.map((r) => this._genRecord(r)).join("\n")}
|
${this.records.map((r) => this._genRecord(r)).join("\n")}
|
||||||
|
|
||||||
@ -112,7 +86,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
|
|
||||||
${typeName}.prototype.hydrate = function(context, locals, directives, pipes) {
|
${typeName}.prototype.hydrate = function(context, locals, directives, pipes) {
|
||||||
${MODE_ACCESSOR} = "${ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy)}";
|
${MODE_ACCESSOR} = "${ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy)}";
|
||||||
${CONTEXT_ACCESSOR} = context;
|
${this._names.getContextName()} = context;
|
||||||
${LOCALS_ACCESSOR} = locals;
|
${LOCALS_ACCESSOR} = locals;
|
||||||
${this._genHydrateDirectives()}
|
${this._genHydrateDirectives()}
|
||||||
${this._genHydrateDetectors()}
|
${this._genHydrateDetectors()}
|
||||||
@ -121,14 +95,14 @@ export class ChangeDetectorJITGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
${typeName}.prototype.dehydrate = function() {
|
${typeName}.prototype.dehydrate = function() {
|
||||||
${this._genPipeOnDestroy()}
|
${this._names.genPipeOnDestroy()}
|
||||||
${this._genFieldDefinitions()}
|
${this._names.genDehydrateFields()}
|
||||||
${LOCALS_ACCESSOR} = null;
|
${LOCALS_ACCESSOR} = null;
|
||||||
${PIPES_ACCESSOR} = null;
|
${PIPES_ACCESSOR} = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
${typeName}.prototype.hydrated = function() {
|
${typeName}.prototype.hydrated = function() {
|
||||||
return ${CONTEXT_ACCESSOR} !== null;
|
return ${this._names.getContextName()} !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return function(dispatcher) {
|
return function(dispatcher) {
|
||||||
@ -140,44 +114,8 @@ export class ChangeDetectorJITGenerator {
|
|||||||
AbstractChangeDetector, ChangeDetectionUtil, this.records, this.directiveRecords);
|
AbstractChangeDetector, ChangeDetectionUtil, this.records, this.directiveRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
_genGetDirectiveFieldNames(): List<string> {
|
|
||||||
return this.directiveRecords.map(d => this._genGetDirective(d.directiveIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
_genGetDetectorFieldNames(): List<string> {
|
|
||||||
return this.directiveRecords.filter(r => r.isOnPushChangeDetection())
|
|
||||||
.map((d) => this._genGetDetector(d.directiveIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
_genGetDirective(d: DirectiveIndex): string { return `this.directive_${d.name}`; }
|
|
||||||
|
|
||||||
_genGetDetector(d: DirectiveIndex): string { return `this.detector_${d.name}`; }
|
|
||||||
|
|
||||||
_getNonNullPipeNames(): List<string> {
|
|
||||||
var pipes = [];
|
|
||||||
this.records.forEach((r) => {
|
|
||||||
if (r.isPipeRecord()) {
|
|
||||||
pipes.push(this._pipeNames[r.selfIndex]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return pipes;
|
|
||||||
}
|
|
||||||
|
|
||||||
_genFieldDefinitions(): string {
|
|
||||||
var fields = [];
|
|
||||||
fields = fields.concat(this._fieldNames);
|
|
||||||
fields = fields.concat(this._getNonNullPipeNames());
|
|
||||||
fields = fields.concat(this._genGetDirectiveFieldNames());
|
|
||||||
fields = fields.concat(this._genGetDetectorFieldNames());
|
|
||||||
return fields.map((n) => {
|
|
||||||
return n == CONTEXT_ACCESSOR ? `${n} = null;` :
|
|
||||||
`${n} = ${UTIL}.uninitialized();`;
|
|
||||||
})
|
|
||||||
.join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
_genHydrateDirectives(): string {
|
_genHydrateDirectives(): string {
|
||||||
var directiveFieldNames = this._genGetDirectiveFieldNames();
|
var directiveFieldNames = this._names.getAllDirectiveNames();
|
||||||
var lines = ListWrapper.createFixedSize(directiveFieldNames.length);
|
var lines = ListWrapper.createFixedSize(directiveFieldNames.length);
|
||||||
for (var i = 0, iLen = directiveFieldNames.length; i < iLen; ++i) {
|
for (var i = 0, iLen = directiveFieldNames.length; i < iLen; ++i) {
|
||||||
lines[i] =
|
lines[i] =
|
||||||
@ -187,7 +125,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_genHydrateDetectors(): string {
|
_genHydrateDetectors(): string {
|
||||||
var detectorFieldNames = this._genGetDetectorFieldNames();
|
var detectorFieldNames = this._names.getAllDetectorNames();
|
||||||
var lines = ListWrapper.createFixedSize(detectorFieldNames.length);
|
var lines = ListWrapper.createFixedSize(detectorFieldNames.length);
|
||||||
for (var i = 0, iLen = detectorFieldNames.length; i < iLen; ++i) {
|
for (var i = 0, iLen = detectorFieldNames.length; i < iLen; ++i) {
|
||||||
lines[i] = `${detectorFieldNames[i]} =
|
lines[i] = `${detectorFieldNames[i]} =
|
||||||
@ -196,10 +134,6 @@ export class ChangeDetectorJITGenerator {
|
|||||||
return lines.join('\n');
|
return lines.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
_genPipeOnDestroy(): string {
|
|
||||||
return this._getNonNullPipeNames().map((p) => `${p}.onDestroy();`).join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
_genCallOnAllChangesDoneBody(): string {
|
_genCallOnAllChangesDoneBody(): string {
|
||||||
var notifications = [];
|
var notifications = [];
|
||||||
var dirs = this.directiveRecords;
|
var dirs = this.directiveRecords;
|
||||||
@ -207,7 +141,8 @@ export class ChangeDetectorJITGenerator {
|
|||||||
for (var i = dirs.length - 1; i >= 0; --i) {
|
for (var i = dirs.length - 1; i >= 0; --i) {
|
||||||
var dir = dirs[i];
|
var dir = dirs[i];
|
||||||
if (dir.callOnAllChangesDone) {
|
if (dir.callOnAllChangesDone) {
|
||||||
notifications.push(`${this._genGetDirective(dir.directiveIndex)}.onAllChangesDone();`);
|
notifications.push(
|
||||||
|
`${this._names.getDirectiveName(dir.directiveIndex)}.onAllChangesDone();`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,12 +154,6 @@ export class ChangeDetectorJITGenerator {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
_genLocalDefinitions(): string { return this._localNames.map((n) => `var ${n};`).join("\n"); }
|
|
||||||
|
|
||||||
_genChangeDefinitions(): string {
|
|
||||||
return this._changeNames.map((n) => `var ${n} = false;`).join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
_genRecord(r: ProtoRecord): string {
|
_genRecord(r: ProtoRecord): string {
|
||||||
var rec;
|
var rec;
|
||||||
if (r.isLifeCycleRecord()) {
|
if (r.isLifeCycleRecord()) {
|
||||||
@ -250,14 +179,14 @@ export class ChangeDetectorJITGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_genPipeCheck(r: ProtoRecord): string {
|
_genPipeCheck(r: ProtoRecord): string {
|
||||||
var context = this._localNames[r.contextIndex];
|
var context = this._names.getLocalName(r.contextIndex);
|
||||||
var argString = r.args.map((arg) => this._localNames[arg]).join(", ");
|
var argString = r.args.map((arg) => this._names.getLocalName(arg)).join(", ");
|
||||||
|
|
||||||
var oldValue = this._fieldNames[r.selfIndex];
|
var oldValue = this._names.getFieldName(r.selfIndex);
|
||||||
var newValue = this._localNames[r.selfIndex];
|
var newValue = this._names.getLocalName(r.selfIndex);
|
||||||
var change = this._changeNames[r.selfIndex];
|
var change = this._names.getChangeName(r.selfIndex);
|
||||||
|
|
||||||
var pipe = this._pipeNames[r.selfIndex];
|
var pipe = this._names.getPipeName(r.selfIndex);
|
||||||
var cdRef = "this.ref";
|
var cdRef = "this.ref";
|
||||||
|
|
||||||
var protoIndex = r.selfIndex - 1;
|
var protoIndex = r.selfIndex - 1;
|
||||||
@ -284,15 +213,15 @@ export class ChangeDetectorJITGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_genReferenceCheck(r: ProtoRecord): string {
|
_genReferenceCheck(r: ProtoRecord): string {
|
||||||
var oldValue = this._fieldNames[r.selfIndex];
|
var oldValue = this._names.getFieldName(r.selfIndex);
|
||||||
var newValue = this._localNames[r.selfIndex];
|
var newValue = this._names.getLocalName(r.selfIndex);
|
||||||
|
|
||||||
var protoIndex = r.selfIndex - 1;
|
var protoIndex = r.selfIndex - 1;
|
||||||
var check = `
|
var check = `
|
||||||
${CURRENT_PROTO} = ${PROTOS_ACCESSOR}[${protoIndex}];
|
${CURRENT_PROTO} = ${PROTOS_ACCESSOR}[${protoIndex}];
|
||||||
${this._genUpdateCurrentValue(r)}
|
${this._genUpdateCurrentValue(r)}
|
||||||
if (${newValue} !== ${oldValue}) {
|
if (${newValue} !== ${oldValue}) {
|
||||||
${this._changeNames[r.selfIndex]} = true;
|
${this._names.getChangeName(r.selfIndex)} = true;
|
||||||
${this._genUpdateDirectiveOrElement(r)}
|
${this._genUpdateDirectiveOrElement(r)}
|
||||||
${this._genAddToChanges(r)}
|
${this._genAddToChanges(r)}
|
||||||
${oldValue} = ${newValue};
|
${oldValue} = ${newValue};
|
||||||
@ -300,7 +229,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
if (r.isPureFunction()) {
|
if (r.isPureFunction()) {
|
||||||
var condition = r.args.map((a) => this._changeNames[a]).join(" || ");
|
var condition = r.args.map((a) => this._names.getChangeName(a)).join(" || ");
|
||||||
return `if (${condition}) { ${check} } else { ${newValue} = ${oldValue}; }`;
|
return `if (${condition}) { ${check} } else { ${newValue} = ${oldValue}; }`;
|
||||||
} else {
|
} else {
|
||||||
return check;
|
return check;
|
||||||
@ -308,10 +237,10 @@ export class ChangeDetectorJITGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_genUpdateCurrentValue(r: ProtoRecord): string {
|
_genUpdateCurrentValue(r: ProtoRecord): string {
|
||||||
var context = (r.contextIndex == -1) ? this._genGetDirective(r.directiveIndex) :
|
var context = (r.contextIndex == -1) ? this._names.getDirectiveName(r.directiveIndex) :
|
||||||
this._localNames[r.contextIndex];
|
this._names.getLocalName(r.contextIndex);
|
||||||
var newValue = this._localNames[r.selfIndex];
|
var newValue = this._names.getLocalName(r.selfIndex);
|
||||||
var argString = r.args.map((arg) => this._localNames[arg]).join(", ");
|
var argString = r.args.map((arg) => this._names.getLocalName(arg)).join(", ");
|
||||||
|
|
||||||
var rhs;
|
var rhs;
|
||||||
switch (r.mode) {
|
switch (r.mode) {
|
||||||
@ -356,7 +285,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.KEYED_ACCESS:
|
case RecordType.KEYED_ACCESS:
|
||||||
rhs = `${context}[${this._localNames[r.args[0]]}]`;
|
rhs = `${context}[${this._names.getLocalName(r.args[0])}]`;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -370,7 +299,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
for (var i = 0; i < r.args.length; ++i) {
|
for (var i = 0; i < r.args.length; ++i) {
|
||||||
res += JSON.stringify(r.fixedArgs[i]);
|
res += JSON.stringify(r.fixedArgs[i]);
|
||||||
res += " + ";
|
res += " + ";
|
||||||
res += `${UTIL}.s(${this._localNames[r.args[i]]})`;
|
res += `${UTIL}.s(${this._names.getLocalName(r.args[i])})`;
|
||||||
res += " + ";
|
res += " + ";
|
||||||
}
|
}
|
||||||
res += JSON.stringify(r.fixedArgs[r.args.length]);
|
res += JSON.stringify(r.fixedArgs[r.args.length]);
|
||||||
@ -380,13 +309,13 @@ export class ChangeDetectorJITGenerator {
|
|||||||
_genUpdateDirectiveOrElement(r: ProtoRecord): string {
|
_genUpdateDirectiveOrElement(r: ProtoRecord): string {
|
||||||
if (!r.lastInBinding) return "";
|
if (!r.lastInBinding) return "";
|
||||||
|
|
||||||
var newValue = this._localNames[r.selfIndex];
|
var newValue = this._names.getLocalName(r.selfIndex);
|
||||||
var oldValue = this._fieldNames[r.selfIndex];
|
var oldValue = this._names.getFieldName(r.selfIndex);
|
||||||
|
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
if (br.isDirective()) {
|
if (br.isDirective()) {
|
||||||
var directiveProperty =
|
var directiveProperty =
|
||||||
`${this._genGetDirective(br.directiveRecord.directiveIndex)}.${br.propertyName}`;
|
`${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.${br.propertyName}`;
|
||||||
return `
|
return `
|
||||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
${directiveProperty} = ${newValue};
|
${directiveProperty} = ${newValue};
|
||||||
@ -409,8 +338,8 @@ export class ChangeDetectorJITGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_genAddToChanges(r: ProtoRecord): string {
|
_genAddToChanges(r: ProtoRecord): string {
|
||||||
var newValue = this._localNames[r.selfIndex];
|
var newValue = this._names.getLocalName(r.selfIndex);
|
||||||
var oldValue = this._fieldNames[r.selfIndex];
|
var oldValue = this._names.getFieldName(r.selfIndex);
|
||||||
if (!r.bindingRecord.callOnChange()) return "";
|
if (!r.bindingRecord.callOnChange()) return "";
|
||||||
return `
|
return `
|
||||||
${CHANGES_LOCAL} = ${UTIL}.addChange(
|
${CHANGES_LOCAL} = ${UTIL}.addChange(
|
||||||
@ -430,17 +359,17 @@ export class ChangeDetectorJITGenerator {
|
|||||||
|
|
||||||
_genOnCheck(r: ProtoRecord): string {
|
_genOnCheck(r: ProtoRecord): string {
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
return `if (!throwOnChange) ${this._genGetDirective(br.directiveRecord.directiveIndex)}.onCheck();`;
|
return `if (!throwOnChange) ${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.onCheck();`;
|
||||||
}
|
}
|
||||||
|
|
||||||
_genOnInit(r: ProtoRecord): string {
|
_genOnInit(r: ProtoRecord): string {
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
return `if (!throwOnChange && !${ALREADY_CHECKED_ACCESSOR}) ${this._genGetDirective(br.directiveRecord.directiveIndex)}.onInit();`;
|
return `if (!throwOnChange && !${ALREADY_CHECKED_ACCESSOR}) ${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.onInit();`;
|
||||||
}
|
}
|
||||||
|
|
||||||
_genOnChange(r: ProtoRecord): string {
|
_genOnChange(r: ProtoRecord): string {
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
return `if (!throwOnChange && ${CHANGES_LOCAL}) ${this._genGetDirective(br.directiveRecord.directiveIndex)}.onChange(${CHANGES_LOCAL});`;
|
return `if (!throwOnChange && ${CHANGES_LOCAL}) ${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.onChange(${CHANGES_LOCAL});`;
|
||||||
}
|
}
|
||||||
|
|
||||||
_genNotifyOnPushDetectors(r: ProtoRecord): string {
|
_genNotifyOnPushDetectors(r: ProtoRecord): string {
|
||||||
@ -448,13 +377,9 @@ export class ChangeDetectorJITGenerator {
|
|||||||
if (!r.lastInDirective || !br.isOnPushChangeDetection()) return "";
|
if (!r.lastInDirective || !br.isOnPushChangeDetection()) return "";
|
||||||
var retVal = `
|
var retVal = `
|
||||||
if(${IS_CHANGED_LOCAL}) {
|
if(${IS_CHANGED_LOCAL}) {
|
||||||
${this._genGetDetector(br.directiveRecord.directiveIndex)}.markAsCheckOnce();
|
${this._names.getDetectorName(br.directiveRecord.directiveIndex)}.markAsCheckOnce();
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _sanitizeName(s: string): string {
|
|
||||||
return s.replace(new RegExp("\\W", "g"), '');
|
|
||||||
}
|
|
||||||
|
134
modules/angular2/src/change_detection/codegen_name_util.ts
Normal file
134
modules/angular2/src/change_detection/codegen_name_util.ts
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import {RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
||||||
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
|
import {DirectiveIndex} from './directive_record';
|
||||||
|
|
||||||
|
import {ProtoRecord} from './proto_record';
|
||||||
|
|
||||||
|
// `context` is always the first field.
|
||||||
|
var _CONTEXT_IDX = 0;
|
||||||
|
|
||||||
|
var _whiteSpaceRegExp = RegExpWrapper.create("\\W", "g");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns `s` with all non-identifier characters removed.
|
||||||
|
*/
|
||||||
|
export function sanitizeName(s: string): string {
|
||||||
|
return StringWrapper.replaceAll(s, _whiteSpaceRegExp, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class responsible for providing field and local variable names for change detector classes.
|
||||||
|
* Also provides some convenience functions, for example, declaring variables, destroying pipes,
|
||||||
|
* and dehydrating the detector.
|
||||||
|
*/
|
||||||
|
export class CodegenNameUtil {
|
||||||
|
/**
|
||||||
|
* Record names sanitized for use as fields.
|
||||||
|
* See [sanitizeName] for details.
|
||||||
|
*/
|
||||||
|
_sanitizedNames: List<string>;
|
||||||
|
|
||||||
|
constructor(public records: List<ProtoRecord>, public directiveRecords: List<any>,
|
||||||
|
public fieldPrefix: string, public utilName: string) {
|
||||||
|
this._sanitizedNames = ListWrapper.createFixedSize(this.records.length + 1);
|
||||||
|
this._sanitizedNames[_CONTEXT_IDX] = 'context';
|
||||||
|
for (var i = 0, iLen = this.records.length; i < iLen; ++i) {
|
||||||
|
this._sanitizedNames[i + 1] = sanitizeName(`${this.records[i].name}${i}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getContextName(): string { return this.getFieldName(_CONTEXT_IDX); }
|
||||||
|
|
||||||
|
getLocalName(idx: int): string { return this._sanitizedNames[idx]; }
|
||||||
|
|
||||||
|
getChangeName(idx: int): string { return `c_${this._sanitizedNames[idx]}`; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a statement initializing local variables used when detecting changes.
|
||||||
|
*/
|
||||||
|
genInitLocals(): string {
|
||||||
|
var declarations = [];
|
||||||
|
var assignments = [];
|
||||||
|
for (var i = 0, iLen = this.getFieldCount(); i < iLen; ++i) {
|
||||||
|
var changeName = this.getChangeName(i);
|
||||||
|
declarations.push(`${this.getLocalName(i)},${changeName}`);
|
||||||
|
assignments.push(changeName);
|
||||||
|
}
|
||||||
|
return `var ${ListWrapper.join(declarations, ',')};` +
|
||||||
|
`${ListWrapper.join(assignments, '=')} = false;`;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFieldCount(): int { return this._sanitizedNames.length; }
|
||||||
|
|
||||||
|
getFieldName(idx: int): string { return `${this.fieldPrefix}${this._sanitizedNames[idx]}`; }
|
||||||
|
|
||||||
|
getAllFieldNames(): List<string> {
|
||||||
|
var fieldList = [];
|
||||||
|
for (var k = 0, kLen = this.getFieldCount(); k < kLen; ++k) {
|
||||||
|
fieldList.push(this.getFieldName(k));
|
||||||
|
}
|
||||||
|
for (var i = 0, iLen = this.records.length; i < iLen; ++i) {
|
||||||
|
var rec = this.records[i];
|
||||||
|
if (rec.isPipeRecord()) {
|
||||||
|
fieldList.push(this.getPipeName(rec.selfIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var j = 0, jLen = this.directiveRecords.length; j < jLen; ++j) {
|
||||||
|
var dRec = this.directiveRecords[j];
|
||||||
|
fieldList.push(this.getDirectiveName(dRec.directiveIndex));
|
||||||
|
if (dRec.isOnPushChangeDetection()) {
|
||||||
|
fieldList.push(this.getDetectorName(dRec.directiveIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fieldList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a statement which declares all fields.
|
||||||
|
* This is only necessary for Dart change detectors.
|
||||||
|
*/
|
||||||
|
genDeclareFields(): string {
|
||||||
|
var fields = this.getAllFieldNames();
|
||||||
|
ListWrapper.removeAt(fields, _CONTEXT_IDX);
|
||||||
|
return ListWrapper.isEmpty(fields) ? '' : `var ${ListWrapper.join(fields, ', ')};`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates statements which clear all fields so that the change detector is dehydrated.
|
||||||
|
*/
|
||||||
|
genDehydrateFields(): string {
|
||||||
|
var fields = this.getAllFieldNames();
|
||||||
|
ListWrapper.removeAt(fields, _CONTEXT_IDX);
|
||||||
|
if (!ListWrapper.isEmpty(fields)) {
|
||||||
|
// At least one assignment.
|
||||||
|
fields.push(`${this.utilName}.uninitialized();`);
|
||||||
|
}
|
||||||
|
return `${this.getContextName()} = null; ${ListWrapper.join(fields, ' = ')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates statements destroying all pipe variables.
|
||||||
|
*/
|
||||||
|
genPipeOnDestroy(): string {
|
||||||
|
return ListWrapper.join(ListWrapper.map(ListWrapper.filter(this.records, (r) => {
|
||||||
|
return r.isPipeRecord();
|
||||||
|
}), (r) => { return `${this.getPipeName(r.selfIndex)}.onDestroy();`; }), '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
getPipeName(idx: int): string { return `${this.fieldPrefix}${this._sanitizedNames[idx]}_pipe`; }
|
||||||
|
|
||||||
|
getAllDirectiveNames(): List<string> {
|
||||||
|
return ListWrapper.map(this.directiveRecords, d => this.getDirectiveName(d.directiveIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
getDirectiveName(d: DirectiveIndex): string { return `${this.fieldPrefix}directive_${d.name}`; }
|
||||||
|
|
||||||
|
getAllDetectorNames(): List<string> {
|
||||||
|
return ListWrapper.map(
|
||||||
|
ListWrapper.filter(this.directiveRecords, r => r.isOnPushChangeDetection()),
|
||||||
|
(d) => this.getDetectorName(d.directiveIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
getDetectorName(d: DirectiveIndex): string { return `${this.fieldPrefix}detector_${d.name}`; }
|
||||||
|
}
|
@ -3,6 +3,7 @@ library angular2.transform.template_compiler.change_detector_codegen;
|
|||||||
import 'dart:convert' show JSON;
|
import 'dart:convert' show JSON;
|
||||||
import 'package:angular2/src/change_detection/change_detection_util.dart';
|
import 'package:angular2/src/change_detection/change_detection_util.dart';
|
||||||
import 'package:angular2/src/change_detection/coalesce.dart';
|
import 'package:angular2/src/change_detection/coalesce.dart';
|
||||||
|
import 'package:angular2/src/change_detection/codegen_name_util.dart';
|
||||||
import 'package:angular2/src/change_detection/directive_record.dart';
|
import 'package:angular2/src/change_detection/directive_record.dart';
|
||||||
import 'package:angular2/src/change_detection/interfaces.dart';
|
import 'package:angular2/src/change_detection/interfaces.dart';
|
||||||
import 'package:angular2/src/change_detection/proto_change_detector.dart';
|
import 'package:angular2/src/change_detection/proto_change_detector.dart';
|
||||||
@ -72,18 +73,14 @@ class _CodegenState {
|
|||||||
final String _changeDetectionMode;
|
final String _changeDetectionMode;
|
||||||
final List<ProtoRecord> _records;
|
final List<ProtoRecord> _records;
|
||||||
final List<DirectiveRecord> _directiveRecords;
|
final List<DirectiveRecord> _directiveRecords;
|
||||||
final List<String> _localNames;
|
final CodegenNameUtil _names;
|
||||||
final List<String> _changeNames;
|
|
||||||
final List<String> _fieldNames;
|
|
||||||
final List<String> _pipeNames;
|
|
||||||
|
|
||||||
_CodegenState._(this._changeDetectorDefId, this._contextTypeName,
|
_CodegenState._(this._changeDetectorDefId, this._contextTypeName,
|
||||||
this._changeDetectorTypeName, String changeDetectionStrategy,
|
this._changeDetectorTypeName, String changeDetectionStrategy,
|
||||||
this._records, this._directiveRecords, List<String> localNames)
|
List<ProtoRecord> records, List<DirectiveRecord> directiveRecords)
|
||||||
: this._localNames = localNames,
|
: _records = records,
|
||||||
_changeNames = _getChangeNames(localNames),
|
_directiveRecords = directiveRecords,
|
||||||
_fieldNames = _getFieldNames(localNames),
|
_names = new CodegenNameUtil(records, directiveRecords, '_', _UTIL),
|
||||||
_pipeNames = _getPipeNames(localNames),
|
|
||||||
_changeDetectionMode = ChangeDetectionUtil
|
_changeDetectionMode = ChangeDetectionUtil
|
||||||
.changeDetectionMode(changeDetectionStrategy);
|
.changeDetectionMode(changeDetectionStrategy);
|
||||||
|
|
||||||
@ -94,33 +91,9 @@ class _CodegenState {
|
|||||||
.forEach((rec) => protoRecords.add(rec, def.variableNames));
|
.forEach((rec) => protoRecords.add(rec, def.variableNames));
|
||||||
var records = coalesce(protoRecords.records);
|
var records = coalesce(protoRecords.records);
|
||||||
return new _CodegenState._(def.id, typeName, changeDetectorTypeName,
|
return new _CodegenState._(def.id, typeName, changeDetectorTypeName,
|
||||||
def.strategy, records, def.directiveRecords, _getLocalNames(records));
|
def.strategy, records, def.directiveRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates sanitized names for use as local variables.
|
|
||||||
static List<String> _getLocalNames(List<ProtoRecord> records) {
|
|
||||||
var whitespacePattern = new RegExp(r'\W');
|
|
||||||
var localNames = new List<String>(records.length + 1);
|
|
||||||
localNames[0] = 'context';
|
|
||||||
for (var i = 0; i < records.length; ++i) {
|
|
||||||
var sanitizedName = records[i].name.replaceAll(whitespacePattern, '');
|
|
||||||
localNames[i + 1] = '$sanitizedName$i';
|
|
||||||
}
|
|
||||||
return localNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates names for use as local change variables.
|
|
||||||
static List<String> _getChangeNames(List<String> localNames) =>
|
|
||||||
localNames.map((name) => 'change_$name').toList();
|
|
||||||
|
|
||||||
/// Generates names for use as private fields.
|
|
||||||
static List<String> _getFieldNames(List<String> localNames) =>
|
|
||||||
localNames.map((name) => '_$name').toList();
|
|
||||||
|
|
||||||
/// Generates names for use as private pipe variables.
|
|
||||||
static List<String> _getPipeNames(List<String> localNames) =>
|
|
||||||
localNames.map((name) => '_${name}_pipe').toList();
|
|
||||||
|
|
||||||
void _writeToBuf(StringBuffer buf) {
|
void _writeToBuf(StringBuffer buf) {
|
||||||
buf.write('''\n
|
buf.write('''\n
|
||||||
class $_changeDetectorTypeName extends $_BASE_CLASS {
|
class $_changeDetectorTypeName extends $_BASE_CLASS {
|
||||||
@ -131,17 +104,16 @@ class _CodegenState {
|
|||||||
dynamic $_LOCALS_ACCESSOR = null;
|
dynamic $_LOCALS_ACCESSOR = null;
|
||||||
dynamic $_ALREADY_CHECKED_ACCESSOR = false;
|
dynamic $_ALREADY_CHECKED_ACCESSOR = false;
|
||||||
dynamic $_CURRENT_PROTO = null;
|
dynamic $_CURRENT_PROTO = null;
|
||||||
${_allFields().map((f) {
|
$_contextTypeName ${_names.getContextName()};
|
||||||
if (f == _CONTEXT_ACCESSOR) {
|
${_names.genDeclareFields()}
|
||||||
return '$_contextTypeName $f = null;';
|
|
||||||
}
|
|
||||||
return 'dynamic $f = $_UTIL.uninitialized();';
|
|
||||||
}).join('')}
|
|
||||||
|
|
||||||
$_changeDetectorTypeName(
|
$_changeDetectorTypeName(
|
||||||
dynamic $_DISPATCHER_ACCESSOR,
|
dynamic $_DISPATCHER_ACCESSOR,
|
||||||
this.$_PROTOS_ACCESSOR,
|
this.$_PROTOS_ACCESSOR,
|
||||||
this.$_DIRECTIVES_ACCESSOR) : super(${_encodeValue(_changeDetectorDefId)}, $_DISPATCHER_ACCESSOR);
|
this.$_DIRECTIVES_ACCESSOR)
|
||||||
|
: super(${_encodeValue(_changeDetectorDefId)}, $_DISPATCHER_ACCESSOR) {
|
||||||
|
${_names.genDehydrateFields()}
|
||||||
|
}
|
||||||
|
|
||||||
void detectChangesInRecords(throwOnChange) {
|
void detectChangesInRecords(throwOnChange) {
|
||||||
if (!hydrated()) {
|
if (!hydrated()) {
|
||||||
@ -155,13 +127,12 @@ class _CodegenState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void __detectChangesInRecords(throwOnChange) {
|
void __detectChangesInRecords(throwOnChange) {
|
||||||
${_genLocalDefinitions()}
|
${_names.genInitLocals()}
|
||||||
${_genChangeDefinitons()}
|
|
||||||
var $_IS_CHANGED_LOCAL = false;
|
var $_IS_CHANGED_LOCAL = false;
|
||||||
$_CURRENT_PROTO = null;
|
$_CURRENT_PROTO = null;
|
||||||
var $_CHANGES_LOCAL = null;
|
var $_CHANGES_LOCAL = null;
|
||||||
|
|
||||||
context = $_CONTEXT_ACCESSOR;
|
context = ${_names.getContextName()};
|
||||||
${_records.map(_genRecord).join('')}
|
${_records.map(_genRecord).join('')}
|
||||||
|
|
||||||
$_ALREADY_CHECKED_ACCESSOR = true;
|
$_ALREADY_CHECKED_ACCESSOR = true;
|
||||||
@ -173,7 +144,7 @@ class _CodegenState {
|
|||||||
|
|
||||||
void hydrate($_contextTypeName context, locals, directives, pipes) {
|
void hydrate($_contextTypeName context, locals, directives, pipes) {
|
||||||
$_MODE_ACCESSOR = '$_changeDetectionMode';
|
$_MODE_ACCESSOR = '$_changeDetectionMode';
|
||||||
$_CONTEXT_ACCESSOR = context;
|
${_names.getContextName()} = context;
|
||||||
$_LOCALS_ACCESSOR = locals;
|
$_LOCALS_ACCESSOR = locals;
|
||||||
${_genHydrateDirectives()}
|
${_genHydrateDirectives()}
|
||||||
${_genHydrateDetectors()}
|
${_genHydrateDetectors()}
|
||||||
@ -182,17 +153,13 @@ class _CodegenState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dehydrate() {
|
void dehydrate() {
|
||||||
${_genPipeOnDestroy()}
|
${_names.genPipeOnDestroy()}
|
||||||
${_allFields().map((f) {
|
${_names.genDehydrateFields()}
|
||||||
return f == _CONTEXT_ACCESSOR
|
|
||||||
? '$f = null;'
|
|
||||||
: '$f = $_UTIL.uninitialized();';
|
|
||||||
}).join('')}
|
|
||||||
$_LOCALS_ACCESSOR = null;
|
$_LOCALS_ACCESSOR = null;
|
||||||
$_PIPES_ACCESSOR = null;
|
$_PIPES_ACCESSOR = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
hydrated() => $_CONTEXT_ACCESSOR != null;
|
hydrated() => ${_names.getContextName()} != null;
|
||||||
|
|
||||||
static $_GEN_PREFIX.ProtoChangeDetector
|
static $_GEN_PREFIX.ProtoChangeDetector
|
||||||
$PROTO_CHANGE_DETECTOR_FACTORY_METHOD(
|
$PROTO_CHANGE_DETECTOR_FACTORY_METHOD(
|
||||||
@ -212,39 +179,9 @@ class _CodegenState {
|
|||||||
''');
|
''');
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> _genGetDirectiveFieldNames() {
|
|
||||||
return _directiveRecords
|
|
||||||
.map((d) => _genGetDirective(d.directiveIndex))
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> _genGetDetectorFieldNames() {
|
|
||||||
return _directiveRecords
|
|
||||||
.where((d) => d.isOnPushChangeDetection())
|
|
||||||
.map((d) => _genGetDetector(d.directiveIndex))
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
String _genGetDirective(DirectiveIndex d) => '_directive_${d.name}';
|
|
||||||
String _genGetDetector(DirectiveIndex d) => '_detector_${d.name}';
|
|
||||||
|
|
||||||
List<String> _getNonNullPipeNames() {
|
|
||||||
return _records
|
|
||||||
.where((r) => r.isPipeRecord())
|
|
||||||
.map((r) => _pipeNames[r.selfIndex])
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> _allFields() {
|
|
||||||
return new List.from(_fieldNames)
|
|
||||||
..addAll(_getNonNullPipeNames())
|
|
||||||
..addAll(_genGetDirectiveFieldNames())
|
|
||||||
..addAll(_genGetDetectorFieldNames());
|
|
||||||
}
|
|
||||||
|
|
||||||
String _genHydrateDirectives() {
|
String _genHydrateDirectives() {
|
||||||
var buf = new StringBuffer();
|
var buf = new StringBuffer();
|
||||||
var directiveFieldNames = _genGetDirectiveFieldNames();
|
var directiveFieldNames = _names.getAllDirectiveNames();
|
||||||
for (var i = 0; i < directiveFieldNames.length; ++i) {
|
for (var i = 0; i < directiveFieldNames.length; ++i) {
|
||||||
buf.writeln('${directiveFieldNames[i]} = directives.getDirectiveFor('
|
buf.writeln('${directiveFieldNames[i]} = directives.getDirectiveFor('
|
||||||
'$_DIRECTIVES_ACCESSOR[$i].directiveIndex);');
|
'$_DIRECTIVES_ACCESSOR[$i].directiveIndex);');
|
||||||
@ -254,7 +191,7 @@ class _CodegenState {
|
|||||||
|
|
||||||
String _genHydrateDetectors() {
|
String _genHydrateDetectors() {
|
||||||
var buf = new StringBuffer();
|
var buf = new StringBuffer();
|
||||||
var detectorFieldNames = _genGetDetectorFieldNames();
|
var detectorFieldNames = _names.getAllDetectorNames();
|
||||||
for (var i = 0; i < detectorFieldNames.length; ++i) {
|
for (var i = 0; i < detectorFieldNames.length; ++i) {
|
||||||
buf.writeln('${detectorFieldNames[i]} = directives.getDetectorFor('
|
buf.writeln('${detectorFieldNames[i]} = directives.getDetectorFor('
|
||||||
'$_DIRECTIVES_ACCESSOR[$i].directiveIndex);');
|
'$_DIRECTIVES_ACCESSOR[$i].directiveIndex);');
|
||||||
@ -262,9 +199,6 @@ class _CodegenState {
|
|||||||
return '$buf';
|
return '$buf';
|
||||||
}
|
}
|
||||||
|
|
||||||
String _genPipeOnDestroy() =>
|
|
||||||
_getNonNullPipeNames().map((p) => '$p.onDestroy();').join('');
|
|
||||||
|
|
||||||
/// Generates calls to `onAllChangesDone` for all `Directive`s that request
|
/// Generates calls to `onAllChangesDone` for all `Directive`s that request
|
||||||
/// them.
|
/// them.
|
||||||
String _getCallOnAllChangesDoneBody() {
|
String _getCallOnAllChangesDoneBody() {
|
||||||
@ -272,7 +206,7 @@ class _CodegenState {
|
|||||||
var directiveNotifications = _directiveRecords.reversed
|
var directiveNotifications = _directiveRecords.reversed
|
||||||
.where((rec) => rec.callOnAllChangesDone)
|
.where((rec) => rec.callOnAllChangesDone)
|
||||||
.map((rec) =>
|
.map((rec) =>
|
||||||
'${_genGetDirective(rec.directiveIndex)}.onAllChangesDone();')
|
'${_names.getDirectiveName(rec.directiveIndex)}.onAllChangesDone();')
|
||||||
.join('');
|
.join('');
|
||||||
return '''
|
return '''
|
||||||
$_DISPATCHER_ACCESSOR.notifyOnAllChangesDone();
|
$_DISPATCHER_ACCESSOR.notifyOnAllChangesDone();
|
||||||
@ -280,12 +214,6 @@ class _CodegenState {
|
|||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
|
|
||||||
String _genLocalDefinitions() =>
|
|
||||||
_localNames.map((name) => 'var $name = null;').join('');
|
|
||||||
|
|
||||||
String _genChangeDefinitons() =>
|
|
||||||
_changeNames.map((name) => 'var $name = false;').join('');
|
|
||||||
|
|
||||||
String _genRecord(ProtoRecord r) {
|
String _genRecord(ProtoRecord r) {
|
||||||
var rec = null;
|
var rec = null;
|
||||||
if (r.isLifeCycleRecord()) {
|
if (r.isLifeCycleRecord()) {
|
||||||
@ -311,14 +239,14 @@ class _CodegenState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _genPipeCheck(ProtoRecord r) {
|
String _genPipeCheck(ProtoRecord r) {
|
||||||
var context = _localNames[r.contextIndex];
|
var context = _names.getLocalName(r.contextIndex);
|
||||||
var argString = r.args.map((arg) => this._localNames[arg]).join(", ");
|
var argString = r.args.map((arg) => _names.getLocalName(arg)).join(", ");
|
||||||
|
|
||||||
var oldValue = _fieldNames[r.selfIndex];
|
var oldValue = _names.getFieldName(r.selfIndex);
|
||||||
var newValue = _localNames[r.selfIndex];
|
var newValue = _names.getLocalName(r.selfIndex);
|
||||||
var change = _changeNames[r.selfIndex];
|
var change = _names.getChangeName(r.selfIndex);
|
||||||
|
|
||||||
var pipe = _pipeNames[r.selfIndex];
|
var pipe = _names.getPipeName(r.selfIndex);
|
||||||
var cdRef = 'this.ref';
|
var cdRef = 'this.ref';
|
||||||
|
|
||||||
var protoIndex = r.selfIndex - 1;
|
var protoIndex = r.selfIndex - 1;
|
||||||
@ -344,15 +272,15 @@ class _CodegenState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _genReferenceCheck(ProtoRecord r) {
|
String _genReferenceCheck(ProtoRecord r) {
|
||||||
var oldValue = _fieldNames[r.selfIndex];
|
var oldValue = _names.getFieldName(r.selfIndex);
|
||||||
var newValue = _localNames[r.selfIndex];
|
var newValue = _names.getLocalName(r.selfIndex);
|
||||||
|
|
||||||
var protoIndex = r.selfIndex - 1;
|
var protoIndex = r.selfIndex - 1;
|
||||||
var check = '''
|
var check = '''
|
||||||
$_CURRENT_PROTO = $_PROTOS_ACCESSOR[$protoIndex];
|
$_CURRENT_PROTO = $_PROTOS_ACCESSOR[$protoIndex];
|
||||||
${_genUpdateCurrentValue(r)}
|
${_genUpdateCurrentValue(r)}
|
||||||
if (!$_IDENTICAL_CHECK_FN($newValue, $oldValue)) {
|
if (!$_IDENTICAL_CHECK_FN($newValue, $oldValue)) {
|
||||||
${_changeNames[r.selfIndex]} = true;
|
${_names.getChangeName(r.selfIndex)} = true;
|
||||||
${_genUpdateDirectiveOrElement(r)}
|
${_genUpdateDirectiveOrElement(r)}
|
||||||
${_genAddToChanges(r)}
|
${_genAddToChanges(r)}
|
||||||
$oldValue = $newValue;
|
$oldValue = $newValue;
|
||||||
@ -360,7 +288,7 @@ class _CodegenState {
|
|||||||
''';
|
''';
|
||||||
if (r.isPureFunction()) {
|
if (r.isPureFunction()) {
|
||||||
// Add an "if changed guard"
|
// Add an "if changed guard"
|
||||||
var condition = r.args.map((a) => _changeNames[a]).join(' || ');
|
var condition = r.args.map((a) => _names.getChangeName(a)).join(' || ');
|
||||||
return 'if ($condition) { $check } else { $newValue = $oldValue; }';
|
return 'if ($condition) { $check } else { $newValue = $oldValue; }';
|
||||||
} else {
|
} else {
|
||||||
return check;
|
return check;
|
||||||
@ -369,11 +297,11 @@ class _CodegenState {
|
|||||||
|
|
||||||
String _genUpdateCurrentValue(ProtoRecord r) {
|
String _genUpdateCurrentValue(ProtoRecord r) {
|
||||||
var context = r.contextIndex == -1
|
var context = r.contextIndex == -1
|
||||||
? _genGetDirective(r.directiveIndex)
|
? _names.getDirectiveName(r.directiveIndex)
|
||||||
: _localNames[r.contextIndex];
|
: _names.getLocalName(r.contextIndex);
|
||||||
|
|
||||||
var newValue = _localNames[r.selfIndex];
|
var newValue = _names.getLocalName(r.selfIndex);
|
||||||
var argString = r.args.map((arg) => _localNames[arg]).join(', ');
|
var argString = r.args.map((arg) => _names.getLocalName(arg)).join(', ');
|
||||||
|
|
||||||
var rhs;
|
var rhs;
|
||||||
switch (r.mode) {
|
switch (r.mode) {
|
||||||
@ -419,7 +347,7 @@ class _CodegenState {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.KEYED_ACCESS:
|
case RecordType.KEYED_ACCESS:
|
||||||
rhs = '$context[${_localNames[r.args[0]]}]';
|
rhs = '$context[${_names.getLocalName(r.args[0])}]';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -432,7 +360,7 @@ class _CodegenState {
|
|||||||
String _genInterpolation(ProtoRecord r) {
|
String _genInterpolation(ProtoRecord r) {
|
||||||
var res = new StringBuffer();
|
var res = new StringBuffer();
|
||||||
for (var i = 0; i < r.args.length; ++i) {
|
for (var i = 0; i < r.args.length; ++i) {
|
||||||
var name = _localNames[r.args[i]];
|
var name = _names.getLocalName(r.args[i]);
|
||||||
res.write(
|
res.write(
|
||||||
'${_encodeValue(r.fixedArgs[i])} "\$\{$name == null ? "" : $name\}" ');
|
'${_encodeValue(r.fixedArgs[i])} "\$\{$name == null ? "" : $name\}" ');
|
||||||
}
|
}
|
||||||
@ -443,13 +371,13 @@ class _CodegenState {
|
|||||||
String _genUpdateDirectiveOrElement(ProtoRecord r) {
|
String _genUpdateDirectiveOrElement(ProtoRecord r) {
|
||||||
if (!r.lastInBinding) return '';
|
if (!r.lastInBinding) return '';
|
||||||
|
|
||||||
var newValue = _localNames[r.selfIndex];
|
var newValue = _names.getLocalName(r.selfIndex);
|
||||||
var oldValue = _fieldNames[r.selfIndex];
|
var oldValue = _names.getFieldName(r.selfIndex);
|
||||||
|
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
if (br.isDirective()) {
|
if (br.isDirective()) {
|
||||||
var directiveProperty =
|
var directiveProperty =
|
||||||
'${_genGetDirective(br.directiveRecord.directiveIndex)}.${br.propertyName}';
|
'${_names.getDirectiveName(br.directiveRecord.directiveIndex)}.${br.propertyName}';
|
||||||
return '''
|
return '''
|
||||||
${_genThrowOnChangeCheck(oldValue, newValue)}
|
${_genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
$directiveProperty = $newValue;
|
$directiveProperty = $newValue;
|
||||||
@ -474,8 +402,8 @@ class _CodegenState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _genAddToChanges(ProtoRecord r) {
|
String _genAddToChanges(ProtoRecord r) {
|
||||||
var newValue = _localNames[r.selfIndex];
|
var newValue = _names.getLocalName(r.selfIndex);
|
||||||
var oldValue = _fieldNames[r.selfIndex];
|
var oldValue = _names.getFieldName(r.selfIndex);
|
||||||
if (!r.bindingRecord.callOnChange()) return '';
|
if (!r.bindingRecord.callOnChange()) return '';
|
||||||
return '''
|
return '''
|
||||||
$_CHANGES_LOCAL = $_UTIL.addChange(
|
$_CHANGES_LOCAL = $_UTIL.addChange(
|
||||||
@ -497,19 +425,19 @@ class _CodegenState {
|
|||||||
String _genOnCheck(ProtoRecord r) {
|
String _genOnCheck(ProtoRecord r) {
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
return 'if (!throwOnChange) '
|
return 'if (!throwOnChange) '
|
||||||
'${_genGetDirective(br.directiveRecord.directiveIndex)}.onCheck();';
|
'${_names.getDirectiveName(br.directiveRecord.directiveIndex)}.onCheck();';
|
||||||
}
|
}
|
||||||
|
|
||||||
String _genOnInit(ProtoRecord r) {
|
String _genOnInit(ProtoRecord r) {
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
return 'if (!throwOnChange && !$_ALREADY_CHECKED_ACCESSOR) '
|
return 'if (!throwOnChange && !$_ALREADY_CHECKED_ACCESSOR) '
|
||||||
'${_genGetDirective(br.directiveRecord.directiveIndex)}.onInit();';
|
'${_names.getDirectiveName(br.directiveRecord.directiveIndex)}.onInit();';
|
||||||
}
|
}
|
||||||
|
|
||||||
String _genOnChange(ProtoRecord r) {
|
String _genOnChange(ProtoRecord r) {
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
return 'if (!throwOnChange && $_CHANGES_LOCAL != null) '
|
return 'if (!throwOnChange && $_CHANGES_LOCAL != null) '
|
||||||
'${_genGetDirective(br.directiveRecord.directiveIndex)}'
|
'${_names.getDirectiveName(br.directiveRecord.directiveIndex)}'
|
||||||
'.onChange($_CHANGES_LOCAL);';
|
'.onChange($_CHANGES_LOCAL);';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,7 +446,7 @@ class _CodegenState {
|
|||||||
if (!r.lastInDirective || !br.isOnPushChangeDetection()) return '';
|
if (!r.lastInDirective || !br.isOnPushChangeDetection()) return '';
|
||||||
return '''
|
return '''
|
||||||
if($_IS_CHANGED_LOCAL) {
|
if($_IS_CHANGED_LOCAL) {
|
||||||
${_genGetDetector(br.directiveRecord.directiveIndex)}.markAsCheckOnce();
|
${_names.getDetectorName(br.directiveRecord.directiveIndex)}.markAsCheckOnce();
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
@ -532,7 +460,6 @@ const PROTO_CHANGE_DETECTOR_FACTORY_METHOD = 'newProtoChangeDetector';
|
|||||||
const _ALREADY_CHECKED_ACCESSOR = '_alreadyChecked';
|
const _ALREADY_CHECKED_ACCESSOR = '_alreadyChecked';
|
||||||
const _BASE_CLASS = '$_GEN_PREFIX.AbstractChangeDetector';
|
const _BASE_CLASS = '$_GEN_PREFIX.AbstractChangeDetector';
|
||||||
const _CHANGES_LOCAL = 'changes';
|
const _CHANGES_LOCAL = 'changes';
|
||||||
const _CONTEXT_ACCESSOR = '_context';
|
|
||||||
const _CURRENT_PROTO = 'currentProto';
|
const _CURRENT_PROTO = 'currentProto';
|
||||||
const _DIRECTIVES_ACCESSOR = '_directiveRecords';
|
const _DIRECTIVES_ACCESSOR = '_directiveRecords';
|
||||||
const _DISPATCHER_ACCESSOR = 'dispatcher';
|
const _DISPATCHER_ACCESSOR = 'dispatcher';
|
||||||
|
@ -30,13 +30,15 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
|||||||
dynamic _locals = null;
|
dynamic _locals = null;
|
||||||
dynamic _alreadyChecked = false;
|
dynamic _alreadyChecked = false;
|
||||||
dynamic currentProto = null;
|
dynamic currentProto = null;
|
||||||
MyComponent _context = null;
|
MyComponent _context;
|
||||||
dynamic _myNum0 = _gen.ChangeDetectionUtil.uninitialized();
|
var _myNum0, _interpolate1;
|
||||||
dynamic _interpolate1 = _gen.ChangeDetectionUtil.uninitialized();
|
|
||||||
|
|
||||||
_MyComponent_ChangeDetector0(
|
_MyComponent_ChangeDetector0(
|
||||||
dynamic dispatcher, this._protos, this._directiveRecords)
|
dynamic dispatcher, this._protos, this._directiveRecords)
|
||||||
: super("MyComponent_comp_0", dispatcher);
|
: super("MyComponent_comp_0", dispatcher) {
|
||||||
|
_context = null;
|
||||||
|
_myNum0 = _interpolate1 = _gen.ChangeDetectionUtil.uninitialized();
|
||||||
|
}
|
||||||
|
|
||||||
void detectChangesInRecords(throwOnChange) {
|
void detectChangesInRecords(throwOnChange) {
|
||||||
if (!hydrated()) {
|
if (!hydrated()) {
|
||||||
@ -50,12 +52,8 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void __detectChangesInRecords(throwOnChange) {
|
void __detectChangesInRecords(throwOnChange) {
|
||||||
var context = null;
|
var context, c_context, myNum0, c_myNum0, interpolate1, c_interpolate1;
|
||||||
var myNum0 = null;
|
c_context = c_myNum0 = c_interpolate1 = false;
|
||||||
var interpolate1 = null;
|
|
||||||
var change_context = false;
|
|
||||||
var change_myNum0 = false;
|
|
||||||
var change_interpolate1 = false;
|
|
||||||
var isChanged = false;
|
var isChanged = false;
|
||||||
currentProto = null;
|
currentProto = null;
|
||||||
var changes = null;
|
var changes = null;
|
||||||
@ -64,15 +62,15 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
|||||||
currentProto = _protos[0];
|
currentProto = _protos[0];
|
||||||
myNum0 = context.myNum;
|
myNum0 = context.myNum;
|
||||||
if (!_gen.looseIdentical(myNum0, _myNum0)) {
|
if (!_gen.looseIdentical(myNum0, _myNum0)) {
|
||||||
change_myNum0 = true;
|
c_myNum0 = true;
|
||||||
|
|
||||||
_myNum0 = myNum0;
|
_myNum0 = myNum0;
|
||||||
}
|
}
|
||||||
if (change_myNum0) {
|
if (c_myNum0) {
|
||||||
currentProto = _protos[1];
|
currentProto = _protos[1];
|
||||||
interpolate1 = "Salad: " "${myNum0 == null ? "" : myNum0}" " is awesome";
|
interpolate1 = "Salad: " "${myNum0 == null ? "" : myNum0}" " is awesome";
|
||||||
if (!_gen.looseIdentical(interpolate1, _interpolate1)) {
|
if (!_gen.looseIdentical(interpolate1, _interpolate1)) {
|
||||||
change_interpolate1 = true;
|
c_interpolate1 = true;
|
||||||
if (throwOnChange) {
|
if (throwOnChange) {
|
||||||
_gen.ChangeDetectionUtil.throwOnChange(currentProto,
|
_gen.ChangeDetectionUtil.throwOnChange(currentProto,
|
||||||
_gen.ChangeDetectionUtil.simpleChange(
|
_gen.ChangeDetectionUtil.simpleChange(
|
||||||
@ -108,8 +106,7 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
|||||||
|
|
||||||
void dehydrate() {
|
void dehydrate() {
|
||||||
_context = null;
|
_context = null;
|
||||||
_myNum0 = _gen.ChangeDetectionUtil.uninitialized();
|
_myNum0 = _interpolate1 = _gen.ChangeDetectionUtil.uninitialized();
|
||||||
_interpolate1 = _gen.ChangeDetectionUtil.uninitialized();
|
|
||||||
_locals = null;
|
_locals = null;
|
||||||
_pipes = null;
|
_pipes = null;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user