X Tutup
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions modules/angular2/src/compiler/change_detector_compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,10 @@ export class ChangeDetectionCompiler {
}

private _createChangeDetectorFactory(definition: ChangeDetectorDefinition): Function {
if (IS_DART) {
if (IS_DART || !this._genConfig.useJit) {
var proto = new DynamicProtoChangeDetector(definition);
return (dispatcher) => proto.instantiate(dispatcher);
} else {
// TODO(tbosch): provide a flag in _genConfig whether to allow eval or fall back to dynamic
// change detection as well!
return new ChangeDetectorJITGenerator(definition, UTIL, ABSTRACT_CHANGE_DETECTOR).generate();
}
}
Expand Down
4 changes: 4 additions & 0 deletions modules/angular2/src/compiler/template_compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export class TemplateCompiler {

normalizeDirectiveMetadata(directive:
CompileDirectiveMetadata): Promise<CompileDirectiveMetadata> {
if (!directive.isComponent) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment: For non components there is nothing to be normalized

// For non components there is nothing to be normalized yet.
return PromiseWrapper.resolve(directive);
}
var normalizedTemplatePromise;
if (directive.isComponent) {
normalizedTemplatePromise =
Expand Down
6 changes: 4 additions & 2 deletions modules/angular2/src/core/compiler/template_commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import {
*/
@CONST()
export class CompiledTemplate {
static getChangeDetectorFromData(data: any[]): Function { return data[0]; }
static getCommandsFromData(data: any[]): TemplateCmd[] { return data[1]; }
static getSylesFromData(data: any[]): string[] { return data[2]; }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tbosch, this was supposed to be named getStylesFromData, right ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks for catching.
On Sat, Sep 26, 2015 at 10:00 AM Georgios Kalpakas notifications@github.com
wrote:

In modules/angular2/src/core/compiler/template_commands.ts
#4367 (comment):

@@ -15,6 +15,10 @@ import {
*/
@const()
export class CompiledTemplate {

  • static getChangeDetectorFromData(data: any[]): Function { return data[0]; }
  • static getCommandsFromData(data: any[]): TemplateCmd[] { return data[1]; }
  • static getSylesFromData(data: any[]): string[] { return data[2]; }

@tbosch https://github.com/tbosch, this was suposed to be named
getStylesFromData, right ?


Reply to this email directly or view it on GitHub
https://github.com/angular/angular/pull/4367/files#r40495596.


// Note: paramGetter is a function so that we can have cycles between templates!
// paramGetter returns a tuple with:
// - ChangeDetector factory function
Expand Down Expand Up @@ -91,13 +95,11 @@ export function endElement(): TemplateCmd {
export class BeginComponentCmd implements TemplateCmd, IBeginElementCmd, RenderBeginComponentCmd {
isBound: boolean = true;
templateId: number;
component: Type;
constructor(public name: string, public attrNameAndValues: string[],
public eventTargetAndNames: string[],
public variableNameAndValues: Array<string | number>, public directives: Type[],
public nativeShadow: boolean, public ngContentIndex: number,
public template: CompiledTemplate) {
this.component = directives[0];
this.templateId = template.id;
}
visit(visitor: RenderCommandVisitor, context: any): any {
Expand Down
4 changes: 3 additions & 1 deletion modules/angular2/src/core/dom/browser_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
removeChild(el, node) { el.removeChild(node); }
replaceChild(el: Node, newChild, oldChild) { el.replaceChild(newChild, oldChild); }
remove(node): Node {
node.parentNode.removeChild(node);
if (node.parentNode) {
node.parentNode.removeChild(node);
}
return node;
}
insertBefore(el, node) { el.parentNode.insertBefore(node, el); }
Expand Down
4 changes: 1 addition & 3 deletions modules/angular2/src/core/dom/html_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,7 @@ class Html5LibDomAdapter implements DomAdapter {
return new Element.tag(tagName);
}

createTextNode(String text, [doc]) {
throw 'not implemented';
}
createTextNode(String text, [doc]) => new Text(text);

createScriptTag(String attrName, String attrValue, [doc]) {
throw 'not implemented';
Expand Down
9 changes: 8 additions & 1 deletion modules/angular2/src/core/dom/parse5_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,11 @@ export class Parse5DomAdapter extends DomAdapter {
createElement(tagName): HTMLElement {
return treeAdapter.createElement(tagName, 'http://www.w3.org/1999/xhtml', []);
}
createTextNode(text: string): Text { throw _notImplemented('createTextNode'); }
createTextNode(text: string): Text {
var t = <any>this.createComment(text);
t.type = 'text';
return t;
}
createScriptTag(attrName: string, attrValue: string): HTMLElement {
return treeAdapter.createElement("script", 'http://www.w3.org/1999/xhtml',
[{name: attrName, value: attrValue}]);
Expand Down Expand Up @@ -424,6 +428,9 @@ export class Parse5DomAdapter extends DomAdapter {
setAttribute(element, attribute: string, value: string) {
if (attribute) {
element.attribs[attribute] = value;
if (attribute === 'class') {
element.className = value;
}
}
}
removeAttribute(element, attribute: string) {
Expand Down
62 changes: 62 additions & 0 deletions modules/angular2/src/core/render/view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {BaseException} from 'angular2/src/core/facade/exceptions';
import {ListWrapper, MapWrapper, Map, StringMapWrapper} from 'angular2/src/core/facade/collection';
import {isPresent, isBlank, stringify} from 'angular2/src/core/facade/lang';

import {
RenderViewRef,
RenderEventDispatcher,
RenderTemplateCmd,
RenderProtoViewRef,
RenderFragmentRef
} from './api';

export class DefaultProtoViewRef extends RenderProtoViewRef {
constructor(public cmds: RenderTemplateCmd[]) { super(); }
}

export class DefaultRenderFragmentRef<N> extends RenderFragmentRef {
constructor(public nodes: N[]) { super(); }
}

export class DefaultRenderView<N> extends RenderViewRef {
hydrated: boolean = false;
eventDispatcher: RenderEventDispatcher = null;
globalEventRemovers: Function[] = null;

constructor(public fragments: DefaultRenderFragmentRef<N>[], public boundTextNodes: N[],
public boundElements: N[], public nativeShadowRoots: N[],
public globalEventAdders: Function[]) {
super();
}

hydrate() {
if (this.hydrated) throw new BaseException('The view is already hydrated.');
this.hydrated = true;
this.globalEventRemovers = ListWrapper.createFixedSize(this.globalEventAdders.length);
for (var i = 0; i < this.globalEventAdders.length; i++) {
this.globalEventRemovers[i] = this.globalEventAdders[i]();
}
}

dehydrate() {
if (!this.hydrated) throw new BaseException('The view is already dehydrated.');
for (var i = 0; i < this.globalEventRemovers.length; i++) {
this.globalEventRemovers[i]();
}
this.globalEventRemovers = null;
this.hydrated = false;
}

setEventDispatcher(dispatcher: RenderEventDispatcher) { this.eventDispatcher = dispatcher; }

dispatchRenderEvent(boundElementIndex: number, eventName: string, event: any): boolean {
var allowDefaultBehavior = true;
if (isPresent(this.eventDispatcher)) {
var locals = new Map();
locals.set('$event', event);
allowDefaultBehavior =
this.eventDispatcher.dispatchRenderEvent(boundElementIndex, eventName, locals);
}
return allowDefaultBehavior;
}
}
230 changes: 230 additions & 0 deletions modules/angular2/src/core/render/view_factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
import {isBlank, isPresent} from 'angular2/src/core/facade/lang';
import {
RenderEventDispatcher,
RenderTemplateCmd,
RenderCommandVisitor,
RenderBeginElementCmd,
RenderBeginComponentCmd,
RenderNgContentCmd,
RenderTextCmd,
RenderEmbeddedTemplateCmd
} from './api';
import {DefaultRenderView, DefaultRenderFragmentRef} from './view';

export function createRenderView(fragmentCmds: RenderTemplateCmd[], inplaceElement: any,
nodeFactory: NodeFactory<any>): DefaultRenderView<any> {
var builders: RenderViewBuilder<any>[] = [];
visitAll(new RenderViewBuilder<any>(null, null, inplaceElement, builders, nodeFactory),
fragmentCmds);
var boundElements: any[] = [];
var boundTextNodes: any[] = [];
var nativeShadowRoots: any[] = [];
var fragments: DefaultRenderFragmentRef<any>[] = [];
var viewElementOffset = 0;
var view: DefaultRenderView<any>;
var eventDispatcher = (boundElementIndex: number, eventName: string, event: any) =>
view.dispatchRenderEvent(boundElementIndex, eventName, event);
var globalEventAdders: Function[] = [];

for (var i = 0; i < builders.length; i++) {
var builder = builders[i];
addAll(builder.boundElements, boundElements);
addAll(builder.boundTextNodes, boundTextNodes);
addAll(builder.nativeShadowRoots, nativeShadowRoots);
if (isBlank(builder.rootNodesParent)) {
fragments.push(new DefaultRenderFragmentRef<any>(builder.fragmentRootNodes));
}
for (var j = 0; j < builder.eventData.length; j++) {
var eventData = builder.eventData[j];
var boundElementIndex = eventData[0] + viewElementOffset;
var target = eventData[1];
var eventName = eventData[2];
if (isPresent(target)) {
var handler =
createEventHandler(boundElementIndex, `${target}:${eventName}`, eventDispatcher);
globalEventAdders.push(createGlobalEventAdder(target, eventName, handler, nodeFactory));
} else {
var handler = createEventHandler(boundElementIndex, eventName, eventDispatcher);
nodeFactory.on(boundElements[boundElementIndex], eventName, handler);
}
}
viewElementOffset += builder.boundElements.length;
}
view = new DefaultRenderView<any>(fragments, boundTextNodes, boundElements, nativeShadowRoots,
globalEventAdders);
return view;
}

function createEventHandler(boundElementIndex: number, eventName: string,
eventDispatcher: Function): Function {
return ($event) => eventDispatcher(boundElementIndex, eventName, $event);
}

function createGlobalEventAdder(target: string, eventName: string, eventHandler: Function,
nodeFactory: NodeFactory<any>): Function {
return () => nodeFactory.globalOn(target, eventName, eventHandler);
}

export interface NodeFactory<N> {
resolveComponentTemplate(templateId: number): RenderTemplateCmd[];
createTemplateAnchor(attrNameAndValues: string[]): N;
createElement(name: string, attrNameAndValues: string[]): N;
mergeElement(existing: N, attrNameAndValues: string[]);
createShadowRoot(host: N): N;
createText(value: string): N;
appendChild(parent: N, child: N);
on(element: N, eventName: string, callback: Function);
globalOn(target: string, eventName: string, callback: Function): Function;
}

class RenderViewBuilder<N> implements RenderCommandVisitor {
parentStack: Array<N | Component<N>>;
boundTextNodes: N[] = [];
boundElements: N[] = [];
eventData: any[][] = [];

fragmentRootNodes: N[] = [];
nativeShadowRoots: N[] = [];

constructor(public parentComponent: Component<N>, public rootNodesParent: N,
public inplaceElement: N, public allBuilders: RenderViewBuilder<N>[],
public factory: NodeFactory<N>) {
this.parentStack = [rootNodesParent];
allBuilders.push(this);
}

get parent(): N | Component<N> { return this.parentStack[this.parentStack.length - 1]; }

visitText(cmd: RenderTextCmd, context: any): any {
var text = this.factory.createText(cmd.value);
this._addChild(text, cmd.ngContentIndex);
if (cmd.isBound) {
this.boundTextNodes.push(text);
}
return null;
}
visitNgContent(cmd: RenderNgContentCmd, context: any): any {
if (isPresent(this.parentComponent)) {
var projectedNodes = this.parentComponent.project();
for (var i = 0; i < projectedNodes.length; i++) {
var node = projectedNodes[i];
this._addChild(node, cmd.ngContentIndex);
}
}
return null;
}
visitBeginElement(cmd: RenderBeginElementCmd, context: any): any {
this.parentStack.push(this._beginElement(cmd));
return null;
}
visitEndElement(context: any): any {
this._endElement();
return null;
}
visitBeginComponent(cmd: RenderBeginComponentCmd, context: any): any {
var el = this._beginElement(cmd);
var root = el;
if (cmd.nativeShadow) {
root = this.factory.createShadowRoot(el);
this.nativeShadowRoots.push(root);
}
this.parentStack.push(new Component(el, root, cmd, this.factory));
return null;
}
visitEndComponent(context: any): any {
var c = <Component<N>>this.parent;
var template = this.factory.resolveComponentTemplate(c.cmd.templateId);
this._visitChildTemplate(template, c, c.shadowRoot);
this._endElement();
return null;
}
visitEmbeddedTemplate(cmd: RenderEmbeddedTemplateCmd, context: any): any {
var el = this.factory.createTemplateAnchor(cmd.attrNameAndValues);
this._addChild(el, cmd.ngContentIndex);
this.boundElements.push(el);
if (cmd.isMerged) {
this._visitChildTemplate(cmd.children, this.parentComponent, null);
}
return null;
}

private _beginElement(cmd: RenderBeginElementCmd): N {
var el: N;
if (isPresent(this.inplaceElement)) {
el = this.inplaceElement;
this.inplaceElement = null;
this.factory.mergeElement(el, cmd.attrNameAndValues);
this.fragmentRootNodes.push(el);
} else {
el = this.factory.createElement(cmd.name, cmd.attrNameAndValues);
this._addChild(el, cmd.ngContentIndex);
}
if (cmd.isBound) {
this.boundElements.push(el);
for (var i = 0; i < cmd.eventTargetAndNames.length; i += 2) {
var target = cmd.eventTargetAndNames[i];
var eventName = cmd.eventTargetAndNames[i + 1];
this.eventData.push([this.boundElements.length - 1, target, eventName]);
}
}
return el;
}

private _endElement() { this.parentStack.pop(); }

private _visitChildTemplate(cmds: RenderTemplateCmd[], parent: Component<N>, rootNodesParent: N) {
visitAll(new RenderViewBuilder(parent, rootNodesParent, null, this.allBuilders, this.factory),
cmds);
}

private _addChild(node: N, ngContentIndex: number) {
var parent = this.parent;
if (isPresent(parent)) {
if (parent instanceof Component) {
parent.addContentNode(ngContentIndex, node);
} else {
this.factory.appendChild(<N>parent, node);
}
} else {
this.fragmentRootNodes.push(node);
}
}
}

class Component<N> {
private contentNodesByNgContentIndex: N[][] = [];
private projectingNgContentIndex: number = 0;

constructor(public hostElement: N, public shadowRoot: N, public cmd: RenderBeginComponentCmd,
public factory: NodeFactory<N>) {}
addContentNode(ngContentIndex: number, node: N) {
if (isBlank(ngContentIndex)) {
if (this.cmd.nativeShadow) {
this.factory.appendChild(this.hostElement, node);
}
} else {
while (this.contentNodesByNgContentIndex.length <= ngContentIndex) {
this.contentNodesByNgContentIndex.push([]);
}
this.contentNodesByNgContentIndex[ngContentIndex].push(node);
}
}
project(): N[] {
var ngContentIndex = this.projectingNgContentIndex++;
return ngContentIndex < this.contentNodesByNgContentIndex.length ?
this.contentNodesByNgContentIndex[ngContentIndex] :
[];
}
}

function addAll(source: any[], target: any[]) {
for (var i = 0; i < source.length; i++) {
target.push(source[i]);
}
}

function visitAll(visitor: RenderCommandVisitor, fragmentCmds: RenderTemplateCmd[]) {
for (var i = 0; i < fragmentCmds.length; i++) {
fragmentCmds[i].visit(visitor, null);
}
}
3 changes: 2 additions & 1 deletion modules/angular2/src/test_lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ export function stringifyElement(el): string {
result += '>';

// Children
var children = DOM.childNodes(DOM.templateAwareRoot(el));
var childrenRoot = DOM.templateAwareRoot(el);
var children = isPresent(childrenRoot) ? DOM.childNodes(childrenRoot) : [];
for (let j = 0; j < children.length; j++) {
result += stringifyElement(children[j]);
}
Expand Down
Loading
X Tutup