refactor(ivy): flatten css selectors (#23074)

PR Close #23074
This commit is contained in:
Kara Erickson 2018-03-29 16:41:45 -07:00 committed by Alex Rickabaugh
parent 6cb1adf105
commit 6e5fb99304
44 changed files with 631 additions and 361 deletions

View File

@ -17,7 +17,7 @@ export class LargeTableComponent {
/** @nocollapse */
static ngComponentDef: ComponentDef<LargeTableComponent> = defineComponent({
type: LargeTableComponent,
selector: [[['largetable'], null]],
selectors: [['largetable']],
template: function(ctx: LargeTableComponent, cm: boolean) {
if (cm) {
E(0, 'table');

View File

@ -37,7 +37,7 @@ export class TreeComponent {
/** @nocollapse */
static ngComponentDef: ComponentDef<TreeComponent> = defineComponent({
type: TreeComponent,
selector: [[['tree'], null]],
selectors: [['tree']],
template: function(ctx: TreeComponent, cm: boolean) {
if (cm) {
E(0, 'span');
@ -91,7 +91,7 @@ export class TreeFunction {
/** @nocollapse */
static ngComponentDef: ComponentDef<TreeFunction> = defineComponent({
type: TreeFunction,
selector: [[['tree'], null]],
selectors: [['tree']],
template: function(ctx: TreeFunction, cm: boolean) {
// bit of a hack
TreeTpl(ctx.data, cm);

View File

@ -22,7 +22,7 @@ export {
InjectFlags as ɵInjectFlags,
PublicFeature as ɵPublicFeature,
NgOnChangesFeature as ɵNgOnChangesFeature,
CssSelector as ɵCssSelector,
CssSelectorList as ɵCssSelectorList,
NC as ɵNC,
C as ɵC,
E as ɵE,

View File

@ -123,8 +123,8 @@ export function renderComponent<T>(
const componentDef = (componentType as ComponentType<T>).ngComponentDef as ComponentDef<T>;
if (componentDef.type != componentType) componentDef.type = componentType;
let component: T;
// TODO: Replace when flattening CssSelector type
const componentTag = componentDef.selector ![0] ![0] ![0];
// The first index of the first selector is the tag name.
const componentTag = componentDef.selectors ![0] ![0] as string;
const hostNode = locateHostElement(rendererFactory, opts.host || componentTag);
const rootContext: RootContext = {
// Incomplete initialization due to circular reference.

View File

@ -17,7 +17,7 @@ import {resolveRendererType2} from '../view/util';
import {diPublic} from './di';
import {ComponentDef, ComponentDefFeature, ComponentTemplate, DirectiveDef, DirectiveDefFeature, DirectiveDefListOrFactory, PipeDef, PipeDefListOrFactory} from './interfaces/definition';
import {CssSelector} from './interfaces/projection';
import {CssSelectorList, SelectorFlags} from './interfaces/projection';
@ -42,8 +42,8 @@ export function defineComponent<T>(componentDefinition: {
*/
type: Type<T>;
/** The selector that will be used to match nodes to this component. */
selector: CssSelector;
/** The selectors that will be used to match nodes to this component. */
selectors: CssSelectorList;
/**
* Factory method used to create an instance of directive.
@ -185,7 +185,7 @@ export function defineComponent<T>(componentDefinition: {
onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
directiveDefs: componentDefinition.directiveDefs || null,
pipeDefs: componentDefinition.pipeDefs || null,
selector: componentDefinition.selector
selectors: componentDefinition.selectors
};
const feature = componentDefinition.features;
feature && feature.forEach((fn) => fn(def));
@ -317,8 +317,8 @@ export const defineDirective = defineComponent as any as<T>(directiveDefinition:
*/
type: Type<T>;
/** The selector that will be used to match nodes to this directive. */
selector: CssSelector;
/** The selectors that will be used to match nodes to this directive. */
selectors: CssSelectorList;
/**
* Factory method used to create an instance of directive.

View File

@ -12,7 +12,7 @@ import {InjectFlags} from './di';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType} from './interfaces/definition';
export {InjectFlags, QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, directiveInject, injectAttribute, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from './di';
export {CssSelector} from './interfaces/projection';
export {CssSelectorList} from './interfaces/projection';

View File

@ -11,14 +11,14 @@ import './ng_dev_mode';
import {assertEqual, assertLessThan, assertNotEqual, assertNotNull, assertNull, assertSame} from './assert';
import {LContainer, TContainer} from './interfaces/container';
import {LInjector} from './interfaces/injector';
import {CssSelector, LProjection, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection';
import {CssSelectorList, LProjection, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection';
import {LQueries} from './interfaces/query';
import {LView, LViewFlags, LifecycleStage, RootContext, TData, TView} from './interfaces/view';
import {LContainerNode, LElementNode, LNode, LNodeType, TNodeFlags, LProjectionNode, LTextNode, LViewNode, TNode, TContainerNode, InitialInputData, InitialInputs, PropertyAliases, PropertyAliasValue,} from './interfaces/node';
import {assertNodeType} from './node_assert';
import {appendChild, insertChild, insertView, appendProjectedNode, removeView, canInsertNativeNode} from './node_manipulation';
import {isNodeMatchingSelector, matchingSelectorIndex} from './node_selector_matcher';
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefList, DirectiveDefListOrFactory, DirectiveType, PipeDef, PipeDefListOrFactory} from './interfaces/definition';
import {RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, ObjectOrientedRenderer3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer';
import {isDifferent, stringify} from './util';
@ -532,7 +532,7 @@ function cacheMatchingDirectivesForNode(tNode: TNode): void {
for (let i = 0; i < registry.length; i++) {
const def = registry[i];
if (isNodeMatchingSelector(tNode, def.selector !)) {
if (isNodeMatchingSelectorList(tNode, def.selectors !)) {
if ((def as ComponentDef<any>).template) {
if (componentFlag) throwMultipleComponentError(tNode);
componentFlag |= TNodeFlags.Component;
@ -1567,7 +1567,7 @@ function viewAttached(view: LView): boolean {
* @param rawSelectors A collection of CSS selectors in the raw, un-parsed form
*/
export function projectionDef(
index: number, selectors?: CssSelector[], textSelectors?: string[]): void {
index: number, selectors?: CssSelectorList[], textSelectors?: string[]): void {
const noOfNodeBuckets = selectors ? selectors.length + 1 : 1;
const distributedNodes = new Array<LNode[]>(noOfNodeBuckets);
for (let i = 0; i < noOfNodeBuckets; i++) {

View File

@ -12,7 +12,7 @@ import {Provider} from '../../core';
import {RendererType2} from '../../render/api';
import {Type} from '../../type';
import {resolveRendererType2} from '../../view/util';
import {CssSelector} from './projection';
import {CssSelectorList} from './projection';
/**
@ -61,8 +61,8 @@ export interface DirectiveDef<T> {
/** Function that makes a directive public to the DI system. */
diPublic: ((def: DirectiveDef<any>) => void)|null;
/** The selector that will be used to match nodes to this directive. */
selector: CssSelector;
/** The selectors that will be used to match nodes to this directive. */
selectors: CssSelectorList;
/**
* A dictionary mapping the inputs' minified property names to their public API names, which

View File

@ -17,33 +17,61 @@ export interface LProjection {
}
/**
* Parsed selector in the following format:
* [tagName, attr1Name, attr1Val, ..., attrnName, attrnValue, 'class', className1, className2, ...,
* classNameN]
* Expresses a single CSS Selector.
*
* * For example, given the following selector:
* `div.foo.bar[attr1=val1][attr2]` a parsed format would be:
* `['div', 'attr1', 'val1', 'attr2', '', 'class', 'foo', 'bar']`.
* Beginning of array
* - First index: element name
* - Subsequent odd indices: attr keys
* - Subsequent even indices: attr values
*
* Things to notice:
* - tag name is always at the position 0
* - the `class` attribute is always the last attribute in a pre-parsed array
* - class names in a selector are at the end of an array (after the attribute with the name
* 'class').
* After SelectorFlags.CLASS flag
* - Class name values
*
* SelectorFlags.NOT flag
* - Changes the mode to NOT
* - Can be combined with other flags to set the element / attr / class mode
*
* e.g. SelectorFlags.NOT | SelectorFlags.ELEMENT
*
* Example:
* Original: `div.foo.bar[attr1=val1][attr2]`
* Parsed: ['div', 'attr1', 'val1', 'attr2', '', SelectorFlags.CLASS, 'foo', 'bar']
*
* Original: 'div[attr1]:not(.foo[attr2])
* Parsed: [
* 'div', 'attr1', '',
* SelectorFlags.NOT | SelectorFlags.ATTRIBUTE 'attr2', '', SelectorFlags.CLASS, 'foo'
* ]
*
* See more examples in node_selector_matcher_spec.ts
*/
export type SimpleCssSelector = string[];
export type CssSelector = (string | SelectorFlags)[];
/**
* A complex selector expressed as an Array where:
* - element at index 0 is a selector (SimpleCSSSelector) to match
* - elements at index 1..n is a selector (SimpleCSSSelector) that should NOT match
* A list of CssSelectors.
*
* A directive or component can have multiple selectors. This type is used for
* directive defs so any of the selectors in the list will match that directive.
*
* Original: 'form, [ngForm]'
* Parsed: [['form'], ['', 'ngForm', '']]
*/
export type CssSelectorWithNegations = [SimpleCssSelector | null, SimpleCssSelector[] | null];
export type CssSelectorList = CssSelector[];
/**
* A collection of complex selectors (CSSSelectorWithNegations) in a parsed form
*/
export type CssSelector = CssSelectorWithNegations[];
/** Flags used to build up CssSelectors */
export const enum SelectorFlags {
/** Indicates this is the beginning of a new negative selector */
NOT = 0b0001,
/** Mode for matching attributes */
ATTRIBUTE = 0b0010,
/** Mode for matching tag names */
ELEMENT = 0b0100,
/** Mode for matching class names */
CLASS = 0b1000,
}
export const NG_PROJECT_AS_ATTR_NAME = 'ngProjectAs';

View File

@ -10,7 +10,7 @@ import './ng_dev_mode';
import {assertNotNull} from './assert';
import {TNode, unusedValueExportToPlacateAjd as unused1} from './interfaces/node';
import {CssSelector, CssSelectorWithNegations, NG_PROJECT_AS_ATTR_NAME, SimpleCssSelector, unusedValueExportToPlacateAjd as unused2} from './interfaces/projection';
import {CssSelector, CssSelectorList, NG_PROJECT_AS_ATTR_NAME, SelectorFlags, unusedValueExportToPlacateAjd as unused2} from './interfaces/projection';
const unusedValueToPlacateAjd = unused1 + unused2;
@ -35,79 +35,80 @@ function isCssClassMatching(nodeClassAttrVal: string, cssClassToMatch: string):
* @param selector
* @returns true if node matches the selector.
*/
export function isNodeMatchingSimpleSelector(tNode: TNode, selector: SimpleCssSelector): boolean {
const noOfSelectorParts = selector.length;
ngDevMode && assertNotNull(selector[0], 'the selector should have a tag name');
const tagNameInSelector = selector[0];
export function isNodeMatchingSelector(tNode: TNode, selector: CssSelector): boolean {
ngDevMode && assertNotNull(selector[0], 'Selector should have a tag name');
// check tag tame
if (tagNameInSelector !== '' && tagNameInSelector !== tNode.tagName) {
return false;
}
let mode: SelectorFlags = SelectorFlags.ELEMENT;
const nodeAttrs = tNode.attrs !;
// short-circuit case where we are only matching on element's tag name
if (noOfSelectorParts === 1) {
return true;
}
// When processing ":not" selectors, we skip to the next ":not" if the
// current one doesn't match
let skipToNextSelector = false;
// short-circuit case where an element has no attrs but a selector tries to match some
if (noOfSelectorParts > 1 && !tNode.attrs) {
return false;
}
for (let i = 0; i < selector.length; i++) {
const current = selector[i];
if (typeof current === 'number') {
// If we finish processing a :not selector and it hasn't failed, return false
if (!skipToNextSelector && !isPositive(mode) && !isPositive(current as number)) {
return false;
}
// If we are skipping to the next :not() and this mode flag is positive,
// it's a part of the current :not() selector, and we should keep skipping
if (skipToNextSelector && isPositive(current)) continue;
skipToNextSelector = false;
mode = (current as number) | (mode & SelectorFlags.NOT);
continue;
}
const attrsInNode = tNode.attrs !;
if (skipToNextSelector) continue;
for (let i = 1; i < noOfSelectorParts; i += 2) {
const attrNameInSelector = selector[i];
const attrIdxInNode = attrsInNode.indexOf(attrNameInSelector);
if (attrIdxInNode % 2 !== 0) { // attribute names are stored at even indexes
return false;
if (mode & SelectorFlags.ELEMENT) {
mode = SelectorFlags.ATTRIBUTE | mode & SelectorFlags.NOT;
if (current !== '' && current !== tNode.tagName) {
if (isPositive(mode)) return false;
skipToNextSelector = true;
}
} else {
const attrValInSelector = selector[i + 1];
if (attrValInSelector !== '') {
// selector should also match on an attribute value
const attrValInNode = attrsInNode[attrIdxInNode + 1];
if (attrNameInSelector === 'class') {
// iterate over all the remaining items in the selector selector array = class names
for (i++; i < noOfSelectorParts; i++) {
if (!isCssClassMatching(attrValInNode, selector[i])) {
return false;
}
}
} else if (attrValInSelector !== attrValInNode) {
return false;
const attrName = mode & SelectorFlags.CLASS ? 'class' : current;
const attrIndexInNode = findAttrIndexInNode(attrName, nodeAttrs);
if (attrIndexInNode === -1) {
if (isPositive(mode)) return false;
skipToNextSelector = true;
continue;
}
const selectorAttrValue = mode & SelectorFlags.CLASS ? current : selector[++i];
if (selectorAttrValue !== '') {
const nodeAttrValue = nodeAttrs[attrIndexInNode + 1];
if (mode & SelectorFlags.CLASS &&
!isCssClassMatching(nodeAttrValue, selectorAttrValue as string) ||
mode & SelectorFlags.ATTRIBUTE && selectorAttrValue !== nodeAttrValue) {
if (isPositive(mode)) return false;
skipToNextSelector = true;
}
}
}
}
return true;
return isPositive(mode) || skipToNextSelector;
}
export function isNodeMatchingSelectorWithNegations(
tNode: TNode, selector: CssSelectorWithNegations): boolean {
const positiveSelector = selector[0];
if (positiveSelector != null && !isNodeMatchingSimpleSelector(tNode, positiveSelector)) {
return false;
}
// do we have any negation parts in this selector?
const negativeSelectors = selector[1];
if (negativeSelectors) {
for (let i = 0; i < negativeSelectors.length; i++) {
// if one of negative selectors matched than the whole selector doesn't match
if (isNodeMatchingSimpleSelector(tNode, negativeSelectors[i])) {
return false;
}
}
}
return true;
function isPositive(mode: SelectorFlags): boolean {
return (mode & SelectorFlags.NOT) === 0;
}
export function isNodeMatchingSelector(tNode: TNode, selector: CssSelector): boolean {
function findAttrIndexInNode(name: string, attrs: string[] | null): number {
if (attrs === null) return -1;
for (let i = 0; i < attrs.length; i += 2) {
if (attrs[i] === name) return i;
}
return -1;
}
export function isNodeMatchingSelectorList(tNode: TNode, selector: CssSelectorList): boolean {
for (let i = 0; i < selector.length; i++) {
if (isNodeMatchingSelectorWithNegations(tNode, selector[i])) {
if (isNodeMatchingSelector(tNode, selector[i])) {
return true;
}
}
@ -136,13 +137,13 @@ export function getProjectAsAttrValue(tNode: TNode): string|null {
* to the raw (un-parsed) CSS selector instead of using standard selector matching logic.
*/
export function matchingSelectorIndex(
tNode: TNode, selectors: CssSelector[], textSelectors: string[]): number {
tNode: TNode, selectors: CssSelectorList[], textSelectors: string[]): number {
const ngProjectAsAttrVal = getProjectAsAttrValue(tNode);
for (let i = 0; i < selectors.length; i++) {
// if a node has the ngProjectAs attribute match it against unparsed selector
// match a node against a parsed selector only if ngProjectAs attribute is not present
if (ngProjectAsAttrVal === textSelectors[i] ||
ngProjectAsAttrVal === null && isNodeMatchingSelector(tNode, selectors[i])) {
ngProjectAsAttrVal === null && isNodeMatchingSelectorList(tNode, selectors[i])) {
return i + 1; // first matching selector "captures" a given node
}
}

View File

@ -34,7 +34,7 @@ describe('iv perf test', () => {
class Component {
static ngComponentDef = defineComponent({
type: Component,
selector: [[['div'], null]],
selectors: [['div']],
template: function Template(ctx: any, cm: any) {
if (cm) {
container(0);

View File

@ -25,7 +25,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: MyComponent,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: () => new MyComponent(),
template: (ctx: MyComponent, cm: boolean) => {
if (cm) {
@ -96,7 +96,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: MyComponent,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: () => comp = new MyComponent(),
/**
* {{ doCheckCount }} - {{ name }}
@ -123,7 +123,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: () => new MyApp(),
/** <my-comp [name]="name"></my-comp> */
template: (ctx: MyApp, cm: boolean) => {
@ -223,7 +223,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: ButtonParent,
selector: [[['button-parent'], null]],
selectors: [['button-parent']],
factory: () => parent = new ButtonParent(),
/** {{ doCheckCount }} - <my-comp></my-comp> */
template: (ctx: ButtonParent, cm: boolean) => {
@ -282,7 +282,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: MyComp,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: () => myComp = new MyComp(injectChangeDetectorRef()),
/** {{ name }} */
template: (ctx: MyComp, cm: boolean) => {
@ -304,7 +304,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: ParentComp,
selector: [[['parent-comp'], null]],
selectors: [['parent-comp']],
factory: () => new ParentComp(injectChangeDetectorRef()),
/**
* {{ doCheckCount}} -
@ -327,7 +327,7 @@ describe('change detection', () => {
static ngDirectiveDef = defineDirective({
type: Dir,
selector: [[['', 'dir', ''], null]],
selectors: [['', 'dir', '']],
factory: () => dir = new Dir(injectChangeDetectorRef())
});
}
@ -436,7 +436,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
/**
* {{ name}}
@ -487,7 +487,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: DetectChangesComp,
selector: [[['detect-changes-comp'], null]],
selectors: [['detect-changes-comp']],
factory: () => new DetectChangesComp(injectChangeDetectorRef()),
/** {{ value }} */
template: (ctx: DetectChangesComp, cm: boolean) => {
@ -516,7 +516,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: DetectChangesComp,
selector: [[['detect-changes-comp'], null]],
selectors: [['detect-changes-comp']],
factory: () => new DetectChangesComp(injectChangeDetectorRef()),
/** {{ doCheckCount }} */
template: (ctx: DetectChangesComp, cm: boolean) => {
@ -542,7 +542,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
/** <detached-comp></detached-comp> */
template: (ctx: MyApp, cm: boolean) => {
@ -565,7 +565,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: DetachedComp,
selector: [[['detached-comp'], null]],
selectors: [['detached-comp']],
factory: () => comp = new DetachedComp(injectChangeDetectorRef()),
/** {{ value }} */
template: (ctx: DetachedComp, cm: boolean) => {
@ -661,7 +661,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: OnPushComp,
selector: [[['on-push-comp'], null]],
selectors: [['on-push-comp']],
factory: () => onPushComp = new OnPushComp(injectChangeDetectorRef()),
/** {{ value }} */
template: (ctx: OnPushComp, cm: boolean) => {
@ -717,7 +717,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: OnPushComp,
selector: [[['on-push-comp'], null]],
selectors: [['on-push-comp']],
factory: () => comp = new OnPushComp(injectChangeDetectorRef()),
/** {{ value }} */
template: (ctx: OnPushComp, cm: boolean) => {
@ -735,7 +735,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: OnPushParent,
selector: [[['on-push-parent'], null]],
selectors: [['on-push-parent']],
factory: () => new OnPushParent(),
/**
* {{ value }} -
@ -802,7 +802,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: EmbeddedViewParent,
selector: [[['embedded-view-parent'], null]],
selectors: [['embedded-view-parent']],
factory: () => new EmbeddedViewParent(),
/**
* {{ value }} -
@ -875,7 +875,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: NoChangesComp,
selector: [[['no-changes-comp'], null]],
selectors: [['no-changes-comp']],
factory: () => comp = new NoChangesComp(injectChangeDetectorRef()),
template: (ctx: NoChangesComp, cm: boolean) => {
if (cm) {
@ -893,7 +893,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: AppComp,
selector: [[['app-comp'], null]],
selectors: [['app-comp']],
factory: () => new AppComp(injectChangeDetectorRef()),
/**
* {{ value }} -
@ -953,7 +953,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: EmbeddedViewApp,
selector: [[['embedded-view-app'], null]],
selectors: [['embedded-view-app']],
factory: () => new EmbeddedViewApp(injectChangeDetectorRef()),
/**
* % if (showing) {

View File

@ -23,7 +23,7 @@ describe('@angular/common integration', () => {
static ngComponentDef = defineComponent({
type: MyApp,
factory: () => new MyApp(),
selector: [[['my-app'], null]],
selectors: [['my-app']],
// <ul>
// <li *ngFor="let item of items">{{item}}</li>
// </ul>

View File

@ -16,7 +16,7 @@ export const NgForOf: DirectiveType<NgForOfDef<any>> = NgForOfDef as any;
NgForOf.ngDirectiveDef = defineDirective({
type: NgForOfDef,
selector: [[['', 'ngForOf', ''], null]],
selectors: [['', 'ngForOf', '']],
factory: () => new NgForOfDef(
injectViewContainerRef(), injectTemplateRef(),
directiveInject(IterableDiffers, InjectFlags.Default, defaultIterableDiffers)),

View File

@ -28,7 +28,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: ChildComponent,
selector: [[['child'], null]],
selectors: [['child']],
factory: () => new ChildComponent(),
template: function(ctx: $ChildComponent$, cm: $boolean$) {
if (cm) {
@ -47,7 +47,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: SomeDirective,
selector: [[['', 'some-directive', ''], null]],
selectors: [['', 'some-directive', '']],
factory: () => new SomeDirective(),
});
// /NORMATIVE
@ -63,7 +63,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: () => new MyComponent(),
template: function(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -95,7 +95,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: HostBindingDir,
selector: [[['', 'hostBindingDir', ''], null]],
selectors: [['', 'hostBindingDir', '']],
factory: function HostBindingDir_Factory() { return new HostBindingDir(); },
hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) {
$r3$.ɵp(elIndex, 'id', $r3$.ɵb($r3$.ɵd<HostBindingDir>(dirIndex).dirId));
@ -115,7 +115,7 @@ describe('components & directives', () => {
class MyApp {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -143,7 +143,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngDirectiveDef = $r3$.ɵdefineDirective({
selector: [[['', 'hostListenerDir', ''], null]],
selectors: [['', 'hostListenerDir', '']],
type: HostListenerDir,
factory: function HostListenerDir_Factory() {
const $dir$ = new HostListenerDir();
@ -165,7 +165,7 @@ describe('components & directives', () => {
class MyApp {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -192,7 +192,7 @@ describe('components & directives', () => {
class HostAttributeDir {
// NORMATIVE
static ngDirectiveDef = $r3$.ɵdefineDirective({
selector: [[['', 'hostAttributeDir', ''], null]],
selectors: [['', 'hostAttributeDir', '']],
type: HostAttributeDir,
factory: function HostAttributeDir_Factory() { return new HostAttributeDir(); },
attributes: ['role', 'listbox']
@ -211,7 +211,7 @@ describe('components & directives', () => {
class MyApp {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -239,7 +239,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: HostBindingDir,
selector: [[['', 'hostBindingDir', ''], null]],
selectors: [['', 'hostBindingDir', '']],
factory: function HostBindingDir_Factory() { return new HostBindingDir(); },
hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) {
$r3$.ɵa(elIndex, 'aria-label', $r3$.ɵb($r3$.ɵd<HostBindingDir>(dirIndex).label));
@ -259,7 +259,7 @@ describe('components & directives', () => {
class MyApp {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -294,7 +294,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp(); },
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
if (cm) {
@ -319,7 +319,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -350,7 +350,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: IfDirective,
selector: [[['', 'if', ''], null]],
selectors: [['', 'if', '']],
factory: () => new IfDirective($r3$.ɵinjectTemplateRef()),
});
// /NORMATIVE
@ -368,7 +368,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: () => new MyComponent(),
template: function(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -411,7 +411,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyArrayComp,
selector: [[['my-array-comp'], null]],
selectors: [['my-array-comp']],
factory: function MyArrayComp_Factory() { return new MyArrayComp(); },
template: function MyArrayComp_Template(ctx: $MyArrayComp$, cm: $boolean$) {
if (cm) {
@ -440,7 +440,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -482,7 +482,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -512,7 +512,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp(); },
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
if (cm) {
@ -538,7 +538,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -578,7 +578,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -622,7 +622,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp(); },
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
if (cm) {
@ -683,7 +683,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(c: MyApp, cm: boolean) {
if (cm) {
@ -721,7 +721,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({
type: ObjectComp,
selector: [[['object-comp'], null]],
selectors: [['object-comp']],
factory: function ObjectComp_Factory() { return new ObjectComp(); },
template: function ObjectComp_Template(ctx: $ObjectComp$, cm: $boolean$) {
if (cm) {
@ -755,7 +755,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -792,7 +792,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({
type: NestedComp,
selector: [[['nested-comp'], null]],
selectors: [['nested-comp']],
factory: function NestedComp_Factory() { return new NestedComp(); },
template: function NestedComp_Template(ctx: $NestedComp$, cm: $boolean$) {
if (cm) {
@ -835,7 +835,7 @@ describe('components & directives', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {

View File

@ -24,7 +24,7 @@ describe('content projection', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: SimpleComponent,
selector: [[['simple'], null]],
selectors: [['simple']],
factory: () => new SimpleComponent(),
template: function(ctx: $SimpleComponent$, cm: $boolean$) {
if (cm) {
@ -39,8 +39,8 @@ describe('content projection', () => {
}
// NORMATIVE
const $pD_0P$: $r3$.ɵCssSelector[] =
[[[['span', 'title', 'toFirst'], null]], [[['span', 'title', 'toSecond'], null]]];
const $pD_0P$: $r3$.ɵCssSelectorList[] =
[[['span', 'title', 'toFirst']], [['span', 'title', 'toSecond']]];
const $pD_0R$: string[] = ['span[title=toFirst]', 'span[title=toSecond]'];
// /NORMATIVE
@ -54,7 +54,7 @@ describe('content projection', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: ComplexComponent,
selector: [[['complex'], null]],
selectors: [['complex']],
factory: () => new ComplexComponent(),
template: function(ctx: $ComplexComponent$, cm: $boolean$) {
if (cm) {
@ -79,7 +79,7 @@ describe('content projection', () => {
class MyApp {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: () => new MyApp(),
template: function(ctx: $MyApp$, cm: $boolean$) {
if (cm) {

View File

@ -32,7 +32,7 @@ describe('elements', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: () => new MyComponent(),
template: function(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -61,7 +61,7 @@ describe('elements', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: Dir,
selector: [[['', 'dir', ''], null]],
selectors: [['', 'dir', '']],
factory: function DirA_Factory() { return new Dir(); },
exportAs: 'dir'
});
@ -83,7 +83,7 @@ describe('elements', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: LocalRefComp,
selector: [[['local-ref-comp'], null]],
selectors: [['local-ref-comp']],
factory: function LocalRefComp_Factory() { return new LocalRefComp(); },
template: function LocalRefComp_Template(ctx: $LocalRefComp$, cm: $boolean$) {
if (cm) {
@ -123,7 +123,7 @@ describe('elements', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: ListenerComp,
selector: [[['listener-comp'], null]],
selectors: [['listener-comp']],
factory: function ListenerComp_Factory() { return new ListenerComp(); },
template: function ListenerComp_Template(ctx: $ListenerComp$, cm: $boolean$) {
if (cm) {
@ -155,7 +155,7 @@ describe('elements', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -185,7 +185,7 @@ describe('elements', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -215,7 +215,7 @@ describe('elements', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -249,7 +249,7 @@ describe('elements', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -297,7 +297,7 @@ describe('elements', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -331,7 +331,7 @@ describe('elements', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: StyleComponent,
selector: [[['style-comp'], null]],
selectors: [['style-comp']],
factory: function StyleComponent_Factory() { return new StyleComponent(); },
template: function StyleComponent_Template(ctx: $StyleComponent$, cm: $boolean$) {
if (cm) {

View File

@ -30,7 +30,7 @@ describe('injection', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: function MyComp_Factory() {
return new MyComp($r3$.ɵinjectChangeDetectorRef());
},
@ -47,7 +47,7 @@ describe('injection', () => {
class MyApp {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
/** <my-comp></my-comp> */
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
@ -77,7 +77,7 @@ describe('injection', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp($r3$.ɵinjectAttribute('title')); },
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
if (cm) {
@ -92,7 +92,7 @@ describe('injection', () => {
class MyApp {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
/** <my-comp></my-comp> */
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
@ -142,7 +142,7 @@ describe('injection', () => {
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() {
return new MyApp(
$r3$.ɵdirectiveInject(ServiceA), $r3$.ɵdirectiveInject(ServiceB), inject(INJECTOR));
@ -189,4 +189,4 @@ describe('injection', () => {
});
});
});

View File

@ -41,7 +41,7 @@ describe('lifecycle hooks', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: LifecycleComp,
selector: [[['lifecycle-comp'], null]],
selectors: [['lifecycle-comp']],
factory: function LifecycleComp_Factory() { return new LifecycleComp(); },
template: function LifecycleComp_Template(ctx: $LifecycleComp$, cm: $boolean$) {},
inputs: {nameMin: 'name'},
@ -64,7 +64,7 @@ describe('lifecycle hooks', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: SimpleLayout,
selector: [[['simple-layout'], null]],
selectors: [['simple-layout']],
factory: function SimpleLayout_Factory() { return simpleLayout = new SimpleLayout(); },
template: function SimpleLayout_Template(ctx: $SimpleLayout$, cm: $boolean$) {
if (cm) {

View File

@ -23,7 +23,7 @@ describe('local references', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: () => new MyComponent,
template: function(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {

View File

@ -79,7 +79,7 @@ describe('pipes', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
@ -133,7 +133,7 @@ describe('pipes', () => {
// NORMATIVE
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: OneTimeIf,
selector: [[['', 'oneTimeIf', ''], null]],
selectors: [['', 'oneTimeIf', '']],
factory: () => new OneTimeIf($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef()),
inputs: {oneTimeIf: 'oneTimeIf'}
});
@ -152,7 +152,7 @@ describe('pipes', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
let $pi$: $any$;

View File

@ -22,7 +22,7 @@ describe('queries', () => {
class SomeDirective {
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: SomeDirective,
selector: [[['', 'someDir', ''], null]],
selectors: [['', 'someDir', '']],
factory: function SomeDirective_Factory() { return someDir = new SomeDirective(); },
features: [$r3$.ɵPublicFeature]
});
@ -48,7 +48,7 @@ describe('queries', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: ViewQueryComponent,
selector: [[['view-query-component'], null]],
selectors: [['view-query-component']],
factory: function ViewQueryComponent_Factory() { return new ViewQueryComponent(); },
template: function ViewQueryComponent_Template(ctx: $ViewQueryComponent$, cm: $boolean$) {
let $tmp$: any;
@ -95,7 +95,7 @@ describe('queries', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: ContentQueryComponent,
selector: [[['content-query-component'], null]],
selectors: [['content-query-component']],
factory: function ContentQueryComponent_Factory() {
return [
new ContentQueryComponent(), $r3$.ɵQ(null, SomeDirective, false),
@ -136,7 +136,7 @@ describe('queries', () => {
// NON-NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {

View File

@ -38,7 +38,7 @@ describe('compiler sanitization', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -72,4 +72,4 @@ describe('compiler sanitization', () => {
expect(img.getAttribute('srcset')).toEqual('unsafe:javascript:evil()');
});
});
});

View File

@ -58,7 +58,7 @@ class ToDoAppComponent {
// NORMATIVE
static ngComponentDef = r3.defineComponent({
type: ToDoAppComponent,
selector: [[['todo-app'], null]],
selectors: [['todo-app']],
factory: function ToDoAppComponent_Factory() {
return new ToDoAppComponent(r3.directiveInject(AppState));
},
@ -123,7 +123,7 @@ class ToDoItemComponent {
// NORMATIVE
static ngComponentDef = r3.defineComponent({
type: ToDoItemComponent,
selector: [[['todo'], null]],
selectors: [['todo']],
factory: function ToDoItemComponent_Factory() { return new ToDoItemComponent(); },
template: function ToDoItemComponent_Template(ctx: ToDoItemComponent, cm: boolean) {
if (cm) {

View File

@ -63,7 +63,7 @@ describe('template variables', () => {
// NORMATIVE
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: ForOfDirective,
selector: [[['', 'forOf', ''], null]],
selectors: [['', 'forOf', '']],
factory: function ForOfDirective_Factory() {
return new ForOfDirective($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef());
},
@ -91,7 +91,7 @@ describe('template variables', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
@ -159,7 +159,7 @@ describe('template variables', () => {
// NORMATIVE
static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selector: [[['my-component'], null]],
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {

View File

@ -24,7 +24,7 @@ describe('component', () => {
static ngComponentDef = defineComponent({
type: CounterComponent,
selector: [[['counter'], null]],
selectors: [['counter']],
template: function(ctx: CounterComponent, cm: boolean) {
if (cm) {
text(0);
@ -87,7 +87,7 @@ describe('component with a container', () => {
items: string[];
static ngComponentDef = defineComponent({
type: WrapperComponent,
selector: [[['wrapper'], null]],
selectors: [['wrapper']],
template: function ChildComponentTemplate(ctx: {items: string[]}, cm: boolean) {
if (cm) {
container(0);
@ -131,7 +131,7 @@ describe('encapsulation', () => {
class WrapperComponent {
static ngComponentDef = defineComponent({
type: WrapperComponent,
selector: [[['wrapper'], null]],
selectors: [['wrapper']],
template: function(ctx: WrapperComponent, cm: boolean) {
if (cm) {
elementStart(0, 'encapsulated');
@ -146,7 +146,7 @@ describe('encapsulation', () => {
class EncapsulatedComponent {
static ngComponentDef = defineComponent({
type: EncapsulatedComponent,
selector: [[['encapsulated'], null]],
selectors: [['encapsulated']],
template: function(ctx: EncapsulatedComponent, cm: boolean) {
if (cm) {
text(0, 'foo');
@ -164,7 +164,7 @@ describe('encapsulation', () => {
class LeafComponent {
static ngComponentDef = defineComponent({
type: LeafComponent,
selector: [[['leaf'], null]],
selectors: [['leaf']],
template: function(ctx: LeafComponent, cm: boolean) {
if (cm) {
elementStart(0, 'span');
@ -194,7 +194,7 @@ describe('encapsulation', () => {
class WrapperComponentWith {
static ngComponentDef = defineComponent({
type: WrapperComponentWith,
selector: [[['wrapper'], null]],
selectors: [['wrapper']],
template: function(ctx: WrapperComponentWith, cm: boolean) {
if (cm) {
elementStart(0, 'leaf');
@ -211,7 +211,7 @@ describe('encapsulation', () => {
class LeafComponentwith {
static ngComponentDef = defineComponent({
type: LeafComponentwith,
selector: [[['leaf'], null]],
selectors: [['leaf']],
template: function(ctx: LeafComponentwith, cm: boolean) {
if (cm) {
elementStart(0, 'span');
@ -250,7 +250,7 @@ describe('recursive components', () => {
static ngComponentDef = defineComponent({
type: TreeComponent,
selector: [[['tree-comp'], null]],
selectors: [['tree-comp']],
factory: () => new TreeComponent(),
template: (ctx: TreeComponent, cm: boolean) => {
if (cm) {

View File

@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {SelectorFlags} from '@angular/core/src/render3/interfaces/projection';
import {detectChanges} from '../../src/render3/index';
import {container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective, projection, projectionDef, text} from '../../src/render3/instructions';
@ -522,7 +524,7 @@ describe('content projection', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(
0, [[[['span', 'title', 'toFirst'], null]], [[['span', 'title', 'toSecond'], null]]],
0, [[['span', 'title', 'toFirst']], [['span', 'title', 'toSecond']]],
['span[title=toFirst]', 'span[title=toSecond]']);
elementStart(1, 'div', ['id', 'first']);
{ projection(2, 0, 1); }
@ -568,7 +570,11 @@ describe('content projection', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(
0, [[[['span', 'class', 'toFirst'], null]], [[['span', 'class', 'toSecond'], null]]],
0,
[
[['span', SelectorFlags.CLASS, 'toFirst']],
[['span', SelectorFlags.CLASS, 'toSecond']]
],
['span.toFirst', 'span.toSecond']);
elementStart(1, 'div', ['id', 'first']);
{ projection(2, 0, 1); }
@ -614,7 +620,11 @@ describe('content projection', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(
0, [[[['span', 'class', 'toFirst'], null]], [[['span', 'class', 'toSecond'], null]]],
0,
[
[['span', SelectorFlags.CLASS, 'toFirst']],
[['span', SelectorFlags.CLASS, 'toSecond']]
],
['span.toFirst', 'span.toSecond']);
elementStart(1, 'div', ['id', 'first']);
{ projection(2, 0, 1); }
@ -660,7 +670,7 @@ describe('content projection', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(
0, [[[['span'], null]], [[['span', 'class', 'toSecond'], null]]],
0, [[['span']], [['span', SelectorFlags.CLASS, 'toSecond']]],
['span', 'span.toSecond']);
elementStart(1, 'div', ['id', 'first']);
{ projection(2, 0, 1); }
@ -705,7 +715,7 @@ describe('content projection', () => {
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(0, [[[['span', 'class', 'toFirst'], null]]], ['span.toFirst']);
projectionDef(0, [[['span', SelectorFlags.CLASS, 'toFirst']]], ['span.toFirst']);
elementStart(1, 'div', ['id', 'first']);
{ projection(2, 0, 1); }
elementEnd();
@ -750,7 +760,7 @@ describe('content projection', () => {
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(0, [[[['span', 'class', 'toSecond'], null]]], ['span.toSecond']);
projectionDef(0, [[['span', SelectorFlags.CLASS, 'toSecond']]], ['span.toSecond']);
elementStart(1, 'div', ['id', 'first']);
{ projection(2, 0); }
elementEnd();
@ -802,7 +812,7 @@ describe('content projection', () => {
*/
const GrandChild = createComponent('grand-child', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(0, [[[['span'], null]]], ['span']);
projectionDef(0, [[['span']]], ['span']);
projection(1, 0, 1);
elementStart(2, 'hr');
elementEnd();
@ -865,7 +875,7 @@ describe('content projection', () => {
const Card = createComponent('card', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(
0, [[[['', 'card-title', ''], null]], [[['', 'card-content', ''], null]]],
0, [[['', 'card-title', '']], [['', 'card-content', '']]],
['[card-title]', '[card-content]']);
projection(1, 0, 1);
elementStart(2, 'hr');
@ -924,7 +934,7 @@ describe('content projection', () => {
const Card = createComponent('card', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(
0, [[[['', 'card-title', ''], null]], [[['', 'card-content', ''], null]]],
0, [[['', 'card-title', '']], [['', 'card-content', '']]],
['[card-title]', '[card-content]']);
projection(1, 0, 1);
elementStart(2, 'hr');
@ -979,7 +989,7 @@ describe('content projection', () => {
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(0, [[[['div'], null]]], ['div']);
projectionDef(0, [[['div']]], ['div']);
projection(1, 0, 1);
}
});
@ -1018,7 +1028,7 @@ describe('content projection', () => {
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
projectionDef(0, [[[['div'], null]]], ['div']);
projectionDef(0, [[['div']]], ['div']);
elementStart(1, 'span');
{ projection(2, 0, 1); }
elementEnd();

View File

@ -541,7 +541,7 @@ describe('JS control flow', () => {
class Comp {
static ngComponentDef = defineComponent({
type: Comp,
selector: [[['comp'], null]],
selectors: [['comp']],
factory: () => {
log.push('comp!');
return new Comp();
@ -556,7 +556,7 @@ describe('JS control flow', () => {
static ngComponentDef = defineComponent({
type: App,
selector: [[['app'], null]],
selectors: [['app']],
factory: () => new App(),
template: function(ctx: any, cm: boolean) {
if (cm) {
@ -604,7 +604,7 @@ describe('JS control flow', () => {
class Comp {
static ngComponentDef = defineComponent({
type: Comp,
selector: [[['comp'], null]],
selectors: [['comp']],
factory: () => {
log.push('comp!');
return new Comp();
@ -619,7 +619,7 @@ describe('JS control flow', () => {
static ngComponentDef = defineComponent({
type: App,
selector: [[['app'], null]],
selectors: [['app']],
factory: () => new App(),
template: function(ctx: any, cm: boolean) {
if (cm) {

View File

@ -29,7 +29,7 @@ describe('define', () => {
static ngDirectiveDef = defineDirective({
type: MyDirective,
selector: [[['', 'myDir', ''], null]],
selectors: [['', 'myDir', '']],
factory: () => new MyDirective(),
features: [NgOnChangesFeature()],
inputs: {valA: 'valA', valB: 'valB'}

View File

@ -26,7 +26,7 @@ describe('di', () => {
value: string = 'Created';
static ngDirectiveDef = defineDirective({
type: Directive,
selector: [[['', 'dir', ''], null]],
selectors: [['', 'dir', '']],
factory: () => new Directive,
exportAs: 'dir'
});
@ -54,7 +54,7 @@ describe('di', () => {
value: string = 'A';
static ngDirectiveDef = defineDirective({
type: DirectiveA,
selector: [[['', 'dirA', ''], null]],
selectors: [['', 'dirA', '']],
factory: () => new DirectiveA,
features: [PublicFeature]
});
@ -64,7 +64,7 @@ describe('di', () => {
value: string = 'B';
static ngDirectiveDef = defineDirective({
type: DirectiveB,
selector: [[['', 'dirB', ''], null]],
selectors: [['', 'dirB', '']],
factory: () => new DirectiveB,
features: [PublicFeature]
});
@ -75,7 +75,7 @@ describe('di', () => {
constructor(a: DirectiveA, b: DirectiveB) { this.value = a.value + b.value; }
static ngDirectiveDef = defineDirective({
type: DirectiveC,
selector: [[['', 'dirC', ''], null]],
selectors: [['', 'dirC', '']],
factory: () => new DirectiveC(directiveInject(DirectiveA), directiveInject(DirectiveB)),
exportAs: 'dirC'
});
@ -116,7 +116,7 @@ describe('di', () => {
}
static ngDirectiveDef = defineDirective({
type: Directive,
selector: [[['', 'dir', ''], null]],
selectors: [['', 'dir', '']],
factory: () => new Directive(injectElementRef()),
features: [PublicFeature],
exportAs: 'dir'
@ -130,7 +130,7 @@ describe('di', () => {
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selector: [[['', 'dirSame', ''], null]],
selectors: [['', 'dirSame', '']],
factory: () => new DirectiveSameInstance(injectElementRef(), directiveInject(Directive)),
exportAs: 'dirSame'
});
@ -168,7 +168,7 @@ describe('di', () => {
}
static ngDirectiveDef = defineDirective({
type: Directive,
selector: [[['', 'dir', ''], null]],
selectors: [['', 'dir', '']],
factory: () => new Directive(injectTemplateRef()),
features: [PublicFeature],
exportAs: 'dir'
@ -182,7 +182,7 @@ describe('di', () => {
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selector: [[['', 'dirSame', ''], null]],
selectors: [['', 'dirSame', '']],
factory: () => new DirectiveSameInstance(injectTemplateRef(), directiveInject(Directive)),
exportAs: 'dirSame'
});
@ -218,7 +218,7 @@ describe('di', () => {
}
static ngDirectiveDef = defineDirective({
type: Directive,
selector: [[['', 'dir', ''], null]],
selectors: [['', 'dir', '']],
factory: () => new Directive(injectViewContainerRef()),
features: [PublicFeature],
exportAs: 'dir'
@ -232,7 +232,7 @@ describe('di', () => {
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selector: [[['', 'dirSame', ''], null]],
selectors: [['', 'dirSame', '']],
factory:
() => new DirectiveSameInstance(injectViewContainerRef(), directiveInject(Directive)),
exportAs: 'dirSame'
@ -272,7 +272,7 @@ describe('di', () => {
static ngComponentDef = defineComponent({
type: MyComp,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: () => comp = new MyComp(injectChangeDetectorRef()),
template: function(ctx: MyComp, cm: boolean) {
if (cm) {
@ -288,7 +288,7 @@ describe('di', () => {
constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; }
static ngDirectiveDef = defineDirective({
type: Directive,
selector: [[['', 'dir', ''], null]],
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(injectChangeDetectorRef()),
features: [PublicFeature],
exportAs: 'dir'
@ -300,7 +300,7 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selector: [[['', 'dirSame', ''], null]],
selectors: [['', 'dirSame', '']],
factory: () => dirSameInstance = new DirectiveSameInstance(injectChangeDetectorRef())
});
}
@ -319,7 +319,7 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({
type: IfDirective,
selector: [[['', 'myIf', ''], null]],
selectors: [['', 'myIf', '']],
factory: () => new IfDirective(injectTemplateRef(), injectViewContainerRef()),
inputs: {myIf: 'myIf'},
features: [PublicFeature, NgOnChangesFeature()]
@ -360,7 +360,7 @@ describe('di', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
/** <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(ctx: any, cm: boolean) {
@ -390,7 +390,7 @@ describe('di', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
/**
* <my-comp>
@ -432,7 +432,7 @@ describe('di', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
/**
* % if (showing) {
@ -478,7 +478,7 @@ describe('di', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
/** <div *myIf="showing" dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(ctx: MyApp, cm: boolean) {
@ -607,7 +607,7 @@ describe('di', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selector: [[['my-app'], null]],
selectors: [['my-app']],
factory: () => new MyApp(
directiveInject(String as any, InjectFlags.Default, 'DefaultValue')),
template: () => null
@ -626,7 +626,7 @@ describe('di', () => {
constructor(public parent: any) { this.value = (parent.constructor as any).name; }
static ngDirectiveDef = defineDirective({
type: ChildDirective,
selector: [[['', 'childDir', ''], null]],
selectors: [['', 'childDir', '']],
factory: () => new ChildDirective(directiveInject(ParentDirective)),
features: [PublicFeature],
exportAs: 'childDir'
@ -637,7 +637,7 @@ describe('di', () => {
value: boolean;
constructor(parent: any, child: ChildDirective) { this.value = parent === child.parent; }
static ngDirectiveDef = defineDirective({
selector: [[['', 'child2Dir', ''], null]],
selectors: [['', 'child2Dir', '']],
type: Child2Directive,
factory: () => new Child2Directive(
directiveInject(ParentDirective), directiveInject(ChildDirective)),

View File

@ -22,7 +22,7 @@ describe('directive', () => {
klass = 'foo';
static ngDirectiveDef = defineDirective({
type: Directive,
selector: [[['', 'dir', ''], null]],
selectors: [['', 'dir', '']],
factory: () => directiveInstance = new Directive,
hostBindings: (directiveIndex: number, elementIndex: number) => {
elementProperty(

View File

@ -46,7 +46,7 @@ describe('exports', () => {
static ngComponentDef = defineComponent({
type: MyComponent,
selector: [[['comp'], null]],
selectors: [['comp']],
template: function() {},
factory: () => new MyComponent
});
@ -63,7 +63,7 @@ describe('exports', () => {
constructor() { myComponent = this; }
static ngComponentDef = defineComponent({
type: MyComponent,
selector: [[['comp'], null]],
selectors: [['comp']],
template: function() {},
factory: () => new MyComponent
});
@ -74,7 +74,7 @@ describe('exports', () => {
constructor() { myDir = this; }
static ngDirectiveDef = defineDirective({
type: MyDir,
selector: [[['', 'myDir', ''], null]],
selectors: [['', 'myDir', '']],
factory: () => new MyDir,
inputs: {myDir: 'myDir'}
});
@ -115,7 +115,7 @@ describe('exports', () => {
name = 'Drew';
static ngDirectiveDef = defineDirective({
type: SomeDir,
selector: [[['', 'someDir', ''], null]],
selectors: [['', 'someDir', '']],
factory: () => new SomeDir,
exportAs: 'someDir'
});
@ -216,7 +216,7 @@ describe('exports', () => {
static ngComponentDef = defineComponent({
type: MyComponent,
selector: [[['comp'], null]],
selectors: [['comp']],
template: function(ctx: MyComponent, cm: boolean) {},
factory: () => new MyComponent
});
@ -229,7 +229,7 @@ describe('exports', () => {
static ngDirectiveDef = defineDirective({
type: MyDir,
selector: [[['', 'myDir', ''], null]],
selectors: [['', 'myDir', '']],
factory: () => new MyDir,
inputs: {myDir: 'myDir'}
});
@ -278,7 +278,7 @@ describe('exports', () => {
static ngComponentDef = defineComponent({
type: MyComponent,
selector: [[['comp'], null]],
selectors: [['comp']],
template: function() {},
factory: () => new MyComponent
});

View File

@ -178,7 +178,7 @@ describe('render3 integration test', () => {
static ngComponentDef = defineComponent({
type: TodoComponent,
selector: [[['todo'], null]],
selectors: [['todo']],
template: function TodoTemplate(ctx: any, cm: boolean) {
if (cm) {
elementStart(0, 'p');
@ -242,7 +242,7 @@ describe('render3 integration test', () => {
title = 'one';
static ngComponentDef = defineComponent({
type: TodoComponentHostBinding,
selector: [[['todo'], null]],
selectors: [['todo']],
template: function TodoComponentHostBindingTemplate(
ctx: TodoComponentHostBinding, cm: boolean) {
if (cm) {
@ -277,7 +277,7 @@ describe('render3 integration test', () => {
class HostAttributeComp {
static ngComponentDef = defineComponent({
type: HostAttributeComp,
selector: [[['host-attr-comp'], null]],
selectors: [['host-attr-comp']],
factory: () => new HostAttributeComp(),
template: (ctx: HostAttributeComp, cm: boolean) => {},
attributes: ['role', 'button']
@ -294,7 +294,7 @@ describe('render3 integration test', () => {
name = 'Bess';
static ngComponentDef = defineComponent({
type: MyComp,
selector: [[['comp'], null]],
selectors: [['comp']],
template: function MyCompTemplate(ctx: any, cm: boolean) {
if (cm) {
elementStart(0, 'p');
@ -328,7 +328,7 @@ describe('render3 integration test', () => {
condition: boolean;
static ngComponentDef = defineComponent({
type: MyComp,
selector: [[['comp'], null]],
selectors: [['comp']],
template: function MyCompTemplate(ctx: any, cm: boolean) {
if (cm) {
container(0);
@ -434,7 +434,7 @@ describe('render3 integration test', () => {
beforeTree: Tree;
afterTree: Tree;
static ngComponentDef = defineComponent({
selector: [[['child'], null]],
selectors: [['child']],
type: ChildComponent,
template: function ChildComponentTemplate(
ctx: {beforeTree: Tree, afterTree: Tree}, cm: boolean) {
@ -640,7 +640,7 @@ describe('render3 integration test', () => {
static ngDirectiveDef = defineDirective({
type: HostBindingDir,
selector: [[['', 'hostBindingDir', ''], null]],
selectors: [['', 'hostBindingDir', '']],
factory: function HostBindingDir_Factory() {
return hostBindingDir = new HostBindingDir();
},

View File

@ -52,7 +52,7 @@ describe('lifecycles', () => {
static ngComponentDef = defineComponent({
type: Component,
selector: [[[name], null]],
selectors: [[name]],
factory: () => new Component(),
inputs: {val: 'val'}, template,
directiveDefs: defs
@ -64,7 +64,7 @@ describe('lifecycles', () => {
ngOnInit() { events.push('dir'); }
static ngDirectiveDef = defineDirective(
{type: Directive, selector: [[['', 'dir', ''], null]], factory: () => new Directive()});
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()});
}
const defs = [
@ -362,7 +362,7 @@ describe('lifecycles', () => {
static ngComponentDef = defineComponent({
type: Component,
selector: [[[name], null]],
selectors: [[name]],
factory: () => new Component(), template,
directiveDefs: defs
});
@ -373,7 +373,7 @@ describe('lifecycles', () => {
ngDoCheck() { events.push('dir'); }
static ngDirectiveDef = defineDirective(
{type: Directive, selector: [[['', 'dir', ''], null]], factory: () => new Directive()});
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()});
}
const defs = [Comp.ngComponentDef, Parent.ngComponentDef, Directive.ngDirectiveDef];
@ -516,7 +516,7 @@ describe('lifecycles', () => {
static ngComponentDef = defineComponent({
type: Component,
selector: [[[name], null]],
selectors: [[name]],
factory: () => new Component(),
inputs: {val: 'val'},
template: template,
@ -530,7 +530,7 @@ describe('lifecycles', () => {
ngAfterContentChecked() { events.push('check'); }
static ngDirectiveDef = defineDirective(
{type: Directive, selector: [[['', 'dir', ''], null]], factory: () => new Directive()});
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()});
}
function ForLoopWithChildrenTemplate(ctx: any, cm: boolean) {
@ -886,7 +886,7 @@ describe('lifecycles', () => {
static ngComponentDef = defineComponent({
type: Component,
selector: [[[name], null]],
selectors: [[name]],
factory: () => new Component(),
inputs: {val: 'val'},
template: template,
@ -900,7 +900,7 @@ describe('lifecycles', () => {
ngAfterViewChecked() { events.push('check'); }
static ngDirectiveDef = defineDirective(
{type: Directive, selector: [[['', 'dir', ''], null]], factory: () => new Directive()});
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()});
}
const defs = [
@ -1313,7 +1313,7 @@ describe('lifecycles', () => {
static ngComponentDef = defineComponent({
type: Component,
selector: [[[name], null]],
selectors: [[name]],
factory: () => new Component(),
inputs: {val: 'val'},
template: template,
@ -1335,7 +1335,7 @@ describe('lifecycles', () => {
ngOnDestroy() { events.push('dir'); }
static ngDirectiveDef = defineDirective(
{type: Directive, selector: [[['', 'dir', ''], null]], factory: () => new Directive()});
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()});
}
const defs = [
@ -1830,7 +1830,7 @@ describe('lifecycles', () => {
static ngComponentDef = defineComponent({
type: Component,
selector: [[[name], null]],
selectors: [[name]],
factory: () => new Component(),
features: [NgOnChangesFeature({b: 'val2'})],
inputs: {a: 'val1', b: 'publicName'}, template,
@ -1851,7 +1851,7 @@ describe('lifecycles', () => {
static ngDirectiveDef = defineDirective({
type: Directive,
selector: [[['', 'dir', ''], null]],
selectors: [['', 'dir', '']],
factory: () => new Directive(),
features: [NgOnChangesFeature({b: 'val2'})],
inputs: {a: 'val1', b: 'publicName'}
@ -2207,7 +2207,7 @@ describe('lifecycles', () => {
static ngComponentDef = defineComponent({
type: Component,
selector: [[[name], null]],
selectors: [[name]],
factory: () => new Component(),
inputs: {val: 'val'}, template,
features: [NgOnChangesFeature()],

View File

@ -24,7 +24,7 @@ describe('event listeners', () => {
static ngComponentDef = defineComponent({
type: MyComp,
selector: [[['comp'], null]],
selectors: [['comp']],
/** <button (click)="onClick()"> Click me </button> */
template: function CompTemplate(ctx: any, cm: boolean) {
if (cm) {
@ -61,7 +61,7 @@ describe('event listeners', () => {
static ngComponentDef = defineComponent({
type: PreventDefaultComp,
selector: [[['prevent-default-comp'], null]],
selectors: [['prevent-default-comp']],
factory: () => new PreventDefaultComp(),
/** <button (click)="onClick($event)">Click</button> */
template: (ctx: PreventDefaultComp, cm: boolean) => {
@ -235,7 +235,7 @@ describe('event listeners', () => {
static ngDirectiveDef = defineDirective({
type: HostListenerDir,
selector: [[['', 'hostListenerDir', ''], null]],
selectors: [['', 'hostListenerDir', '']],
factory: function HostListenerDir_Factory() {
const $dir$ = new HostListenerDir();
listener('click', function() { return $dir$.onClick(); });

View File

@ -7,8 +7,8 @@
*/
import {TNode} from '../../src/render3/interfaces/node';
import {CssSelector, CssSelectorWithNegations, NG_PROJECT_AS_ATTR_NAME, SimpleCssSelector} from '../../src/render3/interfaces/projection';
import {getProjectAsAttrValue, isNodeMatchingSelector, isNodeMatchingSelectorWithNegations, isNodeMatchingSimpleSelector} from '../../src/render3/node_selector_matcher';
import {CssSelector, CssSelectorList, NG_PROJECT_AS_ATTR_NAME, SelectorFlags,} from '../../src/render3/interfaces/projection';
import {getProjectAsAttrValue, isNodeMatchingSelectorList, isNodeMatchingSelector} from '../../src/render3/node_selector_matcher';
function testLStaticData(tagName: string, attrs: string[] | null): TNode {
return {
@ -24,19 +24,21 @@ function testLStaticData(tagName: string, attrs: string[] | null): TNode {
}
describe('css selector matching', () => {
function isMatching(tagName: string, attrs: string[] | null, selector: CssSelector): boolean {
return isNodeMatchingSelector(testLStaticData(tagName, attrs), selector);
}
describe('isNodeMatchingSimpleSelector', () => {
function isMatching(
tagName: string, attrs: string[] | null, selector: SimpleCssSelector): boolean {
return isNodeMatchingSimpleSelector(testLStaticData(tagName, attrs), selector);
}
describe('element matching', () => {
it('should match element name only if names are the same', () => {
expect(isMatching('span', null, ['span'])).toBeTruthy();
expect(isMatching('span', null, ['div'])).toBeFalsy();
expect(isMatching('span', null, ['span']))
.toBeTruthy(`Selector 'span' should match <span>`);
expect(isMatching('span', null, ['div']))
.toBeFalsy(`Selector 'div' should NOT match <span>`);
});
/**
@ -44,8 +46,10 @@ describe('css selector matching', () => {
* and in a selector.
*/
it('should match element name case-sensitively', () => {
expect(isMatching('span', null, ['SPAN'])).toBeFalsy();
expect(isMatching('SPAN', null, ['span'])).toBeFalsy();
expect(isMatching('span', null, ['SPAN']))
.toBeFalsy(`Selector 'SPAN' should NOT match <span>`);
expect(isMatching('SPAN', null, ['span']))
.toBeFalsy(`Selector 'span' should NOT match <SPAN>'`);
});
});
@ -55,132 +59,359 @@ describe('css selector matching', () => {
// TODO: do we need to differentiate no value and empty value? that is: title vs. title="" ?
it('should match single attribute without value', () => {
expect(isMatching('span', ['title', ''], ['', 'title', ''])).toBeTruthy();
expect(isMatching('span', ['title', 'my title'], ['', 'title', ''])).toBeTruthy();
expect(isMatching('span', null, ['', 'title', ''])).toBeFalsy();
expect(isMatching('span', ['title', ''], ['', 'other', ''])).toBeFalsy();
expect(isMatching('span', ['title', ''], [
'', 'title', ''
])).toBeTruthy(`Selector '[title]' should match <span title>`);
expect(isMatching('span', ['title', 'my title'], [
'', 'title', ''
])).toBeTruthy(`Selector '[title]' should match <span title="my title">`);
expect(isMatching('span', ['name', 'name'], [
'', 'title', ''
])).toBeFalsy(`Selector '[title]' should NOT match <span name="name">`);
expect(isMatching('span', null, [
'', 'title', ''
])).toBeFalsy(`Selector '[title]' should NOT match <span>`);
expect(isMatching('span', ['title', ''], [
'', 'other', ''
])).toBeFalsy(`Selector '[other]' should NOT match <span title="">'`);
});
it('should match selector with one attribute without value when element has several attributes',
() => {
expect(isMatching('span', ['id', 'my_id', 'title', 'test_title'], [
'', 'title', ''
])).toBeTruthy();
])).toBeTruthy(`Selector '[title]' should match <span id="my_id" title="test_title">`);
});
it('should match single attribute with value', () => {
expect(isMatching('span', ['title', 'My Title'], ['', 'title', 'My Title'])).toBeTruthy();
expect(isMatching('span', ['title', 'My Title'], ['', 'title', 'Other Title'])).toBeFalsy();
});
expect(isMatching('span', ['title', 'My Title'], [
'', 'title', 'My Title'
])).toBeTruthy(`Selector '[title="My Title"]' should match <span title="My Title">'`);
it('should match single attribute with value', () => {
expect(isMatching('span', ['title', 'My Title'], ['', 'title', 'My Title'])).toBeTruthy();
expect(isMatching('span', ['title', 'My Title'], ['', 'title', 'Other Title'])).toBeFalsy();
expect(isMatching('span', ['title', 'My Title'], [
'', 'title', 'Other Title'
])).toBeFalsy(`Selector '[title="Other Title"]' should NOT match <span title="My Title">`);
});
it('should not match attribute when element name does not match', () => {
expect(isMatching('span', ['title', 'My Title'], ['div', 'title', ''])).toBeFalsy();
expect(isMatching('span', ['title', 'My Title'], ['div', 'title', 'My title'])).toBeFalsy();
expect(isMatching('span', ['title', 'My Title'], [
'div', 'title', ''
])).toBeFalsy(`Selector 'div[title]' should NOT match <span title="My Title">`);
expect(isMatching('span', ['title', 'My Title'], [
'div', 'title', 'My Title'
])).toBeFalsy(`Selector 'div[title="My Title"]' should NOT match <span title="My Title">`);
});
it('should match multiple attributes', () => {
// selector: '[title=title][name=name]'
const selector = ['', 'title', 'title', 'name', 'name'];
// <span title="title" name="name">
expect(isMatching('span', ['title', 'title', 'name', 'name'], selector))
.toBeTruthy(
`Selector '[title=title][name=name]' should NOT match <span title="title" name="name">`);
// <span title="title">
expect(isMatching('span', ['title', 'title'], selector))
.toBeFalsy(`Selector '[title=title][name=name]' should NOT match <span title="title">`);
// <span name="name">
expect(isMatching('span', ['name', 'name'], selector))
.toBeFalsy(`Selector '[title=title][name=name]' should NOT match <span name="name">`);
});
it('should handle attribute values that match attribute names', () => {
// selector: [name=name]
const selector = ['', 'name', 'name'];
// <span title="name">
expect(isMatching('span', ['title', 'name'], selector))
.toBeFalsy(`Selector '[name=name]' should NOT match <span title="name">`);
// <span title="name" name="name">
expect(isMatching('span', ['title', 'name', 'name', 'name'], selector))
.toBeTruthy(`Selector '[name=name]' should match <span title="name" name="name">`);
});
/**
* We assume that compiler will lower-case all attribute names when generating code
*/
it('should match attribute name case-sensitively', () => {
expect(isMatching('span', ['foo', ''], ['', 'foo', ''])).toBeTruthy();
expect(isMatching('span', ['foo', ''], ['', 'Foo', ''])).toBeFalsy();
expect(isMatching('span', ['foo', ''], [
'', 'foo', ''
])).toBeTruthy(`Selector '[foo]' should match <span foo>`);
expect(isMatching('span', ['foo', ''], [
'', 'Foo', ''
])).toBeFalsy(`Selector '[Foo]' should NOT match <span foo>`);
});
it('should match attribute values case-sensitively', () => {
expect(isMatching('span', ['foo', 'Bar'], ['', 'foo', 'Bar'])).toBeTruthy();
expect(isMatching('span', ['foo', 'Bar'], ['', 'Foo', 'bar'])).toBeFalsy();
expect(isMatching('span', ['foo', 'Bar'], [
'', 'foo', 'Bar'
])).toBeTruthy(`Selector '[foo="Bar"]' should match <span foo="Bar">`);
expect(isMatching('span', ['foo', 'Bar'], [
'', 'Foo', 'bar'
])).toBeFalsy(`Selector '[Foo="bar"]' should match <span foo="Bar">`);
});
it('should match class as an attribute', () => {
expect(isMatching('span', ['class', 'foo'], ['', 'class', ''])).toBeTruthy();
expect(isMatching('span', ['class', 'foo'], ['', 'class', 'foo'])).toBeTruthy();
expect(isMatching('span', ['class', 'foo'], [
'', 'class', ''
])).toBeTruthy(`Selector '[class]' should match <span class="foo">`);
expect(isMatching('span', ['class', 'foo'], [
'', 'class', 'foo'
])).toBeTruthy(`Selector '[class="foo"]' should match <span class="foo">`);
});
});
describe('class matching', () => {
it('should match with a class selector when an element has multiple classes', () => {
expect(isMatching('span', ['class', 'foo bar'], ['', 'class', 'foo'])).toBeTruthy();
expect(isMatching('span', ['class', 'foo bar'], ['', 'class', 'bar'])).toBeTruthy();
expect(isMatching('span', ['class', 'foo bar'], ['', 'class', 'baz'])).toBeFalsy();
expect(isMatching('span', ['class', 'foo bar'], [
'', SelectorFlags.CLASS, 'foo'
])).toBeTruthy(`Selector '.foo' should match <span class="foo bar">`);
expect(isMatching('span', ['class', 'foo bar'], [
'', SelectorFlags.CLASS, 'bar'
])).toBeTruthy(`Selector '.bar' should match <span class="foo bar">`);
expect(isMatching('span', ['class', 'foo bar'], [
'', SelectorFlags.CLASS, 'baz'
])).toBeFalsy(`Selector '.baz' should NOT match <span class="foo bar">`);
});
it('should not match on partial class name', () => {
expect(isMatching('span', ['class', 'foobar'], ['', 'class', 'foo'])).toBeFalsy();
expect(isMatching('span', ['class', 'foobar'], ['', 'class', 'bar'])).toBeFalsy();
expect(isMatching('span', ['class', 'foobar'], ['', 'class', 'ob'])).toBeFalsy();
expect(isMatching('span', ['class', 'foobar'], ['', 'class', 'foobar'])).toBeTruthy();
expect(isMatching('span', ['class', 'foobar'], [
'', SelectorFlags.CLASS, 'foo'
])).toBeFalsy(`Selector '.foo' should NOT match <span class="foobar">`);
expect(isMatching('span', ['class', 'foobar'], [
'', SelectorFlags.CLASS, 'bar'
])).toBeFalsy(`Selector '.bar' should NOT match <span class="foobar">`);
expect(isMatching('span', ['class', 'foobar'], [
'', SelectorFlags.CLASS, 'ob'
])).toBeFalsy(`Selector '.ob' should NOT match <span class="foobar">`);
expect(isMatching('span', ['class', 'foobar'], [
'', SelectorFlags.CLASS, 'foobar'
])).toBeTruthy(`Selector '.foobar' should match <span class="foobar">`);
});
it('should support selectors with multiple classes', () => {
expect(isMatching('span', ['class', 'foo bar'], ['', 'class', 'foo', 'bar'])).toBeTruthy();
expect(isMatching('span', ['class', 'foo'], ['', 'class', 'foo', 'bar'])).toBeFalsy();
expect(isMatching('span', ['class', 'bar'], ['', 'class', 'foo', 'bar'])).toBeFalsy();
expect(isMatching('span', ['class', 'foo bar'], [
'', SelectorFlags.CLASS, 'foo', 'bar'
])).toBeTruthy(`Selector '.foo.bar' should match <span class="foo bar">`);
expect(isMatching('span', ['class', 'foo'], [
'', SelectorFlags.CLASS, 'foo', 'bar'
])).toBeFalsy(`Selector '.foo.bar' should NOT match <span class="foo">`);
expect(isMatching('span', ['class', 'bar'], [
'', SelectorFlags.CLASS, 'foo', 'bar'
])).toBeFalsy(`Selector '.foo.bar' should NOT match <span class="bar">`);
});
it('should support selectors with multiple classes regardless of class name order', () => {
expect(isMatching('span', ['class', 'foo bar'], ['', 'class', 'foo', 'bar'])).toBeTruthy();
expect(isMatching('span', ['class', 'foo bar'], ['', 'class', 'bar', 'foo'])).toBeTruthy();
expect(isMatching('span', ['class', 'bar foo'], ['', 'class', 'foo', 'bar'])).toBeTruthy();
expect(isMatching('span', ['class', 'bar foo'], ['', 'class', 'bar', 'foo'])).toBeTruthy();
expect(isMatching('span', ['class', 'foo bar'], [
'', SelectorFlags.CLASS, 'bar', 'foo'
])).toBeTruthy(`Selector '.bar.foo' should match <span class="foo bar">`);
expect(isMatching('span', ['class', 'bar foo'], [
'', SelectorFlags.CLASS, 'foo', 'bar'
])).toBeTruthy(`Selector '.foo.bar' should match <span class="bar foo">`);
expect(isMatching('span', ['class', 'bar foo'], [
'', SelectorFlags.CLASS, 'bar', 'foo'
])).toBeTruthy(`Selector '.bar.foo' should match <span class="bar foo">`);
});
it('should match class name case-sensitively', () => {
expect(isMatching('span', ['class', 'Foo'], ['', 'class', 'Foo'])).toBeTruthy();
expect(isMatching('span', ['class', 'Foo'], ['', 'class', 'foo'])).toBeFalsy();
expect(isMatching('span', ['class', 'Foo'], [
'', SelectorFlags.CLASS, 'Foo'
])).toBeTruthy(`Selector '.Foo' should match <span class="Foo">`);
expect(isMatching('span', ['class', 'Foo'], [
'', SelectorFlags.CLASS, 'foo'
])).toBeFalsy(`Selector '.foo' should NOT match <span class-"Foo">`);
});
});
it('should work without a class attribute', () => {
// selector: '.foo'
const selector = ['', SelectorFlags.CLASS, 'foo'];
// <div title="title">
expect(isMatching('div', ['title', 'title'], selector))
.toBeFalsy(`Selector '.foo' should NOT match <div title="title">`);
// <div>
expect(isMatching('div', null, selector))
.toBeFalsy(`Selector '.foo' should NOT match <div>`);
});
it('should work with elements, attributes, and classes', () => {
// selector: 'div.foo[title=title]'
const selector = ['div', 'title', 'title', SelectorFlags.CLASS, 'foo'];
// <div class="foo" title="title">
expect(isMatching('div', ['class', 'foo', 'title', 'title'], selector)).toBeTruthy();
// <div title="title">
expect(isMatching('div', ['title', 'title'], selector)).toBeFalsy();
// <div class="foo">
expect(isMatching('div', ['class', 'foo'], selector)).toBeFalsy();
});
});
});
describe('isNodeMatchingSelectorWithNegations', () => {
function isMatching(
tagName: string, attrs: string[] | null, selector: CssSelectorWithNegations): boolean {
return isNodeMatchingSelectorWithNegations(testLStaticData(tagName, attrs), selector);
}
describe('negations', () => {
it('should match when negation part is null', () => {
expect(isMatching('span', null, [['span'], null])).toBeTruthy();
expect(isMatching('span', null, ['span'])).toBeTruthy(`Selector 'span' should match <span>`);
});
it('should not match when negation part does not match', () => {
// <span foo=""> not matching ":not(span)"
expect(isMatching('span', ['foo', ''], [null, [['span']]])).toBeFalsy();
// <span foo=""> not matching ":not([foo])"
expect(isMatching('span', ['foo', ''], [['span'], [['', 'foo', '']]])).toBeFalsy();
expect(isMatching('span', ['foo', ''], [
'', SelectorFlags.NOT | SelectorFlags.ELEMENT, 'span'
])).toBeFalsy(`Selector ':not(span)' should NOT match <span foo="">`);
expect(isMatching('span', ['foo', ''], [
'span', SelectorFlags.NOT | SelectorFlags.ATTRIBUTE, 'foo', ''
])).toBeFalsy(`Selector 'span:not([foo])' should NOT match <span foo="">`);
});
it('should not match negative selector with tag name and attributes', () => {
// selector: ':not(span[foo])'
const selector = ['', SelectorFlags.NOT | SelectorFlags.ELEMENT, 'span', 'foo', ''];
// <span foo="">
expect(isMatching('span', ['foo', ''], selector)).toBeFalsy();
// <span bar="">
expect(isMatching('span', ['bar', ''], selector)).toBeTruthy();
});
it('should not match negative classes', () => {
// selector: ':not(.foo.bar)'
const selector = ['', SelectorFlags.NOT | SelectorFlags.CLASS, 'foo', 'bar'];
// <span class="foo bar">
expect(isMatching('span', ['class', 'foo bar'], selector)).toBeFalsy();
// <span class="foo">
expect(isMatching('span', ['class', 'foo'], selector)).toBeTruthy();
// <span class="bar">
expect(isMatching('span', ['class', 'bar'], selector)).toBeTruthy();
});
it('should not match negative selector with classes and attributes', () => {
// selector: ':not(.baz[title])
const selector = [
'', SelectorFlags.NOT | SelectorFlags.ATTRIBUTE, 'title', '', SelectorFlags.CLASS, 'baz'
];
// <div class="baz">
expect(isMatching('div', ['class', 'baz'], selector)).toBeTruthy();
// <div title="title">
expect(isMatching('div', ['title', 'title'], selector)).toBeTruthy();
// <div class="baz" title="title">
expect(isMatching('div', ['class', 'baz', 'title', 'title'], selector)).toBeFalsy();
});
it('should not match negative selector with attribute selector after', () => {
// selector: ':not(.baz[title]):not([foo])'
const selector = [
'', SelectorFlags.NOT | SelectorFlags.ATTRIBUTE, 'title', '', SelectorFlags.CLASS, 'baz',
SelectorFlags.NOT | SelectorFlags.ATTRIBUTE, 'foo', ''
];
// <div class="baz">
expect(isMatching('div', ['class', 'baz'], selector)).toBeTruthy();
// <div class="baz" title="">
expect(isMatching('div', ['class', 'baz', 'title', ''], selector)).toBeFalsy();
// <div class="baz" foo="">
expect(isMatching('div', ['class', 'baz', 'foo', ''], selector)).toBeFalsy();
});
it('should not match with multiple negative selectors', () => {
// selector: ':not(span):not([foo])'
const selector = [
'', SelectorFlags.NOT | SelectorFlags.ELEMENT, 'span',
SelectorFlags.NOT | SelectorFlags.ATTRIBUTE, 'foo', ''
];
// <div foo="">
expect(isMatching('div', ['foo', ''], selector)).toBeFalsy();
// <span bar="">
expect(isMatching('span', ['bar', ''], selector)).toBeFalsy();
// <div bar="">
expect(isMatching('div', ['bar', ''], selector)).toBeTruthy();
});
it('should evaluate complex selector with negative selectors', () => {
// selector: 'div.foo.bar[name=name]:not(.baz):not([title])'
const selector = [
'div', 'name', 'name', SelectorFlags.CLASS, 'foo', 'bar',
SelectorFlags.NOT | SelectorFlags.ATTRIBUTE, 'title', '',
SelectorFlags.NOT | SelectorFlags.CLASS, 'baz'
];
// <div name="name" class="foo bar">
expect(isMatching('div', ['name', 'name', 'class', 'foo bar'], selector)).toBeTruthy();
// <div name="name" class="foo bar baz">
expect(isMatching('div', ['name', 'name', 'class', 'foo bar baz'], selector)).toBeFalsy();
// <div name="name" title class="foo bar">
expect(isMatching('div', ['name', 'name', 'title', '', 'class', 'foo bar'], selector))
.toBeFalsy();
});
});
describe('isNodeMatchingSelector', () => {
describe('isNodeMatchingSelectorList', () => {
function isMatching(tagName: string, attrs: string[] | null, selector: CssSelector): boolean {
return isNodeMatchingSelector(testLStaticData(tagName, attrs), selector);
function isAnyMatching(
tagName: string, attrs: string[] | null, selector: CssSelectorList): boolean {
return isNodeMatchingSelectorList(testLStaticData(tagName, attrs), selector);
}
it('should match when there is only one simple selector without negations', () => {
expect(isMatching('span', null, [[['span'], null]])).toBeTruthy();
expect(isMatching('span', null, [[['div'], null]])).toBeFalsy();
expect(isAnyMatching('span', null, [['span']]))
.toBeTruthy(`Selector 'span' should match <span>`);
expect(isAnyMatching('span', null, [['div']]))
.toBeFalsy(`Selector 'div' should NOT match <span>`);
});
it('should atch when there are multiple parts and only one is matching', () => {
// <span foo="bar"> matching "div, [foo=bar]"
expect(isMatching('span', ['foo', 'bar'], [
[['div'], null], [['', 'foo', 'bar'], null]
])).toBeTruthy();
it('should match when there are multiple parts and only one is matching', () => {
expect(isAnyMatching('span', ['foo', 'bar'], [
['div'], ['', 'foo', 'bar']
])).toBeTruthy(`Selector 'div, [foo=bar]' should match <span foo="bar">`);
});
it('should not match when there are multiple parts and none is matching', () => {
// <span foo="bar"> not matching "div, [foo=baz]"
expect(isMatching('span', ['foo', 'bar'], [
[['div'], null], [['', 'foo', 'baz'], null]
])).toBeFalsy();
expect(isAnyMatching('span', ['foo', 'bar'], [
['div'], ['', 'foo', 'baz']
])).toBeFalsy(`Selector 'div, [foo=baz]' should NOT match <span foo="bar">`);
});
});

View File

@ -24,7 +24,7 @@ describe('outputs', () => {
static ngComponentDef = defineComponent({
type: ButtonToggle,
selector: [[['button-toggle'], null]],
selectors: [['button-toggle']],
template: function(ctx: any, cm: boolean) {},
factory: () => buttonToggle = new ButtonToggle(),
outputs: {change: 'change', resetStream: 'reset'}
@ -38,7 +38,7 @@ describe('outputs', () => {
static ngDirectiveDef = defineDirective({
type: OtherDir,
selector: [[['', 'otherDir', ''], null]],
selectors: [['', 'otherDir', '']],
factory: () => otherDir = new OtherDir,
outputs: {changeStream: 'change'}
});
@ -50,7 +50,7 @@ describe('outputs', () => {
static ngComponentDef = defineComponent({
type: DestroyComp,
selector: [[['destroy-comp'], null]],
selectors: [['destroy-comp']],
template: function(ctx: any, cm: boolean) {},
factory: () => destroyComp = new DestroyComp()
});
@ -62,7 +62,7 @@ describe('outputs', () => {
static ngDirectiveDef = defineDirective({
type: MyButton,
selector: [[['', 'myButton', ''], null]],
selectors: [['', 'myButton', '']],
factory: () => buttonDir = new MyButton,
outputs: {click: 'click'}
});
@ -355,7 +355,7 @@ describe('outputs', () => {
static ngDirectiveDef = defineDirective({
type: OtherChangeDir,
selector: [[['', 'otherChangeDir', ''], null]],
selectors: [['', 'otherChangeDir', '']],
factory: () => otherDir = new OtherChangeDir,
inputs: {change: 'change'}
});

View File

@ -70,7 +70,7 @@ describe('pipe', () => {
static ngDirectiveDef = defineDirective({
type: MyDir,
selector: [[['', 'myDir', ''], null]],
selectors: [['', 'myDir', '']],
factory: () => new MyDir(),
inputs: {dirProp: 'elprop'}
});

View File

@ -68,7 +68,7 @@ describe('elementProperty', () => {
static ngComponentDef = defineComponent({
type: HostBindingComp,
selector: [[['host-binding-comp'], null]],
selectors: [['host-binding-comp']],
factory: () => new HostBindingComp(),
hostBindings: (dirIndex: number, elIndex: number) => {
const instance = loadDirective(dirIndex) as HostBindingComp;
@ -97,7 +97,7 @@ describe('elementProperty', () => {
static ngDirectiveDef = defineDirective({
type: MyButton,
selector: [[['', 'myButton', ''], null]],
selectors: [['', 'myButton', '']],
factory: () => button = new MyButton(),
inputs: {disabled: 'disabled'}
});
@ -109,7 +109,7 @@ describe('elementProperty', () => {
static ngDirectiveDef = defineDirective({
type: OtherDir,
selector: [[['', 'otherDir', ''], null]],
selectors: [['', 'otherDir', '']],
factory: () => otherDir = new OtherDir(),
inputs: {id: 'id'},
outputs: {clickStream: 'click'}
@ -121,7 +121,7 @@ describe('elementProperty', () => {
static ngDirectiveDef = defineDirective({
type: OtherDisabledDir,
selector: [[['', 'otherDisabledDir', ''], null]],
selectors: [['', 'otherDisabledDir', '']],
factory: () => otherDisabledDir = new OtherDisabledDir(),
inputs: {disabled: 'disabled'}
});
@ -132,7 +132,7 @@ describe('elementProperty', () => {
static ngDirectiveDef = defineDirective({
type: IdDir,
selector: [[['', 'idDir', ''], null]],
selectors: [['', 'idDir', '']],
factory: () => idDir = new IdDir(),
inputs: {idNumber: 'id'}
});
@ -207,7 +207,7 @@ describe('elementProperty', () => {
static ngComponentDef = defineComponent({
type: Comp,
selector: [[['comp'], null]],
selectors: [['comp']],
template: function(ctx: any, cm: boolean) {},
factory: () => comp = new Comp(),
inputs: {id: 'id'}
@ -345,7 +345,7 @@ describe('elementProperty', () => {
static ngDirectiveDef = defineDirective({
type: MyDir,
selector: [[['', 'myDir', ''], null]],
selectors: [['', 'myDir', '']],
factory: () => myDir = new MyDir(),
inputs: {role: 'role', direction: 'dir'},
outputs: {changeStream: 'change'},
@ -359,7 +359,7 @@ describe('elementProperty', () => {
static ngDirectiveDef = defineDirective({
type: MyDirB,
selector: [[['', 'myDirB', ''], null]],
selectors: [['', 'myDirB', '']],
factory: () => dirB = new MyDirB(),
inputs: {roleB: 'role'}
});
@ -527,7 +527,7 @@ describe('elementProperty', () => {
class Comp {
static ngComponentDef = defineComponent({
type: Comp,
selector: [[['comp'], null]],
selectors: [['comp']],
/** <div role="button" dir #dir="myDir"></div> {{ dir.role }} */
template: function(ctx: any, cm: boolean) {
if (cm) {

View File

@ -18,7 +18,7 @@ describe('array literals', () => {
static ngComponentDef = defineComponent({
type: MyComp,
selector: [[['my-comp'], null]],
selectors: [['my-comp']],
factory: function MyComp_Factory() { return myComp = new MyComp(); },
template: function MyComp_Template(ctx: MyComp, cm: boolean) {},
inputs: {names: 'names'}
@ -69,7 +69,7 @@ describe('array literals', () => {
static ngComponentDef = defineComponent({
type: ManyPropComp,
selector: [[['many-prop-comp'], null]],
selectors: [['many-prop-comp']],
factory: function ManyPropComp_Factory() { return manyPropComp = new ManyPropComp(); },
template: function ManyPropComp_Template(ctx: ManyPropComp, cm: boolean) {},
inputs: {names1: 'names1', names2: 'names2'}
@ -118,7 +118,7 @@ describe('array literals', () => {
static ngComponentDef = defineComponent({
type: ParentComp,
selector: [[['parent-comp'], null]],
selectors: [['parent-comp']],
factory: () => new ParentComp(),
template: function(ctx: any, cm: boolean) {
if (cm) {
@ -313,7 +313,7 @@ describe('object literals', () => {
static ngComponentDef = defineComponent({
type: ObjectComp,
selector: [[['object-comp'], null]],
selectors: [['object-comp']],
factory: function ObjectComp_Factory() { return objectComp = new ObjectComp(); },
template: function ObjectComp_Template(ctx: ObjectComp, cm: boolean) {},
inputs: {config: 'config'}

View File

@ -436,7 +436,7 @@ describe('query', () => {
class Child {
static ngComponentDef = defineComponent({
type: Child,
selector: [[['child'], null]],
selectors: [['child']],
factory: () => childInstance = new Child(),
template: (ctx: Child, cm: boolean) => {},
exportAs: 'child'

View File

@ -197,7 +197,7 @@ export function createComponent(
value: any;
static ngComponentDef = defineComponent({
type: Component,
selector: [[[name], null]],
selectors: [[name]],
factory: () => new Component,
template: template,
features: [PublicFeature],
@ -212,7 +212,7 @@ export function createDirective(
return class Directive {
static ngDirectiveDef = defineDirective({
type: Directive,
selector: [[['', name, ''], null]],
selectors: [['', name, '']],
factory: () => new Directive(),
features: [PublicFeature],
exportAs: exportAs,

View File

@ -31,7 +31,7 @@ describe('renderer factory lifecycle', () => {
class SomeComponent {
static ngComponentDef = defineComponent({
type: SomeComponent,
selector: [[['some-component'], null]],
selectors: [['some-component']],
template: function(ctx: SomeComponent, cm: boolean) {
logs.push('component');
if (cm) {
@ -45,7 +45,7 @@ describe('renderer factory lifecycle', () => {
class SomeComponentWhichThrows {
static ngComponentDef = defineComponent({
type: SomeComponentWhichThrows,
selector: [[['some-component-with-Error'], null]],
selectors: [['some-component-with-Error']],
template: function(ctx: SomeComponentWhichThrows, cm: boolean) {
throw(new Error('SomeComponentWhichThrows threw'));
},
@ -124,7 +124,7 @@ describe('animation renderer factory', () => {
class SomeComponent {
static ngComponentDef = defineComponent({
type: SomeComponent,
selector: [[['some-component'], null]],
selectors: [['some-component']],
template: function(ctx: SomeComponent, cm: boolean) {
if (cm) {
text(0, 'foo');
@ -141,7 +141,7 @@ describe('animation renderer factory', () => {
}
static ngComponentDef = defineComponent({
type: SomeComponentWithAnimation,
selector: [[['some-component'], null]],
selectors: [['some-component']],
template: function(ctx: SomeComponentWithAnimation, cm: boolean) {
if (cm) {
elementStart(0, 'div');

View File

@ -18,7 +18,7 @@ describe('ViewContainerRef', () => {
static ngDirectiveDef = defineDirective({
type: TestDirective,
selector: [[['', 'testDir', ''], null]],
selectors: [['', 'testDir', '']],
factory: () => new TestDirective(injectViewContainerRef(), injectTemplateRef(), ),
});
}
@ -28,7 +28,7 @@ describe('ViewContainerRef', () => {
static ngComponentDef = defineComponent({
type: TestComponent,
selector: [[['test-cmp'], null]],
selectors: [['test-cmp']],
factory: () => new TestComponent(),
template: (cmp: TestComponent, cm: boolean) => {
if (cm) {