feat(core): speed up view creation via code gen for view factories.

BREAKING CHANGE:
- Platform pipes can only contain types and arrays of types,
  but no bindings any more.
- When using transformers, platform pipes need to be specified explicitly
  in the pubspec.yaml via the new config option
  `platform_pipes`.
- `Compiler.compileInHost` now returns a `HostViewFactoryRef`
- Component view is not yet created when component constructor is called.
  -> use `onInit` lifecycle callback to access the view of a component
- `ViewRef#setLocal` has been moved to new type `EmbeddedViewRef`
- `internalView` is gone, use `EmbeddedViewRef.rootNodes` to access
  the root nodes of an embedded view
- `renderer.setElementProperty`, `..setElementStyle`, `..setElementAttribute` now
  take a native element instead of an ElementRef
- `Renderer` interface now operates on plain native nodes,
  instead of `RenderElementRef`s or `RenderViewRef`s

Closes #5993
This commit is contained in:
Tobias Bosch
2015-12-02 10:35:51 -08:00
parent a08f50badd
commit 7ae23adaff
191 changed files with 6476 additions and 10232 deletions

View File

@ -9,7 +9,7 @@ import {
platform,
ExceptionHandler,
Reflector,
Renderer,
RootRenderer,
reflector,
APPLICATION_COMMON_PROVIDERS,
PLATFORM_COMMON_PROVIDERS
@ -21,7 +21,7 @@ import {DomEventsPlugin} from 'angular2/src/platform/dom/events/dom_events';
import {KeyEventsPlugin} from 'angular2/src/platform/dom/events/key_events';
import {HammerGesturesPlugin} from 'angular2/src/platform/dom/events/hammer_gestures';
import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
import {DomRenderer, DomRenderer_} from 'angular2/src/platform/dom/dom_renderer';
import {DomRootRenderer, DomRootRenderer_} from 'angular2/src/platform/dom/dom_renderer';
import {DomSharedStylesHost} from 'angular2/src/platform/dom/shared_styles_host';
import {SharedStylesHost} from "angular2/src/platform/dom/shared_styles_host";
import {BrowserDetails} from "angular2/src/animate/browser_details";
@ -77,8 +77,8 @@ export const BROWSER_APP_COMMON_PROVIDERS: Array<any /*Type | Provider | any[]*/
new Provider(EVENT_MANAGER_PLUGINS, {useClass: DomEventsPlugin, multi: true}),
new Provider(EVENT_MANAGER_PLUGINS, {useClass: KeyEventsPlugin, multi: true}),
new Provider(EVENT_MANAGER_PLUGINS, {useClass: HammerGesturesPlugin, multi: true}),
new Provider(DomRenderer, {useClass: DomRenderer_}),
new Provider(Renderer, {useExisting: DomRenderer}),
new Provider(DomRootRenderer, {useClass: DomRootRenderer_}),
new Provider(RootRenderer, {useExisting: DomRootRenderer}),
new Provider(SharedStylesHost, {useExisting: DomSharedStylesHost}),
DomSharedStylesHost,
Testability,

View File

@ -4,7 +4,6 @@ import {Injectable, provide, Provider} from 'angular2/src/core/di';
import {AppViewListener} from 'angular2/src/core/linker/view_listener';
import {AppView} from 'angular2/src/core/linker/view';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {Renderer} from 'angular2/src/core/render/api';
import {DebugElement, DebugElement_} from 'angular2/src/core/debug/debug_element';
const NG_ID_PROPERTY = 'ngid';
@ -43,7 +42,7 @@ export function inspectNativeElement(element): DebugElement {
if (isPresent(elId)) {
var view = _allViewsById.get(elId[0]);
if (isPresent(view)) {
return new DebugElement_(view, elId[1]);
return new DebugElement_(view.appElements[elId[1]]);
}
}
return null;
@ -51,17 +50,15 @@ export function inspectNativeElement(element): DebugElement {
@Injectable()
export class DebugElementViewListener implements AppViewListener {
constructor(private _renderer: Renderer) {
DOM.setGlobalVar(INSPECT_GLOBAL_NAME, inspectNativeElement);
}
constructor() { DOM.setGlobalVar(INSPECT_GLOBAL_NAME, inspectNativeElement); }
onViewCreated(view: AppView) {
var viewId = _nextId++;
_allViewsById.set(viewId, view);
_allIdsByView.set(view, viewId);
for (var i = 0; i < view.elementRefs.length; i++) {
var el = view.elementRefs[i];
_setElementId(this._renderer.getNativeElementSync(el), [viewId, i]);
for (var i = 0; i < view.appElements.length; i++) {
var el = view.appElements[i];
_setElementId(el.nativeElement, [viewId, i]);
}
}

View File

@ -7,38 +7,18 @@ import {
RegExpWrapper,
CONST_EXPR,
stringify,
StringWrapper
StringWrapper,
isArray
} from 'angular2/src/facade/lang';
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
import {DomSharedStylesHost} from './shared_styles_host';
import {WtfScopeFn, wtfLeave, wtfCreateScope} from 'angular2/src/core/profile/profile';
import {
Renderer,
RenderProtoViewRef,
RenderViewRef,
RenderElementRef,
RenderFragmentRef,
RenderViewWithFragments,
RenderTemplateCmd,
RenderEventDispatcher,
RenderComponentTemplate
} from 'angular2/core';
import {Renderer, RootRenderer, RenderComponentType} from 'angular2/core';
import {EventManager} from './events/event_manager';
import {DOCUMENT} from './dom_tokens';
import {
createRenderView,
NodeFactory,
encapsulateStyles
} from 'angular2/src/core/render/view_factory';
import {
DefaultRenderView,
DefaultRenderFragmentRef,
DefaultProtoViewRef
} from 'angular2/src/core/render/view';
import {ViewEncapsulation} from 'angular2/src/core/metadata';
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {camelCaseToDashCase} from './util';
@ -48,243 +28,225 @@ const NAMESPACE_URIS =
const TEMPLATE_COMMENT_TEXT = 'template bindings={}';
var TEMPLATE_BINDINGS_EXP = /^template bindings=(.*)$/g;
export abstract class DomRenderer extends Renderer implements NodeFactory<Node> {
abstract registerComponentTemplate(template: RenderComponentTemplate);
export abstract class DomRootRenderer implements RootRenderer {
private _registeredComponents: Map<string, DomRenderer> = new Map<string, DomRenderer>();
abstract resolveComponentTemplate(templateId: string): RenderComponentTemplate;
constructor(public document: any, public eventManager: EventManager,
public sharedStylesHost: DomSharedStylesHost, public animate: AnimationBuilder) {}
abstract createProtoView(componentTemplateId: string,
cmds: RenderTemplateCmd[]): RenderProtoViewRef;
abstract createRootHostView(hostProtoViewRef: RenderProtoViewRef, fragmentCount: number,
hostElementSelector: string): RenderViewWithFragments;
abstract createView(protoViewRef: RenderProtoViewRef,
fragmentCount: number): RenderViewWithFragments;
abstract destroyView(viewRef: RenderViewRef);
abstract createRootContentInsertionPoint();
getNativeElementSync(location: RenderElementRef): any {
return resolveInternalDomView(location.renderView).boundElements[location.boundElementIndex];
renderComponent(componentProto: RenderComponentType): Renderer {
var renderer = this._registeredComponents.get(componentProto.id);
if (isBlank(renderer)) {
renderer = new DomRenderer(this, componentProto);
this._registeredComponents.set(componentProto.id, renderer);
}
return renderer;
}
}
getRootNodes(fragment: RenderFragmentRef): Node[] { return resolveInternalDomFragment(fragment); }
@Injectable()
export class DomRootRenderer_ extends DomRootRenderer {
constructor(@Inject(DOCUMENT) _document: any, _eventManager: EventManager,
sharedStylesHost: DomSharedStylesHost, animate: AnimationBuilder) {
super(_document, _eventManager, sharedStylesHost, animate);
}
}
attachFragmentAfterFragment(previousFragmentRef: RenderFragmentRef,
fragmentRef: RenderFragmentRef) {
var previousFragmentNodes = resolveInternalDomFragment(previousFragmentRef);
if (previousFragmentNodes.length > 0) {
var sibling = previousFragmentNodes[previousFragmentNodes.length - 1];
let nodes = resolveInternalDomFragment(fragmentRef);
moveNodesAfterSibling(sibling, nodes);
this.animateNodesEnter(nodes);
export class DomRenderer implements Renderer {
private _contentAttr: string;
private _hostAttr: string;
private _styles: string[];
constructor(private _rootRenderer: DomRootRenderer, private componentProto: RenderComponentType) {
this._styles = _flattenStyles(componentProto.id, componentProto.styles, []);
if (componentProto.encapsulation !== ViewEncapsulation.Native) {
this._rootRenderer.sharedStylesHost.addStyles(this._styles);
}
if (this.componentProto.encapsulation === ViewEncapsulation.Emulated) {
this._contentAttr = _shimContentAttribute(componentProto.id);
this._hostAttr = _shimHostAttribute(componentProto.id);
} else {
this._contentAttr = null;
this._hostAttr = null;
}
}
/**
* Iterates through all nodes being added to the DOM and animates them if necessary
* @param nodes
*/
animateNodesEnter(nodes: Node[]) {
for (let i = 0; i < nodes.length; i++) this.animateNodeEnter(nodes[i]);
renderComponent(componentProto: RenderComponentType): Renderer {
return this._rootRenderer.renderComponent(componentProto);
}
selectRootElement(selector: string): Element {
var el = DOM.querySelector(this._rootRenderer.document, selector);
if (isBlank(el)) {
throw new BaseException(`The selector "${selector}" did not match any elements`);
}
DOM.clearNodes(el);
return el;
}
createElement(parent: Element, name: string): Node {
var nsAndName = splitNamespace(name);
var el = isPresent(nsAndName[0]) ?
DOM.createElementNS(NAMESPACE_URIS[nsAndName[0]], nsAndName[1]) :
DOM.createElement(nsAndName[1]);
if (isPresent(this._contentAttr)) {
DOM.setAttribute(el, this._contentAttr, '');
}
if (isPresent(parent)) {
DOM.appendChild(parent, el);
}
return el;
}
createViewRoot(hostElement: any): any {
var nodesParent;
if (this.componentProto.encapsulation === ViewEncapsulation.Native) {
nodesParent = DOM.createShadowRoot(hostElement);
this._rootRenderer.sharedStylesHost.addHost(nodesParent);
for (var i = 0; i < this._styles.length; i++) {
DOM.appendChild(nodesParent, DOM.createStyleElement(this._styles[i]));
}
} else {
if (isPresent(this._hostAttr)) {
DOM.setAttribute(hostElement, this._hostAttr, '');
}
nodesParent = hostElement;
}
return nodesParent;
}
createTemplateAnchor(parentElement: any): any {
var comment = DOM.createComment(TEMPLATE_COMMENT_TEXT);
if (isPresent(parentElement)) {
DOM.appendChild(parentElement, comment);
}
return comment;
}
createText(parentElement: any, value: string): any {
var node = DOM.createTextNode(value);
if (isPresent(parentElement)) {
DOM.appendChild(parentElement, node);
}
return node;
}
projectNodes(parentElement: any, nodes: any[]) {
if (isBlank(parentElement)) return;
appendNodes(parentElement, nodes);
}
attachViewAfter(node: any, viewRootNodes: any[]) {
moveNodesAfterSibling(node, viewRootNodes);
for (let i = 0; i < viewRootNodes.length; i++) this.animateNodeEnter(viewRootNodes[i]);
}
detachView(viewRootNodes: any[]) {
for (var i = 0; i < viewRootNodes.length; i++) {
var node = viewRootNodes[i];
DOM.remove(node);
this.animateNodeLeave(node);
}
}
destroyView(hostElement: any, viewAllNodes: any[]) {
if (this.componentProto.encapsulation === ViewEncapsulation.Native && isPresent(hostElement)) {
this._rootRenderer.sharedStylesHost.removeHost(DOM.getShadowRoot(hostElement));
}
}
listen(renderElement: any, name: string, callback: Function) {
this._rootRenderer.eventManager.addEventListener(renderElement, name,
decoratePreventDefault(callback));
}
listenGlobal(target: string, name: string, callback: Function): Function {
return this._rootRenderer.eventManager.addGlobalEventListener(target, name,
decoratePreventDefault(callback));
}
setElementProperty(renderElement: any, propertyName: string, propertyValue: any): void {
DOM.setProperty(renderElement, propertyName, propertyValue);
}
setElementAttribute(renderElement: any, attributeName: string, attributeValue: string): void {
var attrNs;
var nsAndName = splitNamespace(attributeName);
if (isPresent(nsAndName[0])) {
attributeName = nsAndName[0] + ':' + nsAndName[1];
attrNs = NAMESPACE_URIS[nsAndName[0]];
}
if (isPresent(attributeValue)) {
if (isPresent(attrNs)) {
DOM.setAttributeNS(renderElement, attrNs, attributeName, attributeValue);
} else {
DOM.setAttribute(renderElement, nsAndName[1], attributeValue);
}
} else {
DOM.removeAttribute(renderElement, attributeName);
}
}
setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string): void {
var dashCasedPropertyName = camelCaseToDashCase(propertyName);
if (DOM.isCommentNode(renderElement)) {
var existingBindings = RegExpWrapper.firstMatch(
TEMPLATE_BINDINGS_EXP, StringWrapper.replaceAll(DOM.getText(renderElement), /\n/g, ''));
var parsedBindings = Json.parse(existingBindings[1]);
parsedBindings[dashCasedPropertyName] = propertyValue;
DOM.setText(renderElement, StringWrapper.replace(TEMPLATE_COMMENT_TEXT, '{}',
Json.stringify(parsedBindings)));
} else {
this.setElementAttribute(renderElement, propertyName, propertyValue);
}
}
setElementClass(renderElement: any, className: string, isAdd: boolean): void {
if (isAdd) {
DOM.addClass(renderElement, className);
} else {
DOM.removeClass(renderElement, className);
}
}
setElementStyle(renderElement: any, styleName: string, styleValue: string): void {
if (isPresent(styleValue)) {
DOM.setStyle(renderElement, styleName, stringify(styleValue));
} else {
DOM.removeStyle(renderElement, styleName);
}
}
invokeElementMethod(renderElement: any, methodName: string, args: any[]): void {
DOM.invoke(renderElement, methodName, args);
}
setText(renderNode: any, text: string): void { DOM.setText(renderNode, text); }
/**
* Performs animations if necessary
* @param node
*/
abstract animateNodeEnter(node: Node);
/**
* If animations are necessary, performs animations then removes the element; otherwise, it just
* removes the element.
* @param node
*/
abstract animateNodeLeave(node: Node);
attachFragmentAfterElement(elementRef: RenderElementRef, fragmentRef: RenderFragmentRef) {
var parentView = resolveInternalDomView(elementRef.renderView);
var element = parentView.boundElements[elementRef.boundElementIndex];
var nodes = resolveInternalDomFragment(fragmentRef);
moveNodesAfterSibling(element, nodes);
this.animateNodesEnter(nodes);
}
abstract detachFragment(fragmentRef: RenderFragmentRef);
hydrateView(viewRef: RenderViewRef) { resolveInternalDomView(viewRef).hydrate(); }
dehydrateView(viewRef: RenderViewRef) { resolveInternalDomView(viewRef).dehydrate(); }
createTemplateAnchor(attrNameAndValues: string[]): Node {
return DOM.createComment(TEMPLATE_COMMENT_TEXT);
}
abstract createElement(name: string, attrNameAndValues: string[]): Node;
abstract mergeElement(existing: Node, attrNameAndValues: string[]);
abstract createShadowRoot(host: Node, templateId: string): Node;
createText(value: string): Node { return DOM.createTextNode(isPresent(value) ? value : ''); }
appendChild(parent: Node, child: Node) { DOM.appendChild(parent, child); }
abstract on(element: Node, eventName: string, callback: Function);
abstract globalOn(target: string, eventName: string, callback: Function): Function;
setElementProperty(location: RenderElementRef, propertyName: string, propertyValue: any): void {
var view = resolveInternalDomView(location.renderView);
DOM.setProperty(<Element>view.boundElements[location.boundElementIndex], propertyName,
propertyValue);
}
setElementAttribute(location: RenderElementRef, attributeName: string,
attributeValue: string): void {
var view = resolveInternalDomView(location.renderView);
var element = view.boundElements[location.boundElementIndex];
if (isPresent(attributeValue)) {
DOM.setAttribute(element, attributeName, stringify(attributeValue));
} else {
DOM.removeAttribute(element, attributeName);
}
}
/**
* Used only in debug mode to serialize property changes to comment nodes,
* such as <template> placeholders.
*/
setBindingDebugInfo(location: RenderElementRef, propertyName: string,
propertyValue: string): void {
var view: DefaultRenderView<Node> = resolveInternalDomView(location.renderView);
var element = view.boundElements[location.boundElementIndex];
var dashCasedPropertyName = camelCaseToDashCase(propertyName);
if (DOM.isCommentNode(element)) {
var existingBindings = RegExpWrapper.firstMatch(
TEMPLATE_BINDINGS_EXP, StringWrapper.replaceAll(DOM.getText(element), /\n/g, ''));
var parsedBindings = Json.parse(existingBindings[1]);
parsedBindings[dashCasedPropertyName] = propertyValue;
DOM.setText(element, StringWrapper.replace(TEMPLATE_COMMENT_TEXT, '{}',
Json.stringify(parsedBindings)));
} else {
this.setElementAttribute(location, propertyName, propertyValue);
}
}
setElementClass(location: RenderElementRef, className: string, isAdd: boolean): void {
var view = resolveInternalDomView(location.renderView);
var element = view.boundElements[location.boundElementIndex];
if (isAdd) {
DOM.addClass(element, className);
} else {
DOM.removeClass(element, className);
}
}
setElementStyle(location: RenderElementRef, styleName: string, styleValue: string): void {
var view = resolveInternalDomView(location.renderView);
var element = view.boundElements[location.boundElementIndex];
if (isPresent(styleValue)) {
DOM.setStyle(element, styleName, stringify(styleValue));
} else {
DOM.removeStyle(element, styleName);
}
}
invokeElementMethod(location: RenderElementRef, methodName: string, args: any[]): void {
var view = resolveInternalDomView(location.renderView);
var element = <Element>view.boundElements[location.boundElementIndex];
DOM.invoke(element, methodName, args);
}
setText(viewRef: RenderViewRef, textNodeIndex: number, text: string): void {
var view = resolveInternalDomView(viewRef);
DOM.setText(view.boundTextNodes[textNodeIndex], text);
}
setEventDispatcher(viewRef: RenderViewRef, dispatcher: RenderEventDispatcher): void {
resolveInternalDomView(viewRef).setEventDispatcher(dispatcher);
}
}
@Injectable()
export class DomRenderer_ extends DomRenderer {
private _componentTpls: Map<string, RenderComponentTemplate> =
new Map<string, RenderComponentTemplate>();
private _document;
constructor(private _eventManager: EventManager,
private _domSharedStylesHost: DomSharedStylesHost, private _animate: AnimationBuilder,
@Inject(DOCUMENT) document) {
super();
this._document = document;
}
registerComponentTemplate(template: RenderComponentTemplate) {
this._componentTpls.set(template.id, template);
if (template.encapsulation !== ViewEncapsulation.Native) {
var encapsulatedStyles = encapsulateStyles(template);
this._domSharedStylesHost.addStyles(encapsulatedStyles);
}
}
createProtoView(componentTemplateId: string, cmds: RenderTemplateCmd[]): RenderProtoViewRef {
return new DefaultProtoViewRef(this._componentTpls.get(componentTemplateId), cmds);
}
resolveComponentTemplate(templateId: string): RenderComponentTemplate {
return this._componentTpls.get(templateId);
}
/** @internal */
_createRootHostViewScope: WtfScopeFn = wtfCreateScope('DomRenderer#createRootHostView()');
createRootHostView(hostProtoViewRef: RenderProtoViewRef, fragmentCount: number,
hostElementSelector: string): RenderViewWithFragments {
var s = this._createRootHostViewScope();
var element = DOM.querySelector(this._document, hostElementSelector);
if (isBlank(element)) {
wtfLeave(s);
throw new BaseException(`The selector "${hostElementSelector}" did not match any elements`);
}
return wtfLeave(s, this._createView(hostProtoViewRef, element));
}
/** @internal */
_createViewScope = wtfCreateScope('DomRenderer#createView()');
createView(protoViewRef: RenderProtoViewRef, fragmentCount: number): RenderViewWithFragments {
var s = this._createViewScope();
return wtfLeave(s, this._createView(protoViewRef, null));
}
private _createView(protoViewRef: RenderProtoViewRef,
inplaceElement: HTMLElement): RenderViewWithFragments {
var dpvr = <DefaultProtoViewRef>protoViewRef;
var view = createRenderView(dpvr.template, dpvr.cmds, inplaceElement, this);
var sdRoots = view.nativeShadowRoots;
for (var i = 0; i < sdRoots.length; i++) {
this._domSharedStylesHost.addHost(sdRoots[i]);
}
return new RenderViewWithFragments(view, view.fragments);
}
destroyView(viewRef: RenderViewRef) {
var view = <DefaultRenderView<Node>>viewRef;
var sdRoots = view.nativeShadowRoots;
for (var i = 0; i < sdRoots.length; i++) {
this._domSharedStylesHost.removeHost(sdRoots[i]);
}
}
animateNodeEnter(node: Node) {
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
DOM.addClass(node, 'ng-enter');
this._animate.css()
this._rootRenderer.animate.css()
.addAnimationClass('ng-enter-active')
.start(<HTMLElement>node)
.onComplete(() => { DOM.removeClass(node, 'ng-enter'); });
}
}
/**
* If animations are necessary, performs animations then removes the element; otherwise, it just
* removes the element.
* @param node
*/
animateNodeLeave(node: Node) {
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
DOM.addClass(node, 'ng-leave');
this._animate.css()
this._rootRenderer.animate.css()
.addAnimationClass('ng-leave-active')
.start(<HTMLElement>node)
.onComplete(() => {
@ -295,73 +257,6 @@ export class DomRenderer_ extends DomRenderer {
DOM.remove(node);
}
}
/** @internal */
_detachFragmentScope = wtfCreateScope('DomRenderer#detachFragment()');
detachFragment(fragmentRef: RenderFragmentRef) {
var s = this._detachFragmentScope();
var fragmentNodes = resolveInternalDomFragment(fragmentRef);
for (var i = 0; i < fragmentNodes.length; i++) {
this.animateNodeLeave(fragmentNodes[i]);
}
wtfLeave(s);
}
createElement(name: string, attrNameAndValues: string[]): Node {
var nsAndName = splitNamespace(name);
var el = isPresent(nsAndName[0]) ?
DOM.createElementNS(NAMESPACE_URIS[nsAndName[0]], nsAndName[1]) :
DOM.createElement(nsAndName[1]);
this._setAttributes(el, attrNameAndValues);
return el;
}
mergeElement(existing: Node, attrNameAndValues: string[]) {
DOM.clearNodes(existing);
this._setAttributes(existing, attrNameAndValues);
}
private _setAttributes(node: Node, attrNameAndValues: string[]) {
for (var attrIdx = 0; attrIdx < attrNameAndValues.length; attrIdx += 2) {
var attrNs;
var attrName = attrNameAndValues[attrIdx];
var nsAndName = splitNamespace(attrName);
if (isPresent(nsAndName[0])) {
attrName = nsAndName[0] + ':' + nsAndName[1];
attrNs = NAMESPACE_URIS[nsAndName[0]];
}
var attrValue = attrNameAndValues[attrIdx + 1];
if (isPresent(attrNs)) {
DOM.setAttributeNS(node, attrNs, attrName, attrValue);
} else {
DOM.setAttribute(node, nsAndName[1], attrValue);
}
}
}
createRootContentInsertionPoint(): Node {
return DOM.createComment('root-content-insertion-point');
}
createShadowRoot(host: Node, templateId: string): Node {
var sr = DOM.createShadowRoot(host);
var tpl = this._componentTpls.get(templateId);
for (var i = 0; i < tpl.styles.length; i++) {
DOM.appendChild(sr, DOM.createStyleElement(tpl.styles[i]));
}
return sr;
}
on(element: Node, eventName: string, callback: Function) {
this._eventManager.addEventListener(<HTMLElement>element, eventName,
decoratePreventDefault(callback));
}
globalOn(target: string, eventName: string, callback: Function): Function {
return this._eventManager.addGlobalEventListener(target, eventName,
decoratePreventDefault(callback));
}
}
function resolveInternalDomView(viewRef: RenderViewRef): DefaultRenderView<Node> {
return <DefaultRenderView<Node>>viewRef;
}
function resolveInternalDomFragment(fragmentRef: RenderFragmentRef): Node[] {
return (<DefaultRenderFragmentRef<Node>>fragmentRef).nodes;
}
function moveNodesAfterSibling(sibling, nodes) {
@ -380,16 +275,48 @@ function moveNodesAfterSibling(sibling, nodes) {
}
}
function appendNodes(parent, nodes) {
for (var i = 0; i < nodes.length; i++) {
DOM.appendChild(parent, nodes[i]);
}
}
function decoratePreventDefault(eventHandler: Function): Function {
return (event) => {
var allowDefaultBehavior = eventHandler(event);
if (!allowDefaultBehavior) {
if (allowDefaultBehavior === false) {
// TODO(tbosch): move preventDefault into event plugins...
DOM.preventDefault(event);
}
};
}
var COMPONENT_REGEX = /%COMP%/g;
export const COMPONENT_VARIABLE = '%COMP%';
export const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
export const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
function _shimContentAttribute(componentShortId: string): string {
return StringWrapper.replaceAll(CONTENT_ATTR, COMPONENT_REGEX, componentShortId);
}
function _shimHostAttribute(componentShortId: string): string {
return StringWrapper.replaceAll(HOST_ATTR, COMPONENT_REGEX, componentShortId);
}
function _flattenStyles(compId: string, styles: Array<any | any[]>, target: string[]): string[] {
for (var i = 0; i < styles.length; i++) {
var style = styles[i];
if (isArray(style)) {
_flattenStyles(compId, style, target);
} else {
style = StringWrapper.replaceAll(style, COMPONENT_REGEX, compId);
target.push(style);
}
}
return target;
}
var NS_PREFIX_RE = /^@([^:]+):(.+)/g;
function splitNamespace(name: string): string[] {
@ -398,4 +325,4 @@ function splitNamespace(name: string): string[] {
}
let match = RegExpWrapper.firstMatch(NS_PREFIX_RE, name);
return [match[1], match[2]];
}
}

View File

@ -1,8 +1,8 @@
import {XHR} from 'angular2/src/compiler/xhr';
import {WebWorkerXHRImpl} from 'angular2/src/web_workers/worker/xhr_impl';
import {WebWorkerRenderer} from 'angular2/src/web_workers/worker/renderer';
import {WebWorkerRootRenderer} from 'angular2/src/web_workers/worker/renderer';
import {print, Type, CONST_EXPR, isPresent} from 'angular2/src/facade/lang';
import {Renderer} from 'angular2/src/core/render/api';
import {RootRenderer} from 'angular2/src/core/render/api';
import {
PLATFORM_DIRECTIVES,
PLATFORM_PIPES,
@ -23,11 +23,7 @@ import {COMPILER_PROVIDERS} from 'angular2/src/compiler/compiler';
import {Serializer} from "angular2/src/web_workers/shared/serializer";
import {ON_WEB_WORKER} from "angular2/src/web_workers/shared/api";
import {Provider} from 'angular2/src/core/di';
import {RenderProtoViewRefStore} from 'angular2/src/web_workers/shared/render_proto_view_ref_store';
import {
RenderViewWithFragmentsStore
} from 'angular2/src/web_workers/shared/render_view_with_fragments_store';
import {WebWorkerEventDispatcher} from 'angular2/src/web_workers/worker/event_dispatcher';
import {RenderStore} from 'angular2/src/web_workers/shared/render_store';
class PrintLogger {
log = print;
@ -48,15 +44,13 @@ export const WORKER_APP_APPLICATION_COMMON: Array<any /*Type | Provider | any[]*
new Provider(PLATFORM_DIRECTIVES, {useValue: COMMON_DIRECTIVES, multi: true}),
new Provider(ClientMessageBrokerFactory, {useClass: ClientMessageBrokerFactory_}),
new Provider(ServiceMessageBrokerFactory, {useClass: ServiceMessageBrokerFactory_}),
WebWorkerRenderer,
new Provider(Renderer, {useExisting: WebWorkerRenderer}),
WebWorkerRootRenderer,
new Provider(RootRenderer, {useExisting: WebWorkerRootRenderer}),
new Provider(ON_WEB_WORKER, {useValue: true}),
RenderViewWithFragmentsStore,
RenderProtoViewRefStore,
RenderStore,
new Provider(ExceptionHandler, {useFactory: _exceptionHandler, deps: []}),
WebWorkerXHRImpl,
new Provider(XHR, {useExisting: WebWorkerXHRImpl}),
WebWorkerEventDispatcher
new Provider(XHR, {useExisting: WebWorkerXHRImpl})
]);
function _exceptionHandler(): ExceptionHandler {

View File

@ -11,7 +11,7 @@ import {
reflector,
APPLICATION_COMMON_PROVIDERS,
PLATFORM_COMMON_PROVIDERS,
Renderer,
RootRenderer,
PLATFORM_INITIALIZER,
APP_INITIALIZER
} from 'angular2/core';
@ -23,7 +23,7 @@ import {DomEventsPlugin} from 'angular2/src/platform/dom/events/dom_events';
import {KeyEventsPlugin} from 'angular2/src/platform/dom/events/key_events';
import {HammerGesturesPlugin} from 'angular2/src/platform/dom/events/hammer_gestures';
import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
import {DomRenderer, DomRenderer_} from 'angular2/src/platform/dom/dom_renderer';
import {DomRootRenderer, DomRootRenderer_} from 'angular2/src/platform/dom/dom_renderer';
import {DomSharedStylesHost} from 'angular2/src/platform/dom/shared_styles_host';
import {SharedStylesHost} from "angular2/src/platform/dom/shared_styles_host";
import {BrowserDetails} from 'angular2/src/animate/browser_details';
@ -46,10 +46,7 @@ import {
} from 'angular2/src/web_workers/shared/client_message_broker';
import {Serializer} from 'angular2/src/web_workers/shared/serializer';
import {ON_WEB_WORKER} from 'angular2/src/web_workers/shared/api';
import {RenderProtoViewRefStore} from 'angular2/src/web_workers/shared/render_proto_view_ref_store';
import {
RenderViewWithFragmentsStore
} from 'angular2/src/web_workers/shared/render_view_with_fragments_store';
import {RenderStore} from 'angular2/src/web_workers/shared/render_store';
export const WORKER_SCRIPT: OpaqueToken = CONST_EXPR(new OpaqueToken("WebWorkerScript"));
@ -72,8 +69,8 @@ export const WORKER_RENDER_APP_COMMON: Array<any /*Type | Provider | any[]*/> =
new Provider(EVENT_MANAGER_PLUGINS, {useClass: DomEventsPlugin, multi: true}),
new Provider(EVENT_MANAGER_PLUGINS, {useClass: KeyEventsPlugin, multi: true}),
new Provider(EVENT_MANAGER_PLUGINS, {useClass: HammerGesturesPlugin, multi: true}),
new Provider(DomRenderer, {useClass: DomRenderer_}),
new Provider(Renderer, {useExisting: DomRenderer}),
new Provider(DomRootRenderer, {useClass: DomRootRenderer_}),
new Provider(RootRenderer, {useExisting: DomRootRenderer}),
new Provider(SharedStylesHost, {useExisting: DomSharedStylesHost}),
new Provider(XHR, {useClass: XHRImpl}),
MessageBasedXHRImpl,
@ -81,8 +78,7 @@ export const WORKER_RENDER_APP_COMMON: Array<any /*Type | Provider | any[]*/> =
new Provider(ClientMessageBrokerFactory, {useClass: ClientMessageBrokerFactory_}),
Serializer,
new Provider(ON_WEB_WORKER, {useValue: false}),
RenderViewWithFragmentsStore,
RenderProtoViewRefStore,
RenderStore,
DomSharedStylesHost,
Testability,
BrowserDetails,