feat(ivy): ngtsc compiles @Component, @Directive, @NgModule (#24427)

This change supports compilation of components, directives, and modules
within ngtsc. Support is not complete, but is enough to compile and test
//packages/core/test/bundling/todo in full AOT mode. Code size benefits
are not yet achieved as //packages/core itself does not get compiled, and
some decorators (e.g. @Input) are not stripped, leading to unwanted code
being retained by the tree-shaker. This will be improved in future commits.

PR Close #24427
This commit is contained in:
Alex Rickabaugh
2018-05-31 15:50:02 -07:00
committed by Miško Hevery
parent 0f7e4fae20
commit 27bc7dcb43
69 changed files with 1884 additions and 607 deletions

View File

@ -11,6 +11,7 @@ export {
defineComponent as ɵdefineComponent,
defineDirective as ɵdefineDirective,
definePipe as ɵdefinePipe,
defineNgModule as ɵdefineNgModule,
detectChanges as ɵdetectChanges,
renderComponent as ɵrenderComponent,
ComponentType as ɵComponentType,
@ -82,8 +83,8 @@ export {
st as ɵst,
ld as ɵld,
Pp as ɵPp,
ComponentDef as ɵComponentDef,
DirectiveDef as ɵDirectiveDef,
ComponentDefInternal as ɵComponentDef,
DirectiveDefInternal as ɵDirectiveDef,
PipeDef as ɵPipeDef,
whenRendered as ɵwhenRendered,
} from './render3/index';

View File

@ -13,7 +13,7 @@
import {Attribute, ContentChild, ContentChildren, Query, ViewChild, ViewChildren} from './metadata/di';
import {Component, Directive, HostBinding, HostListener, Input, Output, Pipe} from './metadata/directives';
import {ModuleWithProviders, NgModule, NgModuleDef, SchemaMetadata, defineNgModule} from './metadata/ng_module';
import {ModuleWithProviders, NgModule, SchemaMetadata} from './metadata/ng_module';
import {ViewEncapsulation} from './metadata/view';
export {ANALYZE_FOR_ENTRY_COMPONENTS, Attribute, ContentChild, ContentChildDecorator, ContentChildren, ContentChildrenDecorator, Query, ViewChild, ViewChildDecorator, ViewChildren, ViewChildrenDecorator} from './metadata/di';

View File

@ -388,6 +388,14 @@ export interface Directive {
* ```
*/
queries?: {[key: string]: any};
/**
* If true, this directive/component will be skipped by the AOT compiler and so will always be
* compiled using JIT.
*
* This exists to support future Ivy work and has no effect currently.
*/
jit?: true;
}
/**

View File

@ -27,11 +27,39 @@ export interface NgModuleTransitiveScopes {
exported: {directives: Set<any>; pipes: Set<any>;};
}
export interface NgModuleDef<T> {
/**
* A version of {@link NgModuleDef} that represents the runtime type shape only, and excludes
* metadata parameters.
*/
export type NgModuleDefInternal<T> = NgModuleDef<T, any, any, any>;
/**
* Runtime link information for NgModules.
*
* This is the internal data structure used by the runtime to assemble components, directives,
* pipes, and injectors.
*
* NOTE: Always use `defineNgModule` function to create this object,
* never create the object directly since the shape of this object
* can change between versions.
*/
export interface NgModuleDef<T, Declarations, Imports, Exports> {
/** Token representing the module. Used by DI. */
type: T;
/** List of components to bootstrap. */
bootstrap: Type<any>[];
/** List of components, directives, and pipes declared by this module. */
declarations: Type<any>[];
/** List of modules or `ModuleWithProviders` imported by this module. */
imports: Type<any>[];
/**
* List of modules, `ModuleWithProviders`, components, directives, or pipes exported by this
* module.
*/
exports: Type<any>[];
/**
@ -42,18 +70,6 @@ export interface NgModuleDef<T> {
transitiveCompileScopes: NgModuleTransitiveScopes|null;
}
export function defineNgModule<T>(def: {type: T} & Partial<NgModuleDef<T>>): never {
const res: NgModuleDef<T> = {
type: def.type,
bootstrap: def.bootstrap || [],
declarations: def.declarations || [],
imports: def.imports || [],
exports: def.exports || [],
transitiveCompileScopes: null,
};
return res as never;
}
/**
* A wrapper around a module that also includes the providers.
*
@ -226,6 +242,14 @@ export interface NgModule {
* `getModuleFactory`.
*/
id?: string;
/**
* If true, this module will be skipped by the AOT compiler and so will always be compiled
* using JIT.
*
* This exists to support future Ivy work and has no effect currently.
*/
jit?: true;
}
function preR3NgModuleCompile(moduleType: InjectorType<any>, metadata: NgModule): void {

View File

@ -15,7 +15,7 @@ import {Sanitizer} from '../sanitization/security';
import {assertComponentType, assertDefined} from './assert';
import {queueInitHooks, queueLifecycleHooks} from './hooks';
import {CLEAN_PROMISE, ROOT_DIRECTIVE_INDICES, _getComponentHostLElementNode, baseDirectiveCreate, createLViewData, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, getRootView, hostElement, initChangeDetectorIfExisting, leaveView, locateHostElement, setHostBindings,} from './instructions';
import {ComponentDef, ComponentType} from './interfaces/definition';
import {ComponentDef, ComponentDefInternal, ComponentType} from './interfaces/definition';
import {LElementNode} from './interfaces/node';
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {LViewData, LViewFlags, RootContext, INJECTOR, CONTEXT, TVIEW} from './interfaces/view';
@ -52,7 +52,7 @@ export interface CreateComponentOptions {
* features list because there's no way of knowing when the component will be used as
* a root component.
*/
hostFeatures?: (<T>(component: T, componentDef: ComponentDef<T>) => void)[];
hostFeatures?: (<T>(component: T, componentDef: ComponentDef<T, string>) => void)[];
/**
* A function which is used to schedule change detection work in the future.
@ -96,7 +96,8 @@ export function renderComponent<T>(
ngDevMode && assertComponentType(componentType);
const rendererFactory = opts.rendererFactory || domRendererFactory3;
const sanitizer = opts.sanitizer || null;
const componentDef = (componentType as ComponentType<T>).ngComponentDef as ComponentDef<T>;
const componentDef =
(componentType as ComponentType<T>).ngComponentDef as ComponentDefInternal<T>;
if (componentDef.type != componentType) componentDef.type = componentType;
let component: T;
// The first index of the first selector is the tag name.
@ -157,7 +158,7 @@ export function createRootContext(scheduler: (workFn: () => void) => void): Root
* renderComponent(AppComponent, {features: [RootLifecycleHooks]});
* ```
*/
export function LifecycleHooksFeature(component: any, def: ComponentDef<any>): void {
export function LifecycleHooksFeature(component: any, def: ComponentDefInternal<any>): void {
const elementNode = _getComponentHostLElementNode(component);
// Root component is always created at dir index 0

View File

@ -19,7 +19,7 @@ import {Type} from '../type';
import {assertComponentType, assertDefined} from './assert';
import {createRootContext} from './component';
import {baseDirectiveCreate, createLViewData, createTView, enterView, hostElement, initChangeDetectorIfExisting, locateHostElement} from './instructions';
import {ComponentDef, ComponentType} from './interfaces/definition';
import {ComponentDefInternal, ComponentType} from './interfaces/definition';
import {LElementNode} from './interfaces/node';
import {RElement} from './interfaces/renderer';
import {INJECTOR, LViewData, LViewFlags, RootContext} from './interfaces/view';
@ -72,7 +72,7 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
return toRefArray(this.componentDef.outputs);
}
constructor(private componentDef: ComponentDef<any>) {
constructor(private componentDef: ComponentDefInternal<any>) {
super();
this.componentType = componentDef.type;
this.selector = componentDef.selectors[0][0] as string;

View File

@ -11,12 +11,13 @@ import {ChangeDetectionStrategy} from '../change_detection/constants';
import {PipeTransform} from '../change_detection/pipe_transform';
import {Provider} from '../core';
import {OnChanges, SimpleChanges} from '../metadata/lifecycle_hooks';
import {NgModuleDef, NgModuleDefInternal} from '../metadata/ng_module';
import {RendererType2} from '../render/api';
import {Type} from '../type';
import {resolveRendererType2} from '../view/util';
import {diPublic} from './di';
import {ComponentDef, ComponentDefFeature, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFeature, DirectiveDefListOrFactory, DirectiveType, DirectiveTypesOrFactory, PipeDef, PipeType, PipeTypesOrFactory} from './interfaces/definition';
import {ComponentDefFeature, ComponentDefInternal, ComponentTemplate, ComponentType, DirectiveDefFeature, DirectiveDefInternal, DirectiveDefListOrFactory, DirectiveType, DirectiveTypesOrFactory, PipeDef, PipeType, PipeTypesOrFactory} from './interfaces/definition';
import {CssSelectorList, SelectorFlags} from './interfaces/projection';
@ -166,7 +167,7 @@ export function defineComponent<T>(componentDefinition: {
const type = componentDefinition.type;
const pipeTypes = componentDefinition.pipes !;
const directiveTypes = componentDefinition.directives !;
const def = <ComponentDef<any>>{
const def: ComponentDefInternal<any> = {
type: type,
diPublic: null,
factory: componentDefinition.factory,
@ -176,7 +177,7 @@ export function defineComponent<T>(componentDefinition: {
inputs: invertObject(componentDefinition.inputs),
outputs: invertObject(componentDefinition.outputs),
rendererType: resolveRendererType2(componentDefinition.rendererType) || null,
exportAs: componentDefinition.exportAs,
exportAs: componentDefinition.exportAs || null,
onInit: type.prototype.ngOnInit || null,
doCheck: type.prototype.ngDoCheck || null,
afterContentInit: type.prototype.ngAfterContentInit || null,
@ -200,7 +201,7 @@ export function defineComponent<T>(componentDefinition: {
}
export function extractDirectiveDef(type: DirectiveType<any>& ComponentType<any>):
DirectiveDef<any>|ComponentDef<any> {
DirectiveDefInternal<any>|ComponentDefInternal<any> {
const def = type.ngComponentDef || type.ngDirectiveDef;
if (ngDevMode && !def) {
throw new Error(`'${type.name}' is neither 'ComponentType' or 'DirectiveType'.`);
@ -216,7 +217,17 @@ export function extractPipeDef(type: PipeType<any>): PipeDef<any> {
return def;
}
export function defineNgModule<T>(def: {type: T} & Partial<NgModuleDef<T, any, any, any>>): never {
const res: NgModuleDefInternal<T> = {
type: def.type,
bootstrap: def.bootstrap || [],
declarations: def.declarations || [],
imports: def.imports || [],
exports: def.exports || [],
transitiveCompileScopes: null,
};
return res as never;
}
const PRIVATE_PREFIX = '__ngOnChanges_';
@ -250,7 +261,7 @@ type OnChangesExpando = OnChanges & {
*/
export function NgOnChangesFeature(inputPropertyNames?: {[key: string]: string}):
DirectiveDefFeature {
return function(definition: DirectiveDef<any>): void {
return function(definition: DirectiveDefInternal<any>): void {
const inputs = definition.inputs;
const proto = definition.type.prototype;
for (let pubKey in inputs) {
@ -313,7 +324,7 @@ export function NgOnChangesFeature(inputPropertyNames?: {[key: string]: string})
}
export function PublicFeature<T>(definition: DirectiveDef<T>) {
export function PublicFeature<T>(definition: DirectiveDefInternal<T>) {
definition.diPublic = diPublic;
}

View File

@ -21,7 +21,7 @@ import {Type} from '../type';
import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
import {addToViewTree, assertPreviousIsParent, createLContainer, createLNodeObject, createTNode, getDirectiveInstance, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate, resolveDirective} from './instructions';
import {VIEWS} from './interfaces/container';
import {ComponentTemplate, DirectiveDef} from './interfaces/definition';
import {ComponentTemplate, DirectiveDefInternal} from './interfaces/definition';
import {LInjector} from './interfaces/injector';
import {AttributeMarker, LContainerNode, LElementNode, LNode, LViewNode, TNodeFlags, TNodeType} from './interfaces/node';
import {LQueries, QueryReadType} from './interfaces/query';
@ -141,7 +141,7 @@ export function getOrCreateNodeInjectorForNode(node: LElementNode | LContainerNo
* @param di The node injector in which a directive will be added
* @param def The definition of the directive to be made public
*/
export function diPublicInInjector(di: LInjector, def: DirectiveDef<any>): void {
export function diPublicInInjector(di: LInjector, def: DirectiveDefInternal<any>): void {
bloomAdd(di, def.type);
}
@ -150,7 +150,7 @@ export function diPublicInInjector(di: LInjector, def: DirectiveDef<any>): void
*
* @param def The definition of the directive to be made public
*/
export function diPublic(def: DirectiveDef<any>): void {
export function diPublic(def: DirectiveDefInternal<any>): void {
diPublicInInjector(getOrCreateNodeInjector(), def);
}
@ -376,7 +376,7 @@ export function getOrCreateInjectable<T>(
for (let i = start; i < end; i++) {
// Get the definition for the directive at this index and, if it is injectable (diPublic),
// and matches the given token, return the directive instance.
const directiveDef = defs[i] as DirectiveDef<any>;
const directiveDef = defs[i] as DirectiveDefInternal<any>;
if (directiveDef.type === token && directiveDef.diPublic) {
return getDirectiveInstance(node.view[DIRECTIVES] ![i]);
}
@ -409,7 +409,7 @@ function searchMatchesQueuedForCreation<T>(node: LNode, token: any): T|null {
const matches = node.view[TVIEW].currentMatches;
if (matches) {
for (let i = 0; i < matches.length; i += 2) {
const def = matches[i] as DirectiveDef<any>;
const def = matches[i] as DirectiveDefInternal<any>;
if (def.type === token) {
return resolveDirective(def, i + 1, matches, node.view[TVIEW]);
}

View File

@ -7,7 +7,7 @@
*/
import {assertEqual} from './assert';
import {DirectiveDef} from './interfaces/definition';
import {DirectiveDefInternal} from './interfaces/definition';
import {TNodeFlags} from './interfaces/node';
import {DIRECTIVES, FLAGS, HookData, LViewData, LViewFlags, TView} from './interfaces/view';
@ -52,7 +52,7 @@ export function queueLifecycleHooks(flags: number, tView: TView): void {
// directiveCreate) so we can preserve the current hook order. Content, view, and destroy
// hooks for projected components and directives must be called *before* their hosts.
for (let i = start; i < end; i++) {
const def: DirectiveDef<any> = tView.directives ![i];
const def: DirectiveDefInternal<any> = tView.directives ![i];
queueContentHooks(def, tView, i);
queueViewHooks(def, tView, i);
queueDestroyHooks(def, tView, i);
@ -61,7 +61,7 @@ export function queueLifecycleHooks(flags: number, tView: TView): void {
}
/** Queues afterContentInit and afterContentChecked hooks on TView */
function queueContentHooks(def: DirectiveDef<any>, tView: TView, i: number): void {
function queueContentHooks(def: DirectiveDefInternal<any>, tView: TView, i: number): void {
if (def.afterContentInit) {
(tView.contentHooks || (tView.contentHooks = [])).push(i, def.afterContentInit);
}
@ -73,7 +73,7 @@ function queueContentHooks(def: DirectiveDef<any>, tView: TView, i: number): voi
}
/** Queues afterViewInit and afterViewChecked hooks on TView */
function queueViewHooks(def: DirectiveDef<any>, tView: TView, i: number): void {
function queueViewHooks(def: DirectiveDefInternal<any>, tView: TView, i: number): void {
if (def.afterViewInit) {
(tView.viewHooks || (tView.viewHooks = [])).push(i, def.afterViewInit);
}
@ -85,7 +85,7 @@ function queueViewHooks(def: DirectiveDef<any>, tView: TView, i: number): void {
}
/** Queues onDestroy hooks on TView */
function queueDestroyHooks(def: DirectiveDef<any>, tView: TView, i: number): void {
function queueDestroyHooks(def: DirectiveDefInternal<any>, tView: TView, i: number): void {
if (def.onDestroy != null) {
(tView.destroyHooks || (tView.destroyHooks = [])).push(i, def.onDestroy);
}

View File

@ -7,8 +7,8 @@
*/
import {LifecycleHooksFeature, getHostElement, getRenderedText, renderComponent, whenRendered} from './component';
import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective, definePipe} from './definition';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType, PipeDef} from './interfaces/definition';
import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective, defineNgModule, definePipe} from './definition';
import {ComponentDefInternal, ComponentTemplate, ComponentType, DirectiveDefFlags, DirectiveDefInternal, DirectiveType, PipeDef} from './interfaces/definition';
export {ComponentFactory, ComponentFactoryResolver, ComponentRef} from './component_ref';
export {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, directiveInject, injectAttribute, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from './di';
@ -16,6 +16,7 @@ export {RenderFlags} from './interfaces/definition';
export {CssSelectorList} from './interfaces/projection';
// Naming scheme:
// - Capital letters are for creating things: T(Text), E(Element), D(Directive), V(View),
// C(Container), L(Listener)
@ -116,10 +117,10 @@ export {
// clang-format on
export {
ComponentDef,
ComponentDefInternal,
ComponentTemplate,
ComponentType,
DirectiveDef,
DirectiveDefInternal,
DirectiveDefFlags,
DirectiveType,
NgOnChangesFeature,
@ -128,6 +129,7 @@ export {
LifecycleHooksFeature,
defineComponent,
defineDirective,
defineNgModule,
definePipe,
getHostElement,
getRenderedText,

View File

@ -23,7 +23,7 @@ import {AttributeMarker, TAttributes, LContainerNode, LElementNode, LNode, TNode
import {assertNodeType} from './node_assert';
import {appendChild, insertView, appendProjectedNode, removeView, canInsertNativeNode, createTextNode, getNextLNode, getChildLNode, getParentLNode, getLViewChild} from './node_manipulation';
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, PipeDefListOrFactory, RenderFlags} from './interfaces/definition';
import {ComponentDefInternal, ComponentTemplate, DirectiveDefInternal, DirectiveDefListOrFactory, PipeDefListOrFactory, RenderFlags} from './interfaces/definition';
import {RComment, RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer';
import {isDifferent, stringify} from './util';
import {ViewRef} from './view_ref';
@ -258,7 +258,7 @@ export function setHostBindings(bindings: number[] | null): void {
const defs = tView.directives !;
for (let i = 0; i < bindings.length; i += 2) {
const dirIndex = bindings[i];
const def = defs[dirIndex] as DirectiveDef<any>;
const def = defs[dirIndex] as DirectiveDefInternal<any>;
def.hostBindings && def.hostBindings(dirIndex, bindings[i + 1]);
}
}
@ -659,7 +659,7 @@ function cacheMatchingDirectivesForNode(
const matches = tView.currentMatches = findDirectiveMatches(tNode);
if (matches) {
for (let i = 0; i < matches.length; i += 2) {
const def = matches[i] as DirectiveDef<any>;
const def = matches[i] as DirectiveDefInternal<any>;
const valueIndex = i + 1;
resolveDirective(def, valueIndex, matches, tView);
saveNameToExportMap(matches[valueIndex] as number, def, exportsMap);
@ -676,7 +676,7 @@ function findDirectiveMatches(tNode: TNode): CurrentMatchesList|null {
for (let i = 0; i < registry.length; i++) {
const def = registry[i];
if (isNodeMatchingSelectorList(tNode, def.selectors !)) {
if ((def as ComponentDef<any>).template) {
if ((def as ComponentDefInternal<any>).template) {
if (tNode.flags & TNodeFlags.isComponent) throwMultipleComponentError(tNode);
tNode.flags = TNodeFlags.isComponent;
}
@ -689,7 +689,8 @@ function findDirectiveMatches(tNode: TNode): CurrentMatchesList|null {
}
export function resolveDirective(
def: DirectiveDef<any>, valueIndex: number, matches: CurrentMatchesList, tView: TView): any {
def: DirectiveDefInternal<any>, valueIndex: number, matches: CurrentMatchesList,
tView: TView): any {
if (matches[valueIndex] === null) {
matches[valueIndex] = CIRCULAR;
const instance = def.factory();
@ -745,7 +746,7 @@ function instantiateDirectivesDirectly() {
const tDirectives = tView.directives !;
for (let i = start; i < end; i++) {
const def: DirectiveDef<any> = tDirectives[i];
const def: DirectiveDefInternal<any> = tDirectives[i];
directiveCreate(i, def.factory(), def);
}
}
@ -773,11 +774,11 @@ function cacheMatchingLocalNames(
* to their directive instances.
*/
function saveNameToExportMap(
index: number, def: DirectiveDef<any>| ComponentDef<any>,
index: number, def: DirectiveDefInternal<any>| ComponentDefInternal<any>,
exportsMap: {[key: string]: number} | null) {
if (exportsMap) {
if (def.exportAs) exportsMap[def.exportAs] = index;
if ((def as ComponentDef<any>).template) exportsMap[''] = index;
if ((def as ComponentDefInternal<any>).template) exportsMap[''] = index;
}
}
@ -929,7 +930,7 @@ export function locateHostElement(
* @returns LElementNode created
*/
export function hostElement(
tag: string, rNode: RElement | null, def: ComponentDef<any>,
tag: string, rNode: RElement | null, def: ComponentDefInternal<any>,
sanitizer?: Sanitizer | null): LElementNode {
resetApplicationState();
const node = createLNode(
@ -1187,7 +1188,7 @@ function generatePropertyAliases(
const defs = tView.directives !;
for (let i = start; i < end; i++) {
const directiveDef = defs[i] as DirectiveDef<any>;
const directiveDef = defs[i] as DirectiveDefInternal<any>;
const propertyAliasMap: {[publicName: string]: string} =
isInput ? directiveDef.inputs : directiveDef.outputs;
for (let publicName in propertyAliasMap) {
@ -1387,15 +1388,16 @@ export function textBinding<T>(index: number, value: T | NO_CHANGE): void {
* @param directiveDef DirectiveDef object which contains information about the template.
*/
export function directiveCreate<T>(
index: number, directive: T, directiveDef: DirectiveDef<T>| ComponentDef<T>): T {
index: number, directive: T,
directiveDef: DirectiveDefInternal<T>| ComponentDefInternal<T>): T {
const instance = baseDirectiveCreate(index, directive, directiveDef);
ngDevMode && assertDefined(previousOrParentNode.tNode, 'previousOrParentNode.tNode');
const tNode = previousOrParentNode.tNode;
const isComponent = (directiveDef as ComponentDef<T>).template;
const isComponent = (directiveDef as ComponentDefInternal<T>).template;
if (isComponent) {
addComponentLogic(index, directive, directiveDef as ComponentDef<T>);
addComponentLogic(index, directive, directiveDef as ComponentDefInternal<T>);
}
if (firstTemplatePass) {
@ -1413,7 +1415,8 @@ export function directiveCreate<T>(
return instance;
}
function addComponentLogic<T>(directiveIndex: number, instance: T, def: ComponentDef<T>): void {
function addComponentLogic<T>(
directiveIndex: number, instance: T, def: ComponentDefInternal<T>): void {
const tView = getOrCreateTView(def.template, def.directiveDefs, def.pipeDefs);
// Only component views should be added to the view tree directly. Embedded views are
@ -1442,7 +1445,8 @@ function addComponentLogic<T>(directiveIndex: number, instance: T, def: Componen
* current Angular. Example: local refs and inputs on root component.
*/
export function baseDirectiveCreate<T>(
index: number, directive: T, directiveDef: DirectiveDef<T>| ComponentDef<T>): T {
index: number, directive: T,
directiveDef: DirectiveDefInternal<T>| ComponentDefInternal<T>): T {
ngDevMode &&
assertEqual(viewData[BINDING_INDEX], -1, 'directives should be created before any bindings');
ngDevMode && assertPreviousIsParent();

View File

@ -54,6 +54,12 @@ export const enum DirectiveDefFlags {ContentQuery = 0b10}
*/
export interface PipeType<T> extends Type<T> { ngPipeDef: never; }
/**
* A version of {@link DirectiveDef} that represents the runtime type shape only, and excludes
* metadata parameters.
*/
export type DirectiveDefInternal<T> = DirectiveDef<T, string>;
/**
* Runtime link information for Directives.
*
@ -64,14 +70,16 @@ export interface PipeType<T> extends Type<T> { ngPipeDef: never; }
* never create the object directly since the shape of this object
* can change between versions.
*
* @param Selector type metadata specifying the selector of the directive or component
*
* See: {@link defineDirective}
*/
export interface DirectiveDef<T> {
export interface DirectiveDef<T, Selector extends string> {
/** Token representing the directive. Used by DI. */
type: Type<T>;
/** Function that makes a directive public to the DI system. */
diPublic: ((def: DirectiveDef<any>) => void)|null;
diPublic: ((def: DirectiveDef<any, string>) => void)|null;
/** The selectors that will be used to match nodes to this directive. */
selectors: CssSelectorList;
@ -124,6 +132,12 @@ export interface DirectiveDef<T> {
onDestroy: (() => void)|null;
}
/**
* A version of {@link ComponentDef} that represents the runtime type shape only, and excludes
* metadata parameters.
*/
export type ComponentDefInternal<T> = ComponentDef<T, string>;
/**
* Runtime link information for Components.
*
@ -136,7 +150,7 @@ export interface DirectiveDef<T> {
*
* See: {@link defineComponent}
*/
export interface ComponentDef<T> extends DirectiveDef<T> {
export interface ComponentDef<T, Selector extends string> extends DirectiveDef<T, Selector> {
/**
* The View template of the component.
*
@ -220,8 +234,8 @@ export interface PipeDef<T> {
onDestroy: (() => void)|null;
}
export type DirectiveDefFeature = <T>(directiveDef: DirectiveDef<T>) => void;
export type ComponentDefFeature = <T>(componentDef: ComponentDef<T>) => void;
export type DirectiveDefFeature = <T>(directiveDef: DirectiveDef<T, string>) => void;
export type ComponentDefFeature = <T>(componentDef: ComponentDef<T, string>) => void;
/**
* Type used for directiveDefs on component definition.
@ -230,12 +244,12 @@ export type ComponentDefFeature = <T>(componentDef: ComponentDef<T>) => void;
*/
export type DirectiveDefListOrFactory = (() => DirectiveDefList) | DirectiveDefList;
export type DirectiveDefList = (DirectiveDef<any>| ComponentDef<any>)[];
export type DirectiveDefList = (DirectiveDef<any, string>| ComponentDef<any, string>)[];
export type DirectiveTypesOrFactory = (() => DirectiveTypeList) | DirectiveTypeList;
export type DirectiveTypeList =
(DirectiveDef<any>| ComponentDef<any>|
(DirectiveDef<any, string>| ComponentDef<any, string>|
Type<any>/* Type as workaround for: Microsoft/TypeScript/issues/4881 */)[];
/**

View File

@ -10,7 +10,7 @@ import {Injector} from '../../di/injector';
import {Sanitizer} from '../../sanitization/security';
import {LContainer} from './container';
import {ComponentTemplate, DirectiveDef, DirectiveDefList, PipeDef, PipeDefList} from './definition';
import {ComponentTemplate, DirectiveDefInternal, DirectiveDefList, PipeDef, PipeDefList} from './definition';
import {LElementNode, LViewNode, TNode} from './node';
import {LQueries} from './query';
import {Renderer3} from './renderer';
@ -443,7 +443,7 @@ export type HookData = (number | (() => void))[];
export type TData = (TNode | PipeDef<any>| null)[];
/** Type for TView.currentMatches */
export type CurrentMatchesList = [DirectiveDef<any>, (string | number | null)];
export type CurrentMatchesList = [DirectiveDefInternal<any>, (string | number | null)];
// Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.

View File

@ -47,7 +47,9 @@ export function compileComponent(type: Type<any>, metadata: Component): Promise<
const constantPool = new ConstantPool();
// Parse the template and check for errors.
const template = parseTemplate(templateStr, `ng://${type.name}/template.html`);
const template = parseTemplate(templateStr, `ng://${type.name}/template.html`, {
preserveWhitespaces: metadata.preserveWhitespaces || false,
});
if (template.errors !== undefined) {
const errors = template.errors.map(err => err.toString()).join(', ');
throw new Error(`Errors during JIT compilation of template for ${type.name}: ${errors}`);

View File

@ -8,7 +8,6 @@
import {defineInjectable, defineInjector,} from '../../di/defs';
import {inject} from '../../di/injector';
import {defineNgModule} from '../../metadata/ng_module';
import * as r3 from '../index';
@ -22,7 +21,7 @@ export const angularCoreEnv: {[name: string]: Function} = {
'ɵdefineDirective': r3.defineDirective,
'defineInjectable': defineInjectable,
'defineInjector': defineInjector,
'ɵdefineNgModule': defineNgModule,
'ɵdefineNgModule': r3.defineNgModule,
'ɵdefinePipe': r3.definePipe,
'ɵdirectiveInject': r3.directiveInject,
'inject': inject,

View File

@ -8,9 +8,9 @@
import {Expression, R3NgModuleMetadata, WrappedNodeExpr, compileNgModule as compileR3NgModule, jitExpression} from '@angular/compiler';
import {ModuleWithProviders, NgModule, NgModuleDef, NgModuleTransitiveScopes} from '../../metadata/ng_module';
import {ModuleWithProviders, NgModule, NgModuleDefInternal, NgModuleTransitiveScopes} from '../../metadata/ng_module';
import {Type} from '../../type';
import {ComponentDef} from '../interfaces/definition';
import {ComponentDefInternal} from '../interfaces/definition';
import {angularCoreEnv} from './environment';
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from './fields';
@ -48,7 +48,8 @@ export function compileNgModule(type: Type<any>, ngModule: NgModule): void {
if (declaration.hasOwnProperty(NG_COMPONENT_DEF)) {
// An `ngComponentDef` field exists - go ahead and patch the component directly.
patchComponentDefWithScope(
(declaration as Type<any>& {ngComponentDef: ComponentDef<any>}).ngComponentDef, type);
(declaration as Type<any>& {ngComponentDef: ComponentDefInternal<any>}).ngComponentDef,
type);
} else if (
!declaration.hasOwnProperty(NG_DIRECTIVE_DEF) && !declaration.hasOwnProperty(NG_PIPE_DEF)) {
// Set `ngSelectorScope` for future reference when the component compilation finishes.
@ -61,7 +62,8 @@ export function compileNgModule(type: Type<any>, ngModule: NgModule): void {
* Patch the definition of a component with directives and pipes from the compilation scope of
* a given module.
*/
export function patchComponentDefWithScope<C, M>(componentDef: ComponentDef<C>, module: Type<M>) {
export function patchComponentDefWithScope<C, M>(
componentDef: ComponentDefInternal<C>, module: Type<M>) {
componentDef.directiveDefs = () => Array.from(transitiveScopesFor(module).compilation.directives)
.map(dir => dir.ngDirectiveDef || dir.ngComponentDef)
.filter(def => !!def);
@ -113,7 +115,7 @@ export function transitiveScopesFor<T>(moduleType: Type<T>): NgModuleTransitiveS
def.imports.forEach(<I>(imported: Type<I>) => {
let importedTyped = imported as Type<I>& {
// If imported is an @NgModule:
ngModuleDef?: NgModuleDef<I>;
ngModuleDef?: NgModuleDefInternal<I>;
};
if (!isNgModule<I>(importedTyped)) {
@ -132,7 +134,7 @@ export function transitiveScopesFor<T>(moduleType: Type<T>): NgModuleTransitiveS
// Components, Directives, NgModules, and Pipes can all be exported.
ngComponentDef?: any;
ngDirectiveDef?: any;
ngModuleDef?: NgModuleDef<E>;
ngModuleDef?: NgModuleDefInternal<E>;
ngPipeDef?: any;
};
@ -188,6 +190,6 @@ function isModuleWithProviders(value: any): value is ModuleWithProviders {
return (value as{ngModule?: any}).ngModule !== undefined;
}
function isNgModule<T>(value: Type<T>): value is Type<T>&{ngModuleDef: NgModuleDef<T>} {
return (value as{ngModuleDef?: NgModuleDef<T>}).ngModuleDef !== undefined;
function isNgModule<T>(value: Type<T>): value is Type<T>&{ngModuleDef: NgModuleDefInternal<T>} {
return (value as{ngModuleDef?: NgModuleDefInternal<T>}).ngModuleDef !== undefined;
}

View File

@ -18,7 +18,7 @@ import {getSymbolIterator} from '../util';
import {assertDefined, assertEqual} from './assert';
import {ReadFromInjectorFn, getOrCreateNodeInjectorForNode} from './di';
import {assertPreviousIsParent, getCurrentQueries, store, storeCleanupWithContext} from './instructions';
import {DirectiveDef, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition';
import {DirectiveDefInternal, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition';
import {LInjector, unusedValueExportToPlacateAjd as unused2} from './interfaces/injector';
import {LContainerNode, LElementNode, LNode, TNode, TNodeFlags, unusedValueExportToPlacateAjd as unused3} from './interfaces/node';
import {LQueries, QueryReadType, unusedValueExportToPlacateAjd as unused4} from './interfaces/query';
@ -232,7 +232,7 @@ function getIdxOfMatchingDirective(node: LNode, type: Type<any>): number|null {
const start = flags >> TNodeFlags.DirectiveStartingIndexShift;
const end = start + count;
for (let i = start; i < end; i++) {
const def = defs[i] as DirectiveDef<any>;
const def = defs[i] as DirectiveDefInternal<any>;
if (def.type === type && def.diPublic) {
return i;
}

View File

@ -49,6 +49,7 @@ jasmine_node_test(
],
tags = [
"ivy-jit",
"ivy-local",
],
deps = [":test_lib"],
)

View File

@ -51,7 +51,11 @@ jasmine_node_test(
":bundle.min.js",
":bundle.min_debug.js",
],
tags = ["ivy-jit"],
tags = [
"ivy-jit",
"ivy-local",
"ivy-only",
],
deps = [":test_lib"],
)

View File

@ -26,24 +26,12 @@
{
"name": "DIRECTIVES"
},
{
"name": "DefaultIterableDiffer"
},
{
"name": "DefaultIterableDifferFactory"
},
{
"name": "EMPTY$2"
},
{
"name": "EMPTY_RENDERER_TYPE_ID"
},
{
"name": "ElementRef$1"
},
{
"name": "EmbeddedViewRef$1"
},
{
"name": "FLAGS"
},
@ -59,12 +47,6 @@
{
"name": "INJECTOR$1"
},
{
"name": "IterableChangeRecord_"
},
{
"name": "IterableDiffers"
},
{
"name": "NEXT"
},
@ -92,12 +74,6 @@
{
"name": "NgIfContext"
},
{
"name": "Optional"
},
{
"name": "PARAMETERS"
},
{
"name": "PARENT"
},
@ -107,9 +83,6 @@
{
"name": "RENDERER"
},
{
"name": "RENDER_PARENT"
},
{
"name": "ROOT_DIRECTIVE_INDICES"
},
@ -119,18 +92,12 @@
{
"name": "SANITIZER"
},
{
"name": "SkipSelf"
},
{
"name": "TAIL"
},
{
"name": "TVIEW"
},
{
"name": "TemplateRef$1"
},
{
"name": "ToDoAppComponent"
},
@ -149,36 +116,12 @@
{
"name": "VIEWS"
},
{
"name": "ViewContainerRef$1"
},
{
"name": "_CLEAN_PROMISE"
},
{
"name": "_DuplicateItemRecordList"
},
{
"name": "_DuplicateMap"
},
{
"name": "_ROOT_DIRECTIVE_INDICES"
},
{
"name": "__extends"
},
{
"name": "__read"
},
{
"name": "__self"
},
{
"name": "__spread"
},
{
"name": "__window"
},
{
"name": "_c0"
},
@ -242,21 +185,12 @@
{
"name": "_getComponentHostLElementNode"
},
{
"name": "_global"
},
{
"name": "_renderCompCount"
},
{
"name": "_symbolIterator"
},
{
"name": "addComponentLogic"
},
{
"name": "addRemoveViewFromContainer"
},
{
"name": "addToViewTree"
},
@ -293,15 +227,9 @@
{
"name": "canInsertNativeNode"
},
{
"name": "checkNoChanges"
},
{
"name": "checkNoChangesMode"
},
{
"name": "cleanUpView"
},
{
"name": "componentRefresh"
},
@ -341,27 +269,12 @@
{
"name": "defineComponent"
},
{
"name": "defineDirective"
},
{
"name": "defineInjectable"
},
{
"name": "defineInjector"
},
{
"name": "destroyLView"
},
{
"name": "destroyViewTree"
},
{
"name": "detachView"
},
{
"name": "detectChanges"
},
{
"name": "detectChangesInternal"
},
@ -398,18 +311,6 @@
{
"name": "executeInitHooks"
},
{
"name": "executeNodeAction"
},
{
"name": "executeOnDestroys"
},
{
"name": "executePipeOnDestroys"
},
{
"name": "extendStatics"
},
{
"name": "extractDirectiveDef"
},
@ -431,9 +332,6 @@
{
"name": "generatePropertyAliases"
},
{
"name": "getChildLNode"
},
{
"name": "getCleanup"
},
@ -446,18 +344,6 @@
{
"name": "getLViewChild"
},
{
"name": "getNextLNode"
},
{
"name": "getNextLNodeWithProjection"
},
{
"name": "getOrCreateContainerRef"
},
{
"name": "getOrCreateElementRef"
},
{
"name": "getOrCreateInjectable"
},
@ -470,39 +356,21 @@
{
"name": "getOrCreateTView"
},
{
"name": "getOrCreateTemplateRef"
},
{
"name": "getParentLNode"
},
{
"name": "getParentState"
},
{
"name": "getPreviousIndex"
},
{
"name": "getPreviousOrParentNode"
},
{
"name": "getRenderFlags"
},
{
"name": "getRenderer"
},
{
"name": "getRootView"
},
{
"name": "getSymbolIterator"
},
{
"name": "getTViewCleanup"
},
{
"name": "getTypeNameForDebugging"
},
{
"name": "getTypeNameForDebugging$1"
},
@ -518,15 +386,6 @@
{
"name": "inject"
},
{
"name": "injectTemplateRef"
},
{
"name": "injectViewContainerRef"
},
{
"name": "insertView"
},
{
"name": "instantiateDirectivesDirectly"
},
@ -545,12 +404,6 @@
{
"name": "isDifferent"
},
{
"name": "isJsObject"
},
{
"name": "isListLikeIterable"
},
{
"name": "isNodeMatchingSelector"
},
@ -563,9 +416,6 @@
{
"name": "isProceduralRenderer"
},
{
"name": "iterateListLike"
},
{
"name": "leaveView"
},
@ -581,15 +431,6 @@
{
"name": "locateHostElement"
},
{
"name": "looseIdentical"
},
{
"name": "makeMetadataCtor"
},
{
"name": "makeParamDecorator"
},
{
"name": "markDirtyIfOnPush"
},
@ -599,9 +440,6 @@
{
"name": "namespaceHTML"
},
{
"name": "notImplemented"
},
{
"name": "queueComponentIndexForCheck"
},
@ -632,12 +470,6 @@
{
"name": "refreshView"
},
{
"name": "removeListeners"
},
{
"name": "removeView"
},
{
"name": "renderComponent"
},
@ -716,15 +548,9 @@
{
"name": "tickRootContext"
},
{
"name": "trackByIdentity"
},
{
"name": "viewAttached"
},
{
"name": "walkLNodeTree"
},
{
"name": "wrapListenerWithDirtyAndDefault"
},

View File

@ -147,36 +147,7 @@ export class ToDoAppComponent {
}
}
// In JIT mode the @Directive decorators in //packages/common will compile the Ivy fields. When
// running under --define=compile=legacy, //packages/common is not compiled with Ivy fields, so they
// must be monkey-patched on.
if (!(NgIf as any).ngDirectiveDef) {
// TODO(misko): This hack is here because common is not compiled with Ivy flag turned on.
(CommonModule as any).ngInjectorDef = defineInjector({factory: () => new CommonModule});
// TODO(misko): This hack is here because common is not compiled with Ivy flag turned on.
(NgForOf as any).ngDirectiveDef = defineDirective({
type: NgForOf,
selectors: [['', 'ngFor', '', 'ngForOf', '']],
factory: () => new NgForOf(
injectViewContainerRef(), injectTemplateRef(), directiveInject(IterableDiffers)),
inputs: {
ngForOf: 'ngForOf',
ngForTrackBy: 'ngForTrackBy',
ngForTemplate: 'ngForTemplate',
}
});
// TODO(misko): This hack is here because common is not compiled with Ivy flag turned on.
(NgIf as any).ngDirectiveDef = defineDirective({
type: NgIf,
selectors: [['', 'ngIf', '']],
factory: () => new NgIf(injectViewContainerRef(), injectTemplateRef()),
inputs: {ngIf: 'ngIf', ngIfThen: 'ngIfThen', ngIfElse: 'ngIfElse'}
});
}
@NgModule({declarations: [ToDoAppComponent, ToDoAppComponent], imports: [CommonModule]})
@NgModule({declarations: [ToDoAppComponent], imports: [CommonModule]})
export class ToDoAppModule {
}

View File

@ -8,7 +8,7 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentDef} from '../../../src/render3/interfaces/definition';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {renderComponent, toHtml} from '../render_util';
@ -78,8 +78,9 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyComponent.ngComponentDef as ComponentDef<any>).directiveDefs =
[(ChildComponent.ngComponentDef as ComponentDef<any>), SomeDirective.ngDirectiveDef];
(MyComponent.ngComponentDef as ComponentDefInternal<any>).directiveDefs = [
(ChildComponent.ngComponentDef as ComponentDefInternal<any>), SomeDirective.ngDirectiveDef
];
// /NON-NORMATIVE
expect(renderComp(MyComponent)).toEqual('<child some-directive="">child-view</child>!');
@ -127,7 +128,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs = [HostBindingDir.ngDirectiveDef];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[HostBindingDir.ngDirectiveDef];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<div hostbindingdir="" id="some id"></div>`);
@ -178,7 +180,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs = [HostListenerDir.ngDirectiveDef];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[HostListenerDir.ngDirectiveDef];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<button hostlistenerdir="">Click</button>`);
@ -222,7 +225,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs = [HostAttributeDir.ngDirectiveDef];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[HostAttributeDir.ngDirectiveDef];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<div hostattributedir="" role="listbox"></div>`);
@ -269,7 +273,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs = [HostBindingDir.ngDirectiveDef];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[HostBindingDir.ngDirectiveDef];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<div aria-label="some label" hostbindingdir=""></div>`);
@ -331,8 +336,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs =
[(MyComp.ngComponentDef as ComponentDef<any>)];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[(MyComp.ngComponentDef as ComponentDefInternal<any>)];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<my-comp>some name</my-comp>`);
@ -461,8 +466,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs =
[(MyArrayComp.ngComponentDef as ComponentDef<any>)];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[(MyArrayComp.ngComponentDef as ComponentDefInternal<any>)];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<my-array-comp>Nancy Bess</my-array-comp>`);
@ -506,8 +511,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs =
[(MyArrayComp.ngComponentDef as ComponentDef<any>)];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[(MyArrayComp.ngComponentDef as ComponentDefInternal<any>)];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<my-array-comp>NANCY Bess</my-array-comp>`);
@ -571,8 +576,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs =
[(MyComp.ngComponentDef as ComponentDef<any>)];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[(MyComp.ngComponentDef as ComponentDefInternal<any>)];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<my-comp>3</my-comp>`);
@ -614,8 +619,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs =
[(MyArrayComp.ngComponentDef as ComponentDef<any>)];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[(MyArrayComp.ngComponentDef as ComponentDefInternal<any>)];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<my-array-comp>Nancy Bess</my-array-comp>`);
@ -727,8 +732,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs =
[(MyComp.ngComponentDef as ComponentDef<any>)];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[(MyComp.ngComponentDef as ComponentDefInternal<any>)];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<my-comp>start-abcde-middle-fghi-end</my-comp>`);
@ -802,8 +807,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs =
[(ObjectComp.ngComponentDef as ComponentDef<any>)];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[(ObjectComp.ngComponentDef as ComponentDefInternal<any>)];
// /NON-NORMATIVE
expect(renderComp(MyApp)).toEqual(`<object-comp><p>500</p><p>slide</p></object-comp>`);
@ -890,8 +895,8 @@ describe('components & directives', () => {
}
// NON-NORMATIVE (done by defineNgModule)
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs =
[(NestedComp.ngComponentDef as ComponentDef<any>)];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[(NestedComp.ngComponentDef as ComponentDefInternal<any>)];
// /NON-NORMATIVE
expect(renderComp(MyApp))

View File

@ -11,7 +11,7 @@ import {browserDetection} from '@angular/platform-browser/testing/src/browser_ut
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {AttributeMarker} from '../../../src/render3';
import {ComponentDef} from '../../../src/render3/interfaces/definition';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {ComponentFixture, renderComponent, toHtml} from '../render_util';
@ -107,7 +107,8 @@ describe('elements', () => {
}
// NON-NORMATIVE
(LocalRefComp.ngComponentDef as ComponentDef<any>).directiveDefs = () => [Dir.ngDirectiveDef];
(LocalRefComp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
() => [Dir.ngDirectiveDef];
// /NON-NORMATIVE
const fixture = new ComponentFixture(LocalRefComp);

View File

@ -8,7 +8,7 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentDef} from '../../../src/render3/interfaces/definition';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {renderComponent, toHtml} from '../render_util';
@ -83,7 +83,8 @@ describe('lifecycle hooks', () => {
}
// NON-NORMATIVE
(SimpleLayout.ngComponentDef as ComponentDef<any>).directiveDefs = [LifecycleComp.ngComponentDef];
(SimpleLayout.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[LifecycleComp.ngComponentDef];
// /NON-NORMATIVE
it('should gen hooks with a few simple components', () => {

View File

@ -8,7 +8,7 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentDef} from '../../../src/render3/interfaces/definition';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {containerEl, renderComponent, toHtml} from '../render_util';
@ -101,7 +101,7 @@ describe('pipes', () => {
}
// NON-NORMATIVE
(MyApp.ngComponentDef as ComponentDef<any>).pipeDefs =
(MyApp.ngComponentDef as ComponentDefInternal<any>).pipeDefs =
() => [MyPurePipe.ngPipeDef, MyPipe.ngPipeDef];
// /NON-NORMATIVE
@ -197,8 +197,8 @@ describe('pipes', () => {
}
// NON-NORMATIVE
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs = [OneTimeIf.ngDirectiveDef];
(MyApp.ngComponentDef as ComponentDef<any>).pipeDefs = [MyPurePipe.ngPipeDef];
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs = [OneTimeIf.ngDirectiveDef];
(MyApp.ngComponentDef as ComponentDefInternal<any>).pipeDefs = [MyPurePipe.ngPipeDef];
// /NON-NORMATIVE
let myApp: MyApp = renderComponent(MyApp);

View File

@ -8,7 +8,7 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentDef} from '../../../src/render3/interfaces/definition';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {renderComponent, toHtml} from '../render_util';
@ -71,7 +71,7 @@ describe('queries', () => {
}
// NON-NORMATIVE
(ViewQueryComponent.ngComponentDef as ComponentDef<any>).directiveDefs =
(ViewQueryComponent.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[SomeDirective.ngDirectiveDef];
// /NON-NORMATIVE
@ -155,7 +155,7 @@ describe('queries', () => {
}
// NON-NORMATIVE
(MyApp.ngComponentDef as ComponentDef<any>).directiveDefs =
(MyApp.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[ContentQueryComponent.ngComponentDef, SomeDirective.ngDirectiveDef];
// /NON-NORMATIVE

View File

@ -96,7 +96,7 @@ class ToDoAppComponent {
}
// NON-NORMATIVE
(ToDoAppComponent.ngComponentDef as r3.ComponentDef<any>).directiveDefs = () =>
(ToDoAppComponent.ngComponentDef as r3.ComponentDefInternal<any>).directiveDefs = () =>
[ToDoItemComponent.ngComponentDef, (NgForOf as r3.DirectiveType<NgForOf<any>>).ngDirectiveDef];
// /NON-NORMATIVE

View File

@ -8,7 +8,7 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentDef} from '../../../src/render3/interfaces/definition';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {renderComponent, toHtml} from '../render_util';
@ -125,7 +125,7 @@ describe('template variables', () => {
}
// NON-NORMATIVE
(MyComponent.ngComponentDef as ComponentDef<any>).directiveDefs =
(MyComponent.ngComponentDef as ComponentDefInternal<any>).directiveDefs =
[ForOfDirective.ngDirectiveDef];
// /NON-NORMATIVE

View File

@ -11,7 +11,7 @@ import {DoCheck, ViewEncapsulation, createInjector, defineInjectable, defineInje
import {getRenderedText} from '../../src/render3/component';
import {ComponentFactory, LifecycleHooksFeature, defineComponent, directiveInject, markDirty} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, text, textBinding, tick} from '../../src/render3/instructions';
import {ComponentDef, DirectiveDef, RenderFlags} from '../../src/render3/interfaces/definition';
import {ComponentDefInternal, DirectiveDefInternal, RenderFlags} from '../../src/render3/interfaces/definition';
import {createRendererType2} from '../../src/view/index';
import {getRendererFactory2} from './imported_renderer2';
@ -346,7 +346,7 @@ describe('recursive components', () => {
});
}
(TreeComponent.ngComponentDef as ComponentDef<TreeComponent>).directiveDefs =
(TreeComponent.ngComponentDef as ComponentDefInternal<TreeComponent>).directiveDefs =
() => [TreeComponent.ngComponentDef];
function _buildTree(currDepth: number): TreeNode {

View File

@ -7,7 +7,7 @@
*/
import {DoCheck, OnChanges, SimpleChange, SimpleChanges} from '../../src/core';
import {DirectiveDef, NgOnChangesFeature, defineDirective} from '../../src/render3/index';
import {DirectiveDefInternal, NgOnChangesFeature, defineDirective} from '../../src/render3/index';
describe('define', () => {
describe('component', () => {
@ -36,15 +36,15 @@ describe('define', () => {
});
}
const myDir =
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).factory() as MyDirective;
const myDir = (MyDirective.ngDirectiveDef as DirectiveDefInternal<MyDirective>)
.factory() as MyDirective;
myDir.valA = 'first';
expect(myDir.valA).toEqual('first');
myDir.valB = 'second';
expect(myDir.log).toEqual(['second']);
expect(myDir.valB).toEqual('works');
myDir.log.length = 0;
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).doCheck !.call(myDir);
(MyDirective.ngDirectiveDef as DirectiveDefInternal<MyDirective>).doCheck !.call(myDir);
const changeA = new SimpleChange(undefined, 'first', true);
const changeB = new SimpleChange(undefined, 'second', true);
expect(myDir.log).toEqual(['ngOnChanges', 'valA', changeA, 'valB', changeB, 'ngDoCheck']);
@ -70,18 +70,18 @@ describe('define', () => {
});
}
const myDir =
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).factory() as MyDirective;
const myDir = (MyDirective.ngDirectiveDef as DirectiveDefInternal<MyDirective>)
.factory() as MyDirective;
myDir.valA = 'first';
myDir.valB = 'second';
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).doCheck !.call(myDir);
(MyDirective.ngDirectiveDef as DirectiveDefInternal<MyDirective>).doCheck !.call(myDir);
const changeA1 = new SimpleChange(undefined, 'first', true);
const changeB1 = new SimpleChange(undefined, 'second', true);
expect(myDir.log).toEqual(['valA', changeA1, 'valB', changeB1]);
myDir.log.length = 0;
myDir.valA = 'third';
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).doCheck !.call(myDir);
(MyDirective.ngDirectiveDef as DirectiveDefInternal<MyDirective>).doCheck !.call(myDir);
const changeA2 = new SimpleChange('first', 'third', false);
expect(myDir.log).toEqual(['valA', changeA2, 'valB', undefined]);
});
@ -106,11 +106,11 @@ describe('define', () => {
});
}
const myDir =
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).factory() as MyDirective;
const myDir = (MyDirective.ngDirectiveDef as DirectiveDefInternal<MyDirective>)
.factory() as MyDirective;
myDir.onlySetter = 'someValue';
expect(myDir.onlySetter).toBeUndefined();
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).doCheck !.call(myDir);
(MyDirective.ngDirectiveDef as DirectiveDefInternal<MyDirective>).doCheck !.call(myDir);
const changeSetter = new SimpleChange(undefined, 'someValue', true);
expect(myDir.log).toEqual(['someValue', 'ngOnChanges', 'onlySetter', changeSetter]);
});

View File

@ -10,8 +10,8 @@ import {Injectable} from '@angular/core/src/di/injectable';
import {inject, setCurrentInjector} from '@angular/core/src/di/injector';
import {ivyEnabled} from '@angular/core/src/ivy_switch';
import {Component, HostBinding, HostListener} from '@angular/core/src/metadata/directives';
import {NgModule, NgModuleDef} from '@angular/core/src/metadata/ng_module';
import {ComponentDef} from '@angular/core/src/render3/interfaces/definition';
import {NgModule, NgModuleDefInternal} from '@angular/core/src/metadata/ng_module';
import {ComponentDefInternal} from '@angular/core/src/render3/interfaces/definition';
ivyEnabled && describe('render3 jit', () => {
let injector: any;
@ -134,7 +134,7 @@ ivyEnabled && describe('render3 jit', () => {
class Module {
}
const moduleDef: NgModuleDef<Module> = (Module as any).ngModuleDef;
const moduleDef: NgModuleDefInternal<Module> = (Module as any).ngModuleDef;
expect(moduleDef).toBeDefined();
expect(moduleDef.declarations.length).toBe(1);
expect(moduleDef.declarations[0]).toBe(Cmp);
@ -147,7 +147,7 @@ ivyEnabled && describe('render3 jit', () => {
})
class Cmp {
}
const cmpDef: ComponentDef<Cmp> = (Cmp as any).ngComponentDef;
const cmpDef: ComponentDefInternal<Cmp> = (Cmp as any).ngComponentDef;
expect(cmpDef.directiveDefs).toBeNull();
@ -157,7 +157,7 @@ ivyEnabled && describe('render3 jit', () => {
class Module {
}
const moduleDef: NgModuleDef<Module> = (Module as any).ngModuleDef;
const moduleDef: NgModuleDefInternal<Module> = (Module as any).ngModuleDef;
expect(cmpDef.directiveDefs instanceof Function).toBe(true);
expect((cmpDef.directiveDefs as Function)()).toEqual([cmpDef]);
});
@ -179,7 +179,7 @@ ivyEnabled && describe('render3 jit', () => {
onChange(event: any): void {}
}
const cmpDef = (Cmp as any).ngComponentDef as ComponentDef<Cmp>;
const cmpDef = (Cmp as any).ngComponentDef as ComponentDefInternal<Cmp>;
expect(cmpDef.hostBindings).toBeDefined();
expect(cmpDef.hostBindings !.length).toBe(2);

View File

@ -14,6 +14,7 @@ import {angularCoreEnv} from '../../src/render3/jit/environment';
const INTERFACE_EXCEPTIONS = new Set<string>([
'ComponentDef',
'DirectiveDef',
'NgModuleDef',
]);
describe('r3 jit environment', () => {

View File

@ -11,7 +11,7 @@ import {stringifyElement} from '@angular/platform-browser/testing/src/browser_ut
import {Injector} from '../../src/di/injector';
import {CreateComponentOptions} from '../../src/render3/component';
import {extractDirectiveDef, extractPipeDef} from '../../src/render3/definition';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, PublicFeature, RenderFlags, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
import {ComponentDefInternal, ComponentTemplate, ComponentType, DirectiveDefInternal, DirectiveType, PublicFeature, RenderFlags, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
import {NG_HOST_SYMBOL, renderTemplate} from '../../src/render3/instructions';
import {DirectiveDefList, DirectiveDefListOrFactory, DirectiveTypesOrFactory, PipeDef, PipeDefList, PipeDefListOrFactory, PipeTypesOrFactory} from '../../src/render3/interfaces/definition';
import {LElementNode} from '../../src/render3/interfaces/node';
@ -180,13 +180,13 @@ export function renderToHtml(
function toDefs(
types: DirectiveTypesOrFactory | undefined | null,
mapFn: (type: Type<any>) => DirectiveDef<any>): DirectiveDefList|null;
mapFn: (type: Type<any>) => DirectiveDefInternal<any>): DirectiveDefList|null;
function toDefs(
types: PipeTypesOrFactory | undefined | null,
mapFn: (type: Type<any>) => PipeDef<any>): PipeDefList|null;
function toDefs(
types: PipeTypesOrFactory | DirectiveTypesOrFactory | undefined | null,
mapFn: (type: Type<any>) => PipeDef<any>| DirectiveDef<any>): any {
mapFn: (type: Type<any>) => PipeDef<any>| DirectiveDefInternal<any>): any {
if (!types) return null;
if (typeof types == 'function') {
types = types();

View File

@ -389,6 +389,7 @@ export class TestBed implements Injector {
providers: [
...rootProviderOverrides,
],
jit: true,
})
class RootScopeModule {
}
@ -399,7 +400,7 @@ export class TestBed implements Injector {
const imports = [rootScopeImports, this.ngModule, this._imports];
const schemas = this._schemas;
@NgModule({providers, declarations, imports, schemas})
@NgModule({providers, declarations, imports, schemas, jit: true})
class DynamicTestModule {
}
@ -540,7 +541,7 @@ export class TestBed implements Injector {
overrideTemplateUsingTestingModule(component: Type<any>, template: string) {
this._assertNotInstantiated('overrideTemplateUsingTestingModule', 'override template');
@Component({selector: 'empty', template})
@Component({selector: 'empty', template, jit: true})
class OverrideComponent {
}