refactor(change_detect): Move common fields to AbstractChangeDetector
Move fields common to Dynamic, Jit, and Pregen change detectors into the `AbstractChangeDetector` superclass to save on codegen size and reduce code duplication. Update to #3248, closes #3243
This commit is contained in:
parent
d894aa9101
commit
192cf9ddf5
@ -1,10 +1,12 @@
|
|||||||
import {isPresent, BaseException} from 'angular2/src/facade/lang';
|
import {isPresent, BaseException} from 'angular2/src/facade/lang';
|
||||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {ChangeDetectorRef} from './change_detector_ref';
|
import {ChangeDetectorRef} from './change_detector_ref';
|
||||||
import {ChangeDetector} from './interfaces';
|
import {DirectiveRecord} from './directive_record';
|
||||||
|
import {ChangeDetector, ChangeDispatcher} from './interfaces';
|
||||||
import {ChangeDetectionError} from './exceptions';
|
import {ChangeDetectionError} from './exceptions';
|
||||||
import {ProtoRecord} from './proto_record';
|
import {ProtoRecord} from './proto_record';
|
||||||
import {Locals} from './parser/locals';
|
import {Locals} from './parser/locals';
|
||||||
|
import {Pipes} from './pipes/pipes';
|
||||||
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
import {CHECK_ALWAYS, CHECK_ONCE, CHECKED, DETACHED, ON_PUSH} from './constants';
|
||||||
|
|
||||||
class _Context {
|
class _Context {
|
||||||
@ -13,14 +15,31 @@ class _Context {
|
|||||||
public expression: any) {}
|
public expression: any) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AbstractChangeDetector implements ChangeDetector {
|
export class AbstractChangeDetector<T> implements ChangeDetector {
|
||||||
lightDomChildren: List<any> = [];
|
lightDomChildren: List<any> = [];
|
||||||
shadowDomChildren: List<any> = [];
|
shadowDomChildren: List<any> = [];
|
||||||
parent: ChangeDetector;
|
parent: ChangeDetector;
|
||||||
mode: string = null;
|
|
||||||
ref: ChangeDetectorRef;
|
ref: ChangeDetectorRef;
|
||||||
|
|
||||||
constructor(public id: string, public dispatcher: any) { this.ref = new ChangeDetectorRef(this); }
|
// The names of the below fields must be kept in sync with codegen_name_util.ts or
|
||||||
|
// change detection will fail.
|
||||||
|
alreadyChecked: any = false;
|
||||||
|
context: T;
|
||||||
|
currentProto: ProtoRecord = null;
|
||||||
|
directiveRecords: List<DirectiveRecord>;
|
||||||
|
dispatcher: ChangeDispatcher;
|
||||||
|
locals: Locals = null;
|
||||||
|
mode: string = null;
|
||||||
|
pipes: Pipes = null;
|
||||||
|
protos: List<ProtoRecord>;
|
||||||
|
|
||||||
|
constructor(public id: string, dispatcher: ChangeDispatcher, protos: List<ProtoRecord>,
|
||||||
|
directiveRecords: List<DirectiveRecord>) {
|
||||||
|
this.ref = new ChangeDetectorRef(this);
|
||||||
|
this.directiveRecords = directiveRecords;
|
||||||
|
this.dispatcher = dispatcher;
|
||||||
|
this.protos = protos;
|
||||||
|
}
|
||||||
|
|
||||||
addChild(cd: ChangeDetector): void {
|
addChild(cd: ChangeDetector): void {
|
||||||
this.lightDomChildren.push(cd);
|
this.lightDomChildren.push(cd);
|
||||||
@ -58,7 +77,7 @@ export class AbstractChangeDetector implements ChangeDetector {
|
|||||||
|
|
||||||
detectChangesInRecords(throwOnChange: boolean): void {}
|
detectChangesInRecords(throwOnChange: boolean): void {}
|
||||||
|
|
||||||
hydrate(context: any, locals: Locals, directives: any, pipes: any): void {}
|
hydrate(context: T, locals: Locals, directives: any, pipes: any): void {}
|
||||||
|
|
||||||
hydrateDirectives(directives: any): void {}
|
hydrateDirectives(directives: any): void {}
|
||||||
|
|
||||||
|
@ -42,7 +42,8 @@ export {
|
|||||||
ChangeDetector,
|
ChangeDetector,
|
||||||
ChangeDispatcher,
|
ChangeDispatcher,
|
||||||
ChangeDetection,
|
ChangeDetection,
|
||||||
ChangeDetectorDefinition
|
ChangeDetectorDefinition,
|
||||||
|
DebugContext
|
||||||
} from './interfaces';
|
} from './interfaces';
|
||||||
export {CHECK_ONCE, CHECK_ALWAYS, DETACHED, CHECKED, ON_PUSH, DEFAULT} from './constants';
|
export {CHECK_ONCE, CHECK_ALWAYS, DETACHED, CHECKED, ON_PUSH, DEFAULT} from './constants';
|
||||||
export {DynamicProtoChangeDetector} from './proto_change_detector';
|
export {DynamicProtoChangeDetector} from './proto_change_detector';
|
||||||
|
@ -6,7 +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';
|
import {CONTEXT_INDEX, CodegenNameUtil, sanitizeName} from './codegen_name_util';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,16 +20,8 @@ import {CodegenNameUtil, sanitizeName} from './codegen_name_util';
|
|||||||
*/
|
*/
|
||||||
var ABSTRACT_CHANGE_DETECTOR = "AbstractChangeDetector";
|
var ABSTRACT_CHANGE_DETECTOR = "AbstractChangeDetector";
|
||||||
var UTIL = "ChangeDetectionUtil";
|
var UTIL = "ChangeDetectionUtil";
|
||||||
var DISPATCHER_ACCESSOR = "this.dispatcher";
|
|
||||||
var PIPES_ACCESSOR = "this.pipes";
|
|
||||||
var PROTOS_ACCESSOR = "this.protos";
|
|
||||||
var DIRECTIVES_ACCESSOR = "this.directiveRecords";
|
|
||||||
var IS_CHANGED_LOCAL = "isChanged";
|
var IS_CHANGED_LOCAL = "isChanged";
|
||||||
var CHANGES_LOCAL = "changes";
|
var CHANGES_LOCAL = "changes";
|
||||||
var LOCALS_ACCESSOR = "this.locals";
|
|
||||||
var MODE_ACCESSOR = "this.mode";
|
|
||||||
var CURRENT_PROTO = "this.currentProto";
|
|
||||||
var ALREADY_CHECKED_ACCESSOR = "this.alreadyChecked";
|
|
||||||
|
|
||||||
export class ChangeDetectorJITGenerator {
|
export class ChangeDetectorJITGenerator {
|
||||||
_names: CodegenNameUtil;
|
_names: CodegenNameUtil;
|
||||||
@ -38,20 +30,14 @@ export class ChangeDetectorJITGenerator {
|
|||||||
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>,
|
||||||
private generateCheckNoChanges: boolean) {
|
private generateCheckNoChanges: boolean) {
|
||||||
this._names = new CodegenNameUtil(this.records, this.directiveRecords, 'this._', UTIL);
|
this._names = new CodegenNameUtil(this.records, this.directiveRecords, UTIL);
|
||||||
this._typeName = sanitizeName(`ChangeDetector_${this.id}`);
|
this._typeName = sanitizeName(`ChangeDetector_${this.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
generate(): Function {
|
generate(): Function {
|
||||||
var classDefinition = `
|
var classDefinition = `
|
||||||
var ${this._typeName} = function ${this._typeName}(dispatcher, protos, directiveRecords) {
|
var ${this._typeName} = function ${this._typeName}(dispatcher, protos, directiveRecords) {
|
||||||
${ABSTRACT_CHANGE_DETECTOR}.call(this, ${JSON.stringify(this.id)}, dispatcher);
|
${ABSTRACT_CHANGE_DETECTOR}.call(this, ${JSON.stringify(this.id)}, dispatcher, protos, directiveRecords);
|
||||||
${PROTOS_ACCESSOR} = protos;
|
|
||||||
${DIRECTIVES_ACCESSOR} = directiveRecords;
|
|
||||||
${LOCALS_ACCESSOR} = null;
|
|
||||||
${CURRENT_PROTO} = null;
|
|
||||||
${PIPES_ACCESSOR} = null;
|
|
||||||
${ALREADY_CHECKED_ACCESSOR} = false;
|
|
||||||
this.dehydrateDirectives(false);
|
this.dehydrateDirectives(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,22 +50,20 @@ export class ChangeDetectorJITGenerator {
|
|||||||
try {
|
try {
|
||||||
this.__detectChangesInRecords(throwOnChange);
|
this.__detectChangesInRecords(throwOnChange);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.throwError(${CURRENT_PROTO}, e, e.stack);
|
this.throwError(${this._names.getCurrentProtoName()}, e, e.stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
${this._typeName}.prototype.__detectChangesInRecords = function(throwOnChange) {
|
${this._typeName}.prototype.__detectChangesInRecords = function(throwOnChange) {
|
||||||
${CURRENT_PROTO} = null;
|
${this._names.getCurrentProtoName()} = null;
|
||||||
|
|
||||||
${this._names.genInitLocals()}
|
${this._names.genInitLocals()}
|
||||||
var ${IS_CHANGED_LOCAL} = false;
|
var ${IS_CHANGED_LOCAL} = false;
|
||||||
var ${CHANGES_LOCAL} = null;
|
var ${CHANGES_LOCAL} = null;
|
||||||
|
|
||||||
context = ${this._names.getContextName()};
|
|
||||||
|
|
||||||
${this.records.map((r) => this._genRecord(r)).join("\n")}
|
${this.records.map((r) => this._genRecord(r)).join("\n")}
|
||||||
|
|
||||||
${ALREADY_CHECKED_ACCESSOR} = true;
|
${this._names.getAlreadyCheckedName()} = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
${this._genCheckNoChanges()}
|
${this._genCheckNoChanges()}
|
||||||
@ -89,26 +73,27 @@ export class ChangeDetectorJITGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
${this._typeName}.prototype.hydrate = function(context, locals, directives, pipes) {
|
${this._typeName}.prototype.hydrate = function(context, locals, directives, pipes) {
|
||||||
${MODE_ACCESSOR} = "${ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy)}";
|
${this._names.getModeName()} =
|
||||||
${this._names.getContextName()} = context;
|
"${ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy)}";
|
||||||
${LOCALS_ACCESSOR} = locals;
|
${this._names.getFieldName(CONTEXT_INDEX)} = context;
|
||||||
|
${this._names.getLocalsAccessorName()} = locals;
|
||||||
this.hydrateDirectives(directives);
|
this.hydrateDirectives(directives);
|
||||||
${PIPES_ACCESSOR} = pipes;
|
${this._names.getPipesAccessorName()} = pipes;
|
||||||
${ALREADY_CHECKED_ACCESSOR} = false;
|
${this._names.getAlreadyCheckedName()} = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
${this._maybeGenHydrateDirectives()}
|
${this._maybeGenHydrateDirectives()}
|
||||||
|
|
||||||
${this._typeName}.prototype.dehydrate = function() {
|
${this._typeName}.prototype.dehydrate = function() {
|
||||||
this.dehydrateDirectives(true);
|
this.dehydrateDirectives(true);
|
||||||
${LOCALS_ACCESSOR} = null;
|
${this._names.getLocalsAccessorName()} = null;
|
||||||
${PIPES_ACCESSOR} = null;
|
${this._names.getPipesAccessorName()} = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
${this._maybeGenDehydrateDirectives()}
|
${this._maybeGenDehydrateDirectives()}
|
||||||
|
|
||||||
${this._typeName}.prototype.hydrated = function() {
|
${this._typeName}.prototype.hydrated = function() {
|
||||||
return ${this._names.getContextName()} !== null;
|
return ${this._names.getFieldName(CONTEXT_INDEX)} !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return function(dispatcher) {
|
return function(dispatcher) {
|
||||||
@ -148,8 +133,8 @@ export class ChangeDetectorJITGenerator {
|
|||||||
var directiveFieldNames = this._names.getAllDirectiveNames();
|
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] = `${directiveFieldNames[i]} = directives.getDirectiveFor(
|
||||||
`${directiveFieldNames[i]} = directives.getDirectiveFor(${DIRECTIVES_ACCESSOR}[${i}].directiveIndex);`;
|
${this._names.getDirectivesAccessorName()}[${i}].directiveIndex);`;
|
||||||
}
|
}
|
||||||
return lines.join('\n');
|
return lines.join('\n');
|
||||||
}
|
}
|
||||||
@ -158,8 +143,8 @@ export class ChangeDetectorJITGenerator {
|
|||||||
var detectorFieldNames = this._names.getAllDetectorNames();
|
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]} = directives.getDetectorFor(
|
||||||
directives.getDetectorFor(${DIRECTIVES_ACCESSOR}[${i}].directiveIndex);`;
|
${this._names.getDirectivesAccessorName()}[${i}].directiveIndex);`;
|
||||||
}
|
}
|
||||||
return lines.join('\n');
|
return lines.join('\n');
|
||||||
}
|
}
|
||||||
@ -179,7 +164,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
var directiveNotifications = notifications.join("\n");
|
var directiveNotifications = notifications.join("\n");
|
||||||
|
|
||||||
return `
|
return `
|
||||||
this.dispatcher.notifyOnAllChangesDone();
|
${this._names.getDispatcherName()}.notifyOnAllChangesDone();
|
||||||
${directiveNotifications}
|
${directiveNotifications}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -223,12 +208,12 @@ export class ChangeDetectorJITGenerator {
|
|||||||
var pipeType = r.name;
|
var pipeType = r.name;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
${CURRENT_PROTO} = ${PROTOS_ACCESSOR}[${protoIndex}];
|
${this._names.getCurrentProtoName()} = ${this._names.getProtosName()}[${protoIndex}];
|
||||||
if (${pipe} === ${UTIL}.uninitialized) {
|
if (${pipe} === ${UTIL}.uninitialized) {
|
||||||
${pipe} = ${PIPES_ACCESSOR}.get('${pipeType}', ${context}, ${cdRef});
|
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${context}, ${cdRef});
|
||||||
} else if (!${pipe}.supports(${context})) {
|
} else if (!${pipe}.supports(${context})) {
|
||||||
${pipe}.onDestroy();
|
${pipe}.onDestroy();
|
||||||
${pipe} = ${PIPES_ACCESSOR}.get('${pipeType}', ${context}, ${cdRef});
|
${pipe} = ${this._names.getPipesAccessorName()}.get('${pipeType}', ${context}, ${cdRef});
|
||||||
}
|
}
|
||||||
|
|
||||||
${newValue} = ${pipe}.transform(${context}, [${argString}]);
|
${newValue} = ${pipe}.transform(${context}, [${argString}]);
|
||||||
@ -248,7 +233,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
|
|
||||||
var protoIndex = r.selfIndex - 1;
|
var protoIndex = r.selfIndex - 1;
|
||||||
var check = `
|
var check = `
|
||||||
${CURRENT_PROTO} = ${PROTOS_ACCESSOR}[${protoIndex}];
|
${this._names.getCurrentProtoName()} = ${this._names.getProtosName()}[${protoIndex}];
|
||||||
${this._genUpdateCurrentValue(r)}
|
${this._genUpdateCurrentValue(r)}
|
||||||
if (${newValue} !== ${oldValue}) {
|
if (${newValue} !== ${oldValue}) {
|
||||||
${this._names.getChangeName(r.selfIndex)} = true;
|
${this._names.getChangeName(r.selfIndex)} = true;
|
||||||
@ -291,7 +276,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.LOCAL:
|
case RecordType.LOCAL:
|
||||||
rhs = `${LOCALS_ACCESSOR}.get('${r.name}')`;
|
rhs = `${this._names.getLocalsAccessorName()}.get('${r.name}')`;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.INVOKE_METHOD:
|
case RecordType.INVOKE_METHOD:
|
||||||
@ -354,7 +339,8 @@ export class ChangeDetectorJITGenerator {
|
|||||||
} else {
|
} else {
|
||||||
return `
|
return `
|
||||||
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
${this._genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
${DISPATCHER_ACCESSOR}.notifyOnBinding(${CURRENT_PROTO}.bindingRecord, ${newValue});
|
${this._names.getDispatcherName()}.notifyOnBinding(
|
||||||
|
${this._names.getCurrentProtoName()}.bindingRecord, ${newValue});
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,7 +349,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
if (this.generateCheckNoChanges) {
|
if (this.generateCheckNoChanges) {
|
||||||
return `
|
return `
|
||||||
if(throwOnChange) {
|
if(throwOnChange) {
|
||||||
${UTIL}.throwOnChange(${CURRENT_PROTO}, ${UTIL}.simpleChange(${oldValue}, ${newValue}));
|
${UTIL}.throwOnChange(${this._names.getCurrentProtoName()}, ${UTIL}.simpleChange(${oldValue}, ${newValue}));
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
@ -385,7 +371,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
if (!r.bindingRecord.callOnChange()) return "";
|
if (!r.bindingRecord.callOnChange()) return "";
|
||||||
return `
|
return `
|
||||||
${CHANGES_LOCAL} = ${UTIL}.addChange(
|
${CHANGES_LOCAL} = ${UTIL}.addChange(
|
||||||
${CHANGES_LOCAL}, ${CURRENT_PROTO}.bindingRecord.propertyName,
|
${CHANGES_LOCAL}, ${this._names.getCurrentProtoName()}.bindingRecord.propertyName,
|
||||||
${UTIL}.simpleChange(${oldValue}, ${newValue}));
|
${UTIL}.simpleChange(${oldValue}, ${newValue}));
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -406,7 +392,7 @@ export class ChangeDetectorJITGenerator {
|
|||||||
|
|
||||||
_genOnInit(r: ProtoRecord): string {
|
_genOnInit(r: ProtoRecord): string {
|
||||||
var br = r.bindingRecord;
|
var br = r.bindingRecord;
|
||||||
return `if (!throwOnChange && !${ALREADY_CHECKED_ACCESSOR}) ${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.onInit();`;
|
return `if (!throwOnChange && !${this._names.getAlreadyCheckedName()}) ${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.onInit();`;
|
||||||
}
|
}
|
||||||
|
|
||||||
_genOnChange(r: ProtoRecord): string {
|
_genOnChange(r: ProtoRecord): string {
|
||||||
|
@ -5,8 +5,21 @@ import {DirectiveIndex} from './directive_record';
|
|||||||
|
|
||||||
import {ProtoRecord} from './proto_record';
|
import {ProtoRecord} from './proto_record';
|
||||||
|
|
||||||
// `context` is always the first field.
|
// The names of these fields must be kept in sync with abstract_change_detector.ts or change
|
||||||
var _CONTEXT_IDX = 0;
|
// detection will fail.
|
||||||
|
const _ALREADY_CHECKED_ACCESSOR = "alreadyChecked";
|
||||||
|
const _CONTEXT_ACCESSOR = "context";
|
||||||
|
const _CURRENT_PROTO = "currentProto";
|
||||||
|
const _DIRECTIVES_ACCESSOR = "directiveRecords";
|
||||||
|
const _DISPATCHER_ACCESSOR = "dispatcher";
|
||||||
|
const _LOCALS_ACCESSOR = "locals";
|
||||||
|
const _MODE_ACCESSOR = "mode";
|
||||||
|
const _PIPES_ACCESSOR = "pipes";
|
||||||
|
const _PROTOS_ACCESSOR = "protos";
|
||||||
|
|
||||||
|
// `context` is always first.
|
||||||
|
export const CONTEXT_INDEX = 0;
|
||||||
|
const _FIELD_PREFIX = 'this.';
|
||||||
|
|
||||||
var _whiteSpaceRegExp = RegExpWrapper.create("\\W", "g");
|
var _whiteSpaceRegExp = RegExpWrapper.create("\\W", "g");
|
||||||
|
|
||||||
@ -29,18 +42,34 @@ export class CodegenNameUtil {
|
|||||||
*/
|
*/
|
||||||
_sanitizedNames: List<string>;
|
_sanitizedNames: List<string>;
|
||||||
|
|
||||||
constructor(public records: List<ProtoRecord>, public directiveRecords: List<any>,
|
constructor(private records: List<ProtoRecord>, private directiveRecords: List<any>,
|
||||||
public fieldPrefix: string, public utilName: string) {
|
private utilName: string) {
|
||||||
this._sanitizedNames = ListWrapper.createFixedSize(this.records.length + 1);
|
this._sanitizedNames = ListWrapper.createFixedSize(this.records.length + 1);
|
||||||
this._sanitizedNames[_CONTEXT_IDX] = 'context';
|
this._sanitizedNames[CONTEXT_INDEX] = _CONTEXT_ACCESSOR;
|
||||||
for (var i = 0, iLen = this.records.length; i < iLen; ++i) {
|
for (var i = 0, iLen = this.records.length; i < iLen; ++i) {
|
||||||
this._sanitizedNames[i + 1] = sanitizeName(`${this.records[i].name}${i}`);
|
this._sanitizedNames[i + 1] = sanitizeName(`${this.records[i].name}${i}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getContextName(): string { return this.getFieldName(_CONTEXT_IDX); }
|
_addFieldPrefix(name: string): string { return `${_FIELD_PREFIX}${name}`; }
|
||||||
|
|
||||||
getLocalName(idx: int): string { return this._sanitizedNames[idx]; }
|
getDispatcherName(): string { return this._addFieldPrefix(_DISPATCHER_ACCESSOR); }
|
||||||
|
|
||||||
|
getPipesAccessorName(): string { return this._addFieldPrefix(_PIPES_ACCESSOR); }
|
||||||
|
|
||||||
|
getProtosName(): string { return this._addFieldPrefix(_PROTOS_ACCESSOR); }
|
||||||
|
|
||||||
|
getDirectivesAccessorName(): string { return this._addFieldPrefix(_DIRECTIVES_ACCESSOR); }
|
||||||
|
|
||||||
|
getLocalsAccessorName(): string { return this._addFieldPrefix(_LOCALS_ACCESSOR); }
|
||||||
|
|
||||||
|
getAlreadyCheckedName(): string { return this._addFieldPrefix(_ALREADY_CHECKED_ACCESSOR); }
|
||||||
|
|
||||||
|
getModeName(): string { return this._addFieldPrefix(_MODE_ACCESSOR); }
|
||||||
|
|
||||||
|
getCurrentProtoName(): string { return this._addFieldPrefix(_CURRENT_PROTO); }
|
||||||
|
|
||||||
|
getLocalName(idx: int): string { return `l_${this._sanitizedNames[idx]}`; }
|
||||||
|
|
||||||
getChangeName(idx: int): string { return `c_${this._sanitizedNames[idx]}`; }
|
getChangeName(idx: int): string { return `c_${this._sanitizedNames[idx]}`; }
|
||||||
|
|
||||||
@ -51,17 +80,22 @@ export class CodegenNameUtil {
|
|||||||
var declarations = [];
|
var declarations = [];
|
||||||
var assignments = [];
|
var assignments = [];
|
||||||
for (var i = 0, iLen = this.getFieldCount(); i < iLen; ++i) {
|
for (var i = 0, iLen = this.getFieldCount(); i < iLen; ++i) {
|
||||||
var changeName = this.getChangeName(i);
|
if (i == CONTEXT_INDEX) {
|
||||||
declarations.push(`${this.getLocalName(i)},${changeName}`);
|
declarations.push(`${this.getLocalName(i)} = ${this.getFieldName(i)}`);
|
||||||
assignments.push(changeName);
|
} else {
|
||||||
|
var changeName = this.getChangeName(i);
|
||||||
|
declarations.push(`${this.getLocalName(i)},${changeName}`);
|
||||||
|
assignments.push(changeName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return `var ${ListWrapper.join(declarations, ',')};` +
|
var assignmentsCode =
|
||||||
`${ListWrapper.join(assignments, '=')} = false;`;
|
ListWrapper.isEmpty(assignments) ? '' : `${ListWrapper.join(assignments, '=')} = false;`;
|
||||||
|
return `var ${ListWrapper.join(declarations, ',')};${assignmentsCode}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFieldCount(): int { return this._sanitizedNames.length; }
|
getFieldCount(): int { return this._sanitizedNames.length; }
|
||||||
|
|
||||||
getFieldName(idx: int): string { return `${this.fieldPrefix}${this._sanitizedNames[idx]}`; }
|
getFieldName(idx: int): string { return this._addFieldPrefix(this._sanitizedNames[idx]); }
|
||||||
|
|
||||||
getAllFieldNames(): List<string> {
|
getAllFieldNames(): List<string> {
|
||||||
var fieldList = [];
|
var fieldList = [];
|
||||||
@ -84,27 +118,17 @@ export class CodegenNameUtil {
|
|||||||
return fieldList;
|
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.
|
* Generates statements which clear all fields so that the change detector is dehydrated.
|
||||||
*/
|
*/
|
||||||
genDehydrateFields(): string {
|
genDehydrateFields(): string {
|
||||||
var fields = this.getAllFieldNames();
|
var fields = this.getAllFieldNames();
|
||||||
ListWrapper.removeAt(fields, _CONTEXT_IDX);
|
ListWrapper.removeAt(fields, CONTEXT_INDEX);
|
||||||
if (!ListWrapper.isEmpty(fields)) {
|
if (!ListWrapper.isEmpty(fields)) {
|
||||||
// At least one assignment.
|
// At least one assignment.
|
||||||
fields.push(`${this.utilName}.uninitialized;`);
|
fields.push(`${this.utilName}.uninitialized;`);
|
||||||
}
|
}
|
||||||
return `${this.getContextName()} = null; ${ListWrapper.join(fields, ' = ')}`;
|
return `${this.getFieldName(CONTEXT_INDEX)} = null; ${ListWrapper.join(fields, ' = ')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,13 +140,17 @@ export class CodegenNameUtil {
|
|||||||
}), (r) => { return `${this.getPipeName(r.selfIndex)}.onDestroy();`; }), '\n');
|
}), (r) => { return `${this.getPipeName(r.selfIndex)}.onDestroy();`; }), '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
getPipeName(idx: int): string { return `${this.fieldPrefix}${this._sanitizedNames[idx]}_pipe`; }
|
getPipeName(idx: int): string {
|
||||||
|
return this._addFieldPrefix(`${this._sanitizedNames[idx]}_pipe`);
|
||||||
|
}
|
||||||
|
|
||||||
getAllDirectiveNames(): List<string> {
|
getAllDirectiveNames(): List<string> {
|
||||||
return ListWrapper.map(this.directiveRecords, d => this.getDirectiveName(d.directiveIndex));
|
return ListWrapper.map(this.directiveRecords, d => this.getDirectiveName(d.directiveIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
getDirectiveName(d: DirectiveIndex): string { return `${this.fieldPrefix}directive_${d.name}`; }
|
getDirectiveName(d: DirectiveIndex): string {
|
||||||
|
return this._addFieldPrefix(`directive_${d.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
getAllDetectorNames(): List<string> {
|
getAllDetectorNames(): List<string> {
|
||||||
return ListWrapper.map(
|
return ListWrapper.map(
|
||||||
@ -130,5 +158,5 @@ export class CodegenNameUtil {
|
|||||||
(d) => this.getDetectorName(d.directiveIndex));
|
(d) => this.getDetectorName(d.directiveIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
getDetectorName(d: DirectiveIndex): string { return `${this.fieldPrefix}detector_${d.name}`; }
|
getDetectorName(d: DirectiveIndex): string { return this._addFieldPrefix(`detector_${d.name}`); }
|
||||||
}
|
}
|
||||||
|
@ -10,19 +10,16 @@ import {ChangeDetectionUtil, SimpleChange} from './change_detection_util';
|
|||||||
|
|
||||||
import {ProtoRecord, RecordType} from './proto_record';
|
import {ProtoRecord, RecordType} from './proto_record';
|
||||||
|
|
||||||
export class DynamicChangeDetector extends AbstractChangeDetector {
|
export class DynamicChangeDetector extends AbstractChangeDetector<any> {
|
||||||
locals: Locals = null;
|
|
||||||
values: List<any>;
|
values: List<any>;
|
||||||
changes: List<any>;
|
changes: List<any>;
|
||||||
localPipes: List<any>;
|
localPipes: List<any>;
|
||||||
prevContexts: List<any>;
|
prevContexts: List<any>;
|
||||||
directives: any = null;
|
directives: any = null;
|
||||||
alreadyChecked: boolean = false;
|
|
||||||
private pipes: Pipes = null;
|
|
||||||
|
|
||||||
constructor(id: string, private changeControlStrategy: string, dispatcher: any,
|
constructor(id: string, private changeControlStrategy: string, dispatcher: any,
|
||||||
private protos: List<ProtoRecord>, private directiveRecords: List<any>) {
|
protos: List<ProtoRecord>, directiveRecords: List<any>) {
|
||||||
super(id, dispatcher);
|
super(id, dispatcher, protos, directiveRecords);
|
||||||
this.values = ListWrapper.createFixedSize(protos.length + 1);
|
this.values = ListWrapper.createFixedSize(protos.length + 1);
|
||||||
this.localPipes = ListWrapper.createFixedSize(protos.length + 1);
|
this.localPipes = ListWrapper.createFixedSize(protos.length + 1);
|
||||||
this.prevContexts = ListWrapper.createFixedSize(protos.length + 1);
|
this.prevContexts = ListWrapper.createFixedSize(protos.length + 1);
|
||||||
|
@ -2,7 +2,7 @@ import {List} from 'angular2/src/facade/collection';
|
|||||||
import {CONST} from 'angular2/src/facade/lang';
|
import {CONST} from 'angular2/src/facade/lang';
|
||||||
import {Locals} from './parser/locals';
|
import {Locals} from './parser/locals';
|
||||||
import {BindingRecord} from './binding_record';
|
import {BindingRecord} from './binding_record';
|
||||||
import {DirectiveRecord} from './directive_record';
|
import {DirectiveIndex, DirectiveRecord} from './directive_record';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface used by Angular to control the change detection strategy for an application.
|
* Interface used by Angular to control the change detection strategy for an application.
|
||||||
@ -36,7 +36,13 @@ export class ChangeDetection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DebugContext {
|
||||||
|
constructor(public element: any, public componentElement: any, public directive: any,
|
||||||
|
public context: any, public locals: any, public injector: any) {}
|
||||||
|
}
|
||||||
|
|
||||||
export interface ChangeDispatcher {
|
export interface ChangeDispatcher {
|
||||||
|
getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext;
|
||||||
notifyOnBinding(bindingRecord: BindingRecord, value: any): void;
|
notifyOnBinding(bindingRecord: BindingRecord, value: any): void;
|
||||||
notifyOnAllChangesDone(): void;
|
notifyOnAllChangesDone(): void;
|
||||||
}
|
}
|
||||||
@ -58,7 +64,7 @@ export interface ChangeDetector {
|
|||||||
checkNoChanges(): void;
|
checkNoChanges(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProtoChangeDetector { instantiate(dispatcher: any): ChangeDetector; }
|
export interface ProtoChangeDetector { instantiate(dispatcher: ChangeDispatcher): ChangeDetector; }
|
||||||
|
|
||||||
export class ChangeDetectorDefinition {
|
export class ChangeDetectorDefinition {
|
||||||
constructor(public id: string, public strategy: string, public variableNames: List<string>,
|
constructor(public id: string, public strategy: string, public variableNames: List<string>,
|
||||||
|
@ -8,15 +8,16 @@ import {
|
|||||||
} from 'angular2/src/facade/collection';
|
} from 'angular2/src/facade/collection';
|
||||||
import {
|
import {
|
||||||
AST,
|
AST,
|
||||||
Locals,
|
|
||||||
ChangeDispatcher,
|
|
||||||
ProtoChangeDetector,
|
|
||||||
ChangeDetector,
|
|
||||||
BindingRecord,
|
BindingRecord,
|
||||||
DirectiveRecord,
|
ChangeDetector,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
ChangeDispatcher,
|
||||||
DirectiveIndex,
|
DirectiveIndex,
|
||||||
ChangeDetectorRef
|
DirectiveRecord,
|
||||||
|
Locals,
|
||||||
|
ProtoChangeDetector
|
||||||
} from 'angular2/src/change_detection/change_detection';
|
} from 'angular2/src/change_detection/change_detection';
|
||||||
|
import {DebugContext} from 'angular2/src/change_detection/interfaces';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ProtoElementInjector,
|
ProtoElementInjector,
|
||||||
@ -31,6 +32,8 @@ import {RenderEventDispatcher} from 'angular2/src/render/api';
|
|||||||
import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
import {ViewRef, ProtoViewRef, internalView} from './view_ref';
|
||||||
import {ElementRef} from './element_ref';
|
import {ElementRef} from './element_ref';
|
||||||
|
|
||||||
|
export {DebugContext} from 'angular2/src/change_detection/interfaces';
|
||||||
|
|
||||||
export class AppProtoViewMergeMapping {
|
export class AppProtoViewMergeMapping {
|
||||||
renderProtoViewRef: renderApi.RenderProtoViewRef;
|
renderProtoViewRef: renderApi.RenderProtoViewRef;
|
||||||
renderFragmentCount: number;
|
renderFragmentCount: number;
|
||||||
@ -301,11 +304,6 @@ function _localsToStringMap(locals: Locals): StringMap<string, any> {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DebugContext {
|
|
||||||
constructor(public element: any, public componentElement: any, public directive: any,
|
|
||||||
public context: any, public locals: any, public injector: any) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error context included when an event handler throws an exception.
|
* Error context included when an event handler throws an exception.
|
||||||
*/
|
*/
|
||||||
|
@ -82,7 +82,7 @@ class _CodegenState {
|
|||||||
this._generateCheckNoChanges)
|
this._generateCheckNoChanges)
|
||||||
: _records = records,
|
: _records = records,
|
||||||
_directiveRecords = directiveRecords,
|
_directiveRecords = directiveRecords,
|
||||||
_names = new CodegenNameUtil(records, directiveRecords, '_', _UTIL),
|
_names = new CodegenNameUtil(records, directiveRecords, _UTIL),
|
||||||
_changeDetectionMode = ChangeDetectionUtil
|
_changeDetectionMode = ChangeDetectionUtil
|
||||||
.changeDetectionMode(changeDetectionStrategy);
|
.changeDetectionMode(changeDetectionStrategy);
|
||||||
|
|
||||||
@ -99,22 +99,12 @@ class _CodegenState {
|
|||||||
|
|
||||||
void _writeToBuf(StringBuffer buf) {
|
void _writeToBuf(StringBuffer buf) {
|
||||||
buf.write('''\n
|
buf.write('''\n
|
||||||
class $_changeDetectorTypeName extends $_BASE_CLASS {
|
class $_changeDetectorTypeName extends $_BASE_CLASS<$_contextTypeName> {
|
||||||
$_GEN_PREFIX.Pipes $_PIPES_ACCESSOR;
|
${_genDeclareFields()}
|
||||||
final $_GEN_PREFIX.List<$_GEN_PREFIX.ProtoRecord> $_PROTOS_ACCESSOR;
|
|
||||||
final $_GEN_PREFIX.List<$_GEN_PREFIX.DirectiveRecord>
|
|
||||||
$_DIRECTIVES_ACCESSOR;
|
|
||||||
dynamic $_LOCALS_ACCESSOR = null;
|
|
||||||
dynamic $_ALREADY_CHECKED_ACCESSOR = false;
|
|
||||||
dynamic $_CURRENT_PROTO = null;
|
|
||||||
$_contextTypeName ${_names.getContextName()};
|
|
||||||
${_names.genDeclareFields()}
|
|
||||||
|
|
||||||
$_changeDetectorTypeName(
|
$_changeDetectorTypeName(dispatcher, protos, directiveRecords)
|
||||||
dynamic $_DISPATCHER_ACCESSOR,
|
: super(${_encodeValue(_changeDetectorDefId)},
|
||||||
this.$_PROTOS_ACCESSOR,
|
dispatcher, protos, directiveRecords) {
|
||||||
this.$_DIRECTIVES_ACCESSOR)
|
|
||||||
: super(${_encodeValue(_changeDetectorDefId)}, $_DISPATCHER_ACCESSOR) {
|
|
||||||
dehydrateDirectives(false);
|
dehydrateDirectives(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,20 +115,20 @@ class _CodegenState {
|
|||||||
try {
|
try {
|
||||||
__detectChangesInRecords(throwOnChange);
|
__detectChangesInRecords(throwOnChange);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
throwError($_CURRENT_PROTO, e, s);
|
throwError(${_names.getCurrentProtoName()}, e, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __detectChangesInRecords(throwOnChange) {
|
void __detectChangesInRecords(throwOnChange) {
|
||||||
|
${_names.getCurrentProtoName()} = null;
|
||||||
|
|
||||||
${_names.genInitLocals()}
|
${_names.genInitLocals()}
|
||||||
var $_IS_CHANGED_LOCAL = false;
|
var $_IS_CHANGED_LOCAL = false;
|
||||||
$_CURRENT_PROTO = null;
|
|
||||||
var $_CHANGES_LOCAL = null;
|
var $_CHANGES_LOCAL = null;
|
||||||
|
|
||||||
context = ${_names.getContextName()};
|
|
||||||
${_records.map(_genRecord).join('')}
|
${_records.map(_genRecord).join('')}
|
||||||
|
|
||||||
$_ALREADY_CHECKED_ACCESSOR = true;
|
${_names.getAlreadyCheckedName()} = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
${_genCheckNoChanges()}
|
${_genCheckNoChanges()}
|
||||||
@ -147,26 +137,27 @@ class _CodegenState {
|
|||||||
${_getCallOnAllChangesDoneBody()}
|
${_getCallOnAllChangesDoneBody()}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hydrate($_contextTypeName context, locals, directives, pipes) {
|
void hydrate(
|
||||||
$_MODE_ACCESSOR = '$_changeDetectionMode';
|
$_contextTypeName context, locals, directives, pipes) {
|
||||||
${_names.getContextName()} = context;
|
${_names.getModeName()} = '$_changeDetectionMode';
|
||||||
$_LOCALS_ACCESSOR = locals;
|
${_names.getFieldName(CONTEXT_INDEX)} = context;
|
||||||
|
${_names.getLocalsAccessorName()} = locals;
|
||||||
hydrateDirectives(directives);
|
hydrateDirectives(directives);
|
||||||
$_ALREADY_CHECKED_ACCESSOR = false;
|
${_names.getAlreadyCheckedName()} = false;
|
||||||
$_PIPES_ACCESSOR = pipes;
|
${_names.getPipesAccessorName()} = pipes;
|
||||||
}
|
}
|
||||||
|
|
||||||
${_maybeGenHydrateDirectives()}
|
${_maybeGenHydrateDirectives()}
|
||||||
|
|
||||||
void dehydrate() {
|
void dehydrate() {
|
||||||
dehydrateDirectives(true);
|
dehydrateDirectives(true);
|
||||||
$_LOCALS_ACCESSOR = null;
|
${_names.getLocalsAccessorName()} = null;
|
||||||
$_PIPES_ACCESSOR = null;
|
${_names.getPipesAccessorName()} = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
${_maybeGenDehydrateDirectives()}
|
${_maybeGenDehydrateDirectives()}
|
||||||
|
|
||||||
hydrated() => ${_names.getContextName()} != null;
|
hydrated() => ${_names.getFieldName(CONTEXT_INDEX)} != null;
|
||||||
|
|
||||||
static $_GEN_PREFIX.ProtoChangeDetector
|
static $_GEN_PREFIX.ProtoChangeDetector
|
||||||
$PROTO_CHANGE_DETECTOR_FACTORY_METHOD(
|
$PROTO_CHANGE_DETECTOR_FACTORY_METHOD(
|
||||||
@ -190,16 +181,12 @@ class _CodegenState {
|
|||||||
var destroyPipesParamName = 'destroyPipes';
|
var destroyPipesParamName = 'destroyPipes';
|
||||||
var destroyPipesCode = _names.genPipeOnDestroy();
|
var destroyPipesCode = _names.genPipeOnDestroy();
|
||||||
if (destroyPipesCode.isNotEmpty) {
|
if (destroyPipesCode.isNotEmpty) {
|
||||||
destroyPipesCode = 'if (${destroyPipesParamName}) { '
|
destroyPipesCode = 'if (${destroyPipesParamName}) {${destroyPipesCode}}';
|
||||||
'${destroyPipesCode}'
|
|
||||||
'}';
|
|
||||||
}
|
}
|
||||||
var dehydrateFieldsCode = _names.genDehydrateFields();
|
var dehydrateFieldsCode = _names.genDehydrateFields();
|
||||||
if (destroyPipesCode.isEmpty && dehydrateFieldsCode.isEmpty) return '';
|
if (destroyPipesCode.isEmpty && dehydrateFieldsCode.isEmpty) return '';
|
||||||
return 'void dehydrateDirectives(${destroyPipesParamName}) {'
|
return 'void dehydrateDirectives(${destroyPipesParamName}) '
|
||||||
'${destroyPipesCode}'
|
'{ ${destroyPipesCode} ${dehydrateFieldsCode} }';
|
||||||
'${dehydrateFieldsCode}'
|
|
||||||
'}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String _maybeGenHydrateDirectives() {
|
String _maybeGenHydrateDirectives() {
|
||||||
@ -208,10 +195,8 @@ class _CodegenState {
|
|||||||
if (hydrateDirectivesCode.isEmpty && hydrateDetectorsCode.isEmpty) {
|
if (hydrateDirectivesCode.isEmpty && hydrateDetectorsCode.isEmpty) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return 'void hydrateDirectives(directives) { '
|
return 'void hydrateDirectives(directives) '
|
||||||
'$hydrateDirectivesCode'
|
'{ $hydrateDirectivesCode $hydrateDetectorsCode }';
|
||||||
'$hydrateDetectorsCode'
|
|
||||||
'}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String _genHydrateDirectives() {
|
String _genHydrateDirectives() {
|
||||||
@ -219,7 +204,7 @@ class _CodegenState {
|
|||||||
var directiveFieldNames = _names.getAllDirectiveNames();
|
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);');
|
'${_names.getDirectivesAccessorName()}[$i].directiveIndex);');
|
||||||
}
|
}
|
||||||
return '$buf';
|
return '$buf';
|
||||||
}
|
}
|
||||||
@ -229,7 +214,7 @@ class _CodegenState {
|
|||||||
var detectorFieldNames = _names.getAllDetectorNames();
|
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);');
|
'${_names.getDirectivesAccessorName()}[$i].directiveIndex);');
|
||||||
}
|
}
|
||||||
return '$buf';
|
return '$buf';
|
||||||
}
|
}
|
||||||
@ -244,11 +229,22 @@ class _CodegenState {
|
|||||||
'${_names.getDirectiveName(rec.directiveIndex)}.onAllChangesDone();')
|
'${_names.getDirectiveName(rec.directiveIndex)}.onAllChangesDone();')
|
||||||
.join('');
|
.join('');
|
||||||
return '''
|
return '''
|
||||||
$_DISPATCHER_ACCESSOR.notifyOnAllChangesDone();
|
${_names.getDispatcherName()}.notifyOnAllChangesDone();
|
||||||
${directiveNotifications}
|
${directiveNotifications}
|
||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _genDeclareFields() {
|
||||||
|
var fields = _names.getAllFieldNames();
|
||||||
|
// If there's only one field, it's `context`, declared in the superclass.
|
||||||
|
if (fields.length == 1) return '';
|
||||||
|
fields.removeAt(CONTEXT_INDEX);
|
||||||
|
var toRemove = 'this.';
|
||||||
|
var declareNames = fields
|
||||||
|
.map((f) => f.startsWith(toRemove) ? f.substring(toRemove.length) : f);
|
||||||
|
return 'var ${declareNames.join(', ')};';
|
||||||
|
}
|
||||||
|
|
||||||
String _genRecord(ProtoRecord r) {
|
String _genRecord(ProtoRecord r) {
|
||||||
var rec = null;
|
var rec = null;
|
||||||
if (r.isLifeCycleRecord()) {
|
if (r.isLifeCycleRecord()) {
|
||||||
@ -287,12 +283,12 @@ class _CodegenState {
|
|||||||
var protoIndex = r.selfIndex - 1;
|
var protoIndex = r.selfIndex - 1;
|
||||||
var pipeType = r.name;
|
var pipeType = r.name;
|
||||||
return '''
|
return '''
|
||||||
$_CURRENT_PROTO = $_PROTOS_ACCESSOR[$protoIndex];
|
${_names.getCurrentProtoName()} = ${_names.getProtosName()}[$protoIndex];
|
||||||
if ($_IDENTICAL_CHECK_FN($pipe, $_UTIL.uninitialized)) {
|
if ($_IDENTICAL_CHECK_FN($pipe, $_UTIL.uninitialized)) {
|
||||||
$pipe = $_PIPES_ACCESSOR.get('$pipeType', $context, $cdRef);
|
$pipe = ${_names.getPipesAccessorName()}.get('$pipeType', $context, $cdRef);
|
||||||
} else if (!$pipe.supports($context)) {
|
} else if (!$pipe.supports($context)) {
|
||||||
$pipe.onDestroy();
|
$pipe.onDestroy();
|
||||||
$pipe = $_PIPES_ACCESSOR.get('$pipeType', $context, $cdRef);
|
$pipe = ${_names.getPipesAccessorName()}.get('$pipeType', $context, $cdRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
$newValue = $pipe.transform($context, [$argString]);
|
$newValue = $pipe.transform($context, [$argString]);
|
||||||
@ -312,7 +308,7 @@ class _CodegenState {
|
|||||||
|
|
||||||
var protoIndex = r.selfIndex - 1;
|
var protoIndex = r.selfIndex - 1;
|
||||||
var check = '''
|
var check = '''
|
||||||
$_CURRENT_PROTO = $_PROTOS_ACCESSOR[$protoIndex];
|
${_names.getCurrentProtoName()} = ${_names.getProtosName()}[$protoIndex];
|
||||||
${_genUpdateCurrentValue(r)}
|
${_genUpdateCurrentValue(r)}
|
||||||
if ($_NOT_IDENTICAL_CHECK_FN($newValue, $oldValue)) {
|
if ($_NOT_IDENTICAL_CHECK_FN($newValue, $oldValue)) {
|
||||||
${_names.getChangeName(r.selfIndex)} = true;
|
${_names.getChangeName(r.selfIndex)} = true;
|
||||||
@ -357,7 +353,7 @@ class _CodegenState {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.LOCAL:
|
case RecordType.LOCAL:
|
||||||
rhs = '$_LOCALS_ACCESSOR.get("${r.name}")';
|
rhs = '${_names.getLocalsAccessorName()}.get("${r.name}")';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecordType.INVOKE_METHOD:
|
case RecordType.INVOKE_METHOD:
|
||||||
@ -421,8 +417,8 @@ class _CodegenState {
|
|||||||
} else {
|
} else {
|
||||||
return '''
|
return '''
|
||||||
${_genThrowOnChangeCheck(oldValue, newValue)}
|
${_genThrowOnChangeCheck(oldValue, newValue)}
|
||||||
$_DISPATCHER_ACCESSOR.notifyOnBinding(
|
${_names.getDispatcherName()}.notifyOnBinding(
|
||||||
$_CURRENT_PROTO.bindingRecord, ${newValue});
|
${_names.getCurrentProtoName()}.bindingRecord, ${newValue});
|
||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -432,7 +428,7 @@ class _CodegenState {
|
|||||||
return '''
|
return '''
|
||||||
if(throwOnChange) {
|
if(throwOnChange) {
|
||||||
$_UTIL.throwOnChange(
|
$_UTIL.throwOnChange(
|
||||||
$_CURRENT_PROTO, $_UTIL.simpleChange(${oldValue}, ${newValue}));
|
${_names.getCurrentProtoName()}, $_UTIL.simpleChange(${oldValue}, ${newValue}));
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
} else {
|
} else {
|
||||||
@ -455,7 +451,7 @@ class _CodegenState {
|
|||||||
return '''
|
return '''
|
||||||
$_CHANGES_LOCAL = $_UTIL.addChange(
|
$_CHANGES_LOCAL = $_UTIL.addChange(
|
||||||
$_CHANGES_LOCAL,
|
$_CHANGES_LOCAL,
|
||||||
$_CURRENT_PROTO.bindingRecord.propertyName,
|
${_names.getCurrentProtoName()}.bindingRecord.propertyName,
|
||||||
$_UTIL.simpleChange($oldValue, $newValue));
|
$_UTIL.simpleChange($oldValue, $newValue));
|
||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
@ -477,7 +473,7 @@ class _CodegenState {
|
|||||||
|
|
||||||
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 && !${_names.getAlreadyCheckedName()}) '
|
||||||
'${_names.getDirectiveName(br.directiveRecord.directiveIndex)}.onInit();';
|
'${_names.getDirectiveName(br.directiveRecord.directiveIndex)}.onInit();';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,21 +500,13 @@ class _CodegenState {
|
|||||||
|
|
||||||
const PROTO_CHANGE_DETECTOR_FACTORY_METHOD = 'newProtoChangeDetector';
|
const PROTO_CHANGE_DETECTOR_FACTORY_METHOD = 'newProtoChangeDetector';
|
||||||
|
|
||||||
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 _CURRENT_PROTO = 'currentProto';
|
|
||||||
const _DIRECTIVES_ACCESSOR = '_directiveRecords';
|
|
||||||
const _DISPATCHER_ACCESSOR = 'dispatcher';
|
|
||||||
const _GEN_PREFIX = '_gen';
|
const _GEN_PREFIX = '_gen';
|
||||||
const _GEN_RECORDS_METHOD_NAME = '_createRecords';
|
const _GEN_RECORDS_METHOD_NAME = '_createRecords';
|
||||||
const _IDENTICAL_CHECK_FN = '$_GEN_PREFIX.looseIdentical';
|
const _IDENTICAL_CHECK_FN = '$_GEN_PREFIX.looseIdentical';
|
||||||
const _NOT_IDENTICAL_CHECK_FN = '$_GEN_PREFIX.looseNotIdentical';
|
const _NOT_IDENTICAL_CHECK_FN = '$_GEN_PREFIX.looseNotIdentical';
|
||||||
const _IS_CHANGED_LOCAL = 'isChanged';
|
const _IS_CHANGED_LOCAL = 'isChanged';
|
||||||
const _LOCALS_ACCESSOR = '_locals';
|
|
||||||
const _MODE_ACCESSOR = 'mode';
|
|
||||||
const _PREGEN_PROTO_CHANGE_DETECTOR_IMPORT =
|
const _PREGEN_PROTO_CHANGE_DETECTOR_IMPORT =
|
||||||
'package:angular2/src/change_detection/pregen_proto_change_detector.dart';
|
'package:angular2/src/change_detection/pregen_proto_change_detector.dart';
|
||||||
const _PIPES_ACCESSOR = '_pipes';
|
|
||||||
const _PROTOS_ACCESSOR = '_protos';
|
|
||||||
const _UTIL = '$_GEN_PREFIX.ChangeDetectionUtil';
|
const _UTIL = '$_GEN_PREFIX.ChangeDetectionUtil';
|
||||||
|
@ -23,19 +23,12 @@ void initReflector() {
|
|||||||
_gen.preGeneratedProtoDetectors['MyComponent_comp_0'] =
|
_gen.preGeneratedProtoDetectors['MyComponent_comp_0'] =
|
||||||
_MyComponent_ChangeDetector0.newProtoChangeDetector;
|
_MyComponent_ChangeDetector0.newProtoChangeDetector;
|
||||||
}
|
}
|
||||||
class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
class _MyComponent_ChangeDetector0
|
||||||
_gen.Pipes _pipes;
|
extends _gen.AbstractChangeDetector<MyComponent> {
|
||||||
final _gen.List<_gen.ProtoRecord> _protos;
|
var myNum0, interpolate1;
|
||||||
final _gen.List<_gen.DirectiveRecord> _directiveRecords;
|
|
||||||
dynamic _locals = null;
|
|
||||||
dynamic _alreadyChecked = false;
|
|
||||||
dynamic currentProto = null;
|
|
||||||
MyComponent _context;
|
|
||||||
var _myNum0, _interpolate1;
|
|
||||||
|
|
||||||
_MyComponent_ChangeDetector0(
|
_MyComponent_ChangeDetector0(dispatcher, protos, directiveRecords)
|
||||||
dynamic dispatcher, this._protos, this._directiveRecords)
|
: super("MyComponent_comp_0", dispatcher, protos, directiveRecords) {
|
||||||
: super("MyComponent_comp_0", dispatcher) {
|
|
||||||
dehydrateDirectives(false);
|
dehydrateDirectives(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,48 +39,53 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
|||||||
try {
|
try {
|
||||||
__detectChangesInRecords(throwOnChange);
|
__detectChangesInRecords(throwOnChange);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
throwError(currentProto, e, s);
|
throwError(this.currentProto, e, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __detectChangesInRecords(throwOnChange) {
|
void __detectChangesInRecords(throwOnChange) {
|
||||||
var context, c_context, myNum0, c_myNum0, interpolate1, c_interpolate1;
|
this.currentProto = null;
|
||||||
c_context = c_myNum0 = c_interpolate1 = false;
|
var l_context = this.context,
|
||||||
|
l_myNum0,
|
||||||
|
c_myNum0,
|
||||||
|
l_interpolate1,
|
||||||
|
c_interpolate1;
|
||||||
|
c_myNum0 = c_interpolate1 = false;
|
||||||
var isChanged = false;
|
var isChanged = false;
|
||||||
currentProto = null;
|
|
||||||
var changes = null;
|
var changes = null;
|
||||||
|
|
||||||
context = _context;
|
this.currentProto = this.protos[0];
|
||||||
currentProto = _protos[0];
|
l_myNum0 = l_context.myNum;
|
||||||
myNum0 = context.myNum;
|
if (_gen.looseNotIdentical(l_myNum0, this.myNum0)) {
|
||||||
if (_gen.looseNotIdentical(myNum0, _myNum0)) {
|
|
||||||
c_myNum0 = true;
|
c_myNum0 = true;
|
||||||
|
|
||||||
_myNum0 = myNum0;
|
this.myNum0 = l_myNum0;
|
||||||
}
|
}
|
||||||
if (c_myNum0) {
|
if (c_myNum0) {
|
||||||
currentProto = _protos[1];
|
this.currentProto = this.protos[1];
|
||||||
interpolate1 = "Salad: " "${myNum0 == null ? "" : myNum0}" " is awesome";
|
l_interpolate1 =
|
||||||
if (_gen.looseNotIdentical(interpolate1, _interpolate1)) {
|
"Salad: " "${l_myNum0 == null ? "" : l_myNum0}" " is awesome";
|
||||||
|
if (_gen.looseNotIdentical(l_interpolate1, this.interpolate1)) {
|
||||||
c_interpolate1 = true;
|
c_interpolate1 = true;
|
||||||
if (throwOnChange) {
|
if (throwOnChange) {
|
||||||
_gen.ChangeDetectionUtil.throwOnChange(currentProto,
|
_gen.ChangeDetectionUtil.throwOnChange(this.currentProto,
|
||||||
_gen.ChangeDetectionUtil.simpleChange(
|
_gen.ChangeDetectionUtil.simpleChange(
|
||||||
_interpolate1, interpolate1));
|
this.interpolate1, l_interpolate1));
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatcher.notifyOnBinding(currentProto.bindingRecord, interpolate1);
|
this.dispatcher.notifyOnBinding(
|
||||||
|
this.currentProto.bindingRecord, l_interpolate1);
|
||||||
|
|
||||||
_interpolate1 = interpolate1;
|
this.interpolate1 = l_interpolate1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
interpolate1 = _interpolate1;
|
l_interpolate1 = this.interpolate1;
|
||||||
}
|
}
|
||||||
changes = null;
|
changes = null;
|
||||||
|
|
||||||
isChanged = false;
|
isChanged = false;
|
||||||
|
|
||||||
_alreadyChecked = true;
|
this.alreadyChecked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkNoChanges() {
|
void checkNoChanges() {
|
||||||
@ -95,30 +93,30 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void callOnAllChangesDone() {
|
void callOnAllChangesDone() {
|
||||||
dispatcher.notifyOnAllChangesDone();
|
this.dispatcher.notifyOnAllChangesDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
void hydrate(MyComponent context, locals, directives, pipes) {
|
void hydrate(MyComponent context, locals, directives, pipes) {
|
||||||
mode = 'ALWAYS_CHECK';
|
this.mode = 'ALWAYS_CHECK';
|
||||||
_context = context;
|
this.context = context;
|
||||||
_locals = locals;
|
this.locals = locals;
|
||||||
hydrateDirectives(directives);
|
hydrateDirectives(directives);
|
||||||
_alreadyChecked = false;
|
this.alreadyChecked = false;
|
||||||
_pipes = pipes;
|
this.pipes = pipes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dehydrate() {
|
void dehydrate() {
|
||||||
dehydrateDirectives(true);
|
dehydrateDirectives(true);
|
||||||
_locals = null;
|
this.locals = null;
|
||||||
_pipes = null;
|
this.pipes = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dehydrateDirectives(destroyPipes) {
|
void dehydrateDirectives(destroyPipes) {
|
||||||
_context = null;
|
this.context = null;
|
||||||
_myNum0 = _interpolate1 = _gen.ChangeDetectionUtil.uninitialized;
|
this.myNum0 = this.interpolate1 = _gen.ChangeDetectionUtil.uninitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
hydrated() => _context != null;
|
hydrated() => this.context != null;
|
||||||
|
|
||||||
static _gen.ProtoChangeDetector newProtoChangeDetector(
|
static _gen.ProtoChangeDetector newProtoChangeDetector(
|
||||||
_gen.ChangeDetectorDefinition def) {
|
_gen.ChangeDetectorDefinition def) {
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
Parser,
|
Parser,
|
||||||
ChangeDispatcher,
|
ChangeDispatcher,
|
||||||
ChangeDetection,
|
ChangeDetection,
|
||||||
|
DebugContext,
|
||||||
DynamicChangeDetection,
|
DynamicChangeDetection,
|
||||||
JitChangeDetection,
|
JitChangeDetection,
|
||||||
ChangeDetectorDefinition,
|
ChangeDetectorDefinition,
|
||||||
@ -380,6 +381,9 @@ class FakeDirectives {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DummyDispatcher implements ChangeDispatcher {
|
class DummyDispatcher implements ChangeDispatcher {
|
||||||
|
getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext {
|
||||||
|
throw "getDebugContext not implemented.";
|
||||||
|
}
|
||||||
notifyOnBinding(bindingRecord, newValue) { throw "Should not be used"; }
|
notifyOnBinding(bindingRecord, newValue) { throw "Should not be used"; }
|
||||||
notifyOnAllChangesDone() {}
|
notifyOnAllChangesDone() {}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user