feat(change_detection): generate checkNoChanges only in dev mode
This commit is contained in:
parent
a2bb81c406
commit
71bb4b3ee5
|
@ -1,4 +1,4 @@
|
|||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {isPresent, BaseException} from 'angular2/src/facade/lang';
|
||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {ChangeDetectorRef} from './change_detector_ref';
|
||||
import {ChangeDetector} from './interfaces';
|
||||
|
@ -38,11 +38,11 @@ export class AbstractChangeDetector implements ChangeDetector {
|
|||
|
||||
remove(): void { this.parent.removeChild(this); }
|
||||
|
||||
detectChanges(): void { this._detectChanges(false); }
|
||||
detectChanges(): void { this.runDetectChanges(false); }
|
||||
|
||||
checkNoChanges(): void { this._detectChanges(true); }
|
||||
checkNoChanges(): void { throw new BaseException("Not implemented"); }
|
||||
|
||||
_detectChanges(throwOnChange: boolean): void {
|
||||
runDetectChanges(throwOnChange: boolean): void {
|
||||
if (this.mode === DETACHED || this.mode === CHECKED) return;
|
||||
|
||||
this.detectChangesInRecords(throwOnChange);
|
||||
|
@ -67,14 +67,14 @@ export class AbstractChangeDetector implements ChangeDetector {
|
|||
_detectChangesInLightDomChildren(throwOnChange: boolean): void {
|
||||
var c = this.lightDomChildren;
|
||||
for (var i = 0; i < c.length; ++i) {
|
||||
c[i]._detectChanges(throwOnChange);
|
||||
c[i].runDetectChanges(throwOnChange);
|
||||
}
|
||||
}
|
||||
|
||||
_detectChangesInShadowDomChildren(throwOnChange: boolean): void {
|
||||
var c = this.shadowDomChildren;
|
||||
for (var i = 0; i < c.length; ++i) {
|
||||
c[i]._detectChanges(throwOnChange);
|
||||
c[i].runDetectChanges(throwOnChange);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ export class ChangeDetectorJITGenerator {
|
|||
_names: CodegenNameUtil;
|
||||
|
||||
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) {
|
||||
this._names = new CodegenNameUtil(this.records, this.directiveRecords, 'this._', UTIL);
|
||||
}
|
||||
|
||||
|
@ -80,6 +81,8 @@ export class ChangeDetectorJITGenerator {
|
|||
${ALREADY_CHECKED_ACCESSOR} = true;
|
||||
}
|
||||
|
||||
${this._genCheckNoChanges(typeName)}
|
||||
|
||||
${typeName}.prototype.callOnAllChangesDone = function() {
|
||||
${this._genCallOnAllChangesDoneBody()}
|
||||
}
|
||||
|
@ -109,6 +112,7 @@ export class ChangeDetectorJITGenerator {
|
|||
return new ${typeName}(dispatcher, protos, directiveRecords);
|
||||
}
|
||||
`;
|
||||
|
||||
return new Function('AbstractChangeDetector', 'ChangeDetectionUtil', 'protos',
|
||||
'directiveRecords', classDefinition)(
|
||||
AbstractChangeDetector, ChangeDetectionUtil, this.records, this.directiveRecords);
|
||||
|
@ -330,11 +334,23 @@ export class ChangeDetectorJITGenerator {
|
|||
}
|
||||
|
||||
_genThrowOnChangeCheck(oldValue: string, newValue: string): string {
|
||||
return `
|
||||
if(throwOnChange) {
|
||||
${UTIL}.throwOnChange(${CURRENT_PROTO}, ${UTIL}.simpleChange(${oldValue}, ${newValue}));
|
||||
}
|
||||
`;
|
||||
if (this.generateCheckNoChanges) {
|
||||
return `
|
||||
if(throwOnChange) {
|
||||
${UTIL}.throwOnChange(${CURRENT_PROTO}, ${UTIL}.simpleChange(${oldValue}, ${newValue}));
|
||||
}
|
||||
`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
_genCheckNoChanges(typeName: string): string {
|
||||
if (this.generateCheckNoChanges) {
|
||||
return `${typeName}.prototype.checkNoChanges = function() { this.runDetectChanges(true); }`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
_genAddToChanges(r: ProtoRecord): string {
|
||||
|
|
|
@ -65,6 +65,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
|||
|
||||
hydrated(): boolean { return this.values[0] !== null; }
|
||||
|
||||
checkNoChanges(): void { this.runDetectChanges(true); }
|
||||
|
||||
detectChangesInRecords(throwOnChange: boolean) {
|
||||
if (!this.hydrated()) {
|
||||
ChangeDetectionUtil.throwDehydrated();
|
||||
|
|
|
@ -63,5 +63,6 @@ export interface ProtoChangeDetector { instantiate(dispatcher: any): ChangeDetec
|
|||
export class ChangeDetectorDefinition {
|
||||
constructor(public id: string, public strategy: string, public variableNames: List<string>,
|
||||
public bindingRecords: List<BindingRecord>,
|
||||
public directiveRecords: List<DirectiveRecord>) {}
|
||||
public directiveRecords: List<DirectiveRecord>,
|
||||
public generateCheckNoChanges: boolean) {}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@ export class JitProtoChangeDetector implements ProtoChangeDetector {
|
|||
(b) => { recordBuilder.add(b, definition.variableNames); });
|
||||
var records = coalesce(recordBuilder.records);
|
||||
return new ChangeDetectorJITGenerator(definition.id, definition.strategy, records,
|
||||
this.definition.directiveRecords)
|
||||
this.definition.directiveRecords,
|
||||
this.definition.generateCheckNoChanges)
|
||||
.generate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Injectable} from 'angular2/di';
|
||||
|
||||
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||
import {isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
||||
import {isPresent, isBlank, BaseException, assertionsEnabled} from 'angular2/src/facade/lang';
|
||||
import {reflector} from 'angular2/src/reflection/reflection';
|
||||
|
||||
import {
|
||||
|
@ -246,7 +246,7 @@ function _getChangeDetectorDefinitions(
|
|||
var id = `${hostComponentMetadata.id}_${typeString}_${pvWithIndex.index}`;
|
||||
var variableNames = nestedPvVariableNames[pvWithIndex.index];
|
||||
return new ChangeDetectorDefinition(id, strategyName, variableNames, bindingRecords,
|
||||
directiveRecords);
|
||||
directiveRecords, assertionsEnabled());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -74,10 +74,11 @@ class _CodegenState {
|
|||
final List<ProtoRecord> _records;
|
||||
final List<DirectiveRecord> _directiveRecords;
|
||||
final CodegenNameUtil _names;
|
||||
final bool _generateCheckNoChanges;
|
||||
|
||||
_CodegenState._(this._changeDetectorDefId, this._contextTypeName,
|
||||
this._changeDetectorTypeName, String changeDetectionStrategy,
|
||||
List<ProtoRecord> records, List<DirectiveRecord> directiveRecords)
|
||||
List<ProtoRecord> records, List<DirectiveRecord> directiveRecords, this._generateCheckNoChanges)
|
||||
: _records = records,
|
||||
_directiveRecords = directiveRecords,
|
||||
_names = new CodegenNameUtil(records, directiveRecords, '_', _UTIL),
|
||||
|
@ -91,7 +92,7 @@ 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);
|
||||
def.strategy, records, def.directiveRecords, def.generateCheckNoChanges);
|
||||
}
|
||||
|
||||
void _writeToBuf(StringBuffer buf) {
|
||||
|
@ -138,6 +139,8 @@ class _CodegenState {
|
|||
$_ALREADY_CHECKED_ACCESSOR = true;
|
||||
}
|
||||
|
||||
${_genCheckNoChanges()}
|
||||
|
||||
void callOnAllChangesDone() {
|
||||
${_getCallOnAllChangesDoneBody()}
|
||||
}
|
||||
|
@ -393,12 +396,24 @@ class _CodegenState {
|
|||
}
|
||||
|
||||
String _genThrowOnChangeCheck(String oldValue, String newValue) {
|
||||
return '''
|
||||
if(throwOnChange) {
|
||||
$_UTIL.throwOnChange(
|
||||
$_CURRENT_PROTO, $_UTIL.simpleChange(${oldValue}, ${newValue}));
|
||||
}
|
||||
''';
|
||||
if (this._generateCheckNoChanges) {
|
||||
return '''
|
||||
if(throwOnChange) {
|
||||
$_UTIL.throwOnChange(
|
||||
$_CURRENT_PROTO, $_UTIL.simpleChange(${oldValue}, ${newValue}));
|
||||
}
|
||||
''';
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
String _genCheckNoChanges() {
|
||||
if (this._generateCheckNoChanges) {
|
||||
return 'void checkNoChanges() { this.runDetectChanges(true); }';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String _genAddToChanges(ProtoRecord r) {
|
||||
|
|
|
@ -23,7 +23,7 @@ export function main() {
|
|||
|
||||
beforeEach(() => {
|
||||
proto = new SpyProtoChangeDetector();
|
||||
def = new ChangeDetectorDefinition('id', null, [], [], []);
|
||||
def = new ChangeDetectorDefinition('id', null, [], [], [], true);
|
||||
});
|
||||
|
||||
it("should return a proto change detector when one is available", () => {
|
||||
|
|
|
@ -69,7 +69,7 @@ export function getDefinition(id: string): TestDefinition {
|
|||
var bindingRecords = _createBindingRecords(id);
|
||||
var directiveRecords = [];
|
||||
let cdDef = new ChangeDetectorDefinition(id, strategy, variableBindings, bindingRecords,
|
||||
directiveRecords);
|
||||
directiveRecords, true);
|
||||
testDef = new TestDefinition(id, cdDef, null);
|
||||
}
|
||||
if (isBlank(testDef)) {
|
||||
|
@ -107,7 +107,7 @@ class _ExpressionWithLocals {
|
|||
var bindingRecords = _createBindingRecords(this._expression);
|
||||
var directiveRecords = [];
|
||||
return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings, bindingRecords,
|
||||
directiveRecords);
|
||||
directiveRecords, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,7 +151,7 @@ class _ExpressionWithMode {
|
|||
directiveRecords = [];
|
||||
}
|
||||
return new ChangeDetectorDefinition('(empty id)', this._strategy, variableBindings,
|
||||
bindingRecords, directiveRecords);
|
||||
bindingRecords, directiveRecords, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,7 +174,7 @@ class _DirectiveUpdating {
|
|||
var variableBindings = [];
|
||||
|
||||
return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings,
|
||||
this._bindingRecords, this._directiveRecords);
|
||||
this._bindingRecords, this._directiveRecords, true);
|
||||
}
|
||||
|
||||
static updateA(expression: string, dirRecord): BindingRecord {
|
||||
|
|
|
@ -91,6 +91,8 @@ class _MyComponent_ChangeDetector0 extends _gen.AbstractChangeDetector {
|
|||
_alreadyChecked = true;
|
||||
}
|
||||
|
||||
void checkNoChanges() {this.runDetectChanges(true);}
|
||||
|
||||
void callOnAllChangesDone() {
|
||||
dispatcher.notifyOnAllChangesDone();
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@ function setUpChangeDetection(changeDetection: ChangeDetection, iterations, obje
|
|||
var parser = new Parser(new Lexer());
|
||||
|
||||
var parentProto = changeDetection.createProtoChangeDetector(
|
||||
new ChangeDetectorDefinition('parent', null, [], [], []));
|
||||
new ChangeDetectorDefinition('parent', null, [], [], [], false));
|
||||
var parentCd = parentProto.instantiate(dispatcher);
|
||||
|
||||
var directiveRecord = new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0)});
|
||||
|
@ -277,7 +277,7 @@ function setUpChangeDetection(changeDetection: ChangeDetection, iterations, obje
|
|||
];
|
||||
|
||||
var proto = changeDetection.createProtoChangeDetector(
|
||||
new ChangeDetectorDefinition("proto", null, [], bindings, [directiveRecord]));
|
||||
new ChangeDetectorDefinition("proto", null, [], bindings, [directiveRecord], false));
|
||||
|
||||
var targetObj = new Obj();
|
||||
parentCd.hydrate(object, null, new FakeDirectives(targetObj), null);
|
||||
|
|
Loading…
Reference in New Issue