fix(ivy): store local variables in data instead of calling loadDirective (#23029)
PR Close #23029
This commit is contained in:
parent
bd024c02e2
commit
5a86f7144f
|
@ -494,37 +494,27 @@ export function renderComponentOrTemplate<T>(
|
||||||
* ['id', 'warning5', 'class', 'alert']
|
* ['id', 'warning5', 'class', 'alert']
|
||||||
*/
|
*/
|
||||||
export function elementStart(
|
export function elementStart(
|
||||||
index: number, name?: string, attrs?: string[] | null, localRefs?: string[] | null): RElement {
|
index: number, name: string, attrs?: string[] | null, localRefs?: string[] | null): RElement {
|
||||||
let node: LElementNode;
|
let node: LElementNode;
|
||||||
let native: RElement;
|
let native: RElement;
|
||||||
|
ngDevMode &&
|
||||||
|
assertNull(currentView.bindingStartIndex, 'elements should be created before any bindings');
|
||||||
|
|
||||||
if (name == null) {
|
native = renderer.createElement(name);
|
||||||
// native node retrieval - used for exporting elements as tpl local variables (<div #foo>)
|
node = createLNode(index, LNodeType.Element, native !, null);
|
||||||
const node = data[index] !;
|
|
||||||
native = node && (node as LElementNode).native;
|
|
||||||
} else {
|
|
||||||
ngDevMode &&
|
|
||||||
assertNull(currentView.bindingStartIndex, 'elements should be created before any bindings');
|
|
||||||
|
|
||||||
native = renderer.createElement(name);
|
if (attrs) setUpAttributes(native, attrs);
|
||||||
node = createLNode(index, LNodeType.Element, native !, null);
|
appendChild(node.parent !, native, currentView);
|
||||||
|
|
||||||
if (attrs) setUpAttributes(native, attrs);
|
if (firstTemplatePass) {
|
||||||
appendChild(node.parent !, native, currentView);
|
const tNode = createTNode(name, attrs || null, null);
|
||||||
|
cacheMatchingDirectivesForNode(tNode);
|
||||||
|
|
||||||
if (firstTemplatePass) {
|
ngDevMode && assertDataInRange(index - 1);
|
||||||
const tNode = createTNode(name, attrs || null, null, null);
|
node.tNode = tData[index] = tNode;
|
||||||
cacheMatchingDirectivesForNode(tNode);
|
|
||||||
|
|
||||||
ngDevMode && assertDataInRange(index - 1);
|
|
||||||
node.tNode = tData[index] = tNode;
|
|
||||||
|
|
||||||
if (!isComponent(tNode)) {
|
|
||||||
tNode.localNames = findMatchingLocalNames(null, localRefs, -1, '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hack_declareDirectives(index, localRefs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hack_declareDirectives(index, localRefs || null);
|
||||||
return native;
|
return native;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,11 +580,14 @@ export function isComponent(tNode: TNode): boolean {
|
||||||
* This function instantiates the given directives. It is a hack since it assumes the directives
|
* This function instantiates the given directives. It is a hack since it assumes the directives
|
||||||
* come in the correct order for DI.
|
* come in the correct order for DI.
|
||||||
*/
|
*/
|
||||||
function hack_declareDirectives(elementIndex: number, localRefs: string[] | null | undefined) {
|
function hack_declareDirectives(elementIndex: number, localRefs: string[] | null) {
|
||||||
const size = (previousOrParentNode.tNode !.flags & TNodeFlags.SIZE_MASK) >> TNodeFlags.SIZE_SHIFT;
|
const tNode = previousOrParentNode.tNode !;
|
||||||
|
const size = (tNode.flags & TNodeFlags.SIZE_MASK) >> TNodeFlags.SIZE_SHIFT;
|
||||||
|
|
||||||
|
const exportsMap: {[key: string]: number}|null = firstTemplatePass && localRefs ? {'': -1} : null;
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
let startIndex = previousOrParentNode.tNode !.flags >> TNodeFlags.INDX_SHIFT;
|
let startIndex = tNode.flags >> TNodeFlags.INDX_SHIFT;
|
||||||
const endIndex = startIndex + size;
|
const endIndex = startIndex + size;
|
||||||
const tDirectives = currentView.tView.directives !;
|
const tDirectives = currentView.tView.directives !;
|
||||||
|
|
||||||
|
@ -602,32 +595,59 @@ function hack_declareDirectives(elementIndex: number, localRefs: string[] | null
|
||||||
// is not guaranteed. Must be refactored to take it into account.
|
// is not guaranteed. Must be refactored to take it into account.
|
||||||
for (let i = startIndex; i < endIndex; i++) {
|
for (let i = startIndex; i < endIndex; i++) {
|
||||||
const def = tDirectives[i] as DirectiveDef<any>;
|
const def = tDirectives[i] as DirectiveDef<any>;
|
||||||
directiveCreate(elementIndex, def.factory(), def, localRefs);
|
directiveCreate(elementIndex, def.factory(), def);
|
||||||
|
saveNameToExportMap(startIndex, def, exportsMap);
|
||||||
startIndex++;
|
startIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (firstTemplatePass) cacheMatchingLocalNames(tNode, localRefs, exportsMap !);
|
||||||
|
saveResolvedLocalsInData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Caches local names and their matching directive indices for query and template lookups. */
|
||||||
|
function cacheMatchingLocalNames(
|
||||||
|
tNode: TNode, localRefs: string[] | null, exportsMap: {[key: string]: number}): void {
|
||||||
|
if (localRefs) {
|
||||||
|
const localNames: (string | number)[] = tNode.localNames = [];
|
||||||
|
|
||||||
|
// Local names must be stored in tNode in the same order that localRefs are defined
|
||||||
|
// in the template to ensure the data is loaded in the same slots as their refs
|
||||||
|
// in the template (for template queries).
|
||||||
|
for (let i = 0; i < localRefs.length; i += 2) {
|
||||||
|
const index = exportsMap[localRefs[i | 1]];
|
||||||
|
if (index == null) throw new Error(`Export of name '${localRefs[i | 1]}' not found!`);
|
||||||
|
localNames.push(localRefs[i], index);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds any local names that match the given directive's exportAs and returns them with directive
|
* Builds up an export map as directives are created, so local refs can be quickly mapped
|
||||||
* index. If the directiveDef is null, it matches against the default '' value instead of
|
* to their directive instances.
|
||||||
* exportAs.
|
|
||||||
*/
|
*/
|
||||||
function findMatchingLocalNames(
|
function saveNameToExportMap(
|
||||||
directiveDef: DirectiveDef<any>| null, localRefs: string[] | null | undefined, index: number,
|
index: number, def: DirectiveDef<any>| ComponentDef<any>,
|
||||||
defaultExport?: string): (string | number)[]|null {
|
exportsMap: {[key: string]: number} | null) {
|
||||||
const exportAs = directiveDef && directiveDef.exportAs || defaultExport;
|
if (exportsMap) {
|
||||||
let matches: (string | number)[]|null = null;
|
if (def.exportAs) exportsMap[def.exportAs] = index;
|
||||||
if (exportAs != null && localRefs) {
|
if ((def as ComponentDef<any>).template) exportsMap[''] = index;
|
||||||
for (let i = 0; i < localRefs.length; i = i + 2) {
|
}
|
||||||
const local = localRefs[i];
|
}
|
||||||
const toExportAs = localRefs[i | 1];
|
|
||||||
if (toExportAs === exportAs || toExportAs === defaultExport) {
|
/**
|
||||||
(matches || (matches = [])).push(local, index);
|
* Takes a list of local names and indices and pushes the resolved local variable values
|
||||||
}
|
* to data[] in the same order as they are loaded in the template with load().
|
||||||
|
*/
|
||||||
|
function saveResolvedLocalsInData(): void {
|
||||||
|
const localNames = previousOrParentNode.tNode !.localNames;
|
||||||
|
if (localNames) {
|
||||||
|
for (let i = 0; i < localNames.length; i += 2) {
|
||||||
|
const index = localNames[i | 1] as number;
|
||||||
|
const value = index === -1 ? previousOrParentNode.native : directives ![index];
|
||||||
|
data.push(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matches;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -724,7 +744,7 @@ export function hostElement(
|
||||||
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways));
|
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways));
|
||||||
|
|
||||||
if (firstTemplatePass) {
|
if (firstTemplatePass) {
|
||||||
node.tNode = createTNode(tag as string, null, null, null);
|
node.tNode = createTNode(tag as string, null, null);
|
||||||
// Root directive is stored at index 0, size 1
|
// Root directive is stored at index 0, size 1
|
||||||
buildTNodeFlags(node.tNode, 0, 1, TNodeFlags.Component);
|
buildTNodeFlags(node.tNode, 0, 1, TNodeFlags.Component);
|
||||||
currentView.tView.directives = [def];
|
currentView.tView.directives = [def];
|
||||||
|
@ -879,13 +899,12 @@ export function elementProperty<T>(
|
||||||
* @returns the TNode object
|
* @returns the TNode object
|
||||||
*/
|
*/
|
||||||
function createTNode(
|
function createTNode(
|
||||||
tagName: string | null, attrs: string[] | null, data: TContainer | null,
|
tagName: string | null, attrs: string[] | null, data: TContainer | null): TNode {
|
||||||
localNames: (string | number)[] | null): TNode {
|
|
||||||
return {
|
return {
|
||||||
flags: 0,
|
flags: 0,
|
||||||
tagName: tagName,
|
tagName: tagName,
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
localNames: localNames,
|
localNames: null,
|
||||||
initialInputs: undefined,
|
initialInputs: undefined,
|
||||||
inputs: undefined,
|
inputs: undefined,
|
||||||
outputs: undefined,
|
outputs: undefined,
|
||||||
|
@ -1122,8 +1141,7 @@ export function textBinding<T>(index: number, value: T | NO_CHANGE): void {
|
||||||
* @param localRefs Names under which a query can retrieve the directive instance
|
* @param localRefs Names under which a query can retrieve the directive instance
|
||||||
*/
|
*/
|
||||||
export function directiveCreate<T>(
|
export function directiveCreate<T>(
|
||||||
elementIndex: number, directive: T, directiveDef: DirectiveDef<T>| ComponentDef<T>,
|
elementIndex: number, directive: T, directiveDef: DirectiveDef<T>| ComponentDef<T>): T {
|
||||||
localRefs?: string[] | null): T {
|
|
||||||
const index = directives ? directives.length : 0;
|
const index = directives ? directives.length : 0;
|
||||||
const instance = baseDirectiveCreate(index, directive, directiveDef);
|
const instance = baseDirectiveCreate(index, directive, directiveDef);
|
||||||
|
|
||||||
|
@ -1141,13 +1159,6 @@ export function directiveCreate<T>(
|
||||||
queueInitHooks(index, directiveDef.onInit, directiveDef.doCheck, currentView.tView);
|
queueInitHooks(index, directiveDef.onInit, directiveDef.doCheck, currentView.tView);
|
||||||
|
|
||||||
if (directiveDef.hostBindings) queueHostBindingForCheck(index, elementIndex);
|
if (directiveDef.hostBindings) queueHostBindingForCheck(index, elementIndex);
|
||||||
|
|
||||||
if (localRefs) {
|
|
||||||
const localNames =
|
|
||||||
findMatchingLocalNames(directiveDef, localRefs, index, isComponent ? '' : undefined);
|
|
||||||
tNode.localNames =
|
|
||||||
localNames && tNode.localNames ? tNode.localNames.concat(localNames) : localNames;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tNode && tNode.attrs) {
|
if (tNode && tNode.attrs) {
|
||||||
|
@ -1172,9 +1183,7 @@ function addComponentLogic<T>(
|
||||||
|
|
||||||
initChangeDetectorIfExisting(previousOrParentNode.nodeInjector, instance, hostView);
|
initChangeDetectorIfExisting(previousOrParentNode.nodeInjector, instance, hostView);
|
||||||
|
|
||||||
if (firstTemplatePass) {
|
if (firstTemplatePass) queueComponentIndexForCheck(index, elementIndex);
|
||||||
queueComponentIndexForCheck(index, elementIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1308,8 +1317,7 @@ export function container(
|
||||||
const node = createLNode(index, LNodeType.Container, undefined, lContainer);
|
const node = createLNode(index, LNodeType.Container, undefined, lContainer);
|
||||||
|
|
||||||
if (node.tNode == null) {
|
if (node.tNode == null) {
|
||||||
const localNames: (string | number)[]|null = findMatchingLocalNames(null, localRefs, -1, '');
|
node.tNode = tData[index] = createTNode(tagName || null, attrs || null, []);
|
||||||
node.tNode = tData[index] = createTNode(tagName || null, attrs || null, [], localNames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Containers are added to the current view tree instead of their embedded views
|
// Containers are added to the current view tree instead of their embedded views
|
||||||
|
@ -1317,7 +1325,9 @@ export function container(
|
||||||
addToViewTree(node.data);
|
addToViewTree(node.data);
|
||||||
|
|
||||||
if (firstTemplatePass) cacheMatchingDirectivesForNode(node.tNode);
|
if (firstTemplatePass) cacheMatchingDirectivesForNode(node.tNode);
|
||||||
hack_declareDirectives(index, localRefs);
|
|
||||||
|
// TODO: handle TemplateRef!
|
||||||
|
hack_declareDirectives(index, localRefs || null);
|
||||||
|
|
||||||
isParent = false;
|
isParent = false;
|
||||||
ngDevMode && assertNodeType(previousOrParentNode, LNodeType.Container);
|
ngDevMode && assertNodeType(previousOrParentNode, LNodeType.Container);
|
||||||
|
@ -1616,7 +1626,7 @@ export function projection(
|
||||||
const node = createLNode(nodeIndex, LNodeType.Projection, null, {head: null, tail: null});
|
const node = createLNode(nodeIndex, LNodeType.Projection, null, {head: null, tail: null});
|
||||||
|
|
||||||
if (node.tNode == null) {
|
if (node.tNode == null) {
|
||||||
node.tNode = createTNode(null, attrs || null, null, null);
|
node.tNode = createTNode(null, attrs || null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
isParent = false; // self closing
|
isParent = false; // self closing
|
||||||
|
@ -2167,7 +2177,8 @@ function assertDataInRange(index: number, arr?: any[]) {
|
||||||
|
|
||||||
function assertDataNext(index: number, arr?: any[]) {
|
function assertDataNext(index: number, arr?: any[]) {
|
||||||
if (arr == null) arr = data;
|
if (arr == null) arr = data;
|
||||||
assertEqual(arr.length, index, 'index expected to be at the end of arr');
|
assertEqual(
|
||||||
|
arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function _getComponentHostLElementNode<T>(component: T): LElementNode {
|
export function _getComponentHostLElementNode<T>(component: T): LElementNode {
|
||||||
|
|
|
@ -53,6 +53,60 @@ describe('elements', () => {
|
||||||
.toEqual('<div class="my-app" title="Hello">Hello <b>World</b>!</div>');
|
.toEqual('<div class="my-app" title="Hello">Hello <b>World</b>!</div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support local refs', () => {
|
||||||
|
type $LocalRefComp$ = LocalRefComp;
|
||||||
|
|
||||||
|
class Dir {
|
||||||
|
value = 'one';
|
||||||
|
|
||||||
|
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||||
|
type: Dir,
|
||||||
|
selector: [[['', 'dir', ''], null]],
|
||||||
|
factory: function DirA_Factory() { return new Dir(); },
|
||||||
|
exportAs: 'dir'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// NORMATIVE
|
||||||
|
const $e0_attrs$ = ['dir', ''];
|
||||||
|
const $e0_locals$ = ['dir', 'dir', 'foo', ''];
|
||||||
|
// /NORMATIVE
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'local-ref-comp',
|
||||||
|
template: `
|
||||||
|
<div dir #dir="dir" #foo></div>
|
||||||
|
{{ dir.value }} - {{ foo.tagName }}
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class LocalRefComp {
|
||||||
|
// NORMATIVE
|
||||||
|
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||||
|
type: LocalRefComp,
|
||||||
|
selector: [[['local-ref-comp'], null]],
|
||||||
|
factory: function LocalRefComp_Factory() { return new LocalRefComp(); },
|
||||||
|
template: function LocalRefComp_Template(ctx: $LocalRefComp$, cm: $boolean$) {
|
||||||
|
if (cm) {
|
||||||
|
$r3$.ɵE(0, 'div', $e0_attrs$, $e0_locals$);
|
||||||
|
$r3$.ɵe();
|
||||||
|
$r3$.ɵT(3);
|
||||||
|
}
|
||||||
|
const $tmp$ = $r3$.ɵld(1) as any;
|
||||||
|
const $tmp_2$ = $r3$.ɵld(2) as any;
|
||||||
|
$r3$.ɵt(3, $r3$.ɵi2(' ', $tmp$.value, ' - ', $tmp_2$.tagName, ''));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// /NORMATIVE
|
||||||
|
}
|
||||||
|
|
||||||
|
// NON-NORMATIVE
|
||||||
|
LocalRefComp.ngComponentDef.directiveDefs = () => [Dir.ngDirectiveDef];
|
||||||
|
// /NON-NORMATIVE
|
||||||
|
|
||||||
|
const fixture = new ComponentFixture(LocalRefComp);
|
||||||
|
expect(fixture.html).toEqual(`<div dir=""></div> one - DIV`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should support listeners', () => {
|
it('should support listeners', () => {
|
||||||
type $ListenerComp$ = ListenerComp;
|
type $ListenerComp$ = ListenerComp;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {ChangeDetectorRef, ElementRef, TemplateRef, ViewContainerRef} from '@ang
|
||||||
import {defineComponent} from '../../src/render3/definition';
|
import {defineComponent} from '../../src/render3/definition';
|
||||||
import {InjectFlags, bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di';
|
import {InjectFlags, bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di';
|
||||||
import {NgOnChangesFeature, PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
|
import {NgOnChangesFeature, PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
|
||||||
import {bind, container, containerRefreshEnd, containerRefreshStart, createLNode, createLView, createTView, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, load, loadDirective, projection, projectionDef, text, textBinding} from '../../src/render3/instructions';
|
import {bind, container, containerRefreshEnd, containerRefreshStart, createLNode, createLView, createTView, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, load, projection, projectionDef, text, textBinding} from '../../src/render3/instructions';
|
||||||
import {LInjector} from '../../src/render3/interfaces/injector';
|
import {LInjector} from '../../src/render3/interfaces/injector';
|
||||||
import {LNodeType} from '../../src/render3/interfaces/node';
|
import {LNodeType} from '../../src/render3/interfaces/node';
|
||||||
import {LViewFlags} from '../../src/render3/interfaces/view';
|
import {LViewFlags} from '../../src/render3/interfaces/view';
|
||||||
|
@ -24,18 +24,23 @@ describe('di', () => {
|
||||||
it('should create directive with no deps', () => {
|
it('should create directive with no deps', () => {
|
||||||
class Directive {
|
class Directive {
|
||||||
value: string = 'Created';
|
value: string = 'Created';
|
||||||
static ngDirectiveDef = defineDirective(
|
static ngDirectiveDef = defineDirective({
|
||||||
{type: Directive, selector: [[['', 'dir', ''], null]], factory: () => new Directive});
|
type: Directive,
|
||||||
|
selector: [[['', 'dir', ''], null]],
|
||||||
|
factory: () => new Directive,
|
||||||
|
exportAs: 'dir'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** <div dir #dir="dir"> {{ dir.value }} </div> */
|
||||||
function Template(ctx: any, cm: boolean) {
|
function Template(ctx: any, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div', ['dir', '']);
|
elementStart(0, 'div', ['dir', ''], ['dir', 'dir']);
|
||||||
{ text(1); }
|
{ text(2); }
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
const tmp = load(1) as any;
|
||||||
textBinding(1, bind(loadDirective<Directive>(0).value));
|
textBinding(2, bind(tmp.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(renderToHtml(Template, {}, [Directive.ngDirectiveDef]))
|
expect(renderToHtml(Template, {}, [Directive.ngDirectiveDef]))
|
||||||
|
@ -71,22 +76,28 @@ describe('di', () => {
|
||||||
static ngDirectiveDef = defineDirective({
|
static ngDirectiveDef = defineDirective({
|
||||||
type: DirectiveC,
|
type: DirectiveC,
|
||||||
selector: [[['', 'dirC', ''], null]],
|
selector: [[['', 'dirC', ''], null]],
|
||||||
factory: () => new DirectiveC(directiveInject(DirectiveA), directiveInject(DirectiveB))
|
factory: () => new DirectiveC(directiveInject(DirectiveA), directiveInject(DirectiveB)),
|
||||||
|
exportAs: 'dirC'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <div dirA>
|
||||||
|
* <span dirB dirC #dir="dirC"> {{ dir.value }} </span>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
function Template(ctx: any, cm: boolean) {
|
function Template(ctx: any, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div', ['dirA', '']);
|
elementStart(0, 'div', ['dirA', '']);
|
||||||
{
|
{
|
||||||
elementStart(1, 'span', ['dirB', '', 'dirC', '']);
|
elementStart(1, 'span', ['dirB', '', 'dirC', ''], ['dir', 'dirC']);
|
||||||
{ text(2); }
|
{ text(3); }
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
const tmp = load(2) as any;
|
||||||
textBinding(2, bind(loadDirective<DirectiveC>(2).value));
|
textBinding(3, bind(tmp.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
const defs =
|
const defs =
|
||||||
|
@ -107,7 +118,8 @@ describe('di', () => {
|
||||||
type: Directive,
|
type: Directive,
|
||||||
selector: [[['', 'dir', ''], null]],
|
selector: [[['', 'dir', ''], null]],
|
||||||
factory: () => new Directive(injectElementRef()),
|
factory: () => new Directive(injectElementRef()),
|
||||||
features: [PublicFeature]
|
features: [PublicFeature],
|
||||||
|
exportAs: 'dir'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,21 +131,26 @@ describe('di', () => {
|
||||||
static ngDirectiveDef = defineDirective({
|
static ngDirectiveDef = defineDirective({
|
||||||
type: DirectiveSameInstance,
|
type: DirectiveSameInstance,
|
||||||
selector: [[['', 'dirSame', ''], null]],
|
selector: [[['', 'dirSame', ''], null]],
|
||||||
factory: () => new DirectiveSameInstance(injectElementRef(), directiveInject(Directive))
|
factory: () => new DirectiveSameInstance(injectElementRef(), directiveInject(Directive)),
|
||||||
|
exportAs: 'dirSame'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <div dir dirSame #dirSame="dirSame" #dir="dir">
|
||||||
|
* {{ dir.value }} - {{ dirSame.value }}
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
function Template(ctx: any, cm: boolean) {
|
function Template(ctx: any, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div', ['dir', '', 'dirSame', '']);
|
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dirSame', 'dirSame', 'dir', 'dir']);
|
||||||
{ text(1); }
|
{ text(3); }
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
|
||||||
textBinding(
|
const tmp1 = load(1) as any;
|
||||||
1, interpolation2(
|
const tmp2 = load(2) as any;
|
||||||
'', loadDirective<Directive>(0).value, '-',
|
textBinding(3, interpolation2('', tmp2.value, '-', tmp1.value, ''));
|
||||||
loadDirective<DirectiveSameInstance>(1).value, ''));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
|
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
|
||||||
|
@ -153,7 +170,8 @@ describe('di', () => {
|
||||||
type: Directive,
|
type: Directive,
|
||||||
selector: [[['', 'dir', ''], null]],
|
selector: [[['', 'dir', ''], null]],
|
||||||
factory: () => new Directive(injectTemplateRef()),
|
factory: () => new Directive(injectTemplateRef()),
|
||||||
features: [PublicFeature]
|
features: [PublicFeature],
|
||||||
|
exportAs: 'dir'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,21 +183,25 @@ describe('di', () => {
|
||||||
static ngDirectiveDef = defineDirective({
|
static ngDirectiveDef = defineDirective({
|
||||||
type: DirectiveSameInstance,
|
type: DirectiveSameInstance,
|
||||||
selector: [[['', 'dirSame', ''], null]],
|
selector: [[['', 'dirSame', ''], null]],
|
||||||
factory: () => new DirectiveSameInstance(injectTemplateRef(), directiveInject(Directive))
|
factory: () => new DirectiveSameInstance(injectTemplateRef(), directiveInject(Directive)),
|
||||||
|
exportAs: 'dirSame'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <ng-template dir dirSame #dir="dir" #dirSame="dirSame">
|
||||||
|
* {{ dir.value }} - {{ dirSame.value }}
|
||||||
|
* </ng-template>
|
||||||
|
*/
|
||||||
function Template(ctx: any, cm: any) {
|
function Template(ctx: any, cm: any) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
container(0, function() {}, undefined, ['dir', '', 'dirSame', '']);
|
container(0, function() {
|
||||||
text(1);
|
}, undefined, ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
|
||||||
|
text(3);
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
const tmp1 = load(1) as any;
|
||||||
textBinding(
|
const tmp2 = load(2) as any;
|
||||||
1, interpolation2(
|
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
|
||||||
'', loadDirective<Directive>(0).value, '-',
|
|
||||||
loadDirective<DirectiveSameInstance>(1).value, ''));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
|
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
|
||||||
|
@ -198,7 +220,8 @@ describe('di', () => {
|
||||||
type: Directive,
|
type: Directive,
|
||||||
selector: [[['', 'dir', ''], null]],
|
selector: [[['', 'dir', ''], null]],
|
||||||
factory: () => new Directive(injectViewContainerRef()),
|
factory: () => new Directive(injectViewContainerRef()),
|
||||||
features: [PublicFeature]
|
features: [PublicFeature],
|
||||||
|
exportAs: 'dir'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,21 +234,26 @@ describe('di', () => {
|
||||||
type: DirectiveSameInstance,
|
type: DirectiveSameInstance,
|
||||||
selector: [[['', 'dirSame', ''], null]],
|
selector: [[['', 'dirSame', ''], null]],
|
||||||
factory:
|
factory:
|
||||||
() => new DirectiveSameInstance(injectViewContainerRef(), directiveInject(Directive))
|
() => new DirectiveSameInstance(injectViewContainerRef(), directiveInject(Directive)),
|
||||||
|
exportAs: 'dirSame'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <div dir dirSame #dir="dir" #dirSame="dirSame">
|
||||||
|
* {{ dir.value }} - {{ dirSame.value }}
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
function Template(ctx: any, cm: boolean) {
|
function Template(ctx: any, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div', ['dir', '', 'dirSame', '']);
|
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
|
||||||
{ text(1); }
|
{ text(3); }
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
|
||||||
textBinding(
|
const tmp1 = load(1) as any;
|
||||||
1, interpolation2(
|
const tmp2 = load(2) as any;
|
||||||
'', loadDirective<Directive>(0).value, '-',
|
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
|
||||||
loadDirective<DirectiveSameInstance>(1).value, ''));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
|
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
|
||||||
|
@ -310,10 +338,10 @@ describe('di', () => {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
elementStart(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
text(1);
|
text(2);
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
const tmp = load(1) as any;
|
||||||
textBinding(1, bind(loadDirective<Directive>(1).value));
|
textBinding(2, bind(tmp.value));
|
||||||
}, defs);
|
}, defs);
|
||||||
|
|
||||||
const app = renderComponent(MyApp);
|
const app = renderComponent(MyApp);
|
||||||
|
@ -338,11 +366,11 @@ describe('di', () => {
|
||||||
template: function(ctx: any, cm: boolean) {
|
template: function(ctx: any, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
||||||
{ text(1); }
|
{ text(2); }
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
const tmp = load(1) as any;
|
||||||
textBinding(1, bind(loadDirective<Directive>(0).value));
|
textBinding(2, bind(tmp.value));
|
||||||
},
|
},
|
||||||
directiveDefs: defs
|
directiveDefs: defs
|
||||||
});
|
});
|
||||||
|
@ -378,10 +406,10 @@ describe('di', () => {
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
elementEnd();
|
elementEnd();
|
||||||
text(2);
|
text(3);
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
const tmp = load(2) as any;
|
||||||
textBinding(2, bind(loadDirective<Directive>(1).value));
|
textBinding(3, bind(tmp.value));
|
||||||
},
|
},
|
||||||
directiveDefs: defs
|
directiveDefs: defs
|
||||||
});
|
});
|
||||||
|
@ -420,11 +448,11 @@ describe('di', () => {
|
||||||
if (ctx.showing) {
|
if (ctx.showing) {
|
||||||
if (embeddedViewStart(0)) {
|
if (embeddedViewStart(0)) {
|
||||||
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
||||||
{ text(1); }
|
{ text(2); }
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
const tmp = load(1) as any;
|
||||||
textBinding(1, bind(loadDirective<Directive>(0).value));
|
textBinding(2, bind(tmp.value));
|
||||||
}
|
}
|
||||||
embeddedViewEnd();
|
embeddedViewEnd();
|
||||||
}
|
}
|
||||||
|
@ -463,11 +491,11 @@ describe('di', () => {
|
||||||
function C1(ctx1: any, cm1: boolean) {
|
function C1(ctx1: any, cm1: boolean) {
|
||||||
if (cm1) {
|
if (cm1) {
|
||||||
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
||||||
{ text(1); }
|
{ text(2); }
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
const tmp = load(1) as any;
|
||||||
textBinding(1, bind(loadDirective<Directive>(0).value));
|
textBinding(2, bind(tmp.value));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
directiveDefs: defs
|
directiveDefs: defs
|
||||||
|
@ -600,7 +628,8 @@ describe('di', () => {
|
||||||
type: ChildDirective,
|
type: ChildDirective,
|
||||||
selector: [[['', 'childDir', ''], null]],
|
selector: [[['', 'childDir', ''], null]],
|
||||||
factory: () => new ChildDirective(directiveInject(ParentDirective)),
|
factory: () => new ChildDirective(directiveInject(ParentDirective)),
|
||||||
features: [PublicFeature]
|
features: [PublicFeature],
|
||||||
|
exportAs: 'childDir'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,10 +640,18 @@ describe('di', () => {
|
||||||
selector: [[['', 'child2Dir', ''], null]],
|
selector: [[['', 'child2Dir', ''], null]],
|
||||||
type: Child2Directive,
|
type: Child2Directive,
|
||||||
factory: () => new Child2Directive(
|
factory: () => new Child2Directive(
|
||||||
directiveInject(ParentDirective), directiveInject(ChildDirective))
|
directiveInject(ParentDirective), directiveInject(ChildDirective)),
|
||||||
|
exportAs: 'child2Dir'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <div parentDir>
|
||||||
|
* <span childDir child2Dir #child1="childDir" #child2="child2Dir">
|
||||||
|
* {{ child1.value }} - {{ child2.value }}
|
||||||
|
* </span>
|
||||||
|
* </div>
|
||||||
|
*/
|
||||||
function Template(ctx: any, cm: boolean) {
|
function Template(ctx: any, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div', ['parentDir', '']);
|
elementStart(0, 'div', ['parentDir', '']);
|
||||||
|
@ -624,15 +661,15 @@ describe('di', () => {
|
||||||
containerRefreshStart(1);
|
containerRefreshStart(1);
|
||||||
{
|
{
|
||||||
if (embeddedViewStart(0)) {
|
if (embeddedViewStart(0)) {
|
||||||
elementStart(0, 'span', ['childDir', '', 'child2Dir', '']);
|
elementStart(
|
||||||
{ text(1); }
|
0, 'span', ['childDir', '', 'child2Dir', ''],
|
||||||
|
['child1', 'childDir', 'child2', 'child2Dir']);
|
||||||
|
{ text(3); }
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: remove loadDirective when removing directive references
|
const tmp1 = load(1) as any;
|
||||||
textBinding(
|
const tmp2 = load(2) as any;
|
||||||
1, interpolation2(
|
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
|
||||||
'', loadDirective<ChildDirective>(0).value, '-',
|
|
||||||
loadDirective<Child2Directive>(1).value, ''));
|
|
||||||
embeddedViewEnd();
|
embeddedViewEnd();
|
||||||
}
|
}
|
||||||
containerRefreshEnd();
|
containerRefreshEnd();
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {defineComponent, defineDirective} from '../../src/render3/index';
|
import {defineComponent, defineDirective} from '../../src/render3/index';
|
||||||
import {bind, container, containerRefreshEnd, containerRefreshStart, elementAttribute, elementClassNamed, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective, text, textBinding} from '../../src/render3/instructions';
|
import {bind, container, containerRefreshEnd, containerRefreshStart, elementAttribute, elementClassNamed, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, text, textBinding} from '../../src/render3/instructions';
|
||||||
|
|
||||||
import {renderToHtml} from './render_util';
|
import {ComponentFixture, createComponent, renderToHtml} from './render_util';
|
||||||
|
|
||||||
describe('exports', () => {
|
describe('exports', () => {
|
||||||
it('should support export of DOM element', () => {
|
it('should support export of DOM element', () => {
|
||||||
|
@ -19,10 +19,10 @@ describe('exports', () => {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'input', ['value', 'one'], ['myInput', '']);
|
elementStart(0, 'input', ['value', 'one'], ['myInput', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
text(1);
|
text(2);
|
||||||
}
|
}
|
||||||
let myInput = elementStart(0);
|
const tmp = load(1) as any;
|
||||||
textBinding(1, (myInput as any).value);
|
textBinding(2, tmp.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(renderToHtml(Template, {})).toEqual('<input value="one">one');
|
expect(renderToHtml(Template, {})).toEqual('<input value="one">one');
|
||||||
|
@ -35,10 +35,10 @@ describe('exports', () => {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'comp', null, ['myComp', '']);
|
elementStart(0, 'comp', null, ['myComp', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
text(1);
|
text(2);
|
||||||
}
|
}
|
||||||
// TODO: replace loadDirective when removing directive refs
|
const tmp = load(1) as any;
|
||||||
textBinding(1, loadDirective<MyComponent>(0).name);
|
textBinding(2, tmp.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyComponent {
|
class MyComponent {
|
||||||
|
@ -87,11 +87,11 @@ describe('exports', () => {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'comp', null, ['myComp', '']);
|
elementStart(0, 'comp', null, ['myComp', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
elementStart(1, 'div', ['myDir', '']);
|
elementStart(2, 'div', ['myDir', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: replace loadDirective when removing directive refs
|
const tmp = load(1) as any;
|
||||||
elementProperty(1, 'myDir', bind(loadDirective<MyComponent>(0)));
|
elementProperty(2, 'myDir', bind(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
renderToHtml(Template, {}, defs);
|
renderToHtml(Template, {}, defs);
|
||||||
|
@ -105,10 +105,10 @@ describe('exports', () => {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div', ['someDir', ''], ['myDir', 'someDir']);
|
elementStart(0, 'div', ['someDir', ''], ['myDir', 'someDir']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
text(1);
|
text(2);
|
||||||
}
|
}
|
||||||
// TODO: replace loadDirective when removing directive refs
|
const tmp = load(1) as any;
|
||||||
textBinding(1, loadDirective<SomeDir>(0).name);
|
textBinding(2, tmp.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SomeDir {
|
class SomeDir {
|
||||||
|
@ -125,6 +125,21 @@ describe('exports', () => {
|
||||||
.toEqual('<div somedir=""></div>Drew');
|
.toEqual('<div somedir=""></div>Drew');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw if export name is not found', () => {
|
||||||
|
|
||||||
|
/** <div #myDir="someDir"></div> */
|
||||||
|
const App = createComponent('app', function(ctx: any, cm: boolean) {
|
||||||
|
if (cm) {
|
||||||
|
elementStart(0, 'div', null, ['myDir', 'someDir']);
|
||||||
|
elementEnd();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
const fixture = new ComponentFixture(App);
|
||||||
|
}).toThrowError(/Export of name 'someDir' not found!/);
|
||||||
|
});
|
||||||
|
|
||||||
describe('forward refs', () => {
|
describe('forward refs', () => {
|
||||||
it('should work with basic text bindings', () => {
|
it('should work with basic text bindings', () => {
|
||||||
/** {{ myInput.value}} <input value="one" #myInput> */
|
/** {{ myInput.value}} <input value="one" #myInput> */
|
||||||
|
@ -134,8 +149,8 @@ describe('exports', () => {
|
||||||
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
let myInput = elementStart(1);
|
const tmp = load(2) as any;
|
||||||
textBinding(0, bind((myInput as any).value));
|
textBinding(0, bind(tmp.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(renderToHtml(Template, {})).toEqual('one<input value="one">');
|
expect(renderToHtml(Template, {})).toEqual('one<input value="one">');
|
||||||
|
@ -151,8 +166,8 @@ describe('exports', () => {
|
||||||
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
let myInput = elementStart(1);
|
const tmp = load(2) as any;
|
||||||
elementProperty(0, 'title', bind(myInput && (myInput as any).value));
|
elementProperty(0, 'title', bind(tmp.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(renderToHtml(Template, {})).toEqual('<div title="one"></div><input value="one">');
|
expect(renderToHtml(Template, {})).toEqual('<div title="one"></div><input value="one">');
|
||||||
|
@ -167,8 +182,8 @@ describe('exports', () => {
|
||||||
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
let myInput = elementStart(1);
|
const tmp = load(2) as any;
|
||||||
elementAttribute(0, 'aria-label', bind(myInput && (myInput as any).value));
|
elementAttribute(0, 'aria-label', bind(tmp.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(renderToHtml(Template, {})).toEqual('<div aria-label="one"></div><input value="one">');
|
expect(renderToHtml(Template, {})).toEqual('<div aria-label="one"></div><input value="one">');
|
||||||
|
@ -183,8 +198,8 @@ describe('exports', () => {
|
||||||
elementStart(1, 'input', ['type', 'checkbox', 'checked', 'true'], ['myInput', '']);
|
elementStart(1, 'input', ['type', 'checkbox', 'checked', 'true'], ['myInput', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
let myInput = elementStart(1);
|
const tmp = load(2) as any;
|
||||||
elementClassNamed(0, 'red', bind(myInput && (myInput as any).checked));
|
elementClassNamed(0, 'red', bind(tmp.checked));
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(renderToHtml(Template, {}))
|
expect(renderToHtml(Template, {}))
|
||||||
|
@ -228,8 +243,8 @@ describe('exports', () => {
|
||||||
elementStart(1, 'comp', null, ['myComp', '']);
|
elementStart(1, 'comp', null, ['myComp', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
// TODO: replace loadDirective when removing directive refs
|
const tmp = load(2) as any;
|
||||||
elementProperty(0, 'myDir', bind(loadDirective<MyComponent>(1)));
|
elementProperty(0, 'myDir', bind(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
renderToHtml(Template, {}, [MyComponent.ngComponentDef, MyDir.ngDirectiveDef]);
|
renderToHtml(Template, {}, [MyComponent.ngComponentDef, MyDir.ngDirectiveDef]);
|
||||||
|
@ -245,14 +260,13 @@ describe('exports', () => {
|
||||||
text(1);
|
text(1);
|
||||||
elementStart(2, 'comp', null, ['myComp', '']);
|
elementStart(2, 'comp', null, ['myComp', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
elementStart(3, 'input', ['value', 'one'], ['myInput', '']);
|
elementStart(4, 'input', ['value', 'one'], ['myInput', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
let myInput = elementStart(3);
|
const tmp1 = load(3) as any;
|
||||||
// TODO: replace loadDirective when removing directive refs
|
const tmp2 = load(5) as any;
|
||||||
let myComp = loadDirective<MyComponent>(0);
|
textBinding(0, bind(tmp2.value));
|
||||||
textBinding(0, bind(myInput && (myInput as any).value));
|
textBinding(1, bind(tmp1.name));
|
||||||
textBinding(1, bind(myComp && myComp.name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let myComponent: MyComponent;
|
let myComponent: MyComponent;
|
||||||
|
@ -290,8 +304,8 @@ describe('exports', () => {
|
||||||
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
let myInput = elementStart(1);
|
const tmp = load(2) as any;
|
||||||
textBinding(0, bind(myInput && (myInput as any).value));
|
textBinding(0, bind(tmp.value));
|
||||||
}
|
}
|
||||||
embeddedViewEnd();
|
embeddedViewEnd();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
import {EventEmitter} from '@angular/core';
|
import {EventEmitter} from '@angular/core';
|
||||||
|
|
||||||
import {defineComponent, defineDirective, tick} from '../../src/render3/index';
|
import {defineComponent, defineDirective, tick} from '../../src/render3/index';
|
||||||
import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, listener, loadDirective, text, textBinding} from '../../src/render3/instructions';
|
import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, listener, load, loadDirective, text, textBinding} from '../../src/render3/instructions';
|
||||||
|
|
||||||
import {ComponentFixture, TemplateFixture, createComponent, renderToHtml} from './render_util';
|
import {ComponentFixture, renderToHtml} from './render_util';
|
||||||
|
|
||||||
describe('elementProperty', () => {
|
describe('elementProperty', () => {
|
||||||
|
|
||||||
|
@ -533,10 +533,10 @@ describe('elementProperty', () => {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div', ['role', 'button', 'myDir', ''], ['dir', 'myDir']);
|
elementStart(0, 'div', ['role', 'button', 'myDir', ''], ['dir', 'myDir']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
text(1);
|
text(2);
|
||||||
}
|
}
|
||||||
// TODO: remove this loadDirective when removing MyDir
|
const tmp = load(1) as any;
|
||||||
textBinding(1, bind(loadDirective<MyDir>(0).role));
|
textBinding(2, bind(tmp.role));
|
||||||
},
|
},
|
||||||
factory: () => new Comp(),
|
factory: () => new Comp(),
|
||||||
directiveDefs: () => [MyDir.ngDirectiveDef]
|
directiveDefs: () => [MyDir.ngDirectiveDef]
|
||||||
|
|
|
@ -179,7 +179,7 @@ describe('query', () => {
|
||||||
query(0, ['foo'], false, QUERY_READ_FROM_NODE);
|
query(0, ['foo'], false, QUERY_READ_FROM_NODE);
|
||||||
elToQuery = elementStart(1, 'div', null, ['foo', '']);
|
elToQuery = elementStart(1, 'div', null, ['foo', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
elementStart(2, 'div');
|
elementStart(3, 'div');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||||
|
@ -209,7 +209,7 @@ describe('query', () => {
|
||||||
query(1, ['bar'], false, QUERY_READ_FROM_NODE);
|
query(1, ['bar'], false, QUERY_READ_FROM_NODE);
|
||||||
elToQuery = elementStart(2, 'div', null, ['foo', '', 'bar', '']);
|
elToQuery = elementStart(2, 'div', null, ['foo', '', 'bar', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
elementStart(3, 'div');
|
elementStart(5, 'div');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>);
|
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>);
|
||||||
|
@ -245,9 +245,9 @@ describe('query', () => {
|
||||||
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE);
|
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE);
|
||||||
el1ToQuery = elementStart(1, 'div', null, ['foo', '']);
|
el1ToQuery = elementStart(1, 'div', null, ['foo', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
elementStart(2, 'div');
|
elementStart(3, 'div');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
el2ToQuery = elementStart(3, 'div', null, ['bar', '']);
|
el2ToQuery = elementStart(4, 'div', null, ['bar', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||||
|
@ -276,7 +276,7 @@ describe('query', () => {
|
||||||
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF);
|
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF);
|
||||||
elToQuery = elementStart(1, 'div', null, ['foo', '']);
|
elToQuery = elementStart(1, 'div', null, ['foo', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
elementStart(2, 'div');
|
elementStart(3, 'div');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||||
|
@ -708,11 +708,11 @@ describe('query', () => {
|
||||||
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
|
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
|
||||||
firstEl = elementStart(1, 'span', null, ['foo', '']);
|
firstEl = elementStart(1, 'span', null, ['foo', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
container(2);
|
container(3);
|
||||||
lastEl = elementStart(3, 'span', null, ['foo', '']);
|
lastEl = elementStart(4, 'span', null, ['foo', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
containerRefreshStart(2);
|
containerRefreshStart(3);
|
||||||
{
|
{
|
||||||
if (ctx.exp) {
|
if (ctx.exp) {
|
||||||
let cm1 = embeddedViewStart(1);
|
let cm1 = embeddedViewStart(1);
|
||||||
|
@ -838,9 +838,9 @@ describe('query', () => {
|
||||||
if (cm1) {
|
if (cm1) {
|
||||||
firstEl = elementStart(0, 'div', null, ['foo', '']);
|
firstEl = elementStart(0, 'div', null, ['foo', '']);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
container(1);
|
container(2);
|
||||||
}
|
}
|
||||||
containerRefreshStart(1);
|
containerRefreshStart(2);
|
||||||
{
|
{
|
||||||
if (ctx.exp2) {
|
if (ctx.exp2) {
|
||||||
let cm2 = embeddedViewStart(0);
|
let cm2 = embeddedViewStart(0);
|
||||||
|
|
Loading…
Reference in New Issue