refactor(compiler): use the new compiler everywhere

Closes #3605

BREAKING CHANGE:
- we don't mark an element as bound any more if it only contains text bindings
  E.g. <div>{{hello}}</div>
  This changes the indices when using `DebugElement.componentViewChildren` / `DebugElement.children`.
- `@Directive.compileChildren` was removed,
  `ng-non-bindable` is now builtin and not a directive any more
- angular no more adds the `ng-binding` class to elements with bindings
- directives are now ordered as they are listed in the View.directives regarding change detection.
  Previously they had an undefined order.
- the `Renderer` interface has new methods `createProtoView` and `registerComponentTemplate`. See `DomRenderer` for default implementations.
- reprojection with `ng-content` is now all or nothing per `ng-content` element
- angular2 transformer can't be used in tests that modify directive metadata.
  Use `angular2/src/transform/inliner_for_test` transformer instead.
This commit is contained in:
Tobias Bosch
2015-10-01 18:48:27 -07:00
parent 30ca0434a2
commit 76247b7097
124 changed files with 2013 additions and 3451 deletions
+6 -1
View File
@@ -7,6 +7,7 @@ import 'package:angular2/src/core/reflection/reflection_capabilities.dart'
show ReflectionCapabilities;
import 'application_common.dart';
import 'package:angular2/src/compiler/compiler.dart';
import 'package:angular2/src/core/compiler/dynamic_component_loader.dart';
export 'package:angular2/src/core/compiler/dynamic_component_loader.dart' show ComponentRef;
@@ -19,5 +20,9 @@ export 'package:angular2/src/core/compiler/dynamic_component_loader.dart' show C
Future<ComponentRef> bootstrap(Type appComponentType,
[List componentInjectableBindings]) {
reflector.reflectionCapabilities = new ReflectionCapabilities();
return commonBootstrap(appComponentType, componentInjectableBindings);
var bindings = [compilerBindings()];
if (componentInjectableBindings != null) {
bindings.add(componentInjectableBindings);
}
return commonBootstrap(appComponentType, bindings);
}
+19 -1
View File
@@ -1,6 +1,13 @@
// Public API for Application
import {Binding} from './di';
import {Type, isPresent} from 'angular2/src/core/facade/lang';
import {Promise} from 'angular2/src/core/facade/async';
import {compilerBindings} from 'angular2/src/compiler/compiler';
import {commonBootstrap} from './application_common';
import {ComponentRef} from './compiler/dynamic_component_loader';
export {APP_COMPONENT} from './application_tokens';
export {platform, commonBootstrap as bootstrap} from './application_common';
export {platform} from './application_common';
export {
PlatformRef,
ApplicationRef,
@@ -9,3 +16,14 @@ export {
platformCommon,
platformBindings
} from './application_ref';
/// See [commonBootstrap] for detailed documentation.
export function bootstrap(appComponentType: /*Type*/ any,
appBindings: Array<Type | Binding | any[]> = null):
Promise<ComponentRef> {
var bindings = [compilerBindings()];
if (isPresent(appBindings)) {
bindings.push(appBindings);
}
return commonBootstrap(appComponentType, bindings);
}
+8 -7
View File
@@ -18,7 +18,6 @@ import {
import {DOM} from 'angular2/src/core/dom/dom_adapter';
import {internalView} from 'angular2/src/core/compiler/view_ref';
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
import {
Parser,
Lexer,
@@ -35,7 +34,7 @@ import {AppViewPool, APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/compiler/vi
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
import {AppViewManagerUtils} from 'angular2/src/core/compiler/view_manager_utils';
import {AppViewListener} from 'angular2/src/core/compiler/view_listener';
import {Compiler, CompilerCache} from './compiler/compiler';
import {ProtoViewFactory} from './compiler/proto_view_factory';
import {DEFAULT_PIPES} from 'angular2/src/core/pipes';
import {ViewResolver} from './compiler/view_resolver';
import {DirectiveResolver} from './compiler/directive_resolver';
@@ -43,7 +42,10 @@ import {PipeResolver} from './compiler/pipe_resolver';
import {StyleUrlResolver} from 'angular2/src/core/render/dom/compiler/style_url_resolver';
import {UrlResolver} from 'angular2/src/core/services/url_resolver';
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
import {compilerBindings} from 'angular2/src/compiler/compiler';
import {
APP_ID_RANDOM_BINDING,
} from 'angular2/src/core/render/render';
import {Compiler} from 'angular2/src/core/compiler/compiler';
/**
* Constructs the set of bindings meant for use at the platform level.
@@ -95,15 +97,14 @@ export function applicationCommonBindings(): Array<Type | Binding | any[]> {
bestChangeDetection = new JitChangeDetection();
}
return [
compilerBindings(),
ProtoViewFactory,
Compiler,
APP_ID_RANDOM_BINDING,
AppViewPool,
bind(APP_VIEW_POOL_CAPACITY).toValue(10000),
AppViewManager,
AppViewManagerUtils,
AppViewListener,
Compiler,
CompilerCache,
ProtoViewFactory,
ViewResolver,
DEFAULT_PIPES,
bind(IterableDiffers).toValue(defaultIterableDiffers),
+1 -19
View File
@@ -1,21 +1,3 @@
library angular2.src.core.bootstrap;
import 'dart:async';
import 'package:angular2/src/core/compiler/dynamic_component_loader.dart' show ComponentRef;
import 'package:angular2/src/core/reflection/reflection.dart' show reflector;
import 'package:angular2/src/core/reflection/reflection_capabilities.dart'
show ReflectionCapabilities;
import 'application_common.dart';
/// Starts an application from a root component. This implementation uses
/// mirrors. Angular 2 transformer automatically replaces this method with a
/// static implementation (see `application_static.dart`) that does not use
/// mirrors and produces a faster and more compact JS code.
///
/// See [commonBootstrap] for detailed documentation.
Future<ComponentRef> bootstrap(Type appComponentType,
[List componentInjectableBindings]) {
reflector.reflectionCapabilities = new ReflectionCapabilities();
return commonBootstrap(appComponentType, componentInjectableBindings);
}
export './application.dart' show bootstrap;
+1 -1
View File
@@ -1,4 +1,4 @@
// Note: This file only exists so that Dart users can import
// bootstrap from angular2/bootstrap. JS users should import
// from angular2/core.
export {commonBootstrap as bootstrap} from './application_common';
export {bootstrap} from './application';
File diff suppressed because it is too large Load Diff
@@ -119,7 +119,6 @@ export class DirectiveResolver {
bindings: dm.bindings,
exportAs: dm.exportAs,
moduleId: dm.moduleId,
compileChildren: dm.compileChildren,
queries: mergedQueries,
changeDetection: dm.changeDetection,
viewBindings: dm.viewBindings
@@ -134,7 +133,6 @@ export class DirectiveResolver {
bindings: dm.bindings,
exportAs: dm.exportAs,
moduleId: dm.moduleId,
compileChildren: dm.compileChildren,
queries: mergedQueries
});
}
@@ -1,26 +1,16 @@
import {isBlank, isPresent} from 'angular2/src/core/facade/lang';
import {isBlank} from 'angular2/src/core/facade/lang';
import {BaseException} from 'angular2/src/core/facade/exceptions';
import * as eiModule from './element_injector';
import {DirectiveBinding} from './element_injector';
import * as viewModule from './view';
export class ElementBinder {
// updated later, so we are able to resolve cycles
nestedProtoView: viewModule.AppProtoView = null;
constructor(public index: number, public parent: ElementBinder, public distanceToParent: number,
public protoElementInjector: eiModule.ProtoElementInjector,
public componentDirective: DirectiveBinding) {
public componentDirective: DirectiveBinding,
public nestedProtoView: viewModule.AppProtoView) {
if (isBlank(index)) {
throw new BaseException('null index not allowed.');
}
}
hasStaticComponent(): boolean {
return isPresent(this.componentDirective) && isPresent(this.nestedProtoView);
}
hasEmbeddedProtoView(): boolean {
return !isPresent(this.componentDirective) && isPresent(this.nestedProtoView);
}
}
@@ -170,7 +170,7 @@ export class DirectiveBinding extends ResolvedBinding {
type: meta instanceof ComponentMetadata ? RenderDirectiveMetadata.COMPONENT_TYPE :
RenderDirectiveMetadata.DIRECTIVE_TYPE,
selector: meta.selector,
compileChildren: meta.compileChildren,
compileChildren: true,
outputs: meta.outputs,
host: isPresent(meta.host) ? MapWrapper.createFromStringMap(meta.host) : null,
inputs: meta.inputs,
@@ -214,6 +214,7 @@ export class DirectiveBinding extends ResolvedBinding {
// TODO(rado): benchmark and consider rolling in as ElementInjector fields.
export class PreBuiltObjects {
nestedView: viewModule.AppView = null;
constructor(public viewManager: avmModule.AppViewManager, public view: viewModule.AppView,
public elementRef: ElementRef, public templateRef: TemplateRef) {}
}
@@ -474,6 +475,8 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
return new ViewContainerRef(this._preBuiltObjects.viewManager, this.getElementRef());
}
getNestedView(): viewModule.AppView { return this._preBuiltObjects.nestedView; }
getView(): viewModule.AppView { return this._preBuiltObjects.view; }
directParent(): ElementInjector { return this._proto.distanceToParent < 2 ? this.parent : null; }
@@ -33,6 +33,7 @@ export class ElementRef implements RenderElementRef {
/**
* @private
*
* TODO(tbosch): remove this when the new compiler lands
* Index of the element inside the `RenderViewRef`.
*
* This is used internally by the Angular framework to locate elements.
@@ -42,11 +43,10 @@ export class ElementRef implements RenderElementRef {
/**
* @private
*/
constructor(parentView: ViewRef, boundElementIndex: number, renderBoundElementIndex: number,
private _renderer: Renderer) {
constructor(parentView: ViewRef, boundElementIndex: number, private _renderer: Renderer) {
this.parentView = parentView;
this.boundElementIndex = boundElementIndex;
this.renderBoundElementIndex = renderBoundElementIndex;
this.renderBoundElementIndex = boundElementIndex;
}
/**
File diff suppressed because it is too large Load Diff
@@ -52,5 +52,7 @@ export class TemplateRef {
/**
* Allows you to check if this Embedded Template defines Local Variable with name matching `name`.
*/
hasLocal(name: string): boolean { return this._getProtoView().variableBindings.has(name); }
hasLocal(name: string): boolean {
return this._getProtoView().templateVariableBindings.has(name);
}
}
+55 -74
View File
@@ -33,45 +33,12 @@ import {ViewRef, ProtoViewRef, internalView} from './view_ref';
import {ElementRef} from './element_ref';
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
import {camelCaseToDashCase} from 'angular2/src/core/render/dom/util';
import {TemplateCmd} from './template_commands';
export {DebugContext} from 'angular2/src/core/change_detection/interfaces';
const REFLECT_PREFIX: string = 'ng-reflect-';
export class AppProtoViewMergeMapping {
renderProtoViewRef: renderApi.RenderProtoViewRef;
renderFragmentCount: number;
renderElementIndices: number[];
renderInverseElementIndices: number[];
renderTextIndices: number[];
nestedViewIndicesByElementIndex: number[];
hostElementIndicesByViewIndex: number[];
nestedViewCountByViewIndex: number[];
constructor(renderProtoViewMergeMapping: renderApi.RenderProtoViewMergeMapping) {
this.renderProtoViewRef = renderProtoViewMergeMapping.mergedProtoViewRef;
this.renderFragmentCount = renderProtoViewMergeMapping.fragmentCount;
this.renderElementIndices = renderProtoViewMergeMapping.mappedElementIndices;
this.renderInverseElementIndices = inverseIndexMapping(
this.renderElementIndices, renderProtoViewMergeMapping.mappedElementCount);
this.renderTextIndices = renderProtoViewMergeMapping.mappedTextIndices;
this.hostElementIndicesByViewIndex = renderProtoViewMergeMapping.hostElementIndicesByViewIndex;
this.nestedViewIndicesByElementIndex =
inverseIndexMapping(this.hostElementIndicesByViewIndex, this.renderElementIndices.length);
this.nestedViewCountByViewIndex = renderProtoViewMergeMapping.nestedViewCountByViewIndex;
}
}
function inverseIndexMapping(input: number[], resultLength: number): number[] {
var result = ListWrapper.createGrowableSize(resultLength);
for (var i = 0; i < input.length; i++) {
var value = input[i];
if (isPresent(value)) {
result[input[i]] = i;
}
}
return result;
}
export class AppViewContainer {
// The order in this list matches the DOM order.
views: AppView[] = [];
@@ -109,7 +76,6 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
ref: ViewRef;
changeDetector: ChangeDetector = null;
/**
* The context against which data-binding expressions in this view are evaluated against.
* This is always a component instance.
@@ -125,10 +91,10 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
locals: Locals;
constructor(public renderer: renderApi.Renderer, public proto: AppProtoView,
public mainMergeMapping: AppProtoViewMergeMapping, public viewOffset: number,
public elementOffset: number, public textOffset: number,
public viewOffset: number, public elementOffset: number, public textOffset: number,
protoLocals: Map<string, any>, public render: renderApi.RenderViewRef,
public renderFragment: renderApi.RenderFragmentRef) {
public renderFragment: renderApi.RenderFragmentRef,
public containerElementInjector: ElementInjector) {
this.ref = new ViewRef(this);
this.locals = new Locals(null, MapWrapper.clone(protoLocals)); // TODO optimize this
@@ -148,10 +114,10 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
setLocal(contextName: string, value: any): void {
if (!this.hydrated()) throw new BaseException('Cannot set locals on dehydrated view.');
if (!this.proto.variableBindings.has(contextName)) {
if (!this.proto.templateVariableBindings.has(contextName)) {
return;
}
var templateName = this.proto.variableBindings.get(contextName);
var templateName = this.proto.templateVariableBindings.get(contextName);
this.locals.set(templateName, value);
}
@@ -175,9 +141,7 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
// dispatch to element injector or text nodes based on context
notifyOnBinding(b: BindingTarget, currentValue: any): void {
if (b.isTextNode()) {
this.renderer.setText(
this.render, this.mainMergeMapping.renderTextIndices[b.elementIndex + this.textOffset],
currentValue);
this.renderer.setText(this.render, b.elementIndex + this.textOffset, currentValue);
} else {
var elementRef = this.elementRefs[this.elementOffset + b.elementIndex];
if (b.isElementProperty()) {
@@ -226,13 +190,14 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
}
getNestedView(boundElementIndex: number): AppView {
var viewIndex = this.mainMergeMapping.nestedViewIndicesByElementIndex[boundElementIndex];
return isPresent(viewIndex) ? this.views[viewIndex] : null;
var eli = this.elementInjectors[boundElementIndex];
return isPresent(eli) ? eli.getNestedView() : null;
}
getHostElement(): ElementRef {
var boundElementIndex = this.mainMergeMapping.hostElementIndicesByViewIndex[this.viewOffset];
return isPresent(boundElementIndex) ? this.elementRefs[boundElementIndex] : null;
getContainerElement(): ElementRef {
return isPresent(this.containerElementInjector) ?
this.containerElementInjector.getElementRef() :
null;
}
getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext {
@@ -241,11 +206,11 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
var hasRefForIndex = offsettedIndex < this.elementRefs.length;
var elementRef = hasRefForIndex ? this.elementRefs[this.elementOffset + elementIndex] : null;
var host = this.getHostElement();
var container = this.getContainerElement();
var ei = hasRefForIndex ? this.elementInjectors[this.elementOffset + elementIndex] : null;
var element = isPresent(elementRef) ? elementRef.nativeElement : null;
var componentElement = isPresent(host) ? host.nativeElement : null;
var componentElement = isPresent(container) ? container.nativeElement : null;
var directive = isPresent(directiveIndex) ? this.getDirectiveFor(directiveIndex) : null;
var injector = isPresent(ei) ? ei.getInjector() : null;
@@ -269,10 +234,9 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
}
// implementation of RenderEventDispatcher#dispatchRenderEvent
dispatchRenderEvent(renderElementIndex: number, eventName: string,
dispatchRenderEvent(boundElementIndex: number, eventName: string,
locals: Map<string, any>): boolean {
var elementRef =
this.elementRefs[this.mainMergeMapping.renderInverseElementIndices[renderElementIndex]];
var elementRef = this.elementRefs[boundElementIndex];
var view = internalView(elementRef.parentView);
return view.dispatchEvent(elementRef.boundElementIndex, eventName, locals);
}
@@ -326,36 +290,53 @@ class EventEvaluationError extends WrappedException {
}
}
export class AppProtoViewMergeInfo {
constructor(public embeddedViewCount: number, public elementCount: number,
public viewCount: number) {}
}
/**
*
*/
export class AppProtoView {
elementBinders: ElementBinder[] = [];
protoLocals = new Map<string, any>();
mergeMapping: AppProtoViewMergeMapping;
ref: ProtoViewRef;
protoLocals: Map<string, any>;
constructor(public type: renderApi.ViewType, public isEmbeddedFragment: boolean,
public render: renderApi.RenderProtoViewRef,
public protoChangeDetector: ProtoChangeDetector,
public variableBindings: Map<string, string>,
public variableLocations: Map<string, number>, public textBindingCount: number,
public pipes: ProtoPipes) {
elementBinders: ElementBinder[] = null;
mergeInfo: AppProtoViewMergeInfo = null;
variableLocations: Map<string, number> = null;
textBindingCount = null;
render: renderApi.RenderProtoViewRef = null;
constructor(public templateCmds: TemplateCmd[], public type: renderApi.ViewType,
public isMergable: boolean, public changeDetectorFactory: Function,
public templateVariableBindings: Map<string, string>, public pipes: ProtoPipes) {
this.ref = new ProtoViewRef(this);
if (isPresent(variableBindings)) {
MapWrapper.forEach(variableBindings,
}
init(render: renderApi.RenderProtoViewRef, elementBinders: ElementBinder[],
textBindingCount: number, mergeInfo: AppProtoViewMergeInfo,
variableLocations: Map<string, number>) {
this.render = render;
this.elementBinders = elementBinders;
this.textBindingCount = textBindingCount;
this.mergeInfo = mergeInfo;
this.variableLocations = variableLocations;
this.protoLocals = new Map<string, any>();
if (isPresent(this.templateVariableBindings)) {
MapWrapper.forEach(this.templateVariableBindings,
(templateName, _) => { this.protoLocals.set(templateName, null); });
}
if (isPresent(variableLocations)) {
// The view's locals needs to have a full set of variable names at construction time
// in order to prevent new variables from being set later in the lifecycle. Since we don't
// want
// to actually create variable bindings for the $implicit bindings, add to the
// protoLocals manually.
MapWrapper.forEach(variableLocations,
(_, templateName) => { this.protoLocals.set(templateName, null); });
}
}
bindElement(parent: ElementBinder, distanceToParent: number,
protoElementInjector: ProtoElementInjector,
componentDirective: DirectiveBinding = null): ElementBinder {
var elBinder = new ElementBinder(this.elementBinders.length, parent, distanceToParent,
protoElementInjector, componentDirective);
this.elementBinders.push(elBinder);
return elBinder;
}
}
isInitialized(): boolean { return isPresent(this.elementBinders); }
}
@@ -1,4 +1,11 @@
import {Injector, Binding, Injectable, ResolvedBinding} from 'angular2/src/core/di';
import {
Injector,
Inject,
Binding,
Injectable,
ResolvedBinding,
forwardRef
} from 'angular2/src/core/di';
import {isPresent, isBlank} from 'angular2/src/core/facade/lang';
import {BaseException} from 'angular2/src/core/facade/exceptions';
import * as viewModule from './view';
@@ -17,6 +24,7 @@ import {AppViewManagerUtils} from './view_manager_utils';
import {AppViewPool} from './view_pool';
import {AppViewListener} from './view_listener';
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
import {ProtoViewFactory} from './proto_view_factory';
/**
* Service exposing low level API for creating, moving and destroying Views.
@@ -26,11 +34,15 @@ import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
*/
@Injectable()
export class AppViewManager {
private _protoViewFactory: ProtoViewFactory;
/**
* @private
*/
constructor(private _viewPool: AppViewPool, private _viewListener: AppViewListener,
private _utils: AppViewManagerUtils, private _renderer: Renderer) {}
private _utils: AppViewManagerUtils, private _renderer: Renderer,
@Inject(forwardRef(() => ProtoViewFactory)) _protoViewFactory) {
this._protoViewFactory = _protoViewFactory;
}
/**
* Returns a {@link ViewContainerRef} of the View Container at the specified location.
@@ -138,13 +150,13 @@ export class AppViewManager {
injector: Injector): HostViewRef {
var s = this._createRootHostViewScope();
var hostProtoView: viewModule.AppProtoView = internalProtoView(hostProtoViewRef);
this._protoViewFactory.initializeProtoViewIfNeeded(hostProtoView);
var hostElementSelector = overrideSelector;
if (isBlank(hostElementSelector)) {
hostElementSelector = hostProtoView.elementBinders[0].componentDirective.metadata.selector;
}
var renderViewWithFragments = this._renderer.createRootHostView(
hostProtoView.mergeMapping.renderProtoViewRef,
hostProtoView.mergeMapping.renderFragmentCount, hostElementSelector);
hostProtoView.render, hostProtoView.mergeInfo.embeddedViewCount + 1, hostElementSelector);
var hostView = this._createMainView(hostProtoView, renderViewWithFragments);
this._renderer.hydrateView(hostView.render);
@@ -196,6 +208,7 @@ export class AppViewManager {
if (protoView.type !== ViewType.EMBEDDED) {
throw new BaseException('This method can only be called with embedded ProtoViews!');
}
this._protoViewFactory.initializeProtoViewIfNeeded(protoView);
return wtfLeave(s, this._createViewInContainer(viewContainerLocation, index, protoView,
templateRef.elementRef, null));
}
@@ -226,6 +239,7 @@ export class AppViewManager {
if (protoView.type !== ViewType.HOST) {
throw new BaseException('This method can only be called with host ProtoViews!');
}
this._protoViewFactory.initializeProtoViewIfNeeded(protoView);
return wtfLeave(
s, this._createViewInContainer(viewContainerLocation, index, protoView,
viewContainerLocation, imperativelyCreatedInjector));
@@ -345,8 +359,8 @@ export class AppViewManager {
var view = this._viewPool.getView(protoView);
if (isBlank(view)) {
view = this._createMainView(
protoView, this._renderer.createView(protoView.mergeMapping.renderProtoViewRef,
protoView.mergeMapping.renderFragmentCount));
protoView,
this._renderer.createView(protoView.render, protoView.mergeInfo.embeddedViewCount + 1));
}
return view;
}
@@ -385,8 +399,7 @@ export class AppViewManager {
}
var viewContainers = view.viewContainers;
var startViewOffset = view.viewOffset;
var endViewOffset =
view.viewOffset + view.mainMergeMapping.nestedViewCountByViewIndex[view.viewOffset];
var endViewOffset = view.viewOffset + view.proto.mergeInfo.viewCount - 1;
var elementOffset = view.elementOffset;
for (var viewIdx = startViewOffset; viewIdx <= endViewOffset; viewIdx++) {
var currView = view.views[viewIdx];
@@ -3,7 +3,6 @@ import {ListWrapper, MapWrapper, Map, StringMapWrapper} from 'angular2/src/core/
import * as eli from './element_injector';
import {isPresent, isBlank} from 'angular2/src/core/facade/lang';
import * as viewModule from './view';
import {internalView} from './view_ref';
import * as avmModule from './view_manager';
import {ElementRef} from './element_ref';
import {TemplateRef} from './template_ref';
@@ -27,42 +26,52 @@ export class AppViewManagerUtils {
var renderFragments = renderViewWithFragments.fragmentRefs;
var renderView = renderViewWithFragments.viewRef;
var elementCount = mergedParentViewProto.mergeMapping.renderElementIndices.length;
var viewCount = mergedParentViewProto.mergeMapping.nestedViewCountByViewIndex[0] + 1;
var elementCount = mergedParentViewProto.mergeInfo.elementCount;
var viewCount = mergedParentViewProto.mergeInfo.viewCount;
var elementRefs: ElementRef[] = ListWrapper.createFixedSize(elementCount);
var viewContainers = ListWrapper.createFixedSize(elementCount);
var preBuiltObjects: eli.PreBuiltObjects[] = ListWrapper.createFixedSize(elementCount);
var elementInjectors = ListWrapper.createFixedSize(elementCount);
var elementInjectors: eli.ElementInjector[] = ListWrapper.createFixedSize(elementCount);
var views = ListWrapper.createFixedSize(viewCount);
var elementOffset = 0;
var textOffset = 0;
var fragmentIdx = 0;
var containerElementIndicesByViewIndex: number[] = ListWrapper.createFixedSize(viewCount);
for (var viewOffset = 0; viewOffset < viewCount; viewOffset++) {
var hostElementIndex =
mergedParentViewProto.mergeMapping.hostElementIndicesByViewIndex[viewOffset];
var parentView = isPresent(hostElementIndex) ?
internalView(elementRefs[hostElementIndex].parentView) :
null;
var containerElementIndex = containerElementIndicesByViewIndex[viewOffset];
var containerElementInjector =
isPresent(containerElementIndex) ? elementInjectors[containerElementIndex] : null;
var parentView =
isPresent(containerElementInjector) ? preBuiltObjects[containerElementIndex].view : null;
var protoView =
isPresent(hostElementIndex) ?
parentView.proto.elementBinders[hostElementIndex - parentView.elementOffset]
isPresent(containerElementIndex) ?
parentView.proto.elementBinders[containerElementIndex - parentView.elementOffset]
.nestedProtoView :
mergedParentViewProto;
var renderFragment = null;
if (viewOffset === 0 || protoView.type === ViewType.EMBEDDED) {
renderFragment = renderFragments[fragmentIdx++];
}
var currentView = new viewModule.AppView(
renderer, protoView, mergedParentViewProto.mergeMapping, viewOffset, elementOffset,
textOffset, protoView.protoLocals, renderView, renderFragment);
var currentView = new viewModule.AppView(renderer, protoView, viewOffset, elementOffset,
textOffset, protoView.protoLocals, renderView,
renderFragment, containerElementInjector);
views[viewOffset] = currentView;
if (isPresent(containerElementIndex)) {
preBuiltObjects[containerElementIndex].nestedView = currentView;
}
var rootElementInjectors = [];
var nestedViewOffset = viewOffset + 1;
for (var binderIdx = 0; binderIdx < protoView.elementBinders.length; binderIdx++) {
var binder = protoView.elementBinders[binderIdx];
var boundElementIndex = elementOffset + binderIdx;
var elementInjector = null;
if (isPresent(binder.nestedProtoView) && binder.nestedProtoView.isMergable) {
containerElementIndicesByViewIndex[nestedViewOffset] = boundElementIndex;
nestedViewOffset += binder.nestedProtoView.mergeInfo.viewCount;
}
// elementInjectors and rootElementInjectors
var protoElementInjector = binder.protoElementInjector;
if (isPresent(protoElementInjector)) {
@@ -78,19 +87,20 @@ export class AppViewManagerUtils {
elementInjectors[boundElementIndex] = elementInjector;
// elementRefs
var el = new ElementRef(
currentView.ref, boundElementIndex,
mergedParentViewProto.mergeMapping.renderElementIndices[boundElementIndex], renderer);
var el = new ElementRef(currentView.ref, boundElementIndex, renderer);
elementRefs[el.boundElementIndex] = el;
// preBuiltObjects
if (isPresent(elementInjector)) {
var templateRef = binder.hasEmbeddedProtoView() ? new TemplateRef(el) : null;
var templateRef = isPresent(binder.nestedProtoView) &&
binder.nestedProtoView.type === ViewType.EMBEDDED ?
new TemplateRef(el) :
null;
preBuiltObjects[boundElementIndex] =
new eli.PreBuiltObjects(viewManager, currentView, el, templateRef);
}
}
currentView.init(protoView.protoChangeDetector.instantiate(currentView), elementInjectors,
currentView.init(protoView.changeDetectorFactory(currentView), elementInjectors,
rootElementInjectors, preBuiltObjects, views, elementRefs, viewContainers);
if (isPresent(parentView) && protoView.type === ViewType.COMPONENT) {
parentView.changeDetector.addShadowDomChild(currentView.changeDetector);
@@ -166,20 +176,19 @@ export class AppViewManagerUtils {
_hydrateView(initView: viewModule.AppView, imperativelyCreatedInjector: Injector,
hostElementInjector: eli.ElementInjector, context: Object, parentLocals: Locals) {
var viewIdx = initView.viewOffset;
var endViewOffset = viewIdx + initView.mainMergeMapping.nestedViewCountByViewIndex[viewIdx];
var endViewOffset = viewIdx + initView.proto.mergeInfo.viewCount - 1;
while (viewIdx <= endViewOffset) {
var currView = initView.views[viewIdx];
var currProtoView = currView.proto;
if (currView !== initView && currView.proto.type === ViewType.EMBEDDED) {
// Don't hydrate components of embedded fragment views.
viewIdx += initView.mainMergeMapping.nestedViewCountByViewIndex[viewIdx] + 1;
viewIdx += currView.proto.mergeInfo.viewCount;
} else {
if (currView !== initView) {
// hydrate a nested component view
imperativelyCreatedInjector = null;
parentLocals = null;
var hostElementIndex = initView.mainMergeMapping.hostElementIndicesByViewIndex[viewIdx];
hostElementInjector = initView.elementInjectors[hostElementIndex];
hostElementInjector = currView.containerElementInjector;
context = hostElementInjector.getComponent();
}
currView.context = context;
@@ -233,8 +242,7 @@ export class AppViewManagerUtils {
}
dehydrateView(initView: viewModule.AppView) {
var endViewOffset = initView.viewOffset +
initView.mainMergeMapping.nestedViewCountByViewIndex[initView.viewOffset];
var endViewOffset = initView.viewOffset + initView.proto.mergeInfo.viewCount - 1;
for (var viewIdx = initView.viewOffset; viewIdx <= endViewOffset; viewIdx++) {
var currView = initView.views[viewIdx];
if (currView.hydrated()) {
@@ -1,3 +0,0 @@
library angular2.di_transformer_dart;
export '../../transform/di_transformer.dart';
+2 -5
View File
@@ -8,19 +8,16 @@ import {CONST_EXPR, Type} from './facade/lang';
import {NgClass} from './directives/ng_class';
import {NgFor} from './directives/ng_for';
import {NgIf} from './directives/ng_if';
import {NgNonBindable} from './directives/ng_non_bindable';
import {NgStyle} from './directives/ng_style';
import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './directives/ng_switch';
export {NgClass} from './directives/ng_class';
export {NgFor} from './directives/ng_for';
export {NgIf} from './directives/ng_if';
export {NgNonBindable} from './directives/ng_non_bindable';
export {NgStyle} from './directives/ng_style';
export {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './directives/ng_switch';
export * from './directives/observable_list_diff';
/**
* A collection of Angular core directives that are likely to be used in each and every Angular
* application.
@@ -65,5 +62,5 @@ export * from './directives/observable_list_diff';
* }
* ```
*/
export const CORE_DIRECTIVES: Type[] = CONST_EXPR(
[NgClass, NgFor, NgIf, NgNonBindable, NgStyle, NgSwitch, NgSwitchWhen, NgSwitchDefault]);
export const CORE_DIRECTIVES: Type[] =
CONST_EXPR([NgClass, NgFor, NgIf, NgStyle, NgSwitch, NgSwitchWhen, NgSwitchDefault]);
@@ -1,18 +0,0 @@
import {Directive} from 'angular2/src/core/metadata';
/**
* The `NgNonBindable` directive tells Angular not to compile or bind the contents of the current
* DOM element. This is useful if the element contains what appears to be Angular directives and
* bindings but which should be ignored by Angular. This could be the case if you have a site that
* displays snippets of code, for instance.
*
* Example:
*
* ```
* <div>Normal: {{1 + 2}}</div> // output "Normal: 3"
* <div ng-non-bindable>Ignored: {{1 + 2}}</div> // output "Ignored: {{1 + 2}}"
* ```
*/
@Directive({selector: '[ng-non-bindable]', compileChildren: false})
export class NgNonBindable {
}
@@ -6,6 +6,12 @@ import 'package:html/dom.dart';
import 'dom_adapter.dart';
import 'emulated_css.dart';
const _attrToPropMap = const {
'innerHtml': 'innerHTML',
'readonly': 'readOnly',
'tabindex': 'tabIndex',
};
abstract class AbstractHtml5LibAdapter implements DomAdapter {
hasProperty(element, String name) {
// This is needed for serverside compile to generate the right getters/setters.
@@ -23,12 +29,9 @@ abstract class AbstractHtml5LibAdapter implements DomAdapter {
throw 'not implemented';
@override
final attrToPropMap = const {
'innerHtml': 'innerHTML',
'readonly': 'readOnly',
'tabindex': 'tabIndex',
};
get attrToPropMap => _attrToPropMap;
@override
set attrToPropMap(value) {
throw 'readonly';
}
@@ -117,6 +117,7 @@ export abstract class DomAdapter {
abstract cssToRules(css: string): any[];
abstract supportsDOMEvents(): boolean;
abstract supportsNativeShadowDOM(): boolean;
abstract supportsUnprefixedCssAnimation(): boolean;
abstract getGlobalEventTarget(target: string): any;
abstract getHistory(): History;
abstract getLocation(): Location;
@@ -70,6 +70,10 @@ export abstract class GenericBrowserDomAdapter extends DomAdapter {
supportsNativeShadowDOM(): boolean {
return isFunction((<any>this.defaultDoc().body).createShadowRoot);
}
supportsUnprefixedCssAnimation(): boolean {
return isPresent(this.defaultDoc().body.style) &&
isPresent(this.defaultDoc().body.style.animationName);
}
getAnimationPrefix(): string {
return isPresent(this._animationPrefix) ? this._animationPrefix : "";
}
File diff suppressed because it is too large Load Diff
@@ -1,11 +1,9 @@
var parse5 = require('parse5');
var parse5 = require('parse5/index');
var parser = new parse5.Parser(parse5.TreeAdapters.htmlparser2);
var serializer = new parse5.Serializer(parse5.TreeAdapters.htmlparser2);
var treeAdapter = parser.treeAdapter;
var cssParse = require('css').parse;
var url = require('url');
var cssParse = require('css/lib/parse/index');
import {MapWrapper, ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection';
import {DomAdapter, setRootDomAdapter} from './dom_adapter';
@@ -487,7 +485,7 @@ export class Parse5DomAdapter extends DomAdapter {
if (href == null) {
el.href = baseUrl;
} else {
el.href = url.resolve(baseUrl, href);
el.href = baseUrl + '/../' + href;
}
}
_buildRules(parsedRules, css?) {
@@ -546,6 +544,12 @@ export class Parse5DomAdapter extends DomAdapter {
return this.defaultDoc().body;
}
}
supportsUnprefixedCssAnimation(): boolean {
// Currently during offline code transformation we do not know
// what browsers we are targetting. To play it safe, we assume
// unprefixed animations are not supported.
return false;
}
getBaseHref(): string { throw 'not implemented'; }
resetBaseElement(): void { throw 'not implemented'; }
getHistory(): History { throw 'not implemented'; }
@@ -0,0 +1,24 @@
library angular2.dom.webWorkerAdapter;
import 'abstract_html_adapter.dart';
import 'dom_adapter.dart';
class WebWorkerDomAdapter extends AbstractHtml5LibAdapter {
static void makeCurrent() {
setRootDomAdapter(new WebWorkerDomAdapter());
}
logError(error) {
print('${error}');
}
log(error) {
print('${error}');
}
logGroup(error) {
print('${error}');
}
logGroupEnd() {}
}
+3 -6
View File
@@ -17,8 +17,7 @@ class Directive extends DirectiveMetadata {
const Directive({String selector, List<String> inputs,
List<String> outputs, Map<String, String> host,
List bindings, String exportAs, String moduleId,
Map<String, dynamic> queries,
bool compileChildren: true})
Map<String, dynamic> queries})
: super(
selector: selector,
inputs: inputs,
@@ -27,8 +26,7 @@ class Directive extends DirectiveMetadata {
bindings: bindings,
exportAs: exportAs,
moduleId: moduleId,
queries: queries,
compileChildren: compileChildren);
queries: queries);
}
/**
@@ -39,7 +37,7 @@ class Component extends ComponentMetadata {
List<String> outputs, Map<String, String> host,
List bindings, String exportAs, String moduleId,
Map<String, dynamic> queries,
bool compileChildren, List viewBindings, ChangeDetectionStrategy changeDetection})
List viewBindings, ChangeDetectionStrategy changeDetection})
: super(
selector: selector,
inputs: inputs,
@@ -48,7 +46,6 @@ class Component extends ComponentMetadata {
bindings: bindings,
exportAs: exportAs,
moduleId: moduleId,
compileChildren: compileChildren,
viewBindings: viewBindings,
queries: queries,
changeDetection: changeDetection);
-4
View File
@@ -153,7 +153,6 @@ export interface DirectiveFactory {
bindings?: any[],
exportAs?: string,
moduleId?: string,
compileChildren?: boolean,
queries?: StringMap<string, any>
}): DirectiveDecorator;
new (obj: {
@@ -164,7 +163,6 @@ export interface DirectiveFactory {
bindings?: any[],
exportAs?: string,
moduleId?: string,
compileChildren?: boolean,
queries?: StringMap<string, any>
}): DirectiveMetadata;
}
@@ -221,7 +219,6 @@ export interface ComponentFactory {
bindings?: any[],
exportAs?: string,
moduleId?: string,
compileChildren?: boolean,
queries?: StringMap<string, any>,
viewBindings?: any[],
changeDetection?: ChangeDetectionStrategy,
@@ -234,7 +231,6 @@ export interface ComponentFactory {
bindings?: any[],
exportAs?: string,
moduleId?: string,
compileChildren?: boolean,
queries?: StringMap<string, any>,
viewBindings?: any[],
changeDetection?: ChangeDetectionStrategy,
@@ -622,12 +622,6 @@ export class DirectiveMetadata extends InjectableMetadata {
*/
host: StringMap<string, string>;
/**
* If set to false the compiler does not compile the children of this directive.
*/
// TODO(vsavkin): This would better fall under the Macro directive concept.
compileChildren: boolean;
/**
* Defines the set of injectable objects that are visible to a Directive and its light DOM
* children.
@@ -744,10 +738,7 @@ export class DirectiveMetadata extends InjectableMetadata {
*/
queries: StringMap<string, any>;
constructor({
selector, inputs, outputs, host, bindings, exportAs, moduleId, queries,
compileChildren = true,
}: {
constructor({selector, inputs, outputs, host, bindings, exportAs, moduleId, queries}: {
selector?: string,
inputs?: string[],
outputs?: string[],
@@ -755,8 +746,7 @@ export class DirectiveMetadata extends InjectableMetadata {
bindings?: any[],
exportAs?: string,
moduleId?: string,
queries?: StringMap<string, any>,
compileChildren?: boolean,
queries?: StringMap<string, any>
} = {}) {
super();
this.selector = selector;
@@ -766,7 +756,6 @@ export class DirectiveMetadata extends InjectableMetadata {
this.exportAs = exportAs;
this.moduleId = moduleId;
this.queries = queries;
this.compileChildren = compileChildren;
this.bindings = bindings;
}
}
@@ -868,20 +857,18 @@ export class ComponentMetadata extends DirectiveMetadata {
viewBindings: any[];
constructor({selector, inputs, outputs, host, exportAs, moduleId, bindings, viewBindings,
changeDetection = ChangeDetectionStrategy.Default, queries, compileChildren = true}:
{
selector?: string,
inputs?: string[],
outputs?: string[],
host?: StringMap<string, string>,
bindings?: any[],
exportAs?: string,
moduleId?: string,
compileChildren?: boolean,
viewBindings?: any[],
queries?: StringMap<string, any>,
changeDetection?: ChangeDetectionStrategy,
} = {}) {
changeDetection = ChangeDetectionStrategy.Default, queries}: {
selector?: string,
inputs?: string[],
outputs?: string[],
host?: StringMap<string, string>,
bindings?: any[],
exportAs?: string,
moduleId?: string,
viewBindings?: any[],
queries?: StringMap<string, any>,
changeDetection?: ChangeDetectionStrategy,
} = {}) {
super({
selector: selector,
inputs: inputs,
@@ -890,8 +877,7 @@ export class ComponentMetadata extends DirectiveMetadata {
exportAs: exportAs,
moduleId: moduleId,
bindings: bindings,
queries: queries,
compileChildren: compileChildren
queries: queries
});
this.changeDetection = changeDetection;
+12 -5
View File
@@ -13,12 +13,19 @@ import {PipeBinding} from './pipe_binding';
import * as cd from 'angular2/src/core/change_detection/pipes';
export class ProtoPipes {
/**
* Map of {@link PipeMetadata} names to {@link PipeMetadata} implementations.
*/
config: StringMap<string, PipeBinding> = {};
static fromBindings(bindings: PipeBinding[]): ProtoPipes {
var config = {};
bindings.forEach(b => config[b.name] = b);
return new ProtoPipes(config);
}
constructor(bindings: PipeBinding[]) { bindings.forEach(b => this.config[b.name] = b); }
constructor(
/**
* Map of {@link PipeMetadata} names to {@link PipeMetadata} implementations.
*/
public config: StringMap<string, PipeBinding>) {
this.config = config;
}
get(name: string): PipeBinding {
var binding = this.config[name];
@@ -11,8 +11,5 @@ export interface PlatformReflectionCapabilities {
getter(name: string): GetterFn;
setter(name: string): SetterFn;
method(name: string): MethodFn;
// TODO(tbosch): remove this method after the new compiler is done
// (and ComponentUrlMapper as well).
importUri(type: Type): string;
moduleId(type: Type): string;
}
@@ -322,11 +322,4 @@ class ReflectionCapabilities implements PlatformReflectionCapabilities {
String importUri(Type type) {
return '${(reflectClass(type).owner as LibraryMirror).uri}';
}
String moduleId(Type type) {
var rootUri = currentMirrorSystem().isolate.rootLibrary.uri;
var moduleUri = (reflectClass(type).owner as LibraryMirror).uri;
var relativeUri = new Uri(pathSegments:moduleUri.pathSegments.sublist(rootUri.pathSegments.length-1)).toString();
return relativeUri.substring(0, relativeUri.lastIndexOf('.'));
}
}

Some files were not shown because too many files have changed in this diff Show More