refactor(change_detect): Move (de)hydrate logic into dedicated methods

Call new `(de)hydrateDirectives` methods from `(de)hydrate`. Add a null
implementation in `AbstractChangeDetector` and only override if
necessary for the specific change detector.

Update to #3248
This commit is contained in:
Tim Blasi 2015-07-27 18:31:22 -07:00
parent a9efc48e71
commit d84993faf1
4 changed files with 98 additions and 35 deletions

View File

@ -60,8 +60,12 @@ export class AbstractChangeDetector implements ChangeDetector {
hydrate(context: any, locals: Locals, directives: any, pipes: any): void {} hydrate(context: any, locals: Locals, directives: any, pipes: any): void {}
hydrateDirectives(directives: any): void {}
dehydrate(): void {} dehydrate(): void {}
dehydrateDirectives(destroyPipes: boolean): void {}
callOnAllChangesDone(): void {} callOnAllChangesDone(): void {}
_detectChangesInLightDomChildren(throwOnChange: boolean): void { _detectChangesInLightDomChildren(throwOnChange: boolean): void {
@ -95,4 +99,4 @@ export class AbstractChangeDetector implements ChangeDetector {
null; null;
throw new ChangeDetectionError(proto, exception, stack, context); throw new ChangeDetectionError(proto, exception, stack, context);
} }
} }

View File

@ -33,17 +33,18 @@ var ALREADY_CHECKED_ACCESSOR = "this.alreadyChecked";
export class ChangeDetectorJITGenerator { export class ChangeDetectorJITGenerator {
_names: CodegenNameUtil; _names: CodegenNameUtil;
_typeName: 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>,
private generateCheckNoChanges: boolean) { private generateCheckNoChanges: boolean) {
this._names = new CodegenNameUtil(this.records, this.directiveRecords, 'this._', UTIL); this._names = new CodegenNameUtil(this.records, this.directiveRecords, 'this._', UTIL);
this._typeName = sanitizeName(`ChangeDetector_${this.id}`);
} }
generate(): Function { generate(): Function {
var typeName = sanitizeName(`ChangeDetector_${this.id}`);
var classDefinition = ` var classDefinition = `
var ${typeName} = function ${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_ACCESSOR} = protos; ${PROTOS_ACCESSOR} = protos;
${DIRECTIVES_ACCESSOR} = directiveRecords; ${DIRECTIVES_ACCESSOR} = directiveRecords;
@ -51,12 +52,12 @@ export class ChangeDetectorJITGenerator {
${CURRENT_PROTO} = null; ${CURRENT_PROTO} = null;
${PIPES_ACCESSOR} = null; ${PIPES_ACCESSOR} = null;
${ALREADY_CHECKED_ACCESSOR} = false; ${ALREADY_CHECKED_ACCESSOR} = false;
${this._names.genDehydrateFields()} this.dehydrateDirectives(false);
} }
${typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype); ${this._typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype);
${typeName}.prototype.detectChangesInRecords = function(throwOnChange) { ${this._typeName}.prototype.detectChangesInRecords = function(throwOnChange) {
if (!this.hydrated()) { if (!this.hydrated()) {
${UTIL}.throwDehydrated(); ${UTIL}.throwDehydrated();
} }
@ -67,7 +68,7 @@ export class ChangeDetectorJITGenerator {
} }
} }
${typeName}.prototype.__detectChangesInRecords = function(throwOnChange) { ${this._typeName}.prototype.__detectChangesInRecords = function(throwOnChange) {
${CURRENT_PROTO} = null; ${CURRENT_PROTO} = null;
${this._names.genInitLocals()} ${this._names.genInitLocals()}
@ -81,35 +82,37 @@ export class ChangeDetectorJITGenerator {
${ALREADY_CHECKED_ACCESSOR} = true; ${ALREADY_CHECKED_ACCESSOR} = true;
} }
${this._genCheckNoChanges(typeName)} ${this._genCheckNoChanges()}
${typeName}.prototype.callOnAllChangesDone = function() { ${this._typeName}.prototype.callOnAllChangesDone = function() {
${this._genCallOnAllChangesDoneBody()} ${this._genCallOnAllChangesDoneBody()}
} }
${typeName}.prototype.hydrate = function(context, locals, directives, pipes) { ${this._typeName}.prototype.hydrate = function(context, locals, directives, pipes) {
${MODE_ACCESSOR} = "${ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy)}"; ${MODE_ACCESSOR} = "${ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy)}";
${this._names.getContextName()} = context; ${this._names.getContextName()} = context;
${LOCALS_ACCESSOR} = locals; ${LOCALS_ACCESSOR} = locals;
${this._genHydrateDirectives()} this.hydrateDirectives(directives);
${this._genHydrateDetectors()}
${PIPES_ACCESSOR} = pipes; ${PIPES_ACCESSOR} = pipes;
${ALREADY_CHECKED_ACCESSOR} = false; ${ALREADY_CHECKED_ACCESSOR} = false;
} }
${typeName}.prototype.dehydrate = function() { ${this._maybeGenHydrateDirectives()}
${this._names.genPipeOnDestroy()}
${this._names.genDehydrateFields()} ${this._typeName}.prototype.dehydrate = function() {
this.dehydrateDirectives(true);
${LOCALS_ACCESSOR} = null; ${LOCALS_ACCESSOR} = null;
${PIPES_ACCESSOR} = null; ${PIPES_ACCESSOR} = null;
} }
${typeName}.prototype.hydrated = function() { ${this._maybeGenDehydrateDirectives()}
${this._typeName}.prototype.hydrated = function() {
return ${this._names.getContextName()} !== null; return ${this._names.getContextName()} !== null;
} }
return function(dispatcher) { return function(dispatcher) {
return new ${typeName}(dispatcher, protos, directiveRecords); return new ${this._typeName}(dispatcher, protos, directiveRecords);
} }
`; `;
@ -118,6 +121,29 @@ export class ChangeDetectorJITGenerator {
AbstractChangeDetector, ChangeDetectionUtil, this.records, this.directiveRecords); AbstractChangeDetector, ChangeDetectionUtil, this.records, this.directiveRecords);
} }
_maybeGenDehydrateDirectives(): string {
var destroyPipesCode = this._names.genPipeOnDestroy();
if (destroyPipesCode) {
destroyPipesCode = `if (destroyPipes) { ${destroyPipesCode} }`;
}
var dehydrateFieldsCode = this._names.genDehydrateFields();
if (!destroyPipesCode && !dehydrateFieldsCode) return '';
return `${this._typeName}.prototype.dehydrateDirectives = function(destroyPipes) {
${destroyPipesCode}
${dehydrateFieldsCode}
}`;
}
_maybeGenHydrateDirectives(): string {
var hydrateDirectivesCode = this._genHydrateDirectives();
var hydrateDetectorsCode = this._genHydrateDetectors();
if (!hydrateDirectivesCode && !hydrateDetectorsCode) return '';
return `${this._typeName}.prototype.hydrateDirectives = function(directives) {
${hydrateDirectivesCode}
${hydrateDetectorsCode}
}`;
}
_genHydrateDirectives(): string { _genHydrateDirectives(): string {
var directiveFieldNames = this._names.getAllDirectiveNames(); var directiveFieldNames = this._names.getAllDirectiveNames();
var lines = ListWrapper.createFixedSize(directiveFieldNames.length); var lines = ListWrapper.createFixedSize(directiveFieldNames.length);
@ -345,9 +371,9 @@ export class ChangeDetectorJITGenerator {
} }
} }
_genCheckNoChanges(typeName: string): string { _genCheckNoChanges(): string {
if (this.generateCheckNoChanges) { if (this.generateCheckNoChanges) {
return `${typeName}.prototype.checkNoChanges = function() { this.runDetectChanges(true); }`; return `${this._typeName}.prototype.checkNoChanges = function() { this.runDetectChanges(true); }`;
} else { } else {
return ''; return '';
} }

View File

@ -115,7 +115,7 @@ class _CodegenState {
this.$_PROTOS_ACCESSOR, this.$_PROTOS_ACCESSOR,
this.$_DIRECTIVES_ACCESSOR) this.$_DIRECTIVES_ACCESSOR)
: super(${_encodeValue(_changeDetectorDefId)}, $_DISPATCHER_ACCESSOR) { : super(${_encodeValue(_changeDetectorDefId)}, $_DISPATCHER_ACCESSOR) {
${_names.genDehydrateFields()} dehydrateDirectives(false);
} }
void detectChangesInRecords(throwOnChange) { void detectChangesInRecords(throwOnChange) {
@ -123,9 +123,9 @@ class _CodegenState {
$_UTIL.throwDehydrated(); $_UTIL.throwDehydrated();
} }
try { try {
this.__detectChangesInRecords(throwOnChange); __detectChangesInRecords(throwOnChange);
} catch (e, s) { } catch (e, s) {
this.throwError($_CURRENT_PROTO, e, s); throwError($_CURRENT_PROTO, e, s);
} }
} }
@ -151,19 +151,21 @@ class _CodegenState {
$_MODE_ACCESSOR = '$_changeDetectionMode'; $_MODE_ACCESSOR = '$_changeDetectionMode';
${_names.getContextName()} = context; ${_names.getContextName()} = context;
$_LOCALS_ACCESSOR = locals; $_LOCALS_ACCESSOR = locals;
${_genHydrateDirectives()} hydrateDirectives(directives);
${_genHydrateDetectors()}
$_ALREADY_CHECKED_ACCESSOR = false; $_ALREADY_CHECKED_ACCESSOR = false;
$_PIPES_ACCESSOR = pipes; $_PIPES_ACCESSOR = pipes;
} }
${_maybeGenHydrateDirectives()}
void dehydrate() { void dehydrate() {
${_names.genPipeOnDestroy()} dehydrateDirectives(true);
${_names.genDehydrateFields()}
$_LOCALS_ACCESSOR = null; $_LOCALS_ACCESSOR = null;
$_PIPES_ACCESSOR = null; $_PIPES_ACCESSOR = null;
} }
${_maybeGenDehydrateDirectives()}
hydrated() => ${_names.getContextName()} != null; hydrated() => ${_names.getContextName()} != null;
static $_GEN_PREFIX.ProtoChangeDetector static $_GEN_PREFIX.ProtoChangeDetector
@ -184,6 +186,34 @@ class _CodegenState {
'''); ''');
} }
String _maybeGenDehydrateDirectives() {
var destroyPipesParamName = 'destroyPipes';
var destroyPipesCode = _names.genPipeOnDestroy();
if (destroyPipesCode.isNotEmpty) {
destroyPipesCode = 'if (${destroyPipesParamName}) { '
'${destroyPipesCode}'
'}';
}
var dehydrateFieldsCode = _names.genDehydrateFields();
if (destroyPipesCode.isEmpty && dehydrateFieldsCode.isEmpty) return '';
return 'void dehydrateDirectives(${destroyPipesParamName}) {'
'${destroyPipesCode}'
'${dehydrateFieldsCode}'
'}';
}
String _maybeGenHydrateDirectives() {
var hydrateDirectivesCode = _genHydrateDirectives();
var hydrateDetectorsCode = _genHydrateDetectors();
if (hydrateDirectivesCode.isEmpty && hydrateDetectorsCode.isEmpty) {
return '';
}
return 'void hydrateDirectives(directives) { '
'$hydrateDirectivesCode'
'$hydrateDetectorsCode'
'}';
}
String _genHydrateDirectives() { String _genHydrateDirectives() {
var buf = new StringBuffer(); var buf = new StringBuffer();
var directiveFieldNames = _names.getAllDirectiveNames(); var directiveFieldNames = _names.getAllDirectiveNames();
@ -412,7 +442,7 @@ class _CodegenState {
String _genCheckNoChanges() { String _genCheckNoChanges() {
if (this._generateCheckNoChanges) { if (this._generateCheckNoChanges) {
return 'void checkNoChanges() { this.runDetectChanges(true); }'; return 'void checkNoChanges() { runDetectChanges(true); }';
} else { } else {
return ''; return '';
} }

View File

@ -36,8 +36,7 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
_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; dehydrateDirectives(false);
_myNum0 = _interpolate1 = _gen.ChangeDetectionUtil.uninitialized;
} }
void detectChangesInRecords(throwOnChange) { void detectChangesInRecords(throwOnChange) {
@ -45,9 +44,9 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
_gen.ChangeDetectionUtil.throwDehydrated(); _gen.ChangeDetectionUtil.throwDehydrated();
} }
try { try {
this.__detectChangesInRecords(throwOnChange); __detectChangesInRecords(throwOnChange);
} catch (e, s) { } catch (e, s) {
this.throwError(currentProto, e, s); throwError(currentProto, e, s);
} }
} }
@ -92,7 +91,7 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
} }
void checkNoChanges() { void checkNoChanges() {
this.runDetectChanges(true); runDetectChanges(true);
} }
void callOnAllChangesDone() { void callOnAllChangesDone() {
@ -103,18 +102,22 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
mode = 'ALWAYS_CHECK'; mode = 'ALWAYS_CHECK';
_context = context; _context = context;
_locals = locals; _locals = locals;
hydrateDirectives(directives);
_alreadyChecked = false; _alreadyChecked = false;
_pipes = pipes; _pipes = pipes;
} }
void dehydrate() { void dehydrate() {
_context = null; dehydrateDirectives(true);
_myNum0 = _interpolate1 = _gen.ChangeDetectionUtil.uninitialized;
_locals = null; _locals = null;
_pipes = null; _pipes = null;
} }
void dehydrateDirectives(destroyPipes) {
_context = null;
_myNum0 = _interpolate1 = _gen.ChangeDetectionUtil.uninitialized;
}
hydrated() => _context != null; hydrated() => _context != null;
static _gen.ProtoChangeDetector newProtoChangeDetector( static _gen.ProtoChangeDetector newProtoChangeDetector(