From 0906ee8a4e5522e753aad448e6fe228c4905ea05 Mon Sep 17 00:00:00 2001 From: Tim Blasi Date: Thu, 23 Jul 2015 16:08:55 -0700 Subject: [PATCH] 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 --- .../change_detection_jit_generator.ts | 155 +++++----------- .../src/change_detection/codegen_name_util.ts | 134 ++++++++++++++ .../change_detector_codegen.dart | 167 +++++------------- .../expected/bar.ng_deps.dart | 27 ++- 4 files changed, 233 insertions(+), 250 deletions(-) create mode 100644 modules/angular2/src/change_detection/codegen_name_util.ts diff --git a/modules/angular2/src/change_detection/change_detection_jit_generator.ts b/modules/angular2/src/change_detection/change_detection_jit_generator.ts index 2339b4a90d..e1027df795 100644 --- a/modules/angular2/src/change_detection/change_detection_jit_generator.ts +++ b/modules/angular2/src/change_detection/change_detection_jit_generator.ts @@ -6,6 +6,7 @@ import {ChangeDetectionUtil} from './change_detection_util'; import {DirectiveIndex, DirectiveRecord} from './directive_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 PROTOS_ACCESSOR = "this.protos"; var DIRECTIVES_ACCESSOR = "this.directiveRecords"; -var CONTEXT_ACCESSOR = "this.context"; var IS_CHANGED_LOCAL = "isChanged"; var CHANGES_LOCAL = "changes"; var LOCALS_ACCESSOR = "this.locals"; @@ -31,41 +31,16 @@ var MODE_ACCESSOR = "this.mode"; var CURRENT_PROTO = "this.currentProto"; var ALREADY_CHECKED_ACCESSOR = "this.alreadyChecked"; - export class ChangeDetectorJITGenerator { - _localNames: List; - _changeNames: List; - _fieldNames: List; - _pipeNames: List; + _names: CodegenNameUtil; constructor(public id: string, public changeDetectionStrategy: string, public records: List, public directiveRecords: List) { - this._localNames = this._getLocalNames(records); - this._changeNames = this._getChangeNames(this._localNames); - this._fieldNames = this._getFieldNames(this._localNames); - this._pipeNames = this._getPipeNames(this._localNames); - } - - _getLocalNames(records: List): List { - var index = 0; - var names = records.map((r) => { return _sanitizeName(`${r.name}${index++}`); }); - return ["context"].concat(names); - } - - _getChangeNames(_localNames: List): List { - return _localNames.map((n) => `change_${n}`); - } - - _getFieldNames(_localNames: List): List { - return _localNames.map((n) => `this.${n}`); - } - - _getPipeNames(_localNames: List): List { - return _localNames.map((n) => `this.${n}_pipe`); + this._names = new CodegenNameUtil(this.records, this.directiveRecords, 'this._', UTIL); } generate(): Function { - var typeName = _sanitizeName(`ChangeDetector_${this.id}`); + var typeName = sanitizeName(`ChangeDetector_${this.id}`); var classDefinition = ` var ${typeName} = function ${typeName}(dispatcher, protos, directiveRecords) { ${ABSTRACT_CHANGE_DETECTOR}.call(this, ${JSON.stringify(this.id)}, dispatcher); @@ -75,7 +50,7 @@ export class ChangeDetectorJITGenerator { ${CURRENT_PROTO} = null; ${PIPES_ACCESSOR} = null; ${ALREADY_CHECKED_ACCESSOR} = false; - ${this._genFieldDefinitions()} + ${this._names.genDehydrateFields()} } ${typeName}.prototype = Object.create(${ABSTRACT_CHANGE_DETECTOR}.prototype); @@ -94,12 +69,11 @@ export class ChangeDetectorJITGenerator { ${typeName}.prototype.__detectChangesInRecords = function(throwOnChange) { ${CURRENT_PROTO} = null; - ${this._genLocalDefinitions()} - ${this._genChangeDefinitions()} + ${this._names.genInitLocals()} var ${IS_CHANGED_LOCAL} = false; var ${CHANGES_LOCAL} = null; - context = ${CONTEXT_ACCESSOR}; + context = ${this._names.getContextName()}; ${this.records.map((r) => this._genRecord(r)).join("\n")} @@ -112,7 +86,7 @@ export class ChangeDetectorJITGenerator { ${typeName}.prototype.hydrate = function(context, locals, directives, pipes) { ${MODE_ACCESSOR} = "${ChangeDetectionUtil.changeDetectionMode(this.changeDetectionStrategy)}"; - ${CONTEXT_ACCESSOR} = context; + ${this._names.getContextName()} = context; ${LOCALS_ACCESSOR} = locals; ${this._genHydrateDirectives()} ${this._genHydrateDetectors()} @@ -121,14 +95,14 @@ export class ChangeDetectorJITGenerator { } ${typeName}.prototype.dehydrate = function() { - ${this._genPipeOnDestroy()} - ${this._genFieldDefinitions()} + ${this._names.genPipeOnDestroy()} + ${this._names.genDehydrateFields()} ${LOCALS_ACCESSOR} = null; ${PIPES_ACCESSOR} = null; } ${typeName}.prototype.hydrated = function() { - return ${CONTEXT_ACCESSOR} !== null; + return ${this._names.getContextName()} !== null; } return function(dispatcher) { @@ -140,44 +114,8 @@ export class ChangeDetectorJITGenerator { AbstractChangeDetector, ChangeDetectionUtil, this.records, this.directiveRecords); } - _genGetDirectiveFieldNames(): List { - return this.directiveRecords.map(d => this._genGetDirective(d.directiveIndex)); - } - - _genGetDetectorFieldNames(): List { - 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 { - 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 { - var directiveFieldNames = this._genGetDirectiveFieldNames(); + var directiveFieldNames = this._names.getAllDirectiveNames(); var lines = ListWrapper.createFixedSize(directiveFieldNames.length); for (var i = 0, iLen = directiveFieldNames.length; i < iLen; ++i) { lines[i] = @@ -187,7 +125,7 @@ export class ChangeDetectorJITGenerator { } _genHydrateDetectors(): string { - var detectorFieldNames = this._genGetDetectorFieldNames(); + var detectorFieldNames = this._names.getAllDetectorNames(); var lines = ListWrapper.createFixedSize(detectorFieldNames.length); for (var i = 0, iLen = detectorFieldNames.length; i < iLen; ++i) { lines[i] = `${detectorFieldNames[i]} = @@ -196,10 +134,6 @@ export class ChangeDetectorJITGenerator { return lines.join('\n'); } - _genPipeOnDestroy(): string { - return this._getNonNullPipeNames().map((p) => `${p}.onDestroy();`).join("\n"); - } - _genCallOnAllChangesDoneBody(): string { var notifications = []; var dirs = this.directiveRecords; @@ -207,7 +141,8 @@ export class ChangeDetectorJITGenerator { for (var i = dirs.length - 1; i >= 0; --i) { var dir = dirs[i]; 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 { var rec; if (r.isLifeCycleRecord()) { @@ -250,14 +179,14 @@ export class ChangeDetectorJITGenerator { } _genPipeCheck(r: ProtoRecord): string { - var context = this._localNames[r.contextIndex]; - var argString = r.args.map((arg) => this._localNames[arg]).join(", "); + var context = this._names.getLocalName(r.contextIndex); + var argString = r.args.map((arg) => this._names.getLocalName(arg)).join(", "); - var oldValue = this._fieldNames[r.selfIndex]; - var newValue = this._localNames[r.selfIndex]; - var change = this._changeNames[r.selfIndex]; + var oldValue = this._names.getFieldName(r.selfIndex); + var newValue = this._names.getLocalName(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 protoIndex = r.selfIndex - 1; @@ -284,15 +213,15 @@ export class ChangeDetectorJITGenerator { } _genReferenceCheck(r: ProtoRecord): string { - var oldValue = this._fieldNames[r.selfIndex]; - var newValue = this._localNames[r.selfIndex]; + var oldValue = this._names.getFieldName(r.selfIndex); + var newValue = this._names.getLocalName(r.selfIndex); var protoIndex = r.selfIndex - 1; var check = ` ${CURRENT_PROTO} = ${PROTOS_ACCESSOR}[${protoIndex}]; ${this._genUpdateCurrentValue(r)} if (${newValue} !== ${oldValue}) { - ${this._changeNames[r.selfIndex]} = true; + ${this._names.getChangeName(r.selfIndex)} = true; ${this._genUpdateDirectiveOrElement(r)} ${this._genAddToChanges(r)} ${oldValue} = ${newValue}; @@ -300,7 +229,7 @@ export class ChangeDetectorJITGenerator { `; 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}; }`; } else { return check; @@ -308,10 +237,10 @@ export class ChangeDetectorJITGenerator { } _genUpdateCurrentValue(r: ProtoRecord): string { - var context = (r.contextIndex == -1) ? this._genGetDirective(r.directiveIndex) : - this._localNames[r.contextIndex]; - var newValue = this._localNames[r.selfIndex]; - var argString = r.args.map((arg) => this._localNames[arg]).join(", "); + var context = (r.contextIndex == -1) ? this._names.getDirectiveName(r.directiveIndex) : + this._names.getLocalName(r.contextIndex); + var newValue = this._names.getLocalName(r.selfIndex); + var argString = r.args.map((arg) => this._names.getLocalName(arg)).join(", "); var rhs; switch (r.mode) { @@ -356,7 +285,7 @@ export class ChangeDetectorJITGenerator { break; case RecordType.KEYED_ACCESS: - rhs = `${context}[${this._localNames[r.args[0]]}]`; + rhs = `${context}[${this._names.getLocalName(r.args[0])}]`; break; default: @@ -370,7 +299,7 @@ export class ChangeDetectorJITGenerator { for (var i = 0; i < r.args.length; ++i) { res += JSON.stringify(r.fixedArgs[i]); res += " + "; - res += `${UTIL}.s(${this._localNames[r.args[i]]})`; + res += `${UTIL}.s(${this._names.getLocalName(r.args[i])})`; res += " + "; } res += JSON.stringify(r.fixedArgs[r.args.length]); @@ -380,13 +309,13 @@ export class ChangeDetectorJITGenerator { _genUpdateDirectiveOrElement(r: ProtoRecord): string { if (!r.lastInBinding) return ""; - var newValue = this._localNames[r.selfIndex]; - var oldValue = this._fieldNames[r.selfIndex]; + var newValue = this._names.getLocalName(r.selfIndex); + var oldValue = this._names.getFieldName(r.selfIndex); var br = r.bindingRecord; if (br.isDirective()) { var directiveProperty = - `${this._genGetDirective(br.directiveRecord.directiveIndex)}.${br.propertyName}`; + `${this._names.getDirectiveName(br.directiveRecord.directiveIndex)}.${br.propertyName}`; return ` ${this._genThrowOnChangeCheck(oldValue, newValue)} ${directiveProperty} = ${newValue}; @@ -409,8 +338,8 @@ export class ChangeDetectorJITGenerator { } _genAddToChanges(r: ProtoRecord): string { - var newValue = this._localNames[r.selfIndex]; - var oldValue = this._fieldNames[r.selfIndex]; + var newValue = this._names.getLocalName(r.selfIndex); + var oldValue = this._names.getFieldName(r.selfIndex); if (!r.bindingRecord.callOnChange()) return ""; return ` ${CHANGES_LOCAL} = ${UTIL}.addChange( @@ -430,17 +359,17 @@ export class ChangeDetectorJITGenerator { _genOnCheck(r: ProtoRecord): string { 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 { 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 { 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 { @@ -448,13 +377,9 @@ export class ChangeDetectorJITGenerator { if (!r.lastInDirective || !br.isOnPushChangeDetection()) return ""; var retVal = ` if(${IS_CHANGED_LOCAL}) { - ${this._genGetDetector(br.directiveRecord.directiveIndex)}.markAsCheckOnce(); + ${this._names.getDetectorName(br.directiveRecord.directiveIndex)}.markAsCheckOnce(); } `; return retVal; } } - -function _sanitizeName(s: string): string { - return s.replace(new RegExp("\\W", "g"), ''); -} diff --git a/modules/angular2/src/change_detection/codegen_name_util.ts b/modules/angular2/src/change_detection/codegen_name_util.ts new file mode 100644 index 0000000000..b73c33ac8b --- /dev/null +++ b/modules/angular2/src/change_detection/codegen_name_util.ts @@ -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; + + constructor(public records: List, public directiveRecords: List, + 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 { + 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 { + return ListWrapper.map(this.directiveRecords, d => this.getDirectiveName(d.directiveIndex)); + } + + getDirectiveName(d: DirectiveIndex): string { return `${this.fieldPrefix}directive_${d.name}`; } + + getAllDetectorNames(): List { + 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}`; } +} diff --git a/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart b/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart index 49f5ff635b..7d8052ea2e 100644 --- a/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart +++ b/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart @@ -3,6 +3,7 @@ library angular2.transform.template_compiler.change_detector_codegen; import 'dart:convert' show JSON; import 'package:angular2/src/change_detection/change_detection_util.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/interfaces.dart'; import 'package:angular2/src/change_detection/proto_change_detector.dart'; @@ -72,18 +73,14 @@ class _CodegenState { final String _changeDetectionMode; final List _records; final List _directiveRecords; - final List _localNames; - final List _changeNames; - final List _fieldNames; - final List _pipeNames; + final CodegenNameUtil _names; _CodegenState._(this._changeDetectorDefId, this._contextTypeName, this._changeDetectorTypeName, String changeDetectionStrategy, - this._records, this._directiveRecords, List localNames) - : this._localNames = localNames, - _changeNames = _getChangeNames(localNames), - _fieldNames = _getFieldNames(localNames), - _pipeNames = _getPipeNames(localNames), + List records, List directiveRecords) + : _records = records, + _directiveRecords = directiveRecords, + _names = new CodegenNameUtil(records, directiveRecords, '_', _UTIL), _changeDetectionMode = ChangeDetectionUtil .changeDetectionMode(changeDetectionStrategy); @@ -94,33 +91,9 @@ class _CodegenState { .forEach((rec) => protoRecords.add(rec, def.variableNames)); var records = coalesce(protoRecords.records); 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 _getLocalNames(List records) { - var whitespacePattern = new RegExp(r'\W'); - var localNames = new List(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 _getChangeNames(List localNames) => - localNames.map((name) => 'change_$name').toList(); - - /// Generates names for use as private fields. - static List _getFieldNames(List localNames) => - localNames.map((name) => '_$name').toList(); - - /// Generates names for use as private pipe variables. - static List _getPipeNames(List localNames) => - localNames.map((name) => '_${name}_pipe').toList(); - void _writeToBuf(StringBuffer buf) { buf.write('''\n class $_changeDetectorTypeName extends $_BASE_CLASS { @@ -131,17 +104,16 @@ class _CodegenState { dynamic $_LOCALS_ACCESSOR = null; dynamic $_ALREADY_CHECKED_ACCESSOR = false; dynamic $_CURRENT_PROTO = null; - ${_allFields().map((f) { - if (f == _CONTEXT_ACCESSOR) { - return '$_contextTypeName $f = null;'; - } - return 'dynamic $f = $_UTIL.uninitialized();'; - }).join('')} + $_contextTypeName ${_names.getContextName()}; + ${_names.genDeclareFields()} $_changeDetectorTypeName( dynamic $_DISPATCHER_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) { if (!hydrated()) { @@ -155,13 +127,12 @@ class _CodegenState { } void __detectChangesInRecords(throwOnChange) { - ${_genLocalDefinitions()} - ${_genChangeDefinitons()} + ${_names.genInitLocals()} var $_IS_CHANGED_LOCAL = false; $_CURRENT_PROTO = null; var $_CHANGES_LOCAL = null; - context = $_CONTEXT_ACCESSOR; + context = ${_names.getContextName()}; ${_records.map(_genRecord).join('')} $_ALREADY_CHECKED_ACCESSOR = true; @@ -173,7 +144,7 @@ class _CodegenState { void hydrate($_contextTypeName context, locals, directives, pipes) { $_MODE_ACCESSOR = '$_changeDetectionMode'; - $_CONTEXT_ACCESSOR = context; + ${_names.getContextName()} = context; $_LOCALS_ACCESSOR = locals; ${_genHydrateDirectives()} ${_genHydrateDetectors()} @@ -182,17 +153,13 @@ class _CodegenState { } void dehydrate() { - ${_genPipeOnDestroy()} - ${_allFields().map((f) { - return f == _CONTEXT_ACCESSOR - ? '$f = null;' - : '$f = $_UTIL.uninitialized();'; - }).join('')} + ${_names.genPipeOnDestroy()} + ${_names.genDehydrateFields()} $_LOCALS_ACCESSOR = null; $_PIPES_ACCESSOR = null; } - hydrated() => $_CONTEXT_ACCESSOR != null; + hydrated() => ${_names.getContextName()} != null; static $_GEN_PREFIX.ProtoChangeDetector $PROTO_CHANGE_DETECTOR_FACTORY_METHOD( @@ -212,39 +179,9 @@ class _CodegenState { '''); } - List _genGetDirectiveFieldNames() { - return _directiveRecords - .map((d) => _genGetDirective(d.directiveIndex)) - .toList(); - } - - List _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 _getNonNullPipeNames() { - return _records - .where((r) => r.isPipeRecord()) - .map((r) => _pipeNames[r.selfIndex]) - .toList(); - } - - List _allFields() { - return new List.from(_fieldNames) - ..addAll(_getNonNullPipeNames()) - ..addAll(_genGetDirectiveFieldNames()) - ..addAll(_genGetDetectorFieldNames()); - } - String _genHydrateDirectives() { var buf = new StringBuffer(); - var directiveFieldNames = _genGetDirectiveFieldNames(); + var directiveFieldNames = _names.getAllDirectiveNames(); for (var i = 0; i < directiveFieldNames.length; ++i) { buf.writeln('${directiveFieldNames[i]} = directives.getDirectiveFor(' '$_DIRECTIVES_ACCESSOR[$i].directiveIndex);'); @@ -254,7 +191,7 @@ class _CodegenState { String _genHydrateDetectors() { var buf = new StringBuffer(); - var detectorFieldNames = _genGetDetectorFieldNames(); + var detectorFieldNames = _names.getAllDetectorNames(); for (var i = 0; i < detectorFieldNames.length; ++i) { buf.writeln('${detectorFieldNames[i]} = directives.getDetectorFor(' '$_DIRECTIVES_ACCESSOR[$i].directiveIndex);'); @@ -262,9 +199,6 @@ class _CodegenState { return '$buf'; } - String _genPipeOnDestroy() => - _getNonNullPipeNames().map((p) => '$p.onDestroy();').join(''); - /// Generates calls to `onAllChangesDone` for all `Directive`s that request /// them. String _getCallOnAllChangesDoneBody() { @@ -272,7 +206,7 @@ class _CodegenState { var directiveNotifications = _directiveRecords.reversed .where((rec) => rec.callOnAllChangesDone) .map((rec) => - '${_genGetDirective(rec.directiveIndex)}.onAllChangesDone();') + '${_names.getDirectiveName(rec.directiveIndex)}.onAllChangesDone();') .join(''); return ''' $_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) { var rec = null; if (r.isLifeCycleRecord()) { @@ -311,14 +239,14 @@ class _CodegenState { } String _genPipeCheck(ProtoRecord r) { - var context = _localNames[r.contextIndex]; - var argString = r.args.map((arg) => this._localNames[arg]).join(", "); + var context = _names.getLocalName(r.contextIndex); + var argString = r.args.map((arg) => _names.getLocalName(arg)).join(", "); - var oldValue = _fieldNames[r.selfIndex]; - var newValue = _localNames[r.selfIndex]; - var change = _changeNames[r.selfIndex]; + var oldValue = _names.getFieldName(r.selfIndex); + var newValue = _names.getLocalName(r.selfIndex); + var change = _names.getChangeName(r.selfIndex); - var pipe = _pipeNames[r.selfIndex]; + var pipe = _names.getPipeName(r.selfIndex); var cdRef = 'this.ref'; var protoIndex = r.selfIndex - 1; @@ -344,15 +272,15 @@ class _CodegenState { } String _genReferenceCheck(ProtoRecord r) { - var oldValue = _fieldNames[r.selfIndex]; - var newValue = _localNames[r.selfIndex]; + var oldValue = _names.getFieldName(r.selfIndex); + var newValue = _names.getLocalName(r.selfIndex); var protoIndex = r.selfIndex - 1; var check = ''' $_CURRENT_PROTO = $_PROTOS_ACCESSOR[$protoIndex]; ${_genUpdateCurrentValue(r)} if (!$_IDENTICAL_CHECK_FN($newValue, $oldValue)) { - ${_changeNames[r.selfIndex]} = true; + ${_names.getChangeName(r.selfIndex)} = true; ${_genUpdateDirectiveOrElement(r)} ${_genAddToChanges(r)} $oldValue = $newValue; @@ -360,7 +288,7 @@ class _CodegenState { '''; if (r.isPureFunction()) { // 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; }'; } else { return check; @@ -369,11 +297,11 @@ class _CodegenState { String _genUpdateCurrentValue(ProtoRecord r) { var context = r.contextIndex == -1 - ? _genGetDirective(r.directiveIndex) - : _localNames[r.contextIndex]; + ? _names.getDirectiveName(r.directiveIndex) + : _names.getLocalName(r.contextIndex); - var newValue = _localNames[r.selfIndex]; - var argString = r.args.map((arg) => _localNames[arg]).join(', '); + var newValue = _names.getLocalName(r.selfIndex); + var argString = r.args.map((arg) => _names.getLocalName(arg)).join(', '); var rhs; switch (r.mode) { @@ -419,7 +347,7 @@ class _CodegenState { break; case RecordType.KEYED_ACCESS: - rhs = '$context[${_localNames[r.args[0]]}]'; + rhs = '$context[${_names.getLocalName(r.args[0])}]'; break; default: @@ -432,7 +360,7 @@ class _CodegenState { String _genInterpolation(ProtoRecord r) { var res = new StringBuffer(); for (var i = 0; i < r.args.length; ++i) { - var name = _localNames[r.args[i]]; + var name = _names.getLocalName(r.args[i]); res.write( '${_encodeValue(r.fixedArgs[i])} "\$\{$name == null ? "" : $name\}" '); } @@ -443,13 +371,13 @@ class _CodegenState { String _genUpdateDirectiveOrElement(ProtoRecord r) { if (!r.lastInBinding) return ''; - var newValue = _localNames[r.selfIndex]; - var oldValue = _fieldNames[r.selfIndex]; + var newValue = _names.getLocalName(r.selfIndex); + var oldValue = _names.getFieldName(r.selfIndex); var br = r.bindingRecord; if (br.isDirective()) { var directiveProperty = - '${_genGetDirective(br.directiveRecord.directiveIndex)}.${br.propertyName}'; + '${_names.getDirectiveName(br.directiveRecord.directiveIndex)}.${br.propertyName}'; return ''' ${_genThrowOnChangeCheck(oldValue, newValue)} $directiveProperty = $newValue; @@ -474,8 +402,8 @@ class _CodegenState { } String _genAddToChanges(ProtoRecord r) { - var newValue = _localNames[r.selfIndex]; - var oldValue = _fieldNames[r.selfIndex]; + var newValue = _names.getLocalName(r.selfIndex); + var oldValue = _names.getFieldName(r.selfIndex); if (!r.bindingRecord.callOnChange()) return ''; return ''' $_CHANGES_LOCAL = $_UTIL.addChange( @@ -497,19 +425,19 @@ class _CodegenState { String _genOnCheck(ProtoRecord r) { var br = r.bindingRecord; return 'if (!throwOnChange) ' - '${_genGetDirective(br.directiveRecord.directiveIndex)}.onCheck();'; + '${_names.getDirectiveName(br.directiveRecord.directiveIndex)}.onCheck();'; } String _genOnInit(ProtoRecord r) { var br = r.bindingRecord; return 'if (!throwOnChange && !$_ALREADY_CHECKED_ACCESSOR) ' - '${_genGetDirective(br.directiveRecord.directiveIndex)}.onInit();'; + '${_names.getDirectiveName(br.directiveRecord.directiveIndex)}.onInit();'; } String _genOnChange(ProtoRecord r) { var br = r.bindingRecord; return 'if (!throwOnChange && $_CHANGES_LOCAL != null) ' - '${_genGetDirective(br.directiveRecord.directiveIndex)}' + '${_names.getDirectiveName(br.directiveRecord.directiveIndex)}' '.onChange($_CHANGES_LOCAL);'; } @@ -518,7 +446,7 @@ class _CodegenState { if (!r.lastInDirective || !br.isOnPushChangeDetection()) return ''; return ''' 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 _BASE_CLASS = '$_GEN_PREFIX.AbstractChangeDetector'; const _CHANGES_LOCAL = 'changes'; -const _CONTEXT_ACCESSOR = '_context'; const _CURRENT_PROTO = 'currentProto'; const _DIRECTIVES_ACCESSOR = '_directiveRecords'; const _DISPATCHER_ACCESSOR = 'dispatcher'; diff --git a/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart b/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart index e20ef1745f..f42da33fd8 100644 --- a/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart +++ b/modules/angular2/test/transform/integration/two_annotations_files/expected/bar.ng_deps.dart @@ -30,13 +30,15 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector { dynamic _locals = null; dynamic _alreadyChecked = false; dynamic currentProto = null; - MyComponent _context = null; - dynamic _myNum0 = _gen.ChangeDetectionUtil.uninitialized(); - dynamic _interpolate1 = _gen.ChangeDetectionUtil.uninitialized(); + MyComponent _context; + var _myNum0, _interpolate1; _MyComponent_ChangeDetector0( 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) { if (!hydrated()) { @@ -50,12 +52,8 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector { } void __detectChangesInRecords(throwOnChange) { - var context = null; - var myNum0 = null; - var interpolate1 = null; - var change_context = false; - var change_myNum0 = false; - var change_interpolate1 = false; + var context, c_context, myNum0, c_myNum0, interpolate1, c_interpolate1; + c_context = c_myNum0 = c_interpolate1 = false; var isChanged = false; currentProto = null; var changes = null; @@ -64,15 +62,15 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector { currentProto = _protos[0]; myNum0 = context.myNum; if (!_gen.looseIdentical(myNum0, _myNum0)) { - change_myNum0 = true; + c_myNum0 = true; _myNum0 = myNum0; } - if (change_myNum0) { + if (c_myNum0) { currentProto = _protos[1]; interpolate1 = "Salad: " "${myNum0 == null ? "" : myNum0}" " is awesome"; if (!_gen.looseIdentical(interpolate1, _interpolate1)) { - change_interpolate1 = true; + c_interpolate1 = true; if (throwOnChange) { _gen.ChangeDetectionUtil.throwOnChange(currentProto, _gen.ChangeDetectionUtil.simpleChange( @@ -108,8 +106,7 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector { void dehydrate() { _context = null; - _myNum0 = _gen.ChangeDetectionUtil.uninitialized(); - _interpolate1 = _gen.ChangeDetectionUtil.uninitialized(); + _myNum0 = _interpolate1 = _gen.ChangeDetectionUtil.uninitialized(); _locals = null; _pipes = null; }