Skip to content

Commit 8a3b0b3

Browse files
author
Tim Blasi
committed
feat(dart/transform): Generate ChangeDetector classes
Use the `ProtoViewDto` created by the render `Compiler` to create a `ChangeDetectorDefinition`. From there, generate a subclass of `AbstractChangeDetector` for each `ChangeDetectorDefinition`. Run some basic unit tests for the dynamic and JIT change detectors on pre-generated change detectors.
1 parent 383f0a1 commit 8a3b0b3

File tree

15 files changed

+1114
-226
lines changed

15 files changed

+1114
-226
lines changed

gulpfile.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ gulp.task('!build/tree.dart', function() {
178178
// Run a top-level `pub get` for this project.
179179
gulp.task('pubget.dart', pubget.dir(gulp, gulpPlugins, { dir: '.', command: DART_SDK.PUB }));
180180

181+
// Run `pub get` only on the angular2 dir of CONFIG.dest.dart
182+
gulp.task('!build/pubget.angular2.dart', pubget.dir(gulp, gulpPlugins, {
183+
dir: path.join(CONFIG.dest.dart, 'angular2'),
184+
command: DART_SDK.PUB
185+
}));
186+
181187
// Run `pub get` over CONFIG.dest.dart
182188
gulp.task('build/pubspec.dart', pubget.subDir(gulp, gulpPlugins, {
183189
dir: CONFIG.dest.dart,
@@ -588,6 +594,8 @@ gulp.task('build/packages.dart', function(done) {
588594
runSequence(
589595
'build/tree.dart',
590596
// Run after 'build/tree.dart' because broccoli clears the dist/dart folder
597+
'!build/pubget.angular2.dart',
598+
'!build/change_detect.dart',
591599
'build/pure-packages.dart',
592600
'build/format.dart',
593601
done);
@@ -811,6 +819,34 @@ gulp.task('clean', ['build/clean.tools', 'build/clean.js', 'build/clean.dart', '
811819

812820
gulp.task('build', ['build.js', 'build.dart']);
813821

822+
// ------------
823+
// change detection codegen
824+
825+
826+
gulp.task('build.change_detect.dart', function(done) {
827+
return runSequence('build/packages.dart', '!build/pubget.angular2.dart',
828+
'!build/change_detect.dart', done);
829+
});
830+
831+
gulp.task('!build/change_detect.dart', function(done) {
832+
var fs = require('fs');
833+
var changeDetectDir = path.join(CONFIG.dest.dart, 'angular2/test/change_detection/');
834+
var srcDir = path.join(changeDetectDir, 'generator');
835+
var destDir = path.join(changeDetectDir, 'generated');
836+
837+
var dartStream = fs.createWriteStream(path.join(destDir, 'simple_watch_classes.dart'));
838+
var genMain = path.join(srcDir, 'gen_change_detectors.dart');
839+
var proc = spawn(DART_SDK.VM, [genMain], { stdio:['ignore', 'pipe', 'inherit'] });
840+
proc.on('error', function(code) {
841+
done(new Error('Failed while generating change detector classes. Please run manually: ' +
842+
DART_SDK.VM + ' ' + dartArgs.join(' ')));
843+
});
844+
proc.on('close', function() {
845+
dartStream.close();
846+
done();
847+
});
848+
proc.stdout.pipe(dartStream);
849+
});
814850

815851
// ------------
816852
// angular material testing rules

modules/angular2/src/change_detection/change_detection_jit_generator.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ import {
2727
* The code generator takes a list of proto records and creates a function/class
2828
* that "emulates" what the developer would write by hand to implement the same
2929
* kind of behaviour.
30+
*
31+
* This code should be kept in sync with the Dart transformer's
32+
* `angular2.transform.template_compiler.change_detector_codegen` library. If you make updates
33+
* here, please make equivalent changes there.
3034
*/
3135
var ABSTRACT_CHANGE_DETECTOR = "AbstractChangeDetector";
3236
var UTIL = "ChangeDetectionUtil";
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
library angular2.src.change_detection.pregen_proto_change_detector;
2+
3+
import 'package:angular2/src/change_detection/coalesce.dart';
4+
import 'package:angular2/src/change_detection/directive_record.dart';
5+
import 'package:angular2/src/change_detection/interfaces.dart';
6+
import 'package:angular2/src/change_detection/pipes/pipe_registry.dart';
7+
import 'package:angular2/src/change_detection/proto_change_detector.dart';
8+
import 'package:angular2/src/change_detection/proto_record.dart';
9+
10+
export 'dart:core' show List;
11+
export 'package:angular2/src/change_detection/abstract_change_detector.dart'
12+
show AbstractChangeDetector;
13+
export 'package:angular2/src/change_detection/directive_record.dart'
14+
show DirectiveIndex, DirectiveRecord;
15+
export 'package:angular2/src/change_detection/interfaces.dart'
16+
show ChangeDetector, ChangeDetectorDefinition, ProtoChangeDetector;
17+
export 'package:angular2/src/change_detection/pipes/pipe_registry.dart'
18+
show PipeRegistry;
19+
export 'package:angular2/src/change_detection/proto_record.dart'
20+
show ProtoRecord;
21+
export 'package:angular2/src/change_detection/change_detection_util.dart'
22+
show ChangeDetectionUtil;
23+
export 'package:angular2/src/facade/lang.dart' show looseIdentical;
24+
25+
typedef ChangeDetector InstantiateMethod(dynamic dispatcher,
26+
PipeRegistry registry, List<ProtoRecord> protoRecords,
27+
List<DirectiveRecord> directiveRecords);
28+
29+
/// Implementation of [ProtoChangeDetector] for use by pre-generated change
30+
/// detectors in Angular 2 Dart.
31+
/// Classes generated by the `TemplateCompiler` use this. The `export`s above
32+
/// allow the generated code to `import` a single library and get all
33+
/// dependencies.
34+
class PregenProtoChangeDetector extends ProtoChangeDetector {
35+
/// The [ChangeDetectorDefinition#id]. Strictly informational.
36+
final String id;
37+
38+
/// Closure used to generate an actual [ChangeDetector].
39+
final InstantiateMethod _instantiateMethod;
40+
41+
// [ChangeDetector] dependencies.
42+
final PipeRegistry _pipeRegistry;
43+
final List<ProtoRecord> _protoRecords;
44+
final List<DirectiveRecord> _directiveRecords;
45+
46+
/// Internal ctor.
47+
PregenProtoChangeDetector._(this.id, this._instantiateMethod,
48+
this._pipeRegistry, this._protoRecords, this._directiveRecords);
49+
50+
factory PregenProtoChangeDetector(InstantiateMethod instantiateMethod,
51+
PipeRegistry registry, ChangeDetectorDefinition def) {
52+
// TODO(kegluneq): Pre-generate these (#2067).
53+
var recordBuilder = new ProtoRecordBuilder();
54+
def.bindingRecords.forEach((b) {
55+
recordBuilder.add(b, def.variableNames);
56+
});
57+
var protoRecords = coalesce(recordBuilder.records);
58+
return new PregenProtoChangeDetector._(def.id, instantiateMethod, registry,
59+
protoRecords, def.directiveRecords);
60+
}
61+
62+
@override
63+
instantiate(dynamic dispatcher) => _instantiateMethod(
64+
dispatcher, _pipeRegistry, _protoRecords, _directiveRecords);
65+
}

0 commit comments

Comments
 (0)