first chunk of interfaces that are valid via dart analyzer

This commit is contained in:
Misko Hevery
2014-09-19 16:38:37 -07:00
committed by Tobias Bosch
parent 29c20f7a50
commit 8afa421d75
40 changed files with 462 additions and 9 deletions

12
modules/core/src/angular.js vendored Normal file
View File

@ -0,0 +1,12 @@
/**
* Define public API for Angular here
*/
export * from './annotations/directive';
export * from './annotations/component';
export * from './annotations/template_config';
export * from './compiler/compiler';
export * from './compiler/template_loader';
export * from './view/proto_view';
export * from './view/view';

View File

@ -0,0 +1,65 @@
import {Directive} from './directive';
export class Component extends Directive {
@CONST constructor({
selector,
template,
elementServices,
componentServices,
implementsTypes
}:{
selector:String,
template:TemplateConfig,
lightDomServices:DomServicesFunction,
shadowDomServices:DomServicesFunction,
componentServices:ComponentServicesFunction,
implementsTypes:Array<Type>
})
{
// super({selector, lightDomServices, implementsTypes});
}
}
///////////////////////////
/*
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: Example.componentServices,
elementServices: Example.elementServices,
implementsTypes: const [App]
)
class Example implements App {
static componentServices(Module m) {
m.bind();
}
static elementServices(ElementModule m) {
m.bind();
}
}
class CompA {}
@Formatter()
class Stringify {}
<CompA>
LightDOM:
</CompA>
CompA ShadowDOM:
<div>
<CompB></CompB>
</div>
CompB SHadowDOM:
<div></div>
*/

View File

@ -0,0 +1,19 @@
import {Type} from 'facade/lang';
import {ElementServicesFunction} from './facade';
@ABSTRACT
export class Directive {
@CONST constructor({
selector,
lightDomServices,
implementsTypes
}:{
selector:String,
lightDomServices:ElementServicesFunction,
implementsTypes:Array<Type>
})
{
this.lightDomServices = lightDomServices;
this.selector = selector;
}
}

View File

@ -0,0 +1,5 @@
import 'package:di/di.dart' show Module;
import '../view/element_module.dart' show ElementModule;
typedef DomServicesFunction(ElementModule m);
typedef ComponentServicesFunction(Module m);

View File

@ -0,0 +1,2 @@
export var DomServicesFunction = Function;
export var ComponentServicesFunction = Function;

View File

@ -0,0 +1,16 @@
import {Type, List} from 'facade/lang';
export class TemplateConfig {
@CONST constructor({
url,
directives,
formatters,
source
}: {
url: String,
directives: List<Type>,
formatters: List<Type>,
source: List<TemplateConfig>
})
{}
}

View File

@ -1,7 +1,15 @@
import {Future} from '../facade';
import {ProtoView} from './proto_view';
import {Future} from 'facade/lang';
import {Element} from 'facade/dom';
import {ProtoView} from '../view/proto_view';
import {TemplateLoader} from './template_loader';
export class Compiler {
@FIELD('final _templateLoader:TemplateLoader')
constructor(templateLoader:TemplateLoader) {
this._templateLoader = templateLoader;
}
/**
* # Why future?
* - compilation will load templates. Instantiating views before templates are loaded will
@ -10,7 +18,9 @@ export class Compiler {
* - don't know about injector in deserialization
* - compile does not need the injector, only the ViewFactory does
*/
@of(ProtoView) compile(element:TemplateElement):Future {
compile(component:Type, element:Element/* = null*/):Future<ProtoView> {
return null;
}
}

View File

@ -0,0 +1,11 @@
import {Future} from 'facade/lang';
import {Document} from 'facade/dom';
export class TemplateLoader {
constructor() {}
load(url:String):Future<Document> {
return null;
}
}

View File

@ -0,0 +1,11 @@
export class LifeCycle {
@FIELD('final _changeDetection:ChangeDetection')
@FIELD('final _onChangeDispatcher:OnChangeDispatcher')
constructor() {}
digest() {
_changeDetection.detectChanges();
_onChangeDispatcher.done();
}
}

View File

@ -0,0 +1,13 @@
export class ElementInjectorTarget {
@FIELD('final _elementInjectorIndex:int')
@FIELD('final _directiveIndex:int')
@FIELD('final _setterName:String')
@FIELD('final _setter:SetterFn')
constructor() {}
invoke(record:Record, elementInjectors:List<ElementInjector>) {
var elementInjector:ElementInjector = elementInjectors[this._elementInjectorIndex];
var directive = elementInjectors.getByIndex(this._directiveIndex);
this._setter(directive, record.currentValue);
}
}

View File

@ -0,0 +1 @@
export class ElementModule {}

View File

@ -0,0 +1,19 @@
//TODO(tbosch): I don't like to have done be called from a different place than notify
// notify is called by change detection, but done is called by our wrapper on detect changes.
export class OnChangeDispatcher {
@FIELD('_lastView:View')
@FIELD('_lastTarget:ElementInjectorTarget')
constructor() {
}
notify(view:View, eTarget:ElementInjectorTarget) {
}
done() {
}
}

View File

@ -0,0 +1,27 @@
/**
Difference beteween di.Injector and ElementInjector
di.Injector (di.Module):
- imperative based (can create child injectors imperativly)
- Lazy loading of code
- Component/App Level services which are usually not DOM Related.
ElementInjector (ElementModule):
- ProtoBased (Injector structure fixed at compile time)
- understands @Ancestor, @Parent, @Child, @Descendent
- Fast
- Query mechanism for children
- 1:1 to DOM structure.
*/
export class ProtoElementInjector {
@FIELD('final _parent:ProtoElementInjector')
/// Temporory instance while instantiating
@FIELD('_instance:ElementInjector')
constructor() {}
}

View File

@ -0,0 +1,10 @@
import {Module} from 'di/di';
import {TemplateElement} from 'facade/dom';
export class ProtoView {
@FIELD('final _template:TemplateElement')
@FIELD('final _module:Module')
@FIELD('final _protoElementInjectors:List<ProtoElementInjector>')
@FIELD('final _protoWatchGroup:ProtoWatchGroup')
@CONST constructor() { }
}

View File

@ -0,0 +1,34 @@
import {Node, DocumentFragment} from 'facade/dom';
import {ListWrapper wraps List} from 'facade/collection';
import {Record} from 'change_detection/record';
@IMPLEMENTS(WatchGroupDispatcher)
export class View {
@FIELD('final _fragment:DocumentFragment')
/// This list matches the _nodes list. It is sparse, since only Elements have ElementInjector
@FIELD('final _rootElementInjectors:List<ElementInjector>')
@FIELD('final _elementInjectors:List<ElementInjector>')
@FIELD('final _textNodes:List<Text>')
@FIELD('final _watchGroup:WatchGroup')
/// When the view is part of render tree, the DocumentFragment is empty, which is why we need
/// to keep track of the nodes.
@FIELD('final _nodes:List<Node>')
constructor(fragment:DocumentFragment) {
this._fragment = fragment;
this._nodes = ListWrapper.clone(fragment.childNodes);
}
notify(record:Record, target) {
/*
// dispatch to element injector or text nodes based on context
if (Number.is(target)) {
// we know it refferst to _textNodes.
} else {
// we know that it is ElementInjectorTarge
var eTarget:ElementInjectorTarget = target;
onChangeDispatcher.notify(this, eTarget);
eTarget.invoke(record, _elementInjectors);
}
*/
}
}