chore: Make field declarations explicit

This used to be valid code:

```
class Foo {
  constructor() {
    this.bar = ‘string’;
  }
}
```

This will now fail since ‘bar’ is not explicitly
defined as a field. We now have to write:

```
class Foo {
  bar:string; // << REQUIRED
  constructor() {
    this.bar = ‘string’;
  }
}
```
This commit is contained in:
Misko Hevery 2014-11-21 21:19:23 -08:00 committed by vsavkin
parent ab961b327e
commit 044625a098
69 changed files with 572 additions and 504 deletions

View File

@ -12,8 +12,8 @@ import {Lexer} from 'change_detection/parser/lexer';
import {Compiler} from 'core/compiler/compiler'; import {Compiler} from 'core/compiler/compiler';
import {Reflector} from 'core/compiler/reflector'; import {Reflector} from 'core/compiler/reflector';
import {Component} from 'core/annotations/component'; import {Component} from 'core/annotations/annotations';
import {Decorator} from 'core/annotations/decorator'; import {Decorator} from 'core/annotations/annotations';
import {TemplateConfig} from 'core/annotations/template_config'; import {TemplateConfig} from 'core/annotations/template_config';
var COUNT = 30; var COUNT = 30;
@ -64,6 +64,7 @@ function loadTemplate(templateId, repeatCount) {
// Caching reflector as reflection in Dart using Mirrors // Caching reflector as reflection in Dart using Mirrors
class CachingReflector extends Reflector { class CachingReflector extends Reflector {
_cache: Map;
constructor() { constructor() {
this._cache = MapWrapper.create(); this._cache = MapWrapper.create();
} }

View File

@ -6,8 +6,7 @@ export * from './record';
export * from './record_range' export * from './record_range'
export class ChangeDetector { export class ChangeDetector {
_rootRecordRange:RecordRange;
@FIELD('final _rootRecordRange:RecordRange')
constructor(recordRange:RecordRange) { constructor(recordRange:RecordRange) {
this._rootRecordRange = recordRange; this._rootRecordRange = recordRange;
} }

View File

@ -13,18 +13,19 @@ import {
} from 'facade/lang'; } from 'facade/lang';
export class CollectionChanges { export class CollectionChanges {
// todo(vicb) Add fields when supported
/*
_collection; _collection;
int _length; _length:int;
DuplicateMap _linkedRecords; _linkedRecords:_DuplicateMap;
DuplicateMap _unlinkedRecords; _unlinkedRecords:_DuplicateMap;
CollectionChangeItem<V> _previousItHead; _previousItHead:CollectionChangeRecord<V> ;
CollectionChangeItem<V> _itHead, _itTail; _itHead:CollectionChangeRecord<V>;
CollectionChangeItem<V> _additionsHead, _additionsTail; _itTail:CollectionChangeRecord<V> ;
CollectionChangeItem<V> _movesHead, _movesTail; _additionsHead:CollectionChangeRecord<V>;
CollectionChangeItem<V> _removalsHead, _removalsTail; _additionsTail:CollectionChangeRecord<V> ;
*/ _movesHead:CollectionChangeRecord<V>;
_movesTail:CollectionChangeRecord<V> ;
_removalsHead:CollectionChangeRecord<V>;
_removalsTail:CollectionChangeRecord<V> ;
constructor() { constructor() {
this._collection = null; this._collection = null;
this._length = null; this._length = null;
@ -236,9 +237,9 @@ export class CollectionChanges {
} }
/** /**
* Get rid of any excess [CollectionChangeItem]s from the previous collection * Get rid of any excess [CollectionChangeRecord]s from the previous collection
* *
* - [record] The first excess [CollectionChangeItem]. * - [record] The first excess [CollectionChangeRecord].
*/ */
_truncate(record:CollectionChangeRecord) { _truncate(record:CollectionChangeRecord) {
// Anything after that needs to be removed; // Anything after that needs to be removed;
@ -457,19 +458,16 @@ export class CollectionChanges {
} }
export class CollectionChangeRecord { export class CollectionChangeRecord {
// todo(vicb) add fields when supported currentIndex:int;
/* previousIndex:int;
int currentIndex; item;
int previousIndex;
V item;
CollectionChangeItem<V> _nextPrevious; _nextPrevious:CollectionChangeRecord;
CollectionChangeItem<V> _prev, _next; _prev:CollectionChangeRecord; _next:CollectionChangeRecord;
CollectionChangeItem<V> _prevDup, _nextDup; _prevDup:CollectionChangeRecord; _nextDup:CollectionChangeRecord;
CollectionChangeItem<V> _prevRemoved, _nextRemoved; _prevRemoved:CollectionChangeRecord; _nextRemoved:CollectionChangeRecord;
CollectionChangeItem<V> _nextAdded; _nextAdded:CollectionChangeRecord;
CollectionChangeItem<V> _nextMoved; _nextMoved:CollectionChangeRecord;
*/
constructor(item) { constructor(item) {
this.currentIndex = null; this.currentIndex = null;
@ -497,10 +495,8 @@ export class CollectionChangeRecord {
// A linked list of CollectionChangeRecords with the same CollectionChangeRecord.item // A linked list of CollectionChangeRecords with the same CollectionChangeRecord.item
class _DuplicateItemRecordList { class _DuplicateItemRecordList {
/* _head:CollectionChangeRecord;
todo(vicb): add fields when supported _tail:CollectionChangeRecord;
CollectionChangeRecord _head, _tail;
*/
constructor() { constructor() {
this._head = null; this._head = null;
@ -542,7 +538,7 @@ class _DuplicateItemRecordList {
} }
/** /**
* Remove one [CollectionChangeItem] from the list of duplicates. * Remove one [CollectionChangeRecord] from the list of duplicates.
* *
* Returns whether the list of duplicates is empty. * Returns whether the list of duplicates is empty.
*/ */
@ -550,7 +546,7 @@ class _DuplicateItemRecordList {
// todo(vicb) // todo(vicb)
//assert(() { //assert(() {
// // verify that the record being removed is in the list. // // verify that the record being removed is in the list.
// for (CollectionChangeItem cursor = _head; cursor != null; cursor = cursor._nextDup) { // for (CollectionChangeRecord cursor = _head; cursor != null; cursor = cursor._nextDup) {
// if (identical(cursor, record)) return true; // if (identical(cursor, record)) return true;
// } // }
// return false; // return false;
@ -573,7 +569,7 @@ class _DuplicateItemRecordList {
} }
class _DuplicateMap { class _DuplicateMap {
// todo(vicb): add fields when supported map:Map;
constructor() { constructor() {
this.map = MapWrapper.create(); this.map = MapWrapper.create();
} }
@ -605,7 +601,7 @@ class _DuplicateMap {
} }
/** /**
* Removes an [CollectionChangeItem] from the list of duplicates. * Removes an [CollectionChangeRecord] from the list of duplicates.
* *
* The list of duplicates also is removed from the map if it gets empty. * The list of duplicates also is removed from the map if it gets empty.
*/ */

View File

@ -3,19 +3,17 @@ import {ListWrapper, MapWrapper} from 'facade/collection';
import {stringify, looseIdentical} from 'facade/lang'; import {stringify, looseIdentical} from 'facade/lang';
export class MapChanges { export class MapChanges {
// todo(vicb) add as fields when supported _records:Map;
/* _map:Map;
final _records = new HashMap<dynamic, MapKeyValue>();
Map _map;
Map get map => _map; _mapHead:MapChangeRecord;
_previousMapHead:MapChangeRecord;
MapKeyValue<K, V> _mapHead; _changesHead:MapChangeRecord;
MapKeyValue<K, V> _previousMapHead; _changesTail:MapChangeRecord;
MapKeyValue<K, V> _changesHead, _changesTail; _additionsHead:MapChangeRecord;
MapKeyValue<K, V> _additionsHead, _additionsTail; _additionsTail:MapChangeRecord;
MapKeyValue<K, V> _removalsHead, _removalsTail; _removalsHead:MapChangeRecord;
*/ _removalsTail:MapChangeRecord;
constructor() { constructor() {
this._records = MapWrapper.create(); this._records = MapWrapper.create();
@ -317,18 +315,16 @@ export class MapChanges {
} }
export class MapChangeRecord { export class MapChangeRecord {
// todo(vicb) add as fields key;
//final K key; _previousValue;
//V _previousValue, _currentValue; _currentValue;
//
//V get previousValue => _previousValue; _nextPrevious:MapChangeRecord;
//V get currentValue => _currentValue; _next:MapChangeRecord;
// _nextAdded:MapChangeRecord;
//MapKeyValue<K, V> _nextPrevious; _nextRemoved:MapChangeRecord;
//MapKeyValue<K, V> _next; _prevRemoved:MapChangeRecord;
//MapKeyValue<K, V> _nextAdded; _nextChanged:MapChangeRecord;
//MapKeyValue<K, V> _nextRemoved, _prevRemoved;
//MapKeyValue<K, V> _nextChanged;
constructor(key) { constructor(key) {
this.key = key; this.key = key;

View File

@ -33,7 +33,7 @@ export class ImplicitReceiver extends AST {
* Multiple expressions separated by a semicolon. * Multiple expressions separated by a semicolon.
*/ */
export class Chain extends AST { export class Chain extends AST {
@FIELD('final expressions:List') expressions:List;
constructor(expressions:List) { constructor(expressions:List) {
this.expressions = expressions; this.expressions = expressions;
} }
@ -53,9 +53,9 @@ export class Chain extends AST {
} }
export class Conditional extends AST { export class Conditional extends AST {
@FIELD('final condition:AST') condition:AST;
@FIELD('final trueExp:AST') trueExp:AST;
@FIELD('final falseExp:AST') falseExp:AST;
constructor(condition:AST, trueExp:AST, falseExp:AST){ constructor(condition:AST, trueExp:AST, falseExp:AST){
this.condition = condition; this.condition = condition;
this.trueExp = trueExp; this.trueExp = trueExp;
@ -76,10 +76,10 @@ export class Conditional extends AST {
} }
export class AccessMember extends AST { export class AccessMember extends AST {
@FIELD('final receiver:AST') receiver:AST;
@FIELD('final name:string') name:string;
@FIELD('final getter:Function') getter:Function;
@FIELD('final setter:Function') setter:Function;
constructor(receiver:AST, name:string, getter:Function, setter:Function) { constructor(receiver:AST, name:string, getter:Function, setter:Function) {
this.receiver = receiver; this.receiver = receiver;
this.name = name; this.name = name;
@ -105,8 +105,8 @@ export class AccessMember extends AST {
} }
export class KeyedAccess extends AST { export class KeyedAccess extends AST {
@FIELD('final obj:AST') obj:AST;
@FIELD('final key:AST') key:AST;
constructor(obj:AST, key:AST) { constructor(obj:AST, key:AST) {
this.obj = obj; this.obj = obj;
this.key = key; this.key = key;
@ -149,9 +149,10 @@ export class KeyedAccess extends AST {
} }
export class Formatter extends AST { export class Formatter extends AST {
@FIELD('final exp:AST') exp:AST;
@FIELD('final name:string') name:string;
@FIELD('final args:List<AST>') args:List<AST>;
allArgs:List<AST>;
constructor(exp:AST, name:string, args:List) { constructor(exp:AST, name:string, args:List) {
this.exp = exp; this.exp = exp;
this.name = name; this.name = name;
@ -165,7 +166,7 @@ export class Formatter extends AST {
} }
export class LiteralPrimitive extends AST { export class LiteralPrimitive extends AST {
@FIELD('final value') value;
constructor(value) { constructor(value) {
this.value = value; this.value = value;
} }
@ -180,7 +181,7 @@ export class LiteralPrimitive extends AST {
} }
export class LiteralArray extends AST { export class LiteralArray extends AST {
@FIELD('final expressions:List') expressions:List;
constructor(expressions:List) { constructor(expressions:List) {
this.expressions = expressions; this.expressions = expressions;
} }
@ -195,8 +196,8 @@ export class LiteralArray extends AST {
} }
export class LiteralMap extends AST { export class LiteralMap extends AST {
@FIELD('final keys:List') keys:List;
@FIELD('final values:List') values:List;
constructor(keys:List, values:List) { constructor(keys:List, values:List) {
this.keys = keys; this.keys = keys;
this.values = values; this.values = values;
@ -216,9 +217,9 @@ export class LiteralMap extends AST {
} }
export class Binary extends AST { export class Binary extends AST {
@FIELD('final operation:string') operation:string;
@FIELD('final left:AST') left:AST;
@FIELD('final right:AST') right:AST;
constructor(operation:string, left:AST, right:AST) { constructor(operation:string, left:AST, right:AST) {
this.operation = operation; this.operation = operation;
this.left = left; this.left = left;
@ -262,7 +263,7 @@ export class Binary extends AST {
} }
export class PrefixNot extends AST { export class PrefixNot extends AST {
@FIELD('final expression:AST') expression:AST;
constructor(expression:AST) { constructor(expression:AST) {
this.expression = expression; this.expression = expression;
} }
@ -277,8 +278,8 @@ export class PrefixNot extends AST {
} }
export class Assignment extends AST { export class Assignment extends AST {
@FIELD('final target:AST') target:AST;
@FIELD('final value:AST') value:AST;
constructor(target:AST, value:AST) { constructor(target:AST, value:AST) {
this.target = target; this.target = target;
this.value = value; this.value = value;
@ -294,9 +295,9 @@ export class Assignment extends AST {
} }
export class MethodCall extends AST { export class MethodCall extends AST {
@FIELD('final receiver:AST') receiver:AST;
@FIELD('final fn:Function') fn:Function;
@FIELD('final args:List') args:List;
constructor(receiver:AST, fn:Function, args:List) { constructor(receiver:AST, fn:Function, args:List) {
this.receiver = receiver; this.receiver = receiver;
this.fn = fn; this.fn = fn;
@ -314,9 +315,9 @@ export class MethodCall extends AST {
} }
export class FunctionCall extends AST { export class FunctionCall extends AST {
@FIELD('final target:AST') target:AST;
@FIELD('final closureMap:ClosureMap') closureMap:ClosureMap;
@FIELD('final args:List') args:List;
constructor(target:AST, closureMap:ClosureMap, args:List) { constructor(target:AST, closureMap:ClosureMap, args:List) {
this.target = target; this.target = target;
this.closureMap = closureMap; this.closureMap = closureMap;
@ -337,6 +338,8 @@ export class FunctionCall extends AST {
} }
export class ASTWithSource { export class ASTWithSource {
ast:AST;
source:string;
constructor(ast:AST, source:string) { constructor(ast:AST, source:string) {
this.source = source; this.source = source;
this.ast = ast; this.ast = ast;
@ -344,6 +347,9 @@ export class ASTWithSource {
} }
export class TemplateBinding { export class TemplateBinding {
key:string;
name:string;
expression:ASTWithSource;
constructor(key:string, name:string, expression:ASTWithSource) { constructor(key:string, name:string, expression:ASTWithSource) {
this.key = key; this.key = key;
// only either name or expression will be filled. // only either name or expression will be filled.

View File

@ -9,6 +9,7 @@ export const TOKEN_TYPE_OPERATOR = 5;
export const TOKEN_TYPE_NUMBER = 6; export const TOKEN_TYPE_NUMBER = 6;
export class Lexer { export class Lexer {
text:string;
tokenize(text:string):List { tokenize(text:string):List {
var scanner = new _Scanner(text); var scanner = new _Scanner(text);
var tokens = []; var tokens = [];
@ -22,10 +23,10 @@ export class Lexer {
} }
export class Token { export class Token {
@FIELD('final index:int') index:int;
@FIELD('final type:int') type:int;
@FIELD('final _numValue:int') _numValue:number;
@FIELD('final _strValue:int') _strValue:string;
constructor(index:int, type:int, numValue:number, strValue:string) { constructor(index:int, type:int, numValue:number, strValue:string) {
/** /**
* NOTE: To ensure that this constructor creates the same hidden class each time, ensure that * NOTE: To ensure that this constructor creates the same hidden class each time, ensure that
@ -177,6 +178,7 @@ const $NBSP = 160;
export class ScannerError extends Error { export class ScannerError extends Error {
message:string;
constructor(message) { constructor(message) {
this.message = message; this.message = message;
} }
@ -187,10 +189,10 @@ export class ScannerError extends Error {
} }
class _Scanner { class _Scanner {
@FIELD('final input:String') input:string;
@FIELD('final length:int') length:int;
@FIELD('peek:int') peek:int;
@FIELD('index:int') index:int;
constructor(input:string) { constructor(input:string) {
this.input = input; this.input = input;

View File

@ -28,8 +28,8 @@ import {
var _implicitReceiver = new ImplicitReceiver(); var _implicitReceiver = new ImplicitReceiver();
export class Parser { export class Parser {
@FIELD('final _lexer:Lexer') _lexer:Lexer;
@FIELD('final _closureMap:ClosureMap') _closureMap:ClosureMap;
constructor(lexer:Lexer, closureMap:ClosureMap){ constructor(lexer:Lexer, closureMap:ClosureMap){
this._lexer = lexer; this._lexer = lexer;
this._closureMap = closureMap; this._closureMap = closureMap;
@ -54,11 +54,11 @@ export class Parser {
} }
class _ParseAST { class _ParseAST {
@FIELD('final input:string') input:string;
@FIELD('final tokens:List<Token>') tokens:List<Token>;
@FIELD('final closureMap:ClosureMap') closureMap:ClosureMap;
@FIELD('final parseAction:boolean') parseAction:boolean;
@FIELD('index:int') index:int;
constructor(input:string, tokens:List, closureMap:ClosureMap, parseAction:boolean) { constructor(input:string, tokens:List, closureMap:ClosureMap, parseAction:boolean) {
this.input = input; this.input = input;
this.tokens = tokens; this.tokens = tokens;

View File

@ -1,6 +1,6 @@
import {ProtoRecordRange, RecordRange} from './record_range'; import {ProtoRecordRange, RecordRange} from './record_range';
import {FIELD, isPresent, isBlank, int, StringWrapper, FunctionWrapper, BaseException} from 'facade/lang'; import {FIELD, isPresent, isBlank, int, StringWrapper, FunctionWrapper, BaseException} from 'facade/lang';
import {ListWrapper, MapWrapper} from 'facade/collection'; import {List, Map, ListWrapper, MapWrapper} from 'facade/collection';
import {ClosureMap} from 'change_detection/parser/closure_map'; import {ClosureMap} from 'change_detection/parser/closure_map';
var _fresh = new Object(); var _fresh = new Object();
@ -26,15 +26,16 @@ export const RECORD_FLAG_IMPLICIT_RECEIVER = 0x0200;
* real world numbers show that it does not provide significant benefits. * real world numbers show that it does not provide significant benefits.
*/ */
export class ProtoRecord { export class ProtoRecord {
@FIELD('final recordRange:ProtoRecordRange') recordRange:ProtoRecordRange;
@FIELD('final context:Object') _mode:int;
@FIELD('final funcOrValue:Object') context:any;
@FIELD('final arity:int') funcOrValue:any;
@FIELD('final dest') arity:int;
dest;
@FIELD('next:ProtoRecord') next:ProtoRecord;
@FIELD('prev:ProtoRecord') prev:ProtoRecord;
@FIELD('recordInConstruction:Record') recordInConstruction:Record;
constructor(recordRange:ProtoRecordRange, constructor(recordRange:ProtoRecordRange,
mode:int, mode:int,
funcOrValue, funcOrValue,
@ -74,30 +75,29 @@ export class ProtoRecord {
* - Keep this object as lean as possible. (Lean in number of fields) * - Keep this object as lean as possible. (Lean in number of fields)
*/ */
export class Record { export class Record {
@FIELD('final recordRange:RecordRange') recordRange:RecordRange;
@FIELD('final protoRecord:ProtoRecord') protoRecord:ProtoRecord;
@FIELD('next:Record') next:Record;
@FIELD('prev:Record') prev:Record;
/// This reference can change. /// This reference can change.
@FIELD('nextEnabled:Record') nextEnabled:Record;
/// This reference can change. /// This reference can change.
@FIELD('prevEnabled:Record') prevEnabled:Record;
@FIELD('dest:Record')
@FIELD('previousValue') previousValue;
@FIELD('currentValue') currentValue;
@FIELD('mode:int') _mode:int;
@FIELD('context') context;
@FIELD('funcOrValue') funcOrValue;
@FIELD('args:List') args:List;
// Opaque data which will be the target of notification. // Opaque data which will be the target of notification.
// If the object is instance of Record, then it it is directly processed // If the object is instance of Record, then it it is directly processed
// Otherwise it is the context used by WatchGroupDispatcher. // Otherwise it is the context used by WatchGroupDispatcher.
@FIELD('dest') dest;
constructor(recordRange:RecordRange, protoRecord:ProtoRecord, formatters:Map) { constructor(recordRange:RecordRange, protoRecord:ProtoRecord, formatters:Map) {
this.recordRange = recordRange; this.recordRange = recordRange;

View File

@ -11,15 +11,15 @@ import {
} from './record'; } from './record';
import {FIELD, IMPLEMENTS, isBlank, isPresent, int, toBool, autoConvertAdd, BaseException} from 'facade/lang'; import {FIELD, IMPLEMENTS, isBlank, isPresent, int, toBool, autoConvertAdd, BaseException} from 'facade/lang';
import {ListWrapper, MapWrapper} from 'facade/collection'; import {List, Map, ListWrapper, MapWrapper} from 'facade/collection';
import {AST, AccessMember, ImplicitReceiver, AstVisitor, LiteralPrimitive, import {AST, AccessMember, ImplicitReceiver, AstVisitor, LiteralPrimitive,
Binary, Formatter, MethodCall, FunctionCall, PrefixNot, Conditional, Binary, Formatter, MethodCall, FunctionCall, PrefixNot, Conditional,
LiteralArray, LiteralMap, KeyedAccess, Chain, Assignment} from './parser/ast'; LiteralArray, LiteralMap, KeyedAccess, Chain, Assignment} from './parser/ast';
export class ProtoRecordRange { export class ProtoRecordRange {
@FIELD('headRecord:ProtoRecord') headRecord:ProtoRecord;
@FIELD('tailRecord:ProtoRecord') tailRecord:ProtoRecord;
constructor() { constructor() {
this.headRecord = null; this.headRecord = null;
this.tailRecord = null; this.tailRecord = null;
@ -84,11 +84,11 @@ export class ProtoRecordRange {
} }
export class RecordRange { export class RecordRange {
@FIELD('final protoRecordRange:ProtoRecordRange') protoRecordRange:ProtoRecordRange;
@FIELD('final dispatcher:WatchGroupDispatcher') dispatcher:any; //WatchGroupDispatcher
@FIELD('final headRecord:Record') headRecord:Record;
@FIELD('final tailRecord:Record') tailRecord:Record;
@FIELD('final disabled:boolean') disabled:boolean;
// TODO(rado): the type annotation should be dispatcher:WatchGroupDispatcher. // TODO(rado): the type annotation should be dispatcher:WatchGroupDispatcher.
// but @Implements is not ready yet. // but @Implements is not ready yet.
constructor(protoRecordRange:ProtoRecordRange, dispatcher) { constructor(protoRecordRange:ProtoRecordRange, dispatcher) {
@ -270,6 +270,8 @@ export class WatchGroupDispatcher {
//todo: vsavkin: Create Array and Context destinations? //todo: vsavkin: Create Array and Context destinations?
class Destination { class Destination {
record:ProtoRecord;
position:int;
constructor(record:ProtoRecord, position:int) { constructor(record:ProtoRecord, position:int) {
this.record = record; this.record = record;
this.position = position; this.position = position;
@ -279,9 +281,9 @@ class Destination {
@IMPLEMENTS(AstVisitor) @IMPLEMENTS(AstVisitor)
class ProtoRecordCreator { class ProtoRecordCreator {
@FIELD('final protoRecordRange:ProtoRecordRange') protoRecordRange:ProtoRecordRange;
@FIELD('headRecord:ProtoRecord') headRecord:ProtoRecord;
@FIELD('tailRecord:ProtoRecord') tailRecord:ProtoRecord;
constructor(protoRecordRange) { constructor(protoRecordRange) {
this.protoRecordRange = protoRecordRange; this.protoRecordRange = protoRecordRange;
this.headRecord = null; this.headRecord = null;

View File

@ -189,6 +189,8 @@ export function main() {
} }
class Person { class Person {
name:string;
address:Address;
constructor(name:string, address:Address = null) { constructor(name:string, address:Address = null) {
this.name = name; this.name = name;
this.address = address; this.address = address;
@ -206,6 +208,7 @@ class Person {
} }
class Address { class Address {
city:string;
constructor(city:string) { constructor(city:string) {
this.city = city; this.city = city;
} }
@ -216,12 +219,15 @@ class Address {
} }
class TestData { class TestData {
a;
constructor(a) { constructor(a) {
this.a = a; this.a = a;
} }
} }
class LoggingDispatcher extends WatchGroupDispatcher { class LoggingDispatcher extends WatchGroupDispatcher {
log:List;
loggedValues:List;
constructor() { constructor() {
this.log = null; this.log = null;
this.loggedValues = null; this.loggedValues = null;

View File

@ -7,6 +7,9 @@ import {Formatter, LiteralPrimitive} from 'change_detection/parser/ast';
import {ClosureMap} from 'change_detection/parser/closure_map'; import {ClosureMap} from 'change_detection/parser/closure_map';
class TestData { class TestData {
a;
b;
fnReturnValue;
constructor(a, b, fnReturnValue) { constructor(a, b, fnReturnValue) {
this.a = a; this.a = a;
this.b = b; this.b = b;

View File

@ -0,0 +1,115 @@
import {ABSTRACT, CONST, normalizeBlank} from 'facade/lang';
import {List} from 'facade/collection';
import {TemplateConfig} from './template_config';
@ABSTRACT()
export class Directive {
selector:any; //string;
bind:any;
lightDomServices:any; //List;
implementsTypes:any; //List;
@CONST()
constructor({
selector,
bind,
lightDomServices,
implementsTypes
}:{
selector:string,
bind:any,
lightDomServices:List,
implementsTypes:List
}={})
{
this.selector = selector;
this.lightDomServices = lightDomServices;
this.implementsTypes = implementsTypes;
this.bind = bind;
}
}
export class Component extends Directive {
//TODO: vsavkin: uncomment it once the issue with defining fields in a sublass works
template:any; //TemplateConfig;
lightDomServices:any; //List;
shadowDomServices:any; //List;
componentServices:any; //List;
@CONST()
constructor({
selector,
bind,
template,
lightDomServices,
shadowDomServices,
componentServices,
implementsTypes
}:{
selector:String,
bind:Object,
template:TemplateConfig,
lightDomServices:List,
shadowDomServices:List,
componentServices:List,
implementsTypes:List
}={})
{
super({
selector: selector,
bind: bind,
lightDomServices: lightDomServices,
implementsTypes: implementsTypes});
this.template = template;
this.lightDomServices = lightDomServices;
this.shadowDomServices = shadowDomServices;
this.componentServices = componentServices;
}
}
export class Decorator extends Directive {
@CONST()
constructor({
selector,
bind,
lightDomServices,
implementsTypes
}:{
selector:string,
bind:any,
lightDomServices:List,
implementsTypes:List
}={})
{
super({
selector: selector,
bind: bind,
lightDomServices: lightDomServices,
implementsTypes: implementsTypes
});
}
}
export class Template extends Directive {
@CONST()
constructor({
selector,
bind,
lightDomServices,
implementsTypes
}:{
selector:string,
bind:any,
lightDomServices:List,
implementsTypes:List
}={})
{
super({
selector: selector,
bind: bind,
lightDomServices: lightDomServices,
implementsTypes: implementsTypes
});
}
}

View File

@ -1,71 +0,0 @@
import {Directive} from './directive';
import {CONST} from 'facade/lang';
export class Component extends Directive {
@CONST()
constructor({
selector,
bind,
template,
lightDomServices,
shadowDomServices,
componentServices,
implementsTypes
}:{
selector:String,
bind:Object,
template:TemplateConfig,
lightDomServices:List,
shadowDomServices:List,
componentServices:List,
implementsTypes:List
}={})
{
super({
selector: selector,
bind: bind,
lightDomServices: lightDomServices,
implementsTypes: implementsTypes});
this.template = template;
this.lightDomServices = lightDomServices;
this.shadowDomServices = shadowDomServices;
this.componentServices = componentServices;
}
}
///////////////////////////
/*
import 'package:angular/core.dart' as core;
@Component(
selector: 'example',
template: const TemplateConfig(
url: 'example.dart',
uses: const [core.CONFIG],
directives: const [CompA],
formatters: const [Stringify]
),
componentServices: [...],
shadowDomServices: [...]
implementsTypes: const [App]
)
class Example implements App {}
class CompA {}
@Formatter()
class Stringify {}
<CompA>
LightDOM:
</CompA>
CompA ShadowDOM:
<div>
<CompB></CompB>
</div>
CompB SHadowDOM:
<div></div>
*/

View File

@ -1,25 +0,0 @@
import {Directive} from './directive';
import {CONST} from 'facade/lang';
export class Decorator extends Directive {
@CONST()
constructor({
selector,
bind,
lightDomServices,
implementsTypes
}:{
selector:String,
bind:Object,
lightDomServices:List,
implementsTypes:List
}={})
{
super({
selector: selector,
bind: bind,
lightDomServices: lightDomServices,
implementsTypes: implementsTypes
});
}
}

View File

@ -1,25 +0,0 @@
import {ABSTRACT, CONST} from 'facade/lang';
import {List} from 'facade/collection';
@ABSTRACT()
export class Directive {
@CONST()
constructor({
selector,
bind,
lightDomServices,
implementsTypes
}:{
selector:String,
bind:Object,
lightDomServices:List,
implementsTypes:List
}={})
{
this.selector = selector;
this.lightDomServices = lightDomServices;
this.implementsTypes = implementsTypes;
this.bind = bind;
}
}

View File

@ -1,25 +0,0 @@
import {Directive} from './directive';
import {CONST} from 'facade/lang';
export class Template extends Directive {
@CONST()
constructor({
selector,
bind,
lightDomServices,
implementsTypes
}:{
selector:String,
bind:Object,
lightDomServices:List,
implementsTypes:List
}={})
{
super({
selector: selector,
bind: bind,
lightDomServices: lightDomServices,
implementsTypes: implementsTypes
});
}
}

View File

@ -1,7 +1,12 @@
import {ABSTRACT, CONST} from 'facade/lang'; import {ABSTRACT, CONST, Type} from 'facade/lang';
// import {Type, List} from 'facade/lang'; import {List} from 'facade/collection';
export class TemplateConfig { export class TemplateConfig {
url:any; //string;
inline:any; //string;
directives:any; //List<Type>;
formatters:any; //List<Type>;
source:any;//List<TemplateConfig>;
@CONST() @CONST()
constructor({ constructor({
url, url,
@ -10,8 +15,8 @@ export class TemplateConfig {
formatters, formatters,
source source
}: { }: {
url: String, url: string,
inline: String, inline: string,
directives: List<Type>, directives: List<Type>,
formatters: List<Type>, formatters: List<Type>,
source: List<TemplateConfig> source: List<TemplateConfig>

View File

@ -1,10 +1,12 @@
import {Type, FIELD} from 'facade/lang'; import {Type, FIELD} from 'facade/lang';
import {Directive} from '../annotations/directive' import {Directive} from '../annotations/annotations'
/** /**
* Combination of a type with the Directive annotation * Combination of a type with the Directive annotation
*/ */
export class AnnotatedType { export class AnnotatedType {
type:Type;
annotation:Directive;
constructor(type:Type, annotation:Directive) { constructor(type:Type, annotation:Directive) {
this.annotation = annotation; this.annotation = annotation;
this.type = type; this.type = type;

View File

@ -13,7 +13,7 @@ import {CompileElement} from './pipeline/compile_element';
import {createDefaultSteps} from './pipeline/default_steps'; import {createDefaultSteps} from './pipeline/default_steps';
import {TemplateLoader} from './template_loader'; import {TemplateLoader} from './template_loader';
import {AnnotatedType} from './annotated_type'; import {AnnotatedType} from './annotated_type';
import {Component} from '../annotations/component'; import {Component} from '../annotations/annotations';
/** /**
* The compiler loads and translates the html templates of components into * The compiler loads and translates the html templates of components into
@ -21,6 +21,10 @@ import {Component} from '../annotations/component';
* the CompilePipeline and the CompileSteps. * the CompilePipeline and the CompileSteps.
*/ */
export class Compiler { export class Compiler {
_templateLoader:TemplateLoader;
_reflector: Reflector;
_parser:Parser;
_closureMap:ClosureMap;
constructor(templateLoader:TemplateLoader, reflector: Reflector, parser:Parser, closureMap:ClosureMap) { constructor(templateLoader:TemplateLoader, reflector: Reflector, parser:Parser, closureMap:ClosureMap) {
this._templateLoader = templateLoader; this._templateLoader = templateLoader;
this._reflector = reflector; this._reflector = reflector;
@ -53,7 +57,7 @@ export class Compiler {
// - templateRoot string // - templateRoot string
// - precompiled template // - precompiled template
// - ProtoView // - ProtoView
var annotation: Component = component.annotation; var annotation:any = component.annotation;
templateRoot = DOM.createTemplate(annotation.template.inline); templateRoot = DOM.createTemplate(annotation.template.inline);
} }
var pipeline = new CompilePipeline(this.createSteps(component)); var pipeline = new CompilePipeline(this.createSteps(component));

View File

@ -2,16 +2,17 @@ import {ProtoElementInjector} from './element_injector';
import {FIELD} from 'facade/lang'; import {FIELD} from 'facade/lang';
import {MapWrapper} from 'facade/collection'; import {MapWrapper} from 'facade/collection';
import {AnnotatedType} from './annotated_type'; import {AnnotatedType} from './annotated_type';
// Comment out as dartanalyzer does not look into @FIELD import {List, Map} from 'facade/collection';
// import {List} from 'facade/collection'; import {ProtoView} from './view';
// import {ProtoView} from './view';
export class ElementBinder { export class ElementBinder {
@FIELD('final protoElementInjector:ProtoElementInjector') protoElementInjector:ProtoElementInjector;
@FIELD('final componentDirective:AnnotatedType') componentDirective:AnnotatedType;
@FIELD('final templateDirective:AnnotatedType') templateDirective:AnnotatedType;
@FIELD('final textNodeIndices:List<int>') textNodeIndices:List<int>;
@FIELD('hasElementPropertyBindings:bool') hasElementPropertyBindings:boolean;
nestedProtoView: ProtoView;
events:Map;
constructor( constructor(
protoElementInjector: ProtoElementInjector, componentDirective:AnnotatedType, templateDirective:AnnotatedType) { protoElementInjector: ProtoElementInjector, componentDirective:AnnotatedType, templateDirective:AnnotatedType) {
this.protoElementInjector = protoElementInjector; this.protoElementInjector = protoElementInjector;

View File

@ -15,6 +15,8 @@ var _undefined = new Object();
var _staticKeys; var _staticKeys;
class StaticKeys { class StaticKeys {
viewId:int;
ngElementId:int;
constructor() { constructor() {
//TODO: vsavkin Key.annotate(Key.get(View), 'static') //TODO: vsavkin Key.annotate(Key.get(View), 'static')
this.viewId = Key.get(View).id; this.viewId = Key.get(View).id;
@ -28,11 +30,11 @@ class StaticKeys {
} }
class TreeNode { class TreeNode {
@FIELD('_parent:TreeNode') _parent:TreeNode;
@FIELD('_head:TreeNode') _head:TreeNode;
@FIELD('_tail:TreeNode') _tail:TreeNode;
@FIELD('_next:TreeNode') _next:TreeNode;
@FIELD('_prev:TreeNode') _prev:TreeNode;
constructor(parent:TreeNode) { constructor(parent:TreeNode) {
this._parent = parent; this._parent = parent;
this._head = null; this._head = null;
@ -71,6 +73,7 @@ class TreeNode {
} }
class DirectiveDependency extends Dependency { class DirectiveDependency extends Dependency {
depth:int;
constructor(key:Key, asPromise:boolean, lazy:boolean, properties:List, depth:int) { constructor(key:Key, asPromise:boolean, lazy:boolean, properties:List, depth:int) {
super(key, asPromise, lazy, properties); super(key, asPromise, lazy, properties);
this.depth = depth; this.depth = depth;
@ -90,9 +93,9 @@ class DirectiveDependency extends Dependency {
} }
export class PreBuiltObjects { export class PreBuiltObjects {
@FIELD('final view:View') view:View;
@FIELD('final element:NgElement') element:NgElement;
constructor(view, element:NgElement) { constructor(view:View, element:NgElement) {
this.view = view; this.view = view;
this.element = element; this.element = element;
} }
@ -119,30 +122,30 @@ ElementInjector:
*/ */
export class ProtoElementInjector { export class ProtoElementInjector {
@FIELD('_binding0:Binding') _binding0:Binding;
@FIELD('_binding1:Binding') _binding1:Binding;
@FIELD('_binding2:Binding') _binding2:Binding;
@FIELD('_binding3:Binding') _binding3:Binding;
@FIELD('_binding4:Binding') _binding4:Binding;
@FIELD('_binding5:Binding') _binding5:Binding;
@FIELD('_binding6:Binding') _binding6:Binding;
@FIELD('_binding7:Binding') _binding7:Binding;
@FIELD('_binding8:Binding') _binding8:Binding;
@FIELD('_binding9:Binding') _binding9:Binding;
@FIELD('_binding0IsComponent:int') _binding0IsComponent:boolean;
@FIELD('_key0:int') _keyId0:int;
@FIELD('_key1:int') _keyId1:int;
@FIELD('_key2:int') _keyId2:int;
@FIELD('_key3:int') _keyId3:int;
@FIELD('_key4:int') _keyId4:int;
@FIELD('_key5:int') _keyId5:int;
@FIELD('_key6:int') _keyId6:int;
@FIELD('_key7:int') _keyId7:int;
@FIELD('_key8:int') _keyId8:int;
@FIELD('_key9:int') _keyId9:int;
@FIELD('final parent:ProtoElementInjector') parent:ProtoElementInjector;
@FIELD('final index:int') index:int;
@FIELD('view:View') view:View;
constructor(parent:ProtoElementInjector, index:int, bindings:List, firstBindingIsComponent:boolean = false) { constructor(parent:ProtoElementInjector, index:int, bindings:List, firstBindingIsComponent:boolean = false) {
this.parent = parent; this.parent = parent;
this.index = index; this.index = index;
@ -194,21 +197,23 @@ export class ProtoElementInjector {
} }
export class ElementInjector extends TreeNode { export class ElementInjector extends TreeNode {
@FIELD('_proto:ProtoElementInjector') _proto:ProtoElementInjector;
@FIELD('_lightDomAppInjector:Injector') _lightDomAppInjector:Injector;
@FIELD('_shadowDomAppInjector:Injector') _shadowDomAppInjector:Injector;
@FIELD('_host:ElementInjector') _host:ElementInjector;
@FIELD('_obj0:Object') _obj0:any;
@FIELD('_obj1:Object') _obj1:any;
@FIELD('_obj2:Object') _obj2:any;
@FIELD('_obj3:Object') _obj3:any;
@FIELD('_obj4:Object') _obj4:any;
@FIELD('_obj5:Object') _obj5:any;
@FIELD('_obj6:Object') _obj6:any;
@FIELD('_obj7:Object') _obj7:any;
@FIELD('_obj8:Object') _obj8:any;
@FIELD('_obj9:Object') _obj9:any;
@FIELD('_view:View') _view:View;
_preBuiltObjects;
_constructionCounter;
constructor(proto:ProtoElementInjector, parent:ElementInjector, host:ElementInjector) { constructor(proto:ProtoElementInjector, parent:ElementInjector, host:ElementInjector) {
super(parent); super(parent);
if (isPresent(parent) && isPresent(host)) { if (isPresent(parent) && isPresent(host)) {
@ -441,6 +446,7 @@ export class ElementInjector extends TreeNode {
} }
class OutOfBoundsAccess extends Error { class OutOfBoundsAccess extends Error {
message:string;
constructor(index) { constructor(index) {
this.message = `Index ${index} is out-of-bounds.`; this.message = `Index ${index} is out-of-bounds.`;
} }

View File

@ -1,12 +1,18 @@
import {ListWrapper} from 'facade/collection'; import {List, ListWrapper} from 'facade/collection';
import {DOM} from 'facade/dom'; import {DOM} from 'facade/dom';
import {CompileElement} from './compile_element'; import {CompileElement} from './compile_element';
import {CompileStep} from './compile_step';
/** /**
* Controls the processing order of elements. * Controls the processing order of elements.
* Right now it only allows to add a parent element. * Right now it only allows to add a parent element.
*/ */
export class CompileControl { export class CompileControl {
_steps:List<CompileStep>;
_currentStepIndex:number;
_parent:CompileElement;
_current:CompileElement;
_results;
constructor(steps) { constructor(steps) {
this._steps = steps; this._steps = steps;
this._currentStepIndex = 0; this._currentStepIndex = 0;

View File

@ -2,9 +2,12 @@ import {List, Map, ListWrapper, MapWrapper} from 'facade/collection';
import {Element, DOM} from 'facade/dom'; import {Element, DOM} from 'facade/dom';
import {int, isBlank, isPresent} from 'facade/lang'; import {int, isBlank, isPresent} from 'facade/lang';
import {AnnotatedType} from '../annotated_type'; import {AnnotatedType} from '../annotated_type';
import {Decorator} from '../../annotations/decorator'; import {Decorator} from '../../annotations/annotations';
import {Component} from '../../annotations/component'; import {Component} from '../../annotations/annotations';
import {Template} from '../../annotations/template'; import {Template} from '../../annotations/annotations';
import {ElementBinder} from '../element_binder';
import {ProtoElementInjector} from '../element_injector';
import {ProtoView} from '../view';
import {ASTWithSource} from 'change_detection/parser/ast'; import {ASTWithSource} from 'change_detection/parser/ast';
@ -14,6 +17,21 @@ import {ASTWithSource} from 'change_detection/parser/ast';
* by the CompileSteps starting out with the pure HTMLElement. * by the CompileSteps starting out with the pure HTMLElement.
*/ */
export class CompileElement { export class CompileElement {
element:Element;
_attrs:Map;
_classList:List;
textNodeBindings:Map;
propertyBindings:Map;
eventBindings:Map;
variableBindings:Map;
decoratorDirectives:List<AnnotatedType>;
templateDirective:AnnotatedType;
componentDirective:AnnotatedType;
isViewRoot:boolean;
hasBindings:boolean;
inheritedProtoView:ProtoView;
inheritedProtoElementInjector:ProtoElementInjector;
inheritedElementBinder:ElementBinder;
constructor(element:Element) { constructor(element:Element) {
this.element = element; this.element = element;
this._attrs = null; this._attrs = null;

View File

@ -10,6 +10,7 @@ import {AnnotatedType} from '../annotated_type';
* all elements in a template. * all elements in a template.
*/ */
export class CompilePipeline { export class CompilePipeline {
_control:CompileControl;
constructor(steps:List<CompileStep>) { constructor(steps:List<CompileStep>) {
this._control = new CompileControl(steps); this._control = new CompileControl(steps);
} }

View File

@ -5,8 +5,8 @@ import {SelectorMatcher} from '../selector';
import {CssSelector} from '../selector'; import {CssSelector} from '../selector';
import {AnnotatedType} from '../annotated_type'; import {AnnotatedType} from '../annotated_type';
import {Template} from '../../annotations/template'; import {Template} from '../../annotations/annotations';
import {Component} from '../../annotations/component'; import {Component} from '../../annotations/annotations';
import {CompileStep} from './compile_step'; import {CompileStep} from './compile_step';
import {CompileElement} from './compile_element'; import {CompileElement} from './compile_element';
import {CompileControl} from './compile_control'; import {CompileControl} from './compile_control';
@ -28,6 +28,7 @@ import {Reflector} from '../reflector';
* in the property bindings) * in the property bindings)
*/ */
export class DirectiveParser extends CompileStep { export class DirectiveParser extends CompileStep {
_selectorMatcher:SelectorMatcher;
constructor(directives:List<AnnotatedType>) { constructor(directives:List<AnnotatedType>) {
this._selectorMatcher = new SelectorMatcher(); this._selectorMatcher = new SelectorMatcher();
for (var i=0; i<directives.length; i++) { for (var i=0; i<directives.length; i++) {

View File

@ -6,8 +6,7 @@ import {Parser} from 'change_detection/parser/parser';
import {ClosureMap} from 'change_detection/parser/closure_map'; import {ClosureMap} from 'change_detection/parser/closure_map';
import {ProtoRecordRange} from 'change_detection/record_range'; import {ProtoRecordRange} from 'change_detection/record_range';
import {Directive} from '../../annotations/directive'; import {Component, Directive} from '../../annotations/annotations';
import {Component} from '../../annotations/component';
import {AnnotatedType} from '../annotated_type'; import {AnnotatedType} from '../annotated_type';
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from '../view'; import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from '../view';
import {ProtoElementInjector} from '../element_injector'; import {ProtoElementInjector} from '../element_injector';
@ -44,12 +43,13 @@ import {CompileControl} from './compile_control';
* with the flag `isViewRoot`. * with the flag `isViewRoot`.
*/ */
export class ElementBinderBuilder extends CompileStep { export class ElementBinderBuilder extends CompileStep {
_closureMap:ClosureMap;
constructor(closureMap:ClosureMap) { constructor(closureMap:ClosureMap) {
this._closureMap = closureMap; this._closureMap = closureMap;
} }
process(parent:CompileElement, current:CompileElement, control:CompileControl) { process(parent:CompileElement, current:CompileElement, control:CompileControl) {
var elementBinder; var elementBinder = null;
if (current.hasBindings) { if (current.hasBindings) {
var protoView = current.inheritedProtoView; var protoView = current.inheritedProtoView;
elementBinder = protoView.bindElement(current.inheritedProtoElementInjector, elementBinder = protoView.bindElement(current.inheritedProtoElementInjector,

View File

@ -23,6 +23,7 @@ var BIND_NAME_REGEXP = RegExpWrapper.create('^(?:(?:(bind)|(let)|(on))-(.+))|\\[
* - CompileElement#variableBindings * - CompileElement#variableBindings
*/ */
export class PropertyBindingParser extends CompileStep { export class PropertyBindingParser extends CompileStep {
_parser:Parser;
constructor(parser:Parser) { constructor(parser:Parser) {
this._parser = parser; this._parser = parser;
} }

View File

@ -46,6 +46,7 @@ export function interpolationToExpression(value:string):string {
* - CompileElement#textNodeBindings * - CompileElement#textNodeBindings
*/ */
export class TextInterpolationParser extends CompileStep { export class TextInterpolationParser extends CompileStep {
_parser:Parser;
constructor(parser:Parser) { constructor(parser:Parser) {
this._parser = parser; this._parser = parser;
} }

View File

@ -19,6 +19,7 @@ import {CompileControl} from './compile_control';
* - CompileElement#propertyBindings * - CompileElement#propertyBindings
*/ */
export class ViewSplitter extends CompileStep { export class ViewSplitter extends CompileStep {
_parser:Parser;
constructor(parser:Parser) { constructor(parser:Parser) {
this._parser = parser; this._parser = parser;
} }

View File

@ -1,7 +1,7 @@
library facade.compiler.reflector; library facade.compiler.reflector;
import 'dart:mirrors'; import 'dart:mirrors';
import '../annotations/directive.dart'; import '../annotations/annotations.dart';
import './annotated_type.dart'; import './annotated_type.dart';
import 'package:facade/lang.dart'; import 'package:facade/lang.dart';

View File

@ -1,5 +1,5 @@
import {Type, isPresent, BaseException} from 'facade/lang'; import {Type, isPresent, BaseException} from 'facade/lang';
import {Directive} from '../annotations/directive'; import {Directive} from '../annotations/annotations';
import {AnnotatedType} from './annotated_type'; import {AnnotatedType} from './annotated_type';
/** /**

View File

@ -16,6 +16,9 @@ var _SELECTOR_REGEXP =
* of selecting subsets out of them. * of selecting subsets out of them.
*/ */
export class CssSelector { export class CssSelector {
element:string;
classNames:List;
attrs:List;
static parse(selector:string):CssSelector { static parse(selector:string):CssSelector {
var cssSelector = new CssSelector(); var cssSelector = new CssSelector();
var matcher = RegExpWrapper.matcher(_SELECTOR_REGEXP, selector); var matcher = RegExpWrapper.matcher(_SELECTOR_REGEXP, selector);
@ -91,6 +94,13 @@ export class CssSelector {
* are contained in a given CssSelector. * are contained in a given CssSelector.
*/ */
export class SelectorMatcher { export class SelectorMatcher {
_selectables:List;
_elementMap:Map;
_elementPartialMap:Map;
_classMap:Map;
_classPartialMap:Map;
_attrValueMap:Map;
_attrValuePartialMap:Map;
constructor() { constructor() {
this._selectables = ListWrapper.create(); this._selectables = ListWrapper.create();

View File

@ -5,7 +5,7 @@ import {Promise} from 'facade/async';
* Strategy to load component templates. * Strategy to load component templates.
*/ */
export class TemplateLoader { export class TemplateLoader {
load(url:String):Promise<Document> { load(url:string):Promise<Document> {
return null; return null;
} }
} }

View File

@ -1,5 +1,5 @@
import {DOM, Element, Node, Text, DocumentFragment, TemplateElement} from 'facade/dom'; import {DOM, Element, Node, Text, DocumentFragment, TemplateElement} from 'facade/dom';
import {ListWrapper, MapWrapper} from 'facade/collection'; import {ListWrapper, MapWrapper, List} from 'facade/collection';
import {ProtoRecordRange, RecordRange, WatchGroupDispatcher} from 'change_detection/record_range'; import {ProtoRecordRange, RecordRange, WatchGroupDispatcher} from 'change_detection/record_range';
import {Record} from 'change_detection/record'; import {Record} from 'change_detection/record';
import {AST} from 'change_detection/parser/ast'; import {AST} from 'change_detection/parser/ast';
@ -9,7 +9,6 @@ import {ElementBinder} from './element_binder';
import {AnnotatedType} from './annotated_type'; import {AnnotatedType} from './annotated_type';
import {SetterFn} from 'change_detection/parser/closure_map'; import {SetterFn} from 'change_detection/parser/closure_map';
import {FIELD, IMPLEMENTS, int, isPresent, isBlank} from 'facade/lang'; import {FIELD, IMPLEMENTS, int, isPresent, isBlank} from 'facade/lang';
import {List} from 'facade/collection';
import {Injector} from 'di/di'; import {Injector} from 'di/di';
import {NgElement} from 'core/dom/element'; import {NgElement} from 'core/dom/element';
@ -21,16 +20,16 @@ const NG_BINDING_CLASS = 'ng-binding';
@IMPLEMENTS(WatchGroupDispatcher) @IMPLEMENTS(WatchGroupDispatcher)
export class View { export class View {
/// This list matches the _nodes list. It is sparse, since only Elements have ElementInjector /// This list matches the _nodes list. It is sparse, since only Elements have ElementInjector
@FIELD('final rootElementInjectors:List<ElementInjector>') rootElementInjectors:List<ElementInjector>;
@FIELD('final elementInjectors:List<ElementInjector>') elementInjectors:List<ElementInjector>;
@FIELD('final bindElements:List<Element>') bindElements:List<Element>;
@FIELD('final textNodes:List<Text>') textNodes:List<Text>;
@FIELD('final recordRange:RecordRange') recordRange:RecordRange;
/// When the view is part of render tree, the DocumentFragment is empty, which is why we need /// When the view is part of render tree, the DocumentFragment is empty, which is why we need
/// to keep track of the nodes. /// to keep track of the nodes.
@FIELD('final nodes:List<Node>') nodes:List<Node>;
@FIELD('final onChangeDispatcher:OnChangeDispatcher') onChangeDispatcher:OnChangeDispatcher;
@FIELD('childViews: List<View>') childViews: List<View>;
constructor(nodes:List<Node>, elementInjectors:List, constructor(nodes:List<Node>, elementInjectors:List,
rootElementInjectors:List, textNodes:List, bindElements:List, rootElementInjectors:List, textNodes:List, bindElements:List,
protoRecordRange:ProtoRecordRange, context) { protoRecordRange:ProtoRecordRange, context) {
@ -70,9 +69,12 @@ export class View {
} }
export class ProtoView { export class ProtoView {
@FIELD('final element:Element') element:Element;
@FIELD('final elementBinders:List<ElementBinder>') elementBinders:List<ElementBinder>;
@FIELD('final protoRecordRange:ProtoRecordRange') protoRecordRange:ProtoRecordRange;
variableBindings: Map;
textNodesWithBindingCount:int;
elementsWithBindingCount:int;
constructor( constructor(
template:Element, template:Element,
protoRecordRange:ProtoRecordRange) { protoRecordRange:ProtoRecordRange) {
@ -299,8 +301,8 @@ export class ProtoView {
} }
export class ElementPropertyMemento { export class ElementPropertyMemento {
@FIELD('final _elementIndex:int') _elementIndex:int;
@FIELD('final _propertyName:string') _propertyName:string;
constructor(elementIndex:int, propertyName:string) { constructor(elementIndex:int, propertyName:string) {
this._elementIndex = elementIndex; this._elementIndex = elementIndex;
this._propertyName = propertyName; this._propertyName = propertyName;
@ -313,10 +315,10 @@ export class ElementPropertyMemento {
} }
export class DirectivePropertyMemento { export class DirectivePropertyMemento {
@FIELD('final _elementInjectorIndex:int') _elementInjectorIndex:int;
@FIELD('final _directiveIndex:int') _directiveIndex:int;
@FIELD('final _setterName:string') _setterName:string;
@FIELD('final _setter:SetterFn') _setter:SetterFn;
constructor( constructor(
elementInjectorIndex:number, elementInjectorIndex:number,
directiveIndex:number, directiveIndex:number,
@ -341,8 +343,8 @@ export class DirectivePropertyMemento {
// notify is called by change detection, but done is called by our wrapper on detect changes. // notify is called by change detection, but done is called by our wrapper on detect changes.
export class OnChangeDispatcher { export class OnChangeDispatcher {
@FIELD('_lastView:View') _lastView:View;
@FIELD('_lastTarget:DirectivePropertyMemento') _lastTarget:DirectivePropertyMemento;
constructor() { constructor() {
this._lastView = null; this._lastView = null;
this._lastTarget = null; this._lastTarget = null;

View File

@ -1,9 +1,7 @@
/** /**
* Define public API for Angular here * Define public API for Angular here
*/ */
export * from './annotations/directive'; export * from './annotations/annotations';
export * from './annotations/decorator';
export * from './annotations/component';
export * from './annotations/template_config'; export * from './annotations/template_config';
export * from './application'; export * from './application';

View File

@ -1,4 +1,7 @@
import {Element} from 'facade/dom';
export class NgElement { export class NgElement {
domElement:Element;
constructor(domElement) { constructor(domElement) {
this.domElement = domElement; this.domElement = domElement;
} }

View File

@ -1,16 +1,18 @@
import {FIELD} from 'facade/lang'; import {FIELD} from 'facade/lang';
import {OnChangeDispatcher} from '../compiler/view';
import {ChangeDetector} from 'change_detection/change_detector';
export class LifeCycle { export class LifeCycle {
@FIELD('final _changeDetection:ChangeDetection') _changeDetector:ChangeDetector;
@FIELD('final _onChangeDispatcher:OnChangeDispatcher') _onChangeDispatcher:OnChangeDispatcher;
constructor() { constructor() {
this._changeDetection = null; this._changeDetector = null;
this._onChangeDispatcher = null; this._onChangeDispatcher = null;
} }
digest() { digest() {
_changeDetection.detectChanges(); _changeDetector.detectChanges();
_onChangeDispatcher.done(); _onChangeDispatcher.done();
} }
} }

View File

@ -1,7 +1,7 @@
import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach} from 'test_lib/test_lib'; import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach} from 'test_lib/test_lib';
import {bootstrap, appDocumentToken, appElementToken, documentDependentBindings} import {bootstrap, appDocumentToken, appElementToken, documentDependentBindings}
from 'core/application'; from 'core/application';
import {Component} from 'core/annotations/component'; import {Component} from 'core/annotations/annotations';
import {DOM} from 'facade/dom'; import {DOM} from 'facade/dom';
import {ListWrapper} from 'facade/collection'; import {ListWrapper} from 'facade/collection';
import {PromiseWrapper} from 'facade/async'; import {PromiseWrapper} from 'facade/async';
@ -16,6 +16,7 @@ import {TemplateConfig} from 'core/annotations/template_config';
}) })
}) })
class HelloRootCmp { class HelloRootCmp {
greeting:string;
constructor() { constructor() {
this.greeting = 'hello'; this.greeting = 'hello';
} }
@ -29,6 +30,7 @@ class HelloRootCmp {
}) })
}) })
class HelloRootCmp2 { class HelloRootCmp2 {
greeting:string;
constructor() { constructor() {
this.greeting = 'hello'; this.greeting = 'hello';
} }

View File

@ -6,7 +6,7 @@ import {Compiler} from 'core/compiler/compiler';
import {ProtoView} from 'core/compiler/view'; import {ProtoView} from 'core/compiler/view';
import {Reflector} from 'core/compiler/reflector'; import {Reflector} from 'core/compiler/reflector';
import {TemplateLoader} from 'core/compiler/template_loader'; import {TemplateLoader} from 'core/compiler/template_loader';
import {Component} from 'core/annotations/component'; import {Component} from 'core/annotations/annotations';
import {TemplateConfig} from 'core/annotations/template_config'; import {TemplateConfig} from 'core/annotations/template_config';
import {CompileElement} from 'core/compiler/pipeline/compile_element'; import {CompileElement} from 'core/compiler/pipeline/compile_element';
import {CompileStep} from 'core/compiler/pipeline/compile_step' import {CompileStep} from 'core/compiler/pipeline/compile_step'
@ -98,6 +98,7 @@ class MainComponent {}
class NestedComponent {} class NestedComponent {}
class TestableCompiler extends Compiler { class TestableCompiler extends Compiler {
steps:List;
constructor(templateLoader:TemplateLoader, reflector:Reflector, parser, closureMap, steps:List<CompileStep>) { constructor(templateLoader:TemplateLoader, reflector:Reflector, parser, closureMap, steps:List<CompileStep>) {
super(templateLoader, reflector, parser, closureMap); super(templateLoader, reflector, parser, closureMap);
this.steps = steps; this.steps = steps;
@ -108,6 +109,7 @@ class TestableCompiler extends Compiler {
} }
class MockStep extends CompileStep { class MockStep extends CompileStep {
processClosure:Function;
constructor(process) { constructor(process) {
this.processClosure = process; this.processClosure = process;
} }

View File

@ -1,14 +1,19 @@
import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach} from 'test_lib/test_lib'; import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach, FakeObject} from 'test_lib/test_lib';
import {isBlank, isPresent, FIELD, IMPLEMENTS} from 'facade/lang'; import {isBlank, isPresent, FIELD, IMPLEMENTS} from 'facade/lang';
import {ListWrapper, MapWrapper, List} from 'facade/collection'; import {ListWrapper, MapWrapper, List} from 'facade/collection';
import {ProtoElementInjector, PreBuiltObjects} from 'core/compiler/element_injector'; import {ProtoElementInjector, PreBuiltObjects} from 'core/compiler/element_injector';
import {Parent, Ancestor} from 'core/annotations/visibility'; import {Parent, Ancestor} from 'core/annotations/visibility';
import {Injector, Inject, bind} from 'di/di'; import {Injector, Inject, bind} from 'di/di';
import {View} from 'core/compiler/view'; import {View} from 'core/compiler/view';
import {ProtoRecordRange} from 'change_detection/record_range';
import {NgElement} from 'core/dom/element'; import {NgElement} from 'core/dom/element';
@IMPLEMENTS(View) //TODO: vsavkin: use a spy object
class DummyView {} class DummyView extends View {
constructor() {
super(null, null, null, null, null, new ProtoRecordRange(), null);
}
}
class Directive { class Directive {
} }
@ -18,28 +23,28 @@ class SomeOtherDirective {
} }
class NeedsDirective { class NeedsDirective {
@FIELD("dependency:Directive") dependency:Directive;
constructor(dependency:Directive){ constructor(dependency:Directive){
this.dependency = dependency; this.dependency = dependency;
} }
} }
class NeedDirectiveFromParent { class NeedDirectiveFromParent {
@FIELD("dependency:Directive") dependency:Directive;
constructor(@Parent() dependency:Directive){ constructor(@Parent() dependency:Directive){
this.dependency = dependency; this.dependency = dependency;
} }
} }
class NeedDirectiveFromAncestor { class NeedDirectiveFromAncestor {
@FIELD("dependency:Directive") dependency:Directive;
constructor(@Ancestor() dependency:Directive){ constructor(@Ancestor() dependency:Directive){
this.dependency = dependency; this.dependency = dependency;
} }
} }
class NeedsService { class NeedsService {
@FIELD("service:Object") service:any;
constructor(@Inject("service") service) { constructor(@Inject("service") service) {
this.service = service; this.service = service;
} }
@ -54,7 +59,7 @@ class B_Needs_A {
} }
class NeedsView { class NeedsView {
@FIELD("view:Object") view:any;
constructor(@Inject(View) view) { constructor(@Inject(View) view) {
this.view = view; this.view = view;
} }

View File

@ -11,8 +11,8 @@ import {Lexer} from 'change_detection/parser/lexer';
import {Compiler} from 'core/compiler/compiler'; import {Compiler} from 'core/compiler/compiler';
import {Reflector} from 'core/compiler/reflector'; import {Reflector} from 'core/compiler/reflector';
import {Component} from 'core/annotations/component'; import {Component} from 'core/annotations/annotations';
import {Decorator} from 'core/annotations/decorator'; import {Decorator} from 'core/annotations/annotations';
import {TemplateConfig} from 'core/annotations/template_config'; import {TemplateConfig} from 'core/annotations/template_config';
export function main() { export function main() {
@ -87,6 +87,7 @@ export function main() {
bind: {'elprop':'dirProp'} bind: {'elprop':'dirProp'}
}) })
class MyDir { class MyDir {
dirProp:string;
constructor() { constructor() {
this.dirProp = ''; this.dirProp = '';
} }
@ -98,6 +99,7 @@ class MyDir {
}) })
}) })
class MyComp { class MyComp {
ctxProp:string;
constructor() { constructor() {
this.ctxProp = 'initial value'; this.ctxProp = 'initial value';
} }
@ -112,12 +114,14 @@ class MyComp {
}) })
}) })
class ChildComp { class ChildComp {
ctxProp:string;
constructor(service: MyService) { constructor(service: MyService) {
this.ctxProp = service.greeting; this.ctxProp = service.greeting;
} }
} }
class MyService { class MyService {
greeting:string;
constructor() { constructor() {
this.greeting = 'hello'; this.greeting = 'hello';
} }

View File

@ -7,9 +7,9 @@ import {CompileStep} from 'core/compiler/pipeline/compile_step';
import {CompileElement} from 'core/compiler/pipeline/compile_element'; import {CompileElement} from 'core/compiler/pipeline/compile_element';
import {CompileControl} from 'core/compiler/pipeline/compile_control'; import {CompileControl} from 'core/compiler/pipeline/compile_control';
import {DOM} from 'facade/dom'; import {DOM} from 'facade/dom';
import {Component} from 'core/annotations/component'; import {Component} from 'core/annotations/annotations';
import {Decorator} from 'core/annotations/decorator'; import {Decorator} from 'core/annotations/annotations';
import {Template} from 'core/annotations/template'; import {Template} from 'core/annotations/annotations';
import {TemplateConfig} from 'core/annotations/template_config'; import {TemplateConfig} from 'core/annotations/template_config';
import {Reflector} from 'core/compiler/reflector'; import {Reflector} from 'core/compiler/reflector';
import {Parser} from 'change_detection/parser/parser'; import {Parser} from 'change_detection/parser/parser';
@ -165,6 +165,7 @@ export function main() {
} }
class MockStep extends CompileStep { class MockStep extends CompileStep {
processClosure:Function;
constructor(process) { constructor(process) {
this.processClosure = process; this.processClosure = process;
} }

View File

@ -9,9 +9,9 @@ import {CompileElement} from 'core/compiler/pipeline/compile_element';
import {CompileStep} from 'core/compiler/pipeline/compile_step' import {CompileStep} from 'core/compiler/pipeline/compile_step'
import {CompileControl} from 'core/compiler/pipeline/compile_control'; import {CompileControl} from 'core/compiler/pipeline/compile_control';
import {Decorator} from 'core/annotations/decorator'; import {Decorator} from 'core/annotations/annotations';
import {Template} from 'core/annotations/template'; import {Template} from 'core/annotations/annotations';
import {Component} from 'core/annotations/component'; import {Component} from 'core/annotations/annotations';
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'core/compiler/view'; import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'core/compiler/view';
import {ProtoElementInjector} from 'core/compiler/element_injector'; import {ProtoElementInjector} from 'core/compiler/element_injector';
import {Reflector} from 'core/compiler/reflector'; import {Reflector} from 'core/compiler/reflector';
@ -265,6 +265,7 @@ class SomeDecoratorDirective {
bind: {'boundprop1': 'decorProp'} bind: {'boundprop1': 'decorProp'}
}) })
class SomeDecoratorDirectiveWithBinding { class SomeDecoratorDirectiveWithBinding {
decorProp;
constructor() { constructor() {
this.decorProp = null; this.decorProp = null;
} }
@ -278,6 +279,7 @@ class SomeTemplateDirective {
bind: {'boundprop2': 'templProp'} bind: {'boundprop2': 'templProp'}
}) })
class SomeTemplateDirectiveWithBinding { class SomeTemplateDirectiveWithBinding {
templProp;
constructor() { constructor() {
this.templProp = null; this.templProp = null;
} }
@ -291,12 +293,16 @@ class SomeComponentDirective {
bind: {'boundprop3': 'compProp'} bind: {'boundprop3': 'compProp'}
}) })
class SomeComponentDirectiveWithBinding { class SomeComponentDirectiveWithBinding {
compProp;
constructor() { constructor() {
this.compProp = null; this.compProp = null;
} }
} }
class Context { class Context {
prop1;
prop2;
prop3;
constructor() { constructor() {
this.prop1 = null; this.prop1 = null;
this.prop2 = null; this.prop2 = null;
@ -305,6 +311,7 @@ class Context {
} }
class MockStep extends CompileStep { class MockStep extends CompileStep {
processClosure:Function;
constructor(process) { constructor(process) {
this.processClosure = process; this.processClosure = process;
} }

View File

@ -9,9 +9,9 @@ import {CompileElement} from 'core/compiler/pipeline/compile_element';
import {CompileStep} from 'core/compiler/pipeline/compile_step' import {CompileStep} from 'core/compiler/pipeline/compile_step'
import {CompileControl} from 'core/compiler/pipeline/compile_control'; import {CompileControl} from 'core/compiler/pipeline/compile_control';
import {Reflector} from 'core/compiler/reflector'; import {Reflector} from 'core/compiler/reflector';
import {Template} from 'core/annotations/template'; import {Template} from 'core/annotations/annotations';
import {Decorator} from 'core/annotations/decorator'; import {Decorator} from 'core/annotations/annotations';
import {Component} from 'core/annotations/component'; import {Component} from 'core/annotations/annotations';
export function main() { export function main() {
describe('ElementBindingMarker', () => { describe('ElementBindingMarker', () => {
@ -101,6 +101,7 @@ function assertBinding(pipelineElement, shouldBePresent) {
} }
class MockStep extends CompileStep { class MockStep extends CompileStep {
processClosure:Function;
constructor(process) { constructor(process) {
this.processClosure = process; this.processClosure = process;
} }

View File

@ -1,5 +1,5 @@
import {describe, beforeEach, it, expect, iit, ddescribe} from 'test_lib/test_lib'; import {describe, beforeEach, it, expect, iit, ddescribe} from 'test_lib/test_lib';
import {ListWrapper} from 'facade/collection'; import {ListWrapper, List} from 'facade/collection';
import {DOM} from 'facade/dom'; import {DOM} from 'facade/dom';
import {isPresent, NumberWrapper} from 'facade/lang'; import {isPresent, NumberWrapper} from 'facade/lang';
@ -106,6 +106,7 @@ export function main() {
} }
class MockStep extends CompileStep { class MockStep extends CompileStep {
processClosure:Function;
constructor(process) { constructor(process) {
this.processClosure = process; this.processClosure = process;
} }
@ -115,6 +116,7 @@ class MockStep extends CompileStep {
} }
class LoggingStep extends CompileStep { class LoggingStep extends CompileStep {
logs:List;
constructor(logs) { constructor(logs) {
this.logs = logs; this.logs = logs;
} }

View File

@ -1,7 +1,7 @@
import {describe, beforeEach, it, expect, iit, ddescribe} from 'test_lib/test_lib'; import {describe, beforeEach, it, expect, iit, ddescribe} from 'test_lib/test_lib';
import {isPresent, isBlank} from 'facade/lang'; import {isPresent, isBlank} from 'facade/lang';
import {DOM} from 'facade/dom'; import {DOM} from 'facade/dom';
import {ListWrapper} from 'facade/collection'; import {List, ListWrapper} from 'facade/collection';
import {ProtoElementInjectorBuilder} from 'core/compiler/pipeline/proto_element_injector_builder'; import {ProtoElementInjectorBuilder} from 'core/compiler/pipeline/proto_element_injector_builder';
import {CompilePipeline} from 'core/compiler/pipeline/compile_pipeline'; import {CompilePipeline} from 'core/compiler/pipeline/compile_pipeline';
@ -10,9 +10,9 @@ import {CompileStep} from 'core/compiler/pipeline/compile_step'
import {CompileControl} from 'core/compiler/pipeline/compile_control'; import {CompileControl} from 'core/compiler/pipeline/compile_control';
import {ProtoView} from 'core/compiler/view'; import {ProtoView} from 'core/compiler/view';
import {Reflector} from 'core/compiler/reflector'; import {Reflector} from 'core/compiler/reflector';
import {Template} from 'core/annotations/template'; import {Template} from 'core/annotations/annotations';
import {Decorator} from 'core/annotations/decorator'; import {Decorator} from 'core/annotations/annotations';
import {Component} from 'core/annotations/component'; import {Component} from 'core/annotations/annotations';
import {ProtoElementInjector} from 'core/compiler/element_injector'; import {ProtoElementInjector} from 'core/compiler/element_injector';
export function main() { export function main() {
@ -107,6 +107,7 @@ export function main() {
class TestableProtoElementInjectorBuilder extends ProtoElementInjectorBuilder { class TestableProtoElementInjectorBuilder extends ProtoElementInjectorBuilder {
debugObjects:List;
constructor() { constructor() {
this.debugObjects = []; this.debugObjects = [];
} }
@ -127,6 +128,7 @@ class TestableProtoElementInjectorBuilder extends ProtoElementInjectorBuilder {
} }
class MockStep extends CompileStep { class MockStep extends CompileStep {
processClosure:Function;
constructor(process) { constructor(process) {
this.processClosure = process; this.processClosure = process;
} }

View File

@ -75,6 +75,7 @@ export function main() {
} }
class MockStep extends CompileStep { class MockStep extends CompileStep {
processClosure:Function;
constructor(process) { constructor(process) {
this.processClosure = process; this.processClosure = process;
} }

View File

@ -1,6 +1,6 @@
import {ddescribe, describe, it, iit, expect, beforeEach} from 'test_lib/test_lib'; import {ddescribe, describe, it, iit, expect, beforeEach} from 'test_lib/test_lib';
import {Reflector} from 'core/compiler/reflector'; import {Reflector} from 'core/compiler/reflector';
import {Decorator} from 'core/annotations/decorator'; import {Decorator} from 'core/annotations/annotations';
import {AnnotatedType} from 'core/compiler/annotated_type'; import {AnnotatedType} from 'core/compiler/annotated_type';
@Decorator({ @Decorator({

View File

@ -2,8 +2,8 @@ import {describe, xit, it, expect, beforeEach, ddescribe, iit} from 'test_lib/te
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'core/compiler/view'; import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'core/compiler/view';
import {ProtoElementInjector, ElementInjector} from 'core/compiler/element_injector'; import {ProtoElementInjector, ElementInjector} from 'core/compiler/element_injector';
import {Reflector} from 'core/compiler/reflector'; import {Reflector} from 'core/compiler/reflector';
import {Component} from 'core/annotations/component'; import {Component} from 'core/annotations/annotations';
import {Decorator} from 'core/annotations/decorator'; import {Decorator} from 'core/annotations/annotations';
import {ProtoRecordRange} from 'change_detection/record_range'; import {ProtoRecordRange} from 'change_detection/record_range';
import {ChangeDetector} from 'change_detection/change_detector'; import {ChangeDetector} from 'change_detection/change_detector';
import {TemplateConfig} from 'core/annotations/template_config'; import {TemplateConfig} from 'core/annotations/template_config';
@ -296,7 +296,7 @@ export function main() {
} }
class SomeDirective { class SomeDirective {
@FIELD('prop') prop;
constructor() { constructor() {
this.prop = 'foo'; this.prop = 'foo';
} }
@ -308,6 +308,7 @@ class SomeService {}
componentServices: [SomeService] componentServices: [SomeService]
}) })
class SomeComponent { class SomeComponent {
service: SomeService;
constructor(service: SomeService) { constructor(service: SomeService) {
this.service = service; this.service = service;
} }
@ -317,6 +318,8 @@ class SomeComponent {
selector: '[dec]' selector: '[dec]'
}) })
class ServiceDependentDecorator { class ServiceDependentDecorator {
component: SomeComponent;
service: SomeService;
constructor(component: SomeComponent, service: SomeService) { constructor(component: SomeComponent, service: SomeService) {
this.component = component; this.component = component;
this.service = service; this.service = service;
@ -324,14 +327,14 @@ class ServiceDependentDecorator {
} }
class AnotherDirective { class AnotherDirective {
@FIELD('prop') prop:string;
constructor() { constructor() {
this.prop = 'anotherFoo'; this.prop = 'anotherFoo';
} }
} }
class MyEvaluationContext { class MyEvaluationContext {
@FIELD('foo') foo:string;
constructor() { constructor() {
this.foo = 'bar'; this.foo = 'bar';
}; };

View File

@ -9,6 +9,7 @@ import {CONST} from "facade/lang";
* *
*/ */
export class Inject { export class Inject {
token;
@CONST() @CONST()
constructor(token) { constructor(token) {
this.token = token; this.token = token;
@ -26,6 +27,7 @@ export class Inject {
* *
*/ */
export class InjectPromise { export class InjectPromise {
token;
@CONST() @CONST()
constructor(token) { constructor(token) {
this.token = token; this.token = token;
@ -43,6 +45,7 @@ export class InjectPromise {
* *
*/ */
export class InjectLazy { export class InjectLazy {
token;
@CONST() @CONST()
constructor(token) { constructor(token) {
this.token = token; this.token = token;

View File

@ -4,9 +4,10 @@ import {reflector} from './reflector';
import {Key} from './key'; import {Key} from './key';
export class Dependency { export class Dependency {
@FIELD('final key:Key') key:Key;
@FIELD('final asPromise:bool') asPromise:boolean;
@FIELD('final lazy:bool') lazy:boolean;
properties:List;
constructor(key:Key, asPromise:boolean, lazy:boolean, properties:List) { constructor(key:Key, asPromise:boolean, lazy:boolean, properties:List) {
this.key = key; this.key = key;
this.asPromise = asPromise; this.asPromise = asPromise;
@ -16,6 +17,11 @@ export class Dependency {
} }
export class Binding { export class Binding {
key:Key;
factory:Function;
dependencies:List;
providedAsPromise:boolean;
constructor(key:Key, factory:Function, dependencies:List, providedAsPromise:boolean) { constructor(key:Key, factory:Function, dependencies:List, providedAsPromise:boolean) {
this.key = key; this.key = key;
this.factory = factory; this.factory = factory;
@ -29,6 +35,7 @@ export function bind(token):BindingBuilder {
} }
export class BindingBuilder { export class BindingBuilder {
token;
constructor(token) { constructor(token) {
this.token = token; this.token = token;
} }

View File

@ -28,6 +28,9 @@ function constructResolvingPath(keys:List) {
export class KeyMetadataError extends Error {} export class KeyMetadataError extends Error {}
export class ProviderError extends Error { export class ProviderError extends Error {
keys:List;
constructResolvingMessage:Function;
message;
constructor(key:Key, constructResolvingMessage:Function) { constructor(key:Key, constructResolvingMessage:Function) {
this.keys = [key]; this.keys = [key];
this.constructResolvingMessage = constructResolvingMessage; this.constructResolvingMessage = constructResolvingMessage;
@ -82,6 +85,7 @@ export class InstantiationError extends ProviderError {
} }
export class InvalidBindingError extends Error { export class InvalidBindingError extends Error {
message:string;
constructor(binding) { constructor(binding) {
this.message = `Invalid binding ${binding}`; this.message = `Invalid binding ${binding}`;
} }
@ -92,6 +96,7 @@ export class InvalidBindingError extends Error {
} }
export class NoAnnotationError extends Error { export class NoAnnotationError extends Error {
message:string;
constructor(typeOrFunc) { constructor(typeOrFunc) {
this.message = `Cannot resolve all parameters for ${stringify(typeOrFunc)}`; this.message = `Cannot resolve all parameters for ${stringify(typeOrFunc)}`;
} }

View File

@ -10,6 +10,7 @@ import {reflector} from './reflector';
var _constructing = new Object(); var _constructing = new Object();
class _Waiting { class _Waiting {
promise:Promise;
constructor(promise:Promise) { constructor(promise:Promise) {
this.promise = promise; this.promise = promise;
} }
@ -20,6 +21,12 @@ function _isWaiting(obj):boolean {
export class Injector { export class Injector {
_bindings:List;
_instances:List;
_parent:Injector;
_defaultBindings:boolean;
_asyncStrategy: _AsyncInjectorStrategy;
_syncStrategy:_SyncInjectorStrategy;
constructor(bindings:List, {parent=null, defaultBindings=false}={}) { constructor(bindings:List, {parent=null, defaultBindings=false}={}) {
var flatten = _flattenBindings(bindings, MapWrapper.create()); var flatten = _flattenBindings(bindings, MapWrapper.create());
this._bindings = this._createListOfBindings(flatten); this._bindings = this._createListOfBindings(flatten);
@ -116,6 +123,7 @@ export class Injector {
class _SyncInjectorStrategy { class _SyncInjectorStrategy {
injector:Injector;
constructor(injector:Injector) { constructor(injector:Injector) {
this.injector = injector; this.injector = injector;
} }
@ -163,6 +171,7 @@ class _SyncInjectorStrategy {
class _AsyncInjectorStrategy { class _AsyncInjectorStrategy {
injector:Injector;
constructor(injector:Injector) { constructor(injector:Injector) {
this.injector = injector; this.injector = injector;
} }

View File

@ -3,9 +3,9 @@ import {MapWrapper, Map} from 'facade/collection';
import {FIELD, int, isPresent} from 'facade/lang'; import {FIELD, int, isPresent} from 'facade/lang';
export class Key { export class Key {
@FIELD('final token') token;
@FIELD('final id:int') id:int;
@FIELD('metadata:Object') metadata:any;
constructor(token, id:int) { constructor(token, id:int) {
this.token = token; this.token = token;
this.id = id; this.id = id;
@ -30,7 +30,7 @@ export class Key {
} }
export class KeyRegistry { export class KeyRegistry {
@FIELD('final _allKeys:Map') _allKeys:Map;
constructor() { constructor() {
this._allKeys = MapWrapper.create(); this._allKeys = MapWrapper.create();
} }

View File

@ -13,12 +13,14 @@ class SynchronousUserList {
} }
class UserController { class UserController {
list:UserList;
constructor(list:UserList) { constructor(list:UserList) {
this.list = list; this.list = list;
} }
} }
class AsyncUserController { class AsyncUserController {
userList;
constructor(@InjectPromise(UserList) userList) { constructor(@InjectPromise(UserList) userList) {
this.userList = userList; this.userList = userList;
} }

View File

@ -21,18 +21,22 @@ class TurboEngine extends Engine {
} }
class Car { class Car {
engine:Engine;
constructor(engine:Engine) { constructor(engine:Engine) {
this.engine = engine; this.engine = engine;
} }
} }
class CarWithLazyEngine { class CarWithLazyEngine {
engineFactory;
constructor(@InjectLazy(Engine) engineFactory) { constructor(@InjectLazy(Engine) engineFactory) {
this.engineFactory = engineFactory; this.engineFactory = engineFactory;
} }
} }
class CarWithDashboard { class CarWithDashboard {
engine:Engine;
dashboard:Dashboard;
constructor(engine:Engine, dashboard:Dashboard) { constructor(engine:Engine, dashboard:Dashboard) {
this.engine = engine; this.engine = engine;
this.dashboard = dashboard; this.dashboard = dashboard;
@ -40,12 +44,14 @@ class CarWithDashboard {
} }
class SportsCar extends Car { class SportsCar extends Car {
engine:Engine;
constructor(engine:Engine) { constructor(engine:Engine) {
super(engine); super(engine);
} }
} }
class CarWithInject { class CarWithInject {
engine:Engine;
constructor(@Inject(TurboEngine) engine:Engine) { constructor(@Inject(TurboEngine) engine:Engine) {
this.engine = engine; this.engine = engine;
} }

View File

@ -1,7 +1,8 @@
import {describe, it, expect, beforeEach} from 'test_lib/test_lib'; import {describe, iit, it, expect, beforeEach} from 'test_lib/test_lib';
import {Key, KeyRegistry} from 'di/di'; import {Key, KeyRegistry} from 'di/di';
export function main() { export function main() {
describe("key", function () { describe("key", function () {
var registry; var registry;

View File

@ -29,6 +29,7 @@ import {bootstrap, Component, Decorator, TemplateConfig, NgElement} from 'core/c
}) })
}) })
class HelloCmp { class HelloCmp {
greeting: string;
constructor(service: GreetingService) { constructor(service: GreetingService) {
this.greeting = service.greeting; this.greeting = service.greeting;
} }
@ -49,6 +50,7 @@ class RedDec {
// A service used by the HelloCmp component. // A service used by the HelloCmp component.
class GreetingService { class GreetingService {
greeting:string;
constructor() { constructor() {
this.greeting = 'hello'; this.greeting = 'hello';
} }

View File

@ -159,3 +159,6 @@ dynamic getMapKey(value) {
return value.isNaN ? _NAN_KEY : value; return value.isNaN ? _NAN_KEY : value;
} }
normalizeBlank(obj) {
return isBlank(obj) ? null : obj;
}

View File

@ -194,3 +194,7 @@ export function looseIdentical(a, b):boolean {
export function getMapKey(value) { export function getMapKey(value) {
return value; return value;
} }
export function normalizeBlank(obj) {
return isBlank(obj) ? null : obj;
}

View File

@ -2,6 +2,7 @@ import {describe, it, iit, ddescribe, expect} from 'test_lib/test_lib';
import {MapWrapper} from 'facade/collection'; import {MapWrapper} from 'facade/collection';
class TestObj { class TestObj {
prop;
constructor(prop) { constructor(prop) {
this.prop = prop; this.prop = prop;
} }

View File

@ -6,6 +6,8 @@ class Inject {}
class Bar {} class Bar {}
class Provide { class Provide {
token;
@CONST() @CONST()
constructor(token) { constructor(token) {
this.token = token; this.token = token;
@ -13,6 +15,8 @@ class Provide {
} }
class AnnotateMe { class AnnotateMe {
maybe;
@CONST() @CONST()
constructor({maybe = 'default'} = {}) { constructor({maybe = 'default'} = {}) {
this.maybe = maybe; this.maybe = maybe;

View File

@ -13,6 +13,8 @@ var max = (a, b) => {
}; };
class LexicalThis { class LexicalThis {
zero;
constructor() { constructor() {
this.zero = 0; this.zero = 0;
} }

View File

@ -1,9 +1,10 @@
import {ddescribe, describe, it, expect} from 'test_lib/test_lib'; import {ddescribe, describe, it, expect} from 'test_lib/test_lib';
import {CONST} from './fixtures/annotations'; import {CONST} from './fixtures/annotations';
// Constructor
// Define fields
class Foo { class Foo {
a;
b;
constructor(a, b) { constructor(a, b) {
this.a = a; this.a = a;
this.b = b; this.b = b;
@ -15,6 +16,8 @@ class Foo {
} }
class SubFoo extends Foo { class SubFoo extends Foo {
c;
constructor(a, b) { constructor(a, b) {
this.c = 3; this.c = 3;
super(a, b); super(a, b);
@ -25,6 +28,8 @@ class SubFoo extends Foo {
class ConstClass {} class ConstClass {}
class Const { class Const {
a;
@CONST @CONST
constructor(a:number) { constructor(a:number) {
this.a = a; this.a = a;
@ -32,6 +37,8 @@ class Const {
} }
class SubConst extends Const { class SubConst extends Const {
b;
@CONST @CONST
constructor(a:number, b:number) { constructor(a:number, b:number) {
super(a); super(a);

View File

@ -5,6 +5,8 @@ function sum(a, b) {
} }
class ConstructorWithNamedParams { class ConstructorWithNamedParams {
sum;
constructor(a, {b=1, c=2}) { constructor(a, {b=1, c=2}) {
this.sum = a + b + c; this.sum = a + b + c;
} }

View File

@ -30,6 +30,9 @@ class Bar {
} }
class Foo { class Foo {
a;
b;
constructor(a: number, b: number) { constructor(a: number, b: number) {
this.a = a; this.a = a;
this.b = b; this.b = b;

View File

@ -25,7 +25,6 @@ import {
} from 'traceur/src/syntax/trees/ParseTrees'; } from 'traceur/src/syntax/trees/ParseTrees';
import { import {
ClassFieldDeclaration,
PropertyConstructorAssignment PropertyConstructorAssignment
} from '../syntax/trees/ParseTrees'; } from '../syntax/trees/ParseTrees';
@ -73,30 +72,6 @@ export class ClassTransformer extends ParseTreeTransformer {
// Rename "constructor" to the class name. // Rename "constructor" to the class name.
elementTree.name.literalToken.value = className; elementTree.name.literalToken.value = className;
// Collect all fields, defined in the constructor.
elementTree.body.statements.forEach(function(statement) {
var exp = statement.expression;
if (exp &&
exp.type === BINARY_EXPRESSION &&
exp.operator.type === EQUAL &&
exp.left.type === MEMBER_EXPRESSION &&
exp.left.operand.type === THIS_EXPRESSION) {
var typeAnnotation;
if (exp.right.type === IDENTIFIER_EXPRESSION) {
// `this.field = variable;`
// we can infer the type of the field from the variable when it is a typed arg
var varName = exp.right.getStringValue();
typeAnnotation = argumentTypesMap[varName] || null;
}
var fieldName = exp.left.memberName.value;
var lvalue = new BindingIdentifier(tree.location, fieldName);
fields.push(new ClassFieldDeclaration(tree.location, lvalue, typeAnnotation, isConst));
}
});
// Compute the initializer list // Compute the initializer list
var initializerList = []; var initializerList = [];
var superCall = that._extractSuperCall(elementTree.body); var superCall = that._extractSuperCall(elementTree.body);
@ -149,6 +124,11 @@ export class ClassTransformer extends ParseTreeTransformer {
// Add the field definitions to the beginning of the class. // Add the field definitions to the beginning of the class.
tree.elements = fields.concat(tree.elements); tree.elements = fields.concat(tree.elements);
if (isConst) {
tree.elements.forEach(function(element) {
element.isFinal = true;
});
}
return super.transformClassDeclaration(tree); return super.transformClassDeclaration(tree);
} }

View File

@ -45,8 +45,11 @@ export class DartParseTreeWriter extends JavaScriptParseTreeWriter {
} }
if (tree.typeAnnotation === null) { if (tree.typeAnnotation === null) {
this.write_(VAR); this.write_(tree.isFinal ? 'final' : VAR);
} else { } else {
if (tree.isFinal) {
this.write_('final');
}
this.writeType_(tree.typeAnnotation); this.writeType_(tree.typeAnnotation);
} }
this.writeSpace_(); this.writeSpace_();
@ -211,6 +214,7 @@ export class DartParseTreeWriter extends JavaScriptParseTreeWriter {
case 'number': return 'num'; case 'number': return 'num';
case 'boolean': return 'bool'; case 'boolean': return 'bool';
case 'string': return 'String'; case 'string': return 'String';
case 'any': return 'dynamic';
case 'Promise': return 'Future'; case 'Promise': return 'Future';
default: return typeName; default: return typeName;
} }
@ -244,25 +248,6 @@ export class DartParseTreeWriter extends JavaScriptParseTreeWriter {
} }
} }
visitClassFieldDeclaration(tree) {
if (tree.isFinal) {
// `final <type> name;` or `final name;` for untyped variable
this.write_('final');
this.writeSpace_();
this.writeType_(tree.typeAnnotation);
} else {
// `<type> name;` or `var name;`
if (tree.typeAnnotation) {
this.writeType_(tree.typeAnnotation);
} else {
this.write_(VAR);
this.writeSpace_();
}
}
this.write_(tree.lvalue.getStringValue());
this.write_(SEMI_COLON);
}
writeType_(typeAnnotation) { writeType_(typeAnnotation) {
if (!typeAnnotation) { if (!typeAnnotation) {

View File

@ -4,36 +4,6 @@ import {PropertyMethodAssignment} from 'traceur/src/syntax/trees/ParseTrees';
import * as ParseTreeType from './ParseTreeType'; import * as ParseTreeType from './ParseTreeType';
// Class field declaration
export class ClassFieldDeclaration extends ParseTree {
constructor(location, lvalue, typeAnnotation, isFinal) {
this.location = location;
this.lvalue = lvalue;
this.typeAnnotation = typeAnnotation;
this.isFinal = isFinal;
}
get type() {
return CLASS_FIELD_DECLARATION;
}
visit(visitor) {
if (visitor.visitClassFieldDeclaration) {
visitor.visitClassFieldDeclaration(this);
}
}
transform(transformer) {
if (transformer.transformClassFieldDeclaration) {
return transformer.transformClassFieldDeclaration(this);
}
return this;
}
}
var CLASS_FIELD_DECLARATION = ParseTreeType.CLASS_FIELD_DECLARATION;
// Class constructor // Class constructor
export class PropertyConstructorAssignment extends PropertyMethodAssignment { export class PropertyConstructorAssignment extends PropertyMethodAssignment {
/** /**