fix(ivy): TestBed.get(Compiler) throws "Error: Runtime compiler is not loaded" (#27223)

BREAKING CHANGE:

The public API for `DebugNode` was accidentally too broad. This change removes
1. Public constructor. Since `DebugNode` is a way for Angular to communicate information
   on to the developer there is no reason why the developer should ever need to
   Instantiate the `DebugNode`
2. We are also removing `removeChild`, `addChild`, `insertBefore`, and `insertChildAfter`.
   All of these methods are used by Angular to constructor the correct `DebugNode` tree.
   There is no reason why the developer should ever be constructing a `DebugNode` tree
   And these methods should have never been made public.
3. All properties have been change to `readonly` since `DebugNode` is used by Angular
   to communicate to developer and there is no reason why these APIs should be writable.

While technically breaking change we don’t expect anyone to be effected by this change.

PR Close #27223
This commit is contained in:
Misko Hevery 2018-11-21 21:14:06 -08:00 committed by Jason Aden
parent 60e403bf6d
commit 39e426cde3
34 changed files with 1648 additions and 1468 deletions

View File

@ -144,7 +144,6 @@ describe('insert/remove', () => {
expect(fixture.nativeElement).toHaveText('projected foo');
}));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should resolve components from other modules, if supplied', async(() => {
const compiler = TestBed.get(Compiler) as Compiler;
let fixture = TestBed.createComponent(TestComponent);
@ -159,7 +158,7 @@ describe('insert/remove', () => {
expect(fixture.nativeElement).toHaveText('baz');
}));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-739: destroy on NgModuleRef is not being called') &&
it('should clean up moduleRef, if supplied', async(() => {
let destroyed = false;
const compiler = TestBed.get(Compiler) as Compiler;
@ -176,7 +175,6 @@ describe('insert/remove', () => {
expect(moduleRef.destroy).toHaveBeenCalled();
}));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should not re-create moduleRef when it didn\'t actually change', async(() => {
const compiler = TestBed.get(Compiler) as Compiler;
const fixture = TestBed.createComponent(TestComponent);
@ -194,7 +192,6 @@ describe('insert/remove', () => {
expect(moduleRef).toBe(fixture.componentInstance.ngComponentOutlet['_moduleRef']);
}));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should re-create moduleRef when changed', async(() => {
const compiler = TestBed.get(Compiler) as Compiler;
const fixture = TestBed.createComponent(TestComponent);

View File

@ -114,12 +114,9 @@ export {
i18nEnd as ɵi18nEnd,
i18nApply as ɵi18nApply,
i18nPostprocess as ɵi18nPostprocess,
WRAP_RENDERER_FACTORY2 as ɵWRAP_RENDERER_FACTORY2,
setClassMetadata as ɵsetClassMetadata,
} from './render3/index';
export { Render3DebugRendererFactory2 as ɵRender3DebugRendererFactory2 } from './render3/debug';
export {
compileComponent as ɵcompileComponent,

View File

@ -7,6 +7,11 @@
*/
import {Injector} from '../di';
import {DirectiveDef} from '../render3';
import {assertDomNode} from '../render3/assert';
import {getComponent, getInjector, getLocalRefs, loadContext} from '../render3/discovery_utils';
import {TNode, TNodeFlags} from '../render3/interfaces/node';
import {TVIEW} from '../render3/interfaces/view';
import {DebugContext} from '../view/index';
export class EventListener {
@ -16,12 +21,26 @@ export class EventListener {
/**
* @publicApi
*/
export class DebugNode {
listeners: EventListener[] = [];
parent: DebugElement|null = null;
export interface DebugNode {
readonly listeners: EventListener[];
readonly parent: DebugElement|null;
readonly nativeNode: any;
readonly injector: Injector;
readonly componentInstance: any;
readonly context: any;
readonly references: {[key: string]: any};
readonly providerTokens: any[];
}
export class DebugNode__PRE_R3__ {
readonly listeners: EventListener[] = [];
readonly parent: DebugElement|null = null;
readonly nativeNode: any;
private readonly _debugContext: DebugContext;
constructor(public nativeNode: any, parent: DebugNode|null, private _debugContext: DebugContext) {
if (parent && parent instanceof DebugElement) {
constructor(nativeNode: any, parent: DebugNode|null, _debugContext: DebugContext) {
this._debugContext = _debugContext;
this.nativeNode = nativeNode;
if (parent && parent instanceof DebugElement__PRE_R3__) {
parent.addChild(this);
}
}
@ -40,14 +59,29 @@ export class DebugNode {
/**
* @publicApi
*/
export class DebugElement extends DebugNode {
name !: string;
properties: {[key: string]: any} = {};
attributes: {[key: string]: string | null} = {};
classes: {[key: string]: boolean} = {};
styles: {[key: string]: string | null} = {};
childNodes: DebugNode[] = [];
nativeElement: any;
export interface DebugElement extends DebugNode {
readonly name: string;
readonly properties: {[key: string]: any};
readonly attributes: {[key: string]: string | null};
readonly classes: {[key: string]: boolean};
readonly styles: {[key: string]: string | null};
readonly childNodes: DebugNode[];
readonly nativeElement: any;
readonly children: DebugElement[];
query(predicate: Predicate<DebugElement>): DebugElement;
queryAll(predicate: Predicate<DebugElement>): DebugElement[];
queryAllNodes(predicate: Predicate<DebugNode>): DebugNode[];
triggerEventHandler(eventName: string, eventObj: any): void;
}
export class DebugElement__PRE_R3__ extends DebugNode__PRE_R3__ implements DebugElement {
readonly name !: string;
readonly properties: {[key: string]: any} = {};
readonly attributes: {[key: string]: string | null} = {};
readonly classes: {[key: string]: boolean} = {};
readonly styles: {[key: string]: string | null} = {};
readonly childNodes: DebugNode[] = [];
readonly nativeElement: any;
constructor(nativeNode: any, parent: any, _debugContext: DebugContext) {
super(nativeNode, parent, _debugContext);
@ -57,14 +91,14 @@ export class DebugElement extends DebugNode {
addChild(child: DebugNode) {
if (child) {
this.childNodes.push(child);
child.parent = this;
(child as{parent: DebugNode}).parent = this;
}
}
removeChild(child: DebugNode) {
const childIndex = this.childNodes.indexOf(child);
if (childIndex !== -1) {
child.parent = null;
(child as{parent: DebugNode | null}).parent = null;
this.childNodes.splice(childIndex, 1);
}
}
@ -75,9 +109,9 @@ export class DebugElement extends DebugNode {
this.childNodes.splice(siblingIndex + 1, 0, ...newChildren);
newChildren.forEach(c => {
if (c.parent) {
c.parent.removeChild(c);
(c.parent as DebugElement__PRE_R3__).removeChild(c);
}
c.parent = this;
(child as{parent: DebugNode}).parent = this;
});
}
}
@ -88,9 +122,9 @@ export class DebugElement extends DebugNode {
this.addChild(newChild);
} else {
if (newChild.parent) {
newChild.parent.removeChild(newChild);
(newChild.parent as DebugElement__PRE_R3__).removeChild(newChild);
}
newChild.parent = this;
(newChild as{parent: DebugNode}).parent = this;
this.childNodes.splice(refIndex, 0, newChild);
}
}
@ -113,7 +147,9 @@ export class DebugElement extends DebugNode {
}
get children(): DebugElement[] {
return this.childNodes.filter((node) => node instanceof DebugElement) as DebugElement[];
return this
.childNodes //
.filter((node) => node instanceof DebugElement__PRE_R3__) as DebugElement[];
}
triggerEventHandler(eventName: string, eventObj: any) {
@ -135,7 +171,7 @@ export function asNativeElements(debugEls: DebugElement[]): any {
function _queryElementChildren(
element: DebugElement, predicate: Predicate<DebugElement>, matches: DebugElement[]) {
element.childNodes.forEach(node => {
if (node instanceof DebugElement) {
if (node instanceof DebugElement__PRE_R3__) {
if (predicate(node)) {
matches.push(node);
}
@ -146,27 +182,215 @@ function _queryElementChildren(
function _queryNodeChildren(
parentNode: DebugNode, predicate: Predicate<DebugNode>, matches: DebugNode[]) {
if (parentNode instanceof DebugElement) {
if (parentNode instanceof DebugElement__PRE_R3__) {
parentNode.childNodes.forEach(node => {
if (predicate(node)) {
matches.push(node);
}
if (node instanceof DebugElement) {
if (node instanceof DebugElement__PRE_R3__) {
_queryNodeChildren(node, predicate, matches);
}
});
}
}
function notImplemented(): Error {
throw new Error('Missing proper ivy implementation.');
}
class DebugNode__POST_R3__ implements DebugNode {
readonly nativeNode: Node;
constructor(nativeNode: Node) { this.nativeNode = nativeNode; }
get parent(): DebugElement|null {
const parent = this.nativeNode.parentNode as HTMLElement;
return parent ? new DebugElement__POST_R3__(parent) : null;
}
get injector(): Injector { return getInjector(this.nativeNode); }
get componentInstance(): any {
const nativeElement = this.nativeNode;
return nativeElement && getComponent(nativeElement as HTMLElement);
}
get context(): any {
// https://angular-team.atlassian.net/browse/FW-719
throw notImplemented();
}
get listeners(): EventListener[] {
// TODO: add real implementation;
// https://angular-team.atlassian.net/browse/FW-719
return [];
}
get references(): {[key: string]: any;} { return getLocalRefs(this.nativeNode); }
get providerTokens(): any[] {
// TODO move to discoverable utils
const context = loadContext(this.nativeNode as HTMLElement, false) !;
if (!context) return [];
const lView = context.lViewData;
const tView = lView[TVIEW];
const tNode = tView.data[context.nodeIndex] as TNode;
const providerTokens: any[] = [];
const nodeFlags = tNode.flags;
const startIndex = nodeFlags >> TNodeFlags.DirectiveStartingIndexShift;
const directiveCount = nodeFlags & TNodeFlags.DirectiveCountMask;
const endIndex = startIndex + directiveCount;
for (let i = startIndex; i < endIndex; i++) {
let value = tView.data[i];
if (isDirectiveDefHack(value)) {
// The fact that we sometimes store Type and sometimes DirectiveDef in this location is a
// design flaw. We should always store same type so that we can be monomorphic. The issue
// is that for Components/Directives we store the def instead the type. The correct behavior
// is that we should always be storing injectable type in this location.
value = value.type;
}
providerTokens.push(value);
}
return providerTokens;
}
}
class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugElement {
constructor(nativeNode: Element) {
ngDevMode && assertDomNode(nativeNode);
super(nativeNode);
}
get nativeElement(): Element|null {
return this.nativeNode.nodeType == Node.ELEMENT_NODE ? this.nativeNode as Element : null;
}
get name(): string { return (this.nativeElement as HTMLElement).nodeName; }
get properties(): {[key: string]: any;} {
const context = loadContext(this.nativeNode) !;
const lView = context.lViewData;
const tView = lView[TVIEW];
const tNode = tView.data[context.nodeIndex] as TNode;
const properties = {};
// TODO: https://angular-team.atlassian.net/browse/FW-681
// Missing implementation here...
return properties;
}
get attributes(): {[key: string]: string | null;} {
// https://angular-team.atlassian.net/browse/FW-719
throw notImplemented();
}
get classes(): {[key: string]: boolean;} {
// https://angular-team.atlassian.net/browse/FW-719
throw notImplemented();
}
get styles(): {[key: string]: string | null;} {
// https://angular-team.atlassian.net/browse/FW-719
throw notImplemented();
}
get childNodes(): DebugNode[] {
const childNodes = this.nativeNode.childNodes;
const children: DebugNode[] = [];
for (let i = 0; i < childNodes.length; i++) {
const element = childNodes[i];
children.push(getDebugNode__POST_R3__(element));
}
return children;
}
get children(): DebugElement[] {
const nativeElement = this.nativeElement;
if (!nativeElement) return [];
const childNodes = nativeElement.children;
const children: DebugElement[] = [];
for (let i = 0; i < childNodes.length; i++) {
const element = childNodes[i];
children.push(getDebugNode__POST_R3__(element));
}
return children;
}
query(predicate: Predicate<DebugElement>): DebugElement {
const results = this.queryAll(predicate);
return results[0] || null;
}
queryAll(predicate: Predicate<DebugElement>): DebugElement[] {
const matches: DebugElement[] = [];
_queryNodeChildrenR3(this, predicate, matches, true);
return matches;
}
queryAllNodes(predicate: Predicate<DebugNode>): DebugNode[] {
const matches: DebugNode[] = [];
_queryNodeChildrenR3(this, predicate, matches, false);
return matches;
}
triggerEventHandler(eventName: string, eventObj: any): void {
// This is a hack implementation. The correct implementation would bypass the DOM and `TNode`
// information to invoke the listeners directly.
// https://angular-team.atlassian.net/browse/FW-719
const event = document.createEvent('MouseEvent');
event.initEvent(eventName, true, true);
(this.nativeElement as HTMLElement).dispatchEvent(event);
}
}
/**
* This function should not exist because it is megamorphic and only mostly correct.
*
* See call site for more info.
*/
function isDirectiveDefHack(obj: any): obj is DirectiveDef<any> {
return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined;
}
function _queryNodeChildrenR3(
parentNode: DebugNode, predicate: Predicate<DebugNode>, matches: DebugNode[],
elementsOnly: boolean) {
if (parentNode instanceof DebugElement__POST_R3__) {
parentNode.childNodes.forEach(node => {
if (predicate(node)) {
matches.push(node);
}
if (node instanceof DebugElement__POST_R3__) {
if (elementsOnly ? node.nativeElement : true) {
_queryNodeChildrenR3(node, predicate, matches, elementsOnly);
}
}
});
}
}
// Need to keep the nodes in a global Map so that multiple angular apps are supported.
const _nativeNodeToDebugNode = new Map<any, DebugNode>();
function getDebugNode__PRE_R3__(nativeNode: any): DebugNode|null {
return _nativeNodeToDebugNode.get(nativeNode) || null;
}
export function getDebugNode__POST_R3__(nativeNode: Element): DebugElement__POST_R3__;
export function getDebugNode__POST_R3__(nativeNode: Node): DebugNode__POST_R3__;
export function getDebugNode__POST_R3__(nativeNode: null): null;
export function getDebugNode__POST_R3__(nativeNode: any): DebugNode|null {
if (nativeNode instanceof Node) {
return nativeNode.nodeType == Node.ELEMENT_NODE ?
new DebugElement__POST_R3__(nativeNode as Element) :
new DebugNode__POST_R3__(nativeNode);
}
return null;
}
/**
* @publicApi
*/
export function getDebugNode(nativeNode: any): DebugNode|null {
return _nativeNodeToDebugNode.get(nativeNode) || null;
}
export const getDebugNode: (nativeNode: any) => DebugNode | null = getDebugNode__PRE_R3__;
export function getAllDebugNodes(): DebugNode[] {
return Array.from(_nativeNodeToDebugNode.values());
@ -187,3 +411,13 @@ export function removeDebugNodeFromIndex(node: DebugNode) {
* @publicApi
*/
export interface Predicate<T> { (value: T): boolean; }
/**
* @publicApi
*/
export const DebugNode: {new (...args: any[]): DebugNode} = DebugNode__PRE_R3__ as any;
/**
* @publicApi
*/
export const DebugElement: {new (...args: any[]): DebugElement} = DebugElement__PRE_R3__ as any;

View File

@ -11,6 +11,7 @@ import {InjectionToken} from '../di/injection_token';
import {StaticProvider} from '../di/provider';
import {MissingTranslationStrategy} from '../i18n/tokens';
import {ViewEncapsulation} from '../metadata';
import {NgModuleFactory as NgModuleFactoryR3} from '../render3/ng_module_ref';
import {Type} from '../type';
import {ComponentFactory} from './component_factory';
@ -34,6 +35,42 @@ function _throwError() {
throw new Error(`Runtime compiler is not loaded`);
}
const Compiler_compileModuleSync__PRE_R3__: <T>(moduleType: Type<T>) => NgModuleFactory<T> =
_throwError as any;
export const Compiler_compileModuleSync__POST_R3__: <T>(moduleType: Type<T>) =>
NgModuleFactory<T> = function<T>(moduleType: Type<T>): NgModuleFactory<T> {
return new NgModuleFactoryR3(moduleType);
};
const Compiler_compileModuleSync = Compiler_compileModuleSync__PRE_R3__;
const Compiler_compileModuleAsync__PRE_R3__: <T>(moduleType: Type<T>) =>
Promise<NgModuleFactory<T>> = _throwError as any;
export const Compiler_compileModuleAsync__POST_R3__: <T>(moduleType: Type<T>) =>
Promise<NgModuleFactory<T>> = function<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>> {
return Promise.resolve(Compiler_compileModuleSync__POST_R3__(moduleType));
};
const Compiler_compileModuleAsync = Compiler_compileModuleAsync__PRE_R3__;
const Compiler_compileModuleAndAllComponentsSync__PRE_R3__: <T>(moduleType: Type<T>) =>
ModuleWithComponentFactories<T> = _throwError as any;
export const Compiler_compileModuleAndAllComponentsSync__POST_R3__: <T>(moduleType: Type<T>) =>
ModuleWithComponentFactories<T> = function<T>(moduleType: Type<T>):
ModuleWithComponentFactories<T> {
return new ModuleWithComponentFactories(Compiler_compileModuleSync__POST_R3__(moduleType), []);
};
const Compiler_compileModuleAndAllComponentsSync =
Compiler_compileModuleAndAllComponentsSync__PRE_R3__;
const Compiler_compileModuleAndAllComponentsAsync__PRE_R3__: <T>(moduleType: Type<T>) =>
Promise<ModuleWithComponentFactories<T>> = _throwError as any;
export const Compiler_compileModuleAndAllComponentsAsync__POST_R3__: <T>(moduleType: Type<T>) =>
Promise<ModuleWithComponentFactories<T>> = function<T>(moduleType: Type<T>):
Promise<ModuleWithComponentFactories<T>> {
return Promise.resolve(Compiler_compileModuleAndAllComponentsSync__POST_R3__(moduleType));
};
const Compiler_compileModuleAndAllComponentsAsync =
Compiler_compileModuleAndAllComponentsAsync__PRE_R3__;
/**
* Low-level service for running the angular compiler during runtime
* to create {@link ComponentFactory}s, which
@ -51,27 +88,25 @@ export class Compiler {
* Compiles the given NgModule and all of its components. All templates of the components listed
* in `entryComponents` have to be inlined.
*/
compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T> { throw _throwError(); }
compileModuleSync: <T>(moduleType: Type<T>) => NgModuleFactory<T> = Compiler_compileModuleSync;
/**
* Compiles the given NgModule and all of its components
*/
compileModuleAsync<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>> { throw _throwError(); }
compileModuleAsync:
<T>(moduleType: Type<T>) => Promise<NgModuleFactory<T>> = Compiler_compileModuleAsync;
/**
* Same as {@link #compileModuleSync} but also creates ComponentFactories for all components.
*/
compileModuleAndAllComponentsSync<T>(moduleType: Type<T>): ModuleWithComponentFactories<T> {
throw _throwError();
}
compileModuleAndAllComponentsSync: <T>(moduleType: Type<T>) => ModuleWithComponentFactories<T> =
Compiler_compileModuleAndAllComponentsSync;
/**
* Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components.
*/
compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>):
Promise<ModuleWithComponentFactories<T>> {
throw _throwError();
}
compileModuleAndAllComponentsAsync: <T>(moduleType: Type<T>) =>
Promise<ModuleWithComponentFactories<T>> = Compiler_compileModuleAndAllComponentsAsync;
/**
* Clears all caches.

View File

@ -90,7 +90,7 @@ export interface AttributeDecorator {
* ]
* ```
*
*
* @publicApi
*/
(name: string): any;
new (name: string): Attribute;

View File

@ -83,3 +83,7 @@ function throwError(msg: string): never {
debugger; // Left intentionally for better debugger experience.
throw new Error(`ASSERTION ERROR: ${msg}`);
}
export function assertDomNode(node: any) {
assertEqual(node instanceof Node, true, 'The provided value must be an instance of a DOM Node');
}

View File

@ -13,10 +13,8 @@ import {Injector} from '../di/injector';
import {Sanitizer} from '../sanitization/security';
import {assertComponentType, assertDefined} from './assert';
import {getContext} from './context_discovery';
import {getComponentDef} from './definition';
import {diPublicInInjector, getOrCreateNodeInjectorForNode} from './di';
import {getHostElement} from './discovery_utils';
import {publishDefaultGlobalUtils} from './global_utils';
import {queueInitHooks, queueLifecycleHooks} from './hooks';
import {CLEAN_PROMISE, createLViewData, createNodeAtIndex, createTView, getOrCreateTView, initNodeFlags, instantiateRootComponent, locateHostElement, prefillHostVars, queueComponentIndexForCheck, refreshDescendantViews} from './instructions';
@ -26,7 +24,7 @@ import {PlayerHandler} from './interfaces/player';
import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {CONTEXT, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LViewData, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
import {enterView, leaveView, resetComponentState} from './state';
import {defaultScheduler, getRootView, readElementValue, readPatchedLViewData, stringify} from './util';
import {defaultScheduler, getRootView, readPatchedLViewData, stringify} from './util';
@ -123,15 +121,15 @@ export function renderComponent<T>(
const renderer = rendererFactory.createRenderer(hostRNode, componentDef);
const rootView: LViewData = createLViewData(
null, renderer, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags,
undefined, opts.injector || null);
null, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags, rendererFactory,
renderer, undefined, opts.injector || null);
const oldView = enterView(rootView, null);
let component: T;
try {
if (rendererFactory.begin) rendererFactory.begin();
const componentView =
createRootComponentView(hostRNode, componentDef, rootView, renderer, sanitizer);
const componentView = createRootComponentView(
hostRNode, componentDef, rootView, rendererFactory, renderer, sanitizer);
component = createRootComponent(
componentView, componentDef, rootView, rootContext, opts.hostFeatures || null);
@ -156,15 +154,17 @@ export function renderComponent<T>(
* @returns Component view created
*/
export function createRootComponentView(
rNode: RElement | null, def: ComponentDef<any>, rootView: LViewData, renderer: Renderer3,
rNode: RElement | null, def: ComponentDef<any>, rootView: LViewData,
rendererFactory: RendererFactory3, renderer: Renderer3,
sanitizer?: Sanitizer | null): LViewData {
resetComponentState();
const tView = rootView[TVIEW];
const componentView = createLViewData(
rootView, renderer,
rootView,
getOrCreateTView(
def.template, def.consts, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery),
null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, sanitizer);
null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, rendererFactory, renderer,
sanitizer);
const tNode = createNodeAtIndex(0, TNodeType.Element, rNode, null, null);
if (tView.firstTemplatePass) {

View File

@ -15,6 +15,7 @@ import {ComponentFactoryResolver as viewEngine_ComponentFactoryResolver} from '.
import {ElementRef as viewEngine_ElementRef} from '../linker/element_ref';
import {NgModuleRef as viewEngine_NgModuleRef} from '../linker/ng_module_factory';
import {RendererFactory2} from '../render/api';
import {Sanitizer} from '../sanitization/security';
import {Type} from '../type';
import {VERSION} from '../version';
import {assertComponentType, assertDefined} from './assert';
@ -25,6 +26,7 @@ import {createLViewData, createNodeAtIndex, createTView, createViewNode, element
import {ComponentDef, RenderFlags} from './interfaces/definition';
import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeType} from './interfaces/node';
import {RElement, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer';
import {SanitizerFn} from './interfaces/sanitization';
import {HEADER_OFFSET, LViewData, LViewFlags, RootContext, TVIEW} from './interfaces/view';
import {enterView, leaveView} from './state';
import {defaultScheduler, getTNode} from './util';
@ -66,13 +68,6 @@ export const SCHEDULER = new InjectionToken<((fn: () => void) => void)>('SCHEDUL
factory: () => defaultScheduler,
});
/**
* A function used to wrap the `RendererFactory2`.
* Used in tests to change the `RendererFactory2` into a `DebugRendererFactory2`.
*/
export const WRAP_RENDERER_FACTORY2 =
new InjectionToken<(rf: RendererFactory2) => RendererFactory2>('WRAP_RENDERER_FACTORY2');
const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};
function createChainedInjector(rootViewInjector: Injector, moduleInjector: Injector): Injector {
@ -121,10 +116,11 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
const isInternalRootView = rootSelectorOrNode === undefined;
let rendererFactory: RendererFactory3;
let sanitizer: Sanitizer|null = null;
if (ngModule) {
const wrapper = ngModule.injector.get(WRAP_RENDERER_FACTORY2, (v: RendererFactory2) => v);
rendererFactory = wrapper(ngModule.injector.get(RendererFactory2)) as RendererFactory3;
rendererFactory = ngModule.injector.get(RendererFactory2) as RendererFactory3;
sanitizer = ngModule.injector.get(Sanitizer, null);
} else {
rendererFactory = domRendererFactory3;
}
@ -151,8 +147,8 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
// Create the root view. Uses empty TView and ContentTemplate.
const rootView: LViewData = createLViewData(
null, renderer, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags,
undefined, rootViewInjector);
null, createTView(-1, null, 1, 0, null, null, null), rootContext, rootFlags,
rendererFactory, renderer, sanitizer, rootViewInjector);
// rootView is the parent when bootstrapping
const oldView = enterView(rootView, null);
@ -162,8 +158,8 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
try {
if (rendererFactory.begin) rendererFactory.begin();
const componentView =
createRootComponentView(hostRNode, this.componentDef, rootView, renderer);
const componentView = createRootComponentView(
hostRNode, this.componentDef, rootView, rendererFactory, renderer);
tElementNode = getTNode(0, rootView) as TElementNode;
// Transform the arrays of native nodes into a structure that can be consumed by the

View File

@ -7,7 +7,7 @@
*/
import './ng_dev_mode';
import {assertEqual} from './assert';
import {assertDomNode} from './assert';
import {EMPTY_ARRAY} from './definition';
import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context';
import {TNode, TNodeFlags} from './interfaces/node';
@ -95,7 +95,7 @@ export function getContext(target: any): LContext|null {
}
} else {
const rElement = target as RElement;
ngDevMode && assertDomElement(rElement);
ngDevMode && assertDomNode(rElement);
// if the context is not found then we need to traverse upwards up the DOM
// to find the nearest element that has already been monkey patched with data
@ -262,12 +262,6 @@ function findViaDirective(lViewData: LViewData, directiveInstance: {}): number {
return -1;
}
function assertDomElement(element: any) {
assertEqual(
element && (element.nodeType == Node.ELEMENT_NODE || element.nodeType == Node.TEXT_NODE),
true, 'The provided value must be an instance of an HTMLElement');
}
/**
* Returns a list of directives extracted from the given view based on the
* provided list of directive index values.

View File

@ -1,81 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injector} from '../di/injector';
import {Renderer2, RendererType2} from '../render/api';
import {DebugContext} from '../view';
import {DebugRenderer2, DebugRendererFactory2} from '../view/services';
import {getComponent, getInjector, getLocalRefs, loadContext} from './discovery_utils';
import {DirectiveDef} from './interfaces/definition';
import {TNode, TNodeFlags} from './interfaces/node';
import {TVIEW} from './interfaces/view';
/**
* Adapts the DebugRendererFactory2 to create a DebugRenderer2 specific for IVY.
*
* The created DebugRenderer know how to create a Debug Context specific to IVY.
*/
export class Render3DebugRendererFactory2 extends DebugRendererFactory2 {
createRenderer(element: any, renderData: RendererType2|null): Renderer2 {
const renderer = super.createRenderer(element, renderData) as DebugRenderer2;
renderer.debugContextFactory = (nativeElement: any) => new Render3DebugContext(nativeElement);
return renderer;
}
}
/**
* Stores context information about view nodes.
*
* Used in tests to retrieve information those nodes.
*/
class Render3DebugContext implements DebugContext {
constructor(private _nativeNode: any) {}
get nodeIndex(): number|null { return loadContext(this._nativeNode).nodeIndex; }
get view(): any { return loadContext(this._nativeNode).lViewData; }
get injector(): Injector { return getInjector(this._nativeNode); }
get component(): any { return getComponent(this._nativeNode); }
get providerTokens(): any[] {
const lDebugCtx = loadContext(this._nativeNode);
const lViewData = lDebugCtx.lViewData;
const tNode = lViewData[TVIEW].data[lDebugCtx.nodeIndex] as TNode;
const directivesCount = tNode.flags & TNodeFlags.DirectiveCountMask;
if (directivesCount > 0) {
const directiveIdxStart = tNode.flags >> TNodeFlags.DirectiveStartingIndexShift;
const directiveIdxEnd = directiveIdxStart + directivesCount;
const viewDirectiveDefs = this.view[TVIEW].data;
const directiveDefs =
viewDirectiveDefs.slice(directiveIdxStart, directiveIdxEnd) as DirectiveDef<any>[];
return directiveDefs.map(directiveDef => directiveDef.type);
}
return [];
}
get references(): {[key: string]: any} { return getLocalRefs(this._nativeNode); }
// TODO(pk): check previous implementation and re-implement
get context(): any { throw new Error('Not implemented in ivy'); }
// TODO(pk): check previous implementation and re-implement
get componentRenderElement(): any { throw new Error('Not implemented in ivy'); }
// TODO(pk): check previous implementation and re-implement
get renderNode(): any { throw new Error('Not implemented in ivy'); }
// TODO(pk): check previous implementation and re-implement
logError(console: Console, ...values: any[]): void { console.error(...values); }
}

View File

@ -20,7 +20,7 @@ import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInject
import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType} from './interfaces/node';
import {DECLARATION_VIEW, HOST_NODE, INJECTOR, LViewData, TData, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert';
import {getPreviousOrParentTNode, getViewData, setTNodeAndViewData} from './state';
import {_getViewData, getPreviousOrParentTNode, getViewData, setTNodeAndViewData} from './state';
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector, isComponent, stringify} from './util';
/**
@ -556,13 +556,19 @@ export class NodeInjector implements Injector {
constructor(
private _tNode: TElementNode|TContainerNode|TElementContainerNode,
private _hostView: LViewData) {
this._injectorIndex = getOrCreateNodeInjectorForNode(_tNode, _hostView);
private _lView: LViewData) {
this._injectorIndex = getOrCreateNodeInjectorForNode(_tNode, _lView);
}
get(token: any): any {
setTNodeAndViewData(this._tNode, this._hostView);
return getOrCreateInjectable(this._tNode, this._hostView, token);
const previousTNode = getPreviousOrParentTNode();
const previousLView = _getViewData();
setTNodeAndViewData(this._tNode, this._lView);
try {
return getOrCreateInjectable(this._tNode, this._lView, token);
} finally {
setTNodeAndViewData(previousTNode, previousLView);
}
}
}

View File

@ -141,9 +141,11 @@ export function getDirectives(target: {}): Array<{}> {
* Throws if a given target doesn't have associated LContext.
*
*/
export function loadContext(target: {}): LContext {
export function loadContext(target: {}): LContext;
export function loadContext(target: {}, throwOnNotFound: false): LContext|null;
export function loadContext(target: {}, throwOnNotFound: boolean = true): LContext|null {
const context = getContext(target);
if (!context) {
if (!context && throwOnNotFound) {
throw new Error(
ngDevMode ? `Unable to find context associated with ${stringify(target)}` :
'Invalid ng target');

View File

@ -13,7 +13,7 @@ import {NgOnChangesFeature} from './features/ng_onchanges_feature';
import {ProvidersFeature} from './features/providers_feature';
import {BaseDef, ComponentDef, ComponentDefWithMeta, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveDefWithMeta, DirectiveType, PipeDef, PipeDefWithMeta} from './interfaces/definition';
export {ComponentFactory, ComponentFactoryResolver, ComponentRef, WRAP_RENDERER_FACTORY2, injectComponentFactoryResolver} from './component_ref';
export {ComponentFactory, ComponentFactoryResolver, ComponentRef, injectComponentFactoryResolver} from './component_ref';
export {getFactoryOf, getInheritedFactory} from './di';
export {RenderFlags} from './interfaces/definition';
export {CssSelectorList} from './interfaces/projection';

View File

@ -32,11 +32,11 @@ import {LQueries} from './interfaces/query';
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, isProceduralRenderer} from './interfaces/renderer';
import {SanitizerFn} from './interfaces/sanitization';
import {StylingIndex} from './interfaces/styling';
import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RootContext, RootContextFlags, SANITIZER, TAIL, TVIEW, TView} from './interfaces/view';
import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TAIL, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
import {appendChild, appendProjectedNode, createTextNode, findComponentView, getLViewChild, getRenderParent, insertView, removeView} from './node_manipulation';
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
import {assertDataInRange, assertHasParent, assertPreviousIsParent, decreaseElementDepthCount, enterView, getBindingsEnabled, getCheckNoChangesMode, getCleanup, getContextViewData, getCreationMode, getCurrentQueries, getCurrentSanitizer, getElementDepthCount, getFirstTemplatePass, getIsParent, getPreviousOrParentTNode, getRenderer, getRendererFactory, getTView, getTViewCleanup, getViewData, increaseElementDepthCount, leaveView, nextContextImpl, resetComponentState, setBindingRoot, setCheckNoChangesMode, setCurrentQueries, setFirstTemplatePass, setIsParent, setPreviousOrParentTNode, setRenderer, setRendererFactory} from './state';
import {assertDataInRange, assertHasParent, assertPreviousIsParent, decreaseElementDepthCount, enterView, getBindingsEnabled, getCheckNoChangesMode, getCleanup, getContextViewData, getCreationMode, getCurrentQueries, getCurrentSanitizer, getElementDepthCount, getFirstTemplatePass, getIsParent, getPreviousOrParentTNode, getRenderer, getRendererFactory, getTView, getTViewCleanup, getViewData, increaseElementDepthCount, leaveView, nextContextImpl, resetComponentState, setBindingRoot, setCheckNoChangesMode, setCurrentQueries, setFirstTemplatePass, setIsParent, setPreviousOrParentTNode} from './state';
import {createStylingContextTemplate, renderStyleAndClassBindings, updateClassProp as updateElementClassProp, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling/class_and_style_bindings';
import {BoundPlayerFactory} from './styling/player_factory';
import {getStylingContext} from './styling/util';
@ -155,17 +155,20 @@ function refreshChildComponents(components: number[] | null, rf: RenderFlags | n
}
export function createLViewData<T>(
parentViewData: LViewData | null, renderer: Renderer3, tView: TView, context: T | null,
flags: LViewFlags, sanitizer?: Sanitizer | null, injector?: Injector | null): LViewData {
const instance = tView.blueprint.slice() as LViewData;
instance[FLAGS] = flags | LViewFlags.CreationMode | LViewFlags.Attached | LViewFlags.RunInit;
instance[PARENT] = instance[DECLARATION_VIEW] = parentViewData;
instance[CONTEXT] = context;
instance[INJECTOR as any] =
injector === undefined ? (parentViewData ? parentViewData[INJECTOR] : null) : injector;
instance[RENDERER] = renderer;
instance[SANITIZER] = sanitizer || null;
return instance;
parentLView: LViewData | null, tView: TView, context: T | null, flags: LViewFlags,
rendererFactory?: RendererFactory3 | null, renderer?: Renderer3 | null,
sanitizer?: Sanitizer | null, injector?: Injector | null): LViewData {
const lView = tView.blueprint.slice() as LViewData;
lView[FLAGS] = flags | LViewFlags.CreationMode | LViewFlags.Attached | LViewFlags.RunInit;
lView[PARENT] = lView[DECLARATION_VIEW] = parentLView;
lView[CONTEXT] = context;
lView[RENDERER_FACTORY] = (rendererFactory || parentLView && parentLView[RENDERER_FACTORY]) !;
ngDevMode && assertDefined(lView[RENDERER_FACTORY], 'RendererFactory is required');
lView[RENDERER] = (renderer || parentLView && parentLView[RENDERER]) !;
ngDevMode && assertDefined(lView[RENDERER], 'Renderer is required');
lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null !;
lView[INJECTOR as any] = injector || parentLView && parentLView[INJECTOR] || null;
return lView;
}
/**
@ -285,20 +288,19 @@ export function renderTemplate<T>(
sanitizer?: Sanitizer | null): LViewData {
if (hostView == null) {
resetComponentState();
setRendererFactory(providedRendererFactory);
const renderer = providedRendererFactory.createRenderer(null, null);
setRenderer(renderer);
// We need to create a root view so it's possible to look up the host element through its index
const lView = createLViewData(
null, renderer, createTView(-1, null, 1, 0, null, null, null), {},
LViewFlags.CheckAlways | LViewFlags.IsRoot);
enterView(lView, null);
const hostLView = createLViewData(
null, createTView(-1, null, 1, 0, null, null, null), {},
LViewFlags.CheckAlways | LViewFlags.IsRoot, providedRendererFactory, renderer);
enterView(hostLView, null); // SUSPECT! why do we need to enter the View?
const componentTView =
getOrCreateTView(templateFn, consts, vars, directives || null, pipes || null, null);
hostView = createLViewData(
lView, renderer, componentTView, context, LViewFlags.CheckAlways, sanitizer);
hostLView, componentTView, context, LViewFlags.CheckAlways, providedRendererFactory,
renderer, sanitizer);
hostView[HOST_NODE] = createNodeAtIndex(0, TNodeType.Element, hostNode, null, null);
}
renderComponentOrTemplate(hostView, context, null, templateFn);
@ -319,8 +321,7 @@ export function createEmbeddedViewAndNode<T>(
setIsParent(true);
setPreviousOrParentTNode(null !);
const lView = createLViewData(
declarationView, renderer, tView, context, LViewFlags.CheckAlways, getCurrentSanitizer());
const lView = createLViewData(declarationView, tView, context, LViewFlags.CheckAlways);
lView[DECLARATION_VIEW] = declarationView;
if (queries) {
@ -403,7 +404,7 @@ export function nextContext<T = any>(level: number = 1): T {
function renderComponentOrTemplate<T>(
hostView: LViewData, componentOrContext: T, rf: RenderFlags | null,
templateFn?: ComponentTemplate<T>) {
const rendererFactory = getRendererFactory();
const rendererFactory = hostView[RENDERER_FACTORY];
const oldView = enterView(hostView, hostView[HOST_NODE]);
try {
if (rendererFactory.begin) {
@ -765,7 +766,6 @@ export function createError(text: string, token: any) {
export function locateHostElement(
factory: RendererFactory3, elementOrSelector: RElement | string): RElement|null {
ngDevMode && assertDataInRange(-1);
setRendererFactory(factory);
const defaultRenderer = factory.createRenderer(null, null);
const rNode = typeof elementOrSelector === 'string' ?
(isProceduralRenderer(defaultRenderer) ?
@ -1671,11 +1671,12 @@ function addComponentLogic<T>(
// Only component views should be added to the view tree directly. Embedded views are
// accessed through their containers because they may be removed / re-added later.
const rendererFactory = getRendererFactory();
const componentView = addToViewTree(
viewData, previousOrParentTNode.index as number,
createLViewData(
getViewData(), getRendererFactory().createRenderer(native as RElement, def), tView, null,
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, getCurrentSanitizer()));
getViewData(), tView, null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways,
rendererFactory, getRendererFactory().createRenderer(native as RElement, def)));
componentView[HOST_NODE] = previousOrParentTNode as TElementNode;
@ -2002,9 +2003,9 @@ export function embeddedViewStart(viewBlockId: number, consts: number, vars: num
} else {
// When we create a new LView, we always reset the state of the instructions.
viewToRender = createLViewData(
getViewData(), getRenderer(),
getViewData(),
getOrCreateEmbeddedTView(viewBlockId, consts, vars, containerTNode as TContainerNode), null,
LViewFlags.CheckAlways, getCurrentSanitizer());
LViewFlags.CheckAlways);
if (lContainer[QUERIES]) {
viewToRender[QUERIES] = lContainer[QUERIES] !.createView();

View File

@ -17,13 +17,10 @@ import {I18nUpdateOpCodes, TI18n} from './i18n';
import {TElementNode, TNode, TViewNode} from './node';
import {PlayerHandler} from './player';
import {LQueries} from './query';
import {RElement, Renderer3} from './renderer';
import {RElement, Renderer3, RendererFactory3} from './renderer';
import {StylingContext} from './styling';
/** Size of LViewData's header. Necessary to adjust for it when setting slots. */
export const HEADER_OFFSET = 17;
// Below are constants for LViewData indices to help us look up LViewData members
// without having to remember the specific indices.
// Uglify will inline these when minifying so there shouldn't be a cost.
@ -33,17 +30,21 @@ export const PARENT = 2;
export const NEXT = 3;
export const QUERIES = 4;
export const HOST = 5;
export const HOST_NODE = 6;
export const HOST_NODE = 6; // Rename to `T_HOST`?
export const BINDING_INDEX = 7;
export const CLEANUP = 8;
export const CONTEXT = 9;
export const INJECTOR = 10;
export const RENDERER = 11;
export const SANITIZER = 12;
export const TAIL = 13;
export const CONTAINER_INDEX = 14;
export const CONTENT_QUERIES = 15;
export const DECLARATION_VIEW = 16;
export const RENDERER_FACTORY = 11;
export const RENDERER = 12;
export const SANITIZER = 13;
export const TAIL = 14;
export const CONTAINER_INDEX = 15;
export const CONTENT_QUERIES = 16;
export const DECLARATION_VIEW = 17;
/** Size of LViewData's header. Necessary to adjust for it when setting slots. */
export const HEADER_OFFSET = 18;
// This interface replaces the real LViewData interface if it is an arg or a
// return value of a public instruction. This ensures we don't need to expose
@ -149,6 +150,9 @@ export interface LViewData extends Array<any> {
/** An optional Module Injector to be used as fall back after Element Injectors are consulted. */
readonly[INJECTOR]: Injector|null;
/** Renderer to be used for this view. */
[RENDERER_FACTORY]: RendererFactory3;
/** Renderer to be used for this view. */
[RENDERER]: Renderer3;

View File

@ -8,6 +8,7 @@
import {ModuleWithProviders, NgModule, NgModuleDef, NgModuleTransitiveScopes} from '../../metadata/ng_module';
import {Type} from '../../type';
import {assertDefined} from '../assert';
import {getComponentDef, getDirectiveDef, getNgModuleDef, getPipeDef} from '../definition';
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_INJECTOR_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from '../fields';
import {ComponentDef} from '../interfaces/definition';
@ -32,6 +33,8 @@ export function compileNgModule(moduleType: Type<any>, ngModule: NgModule = {}):
* Compiles and adds the `ngModuleDef` and `ngInjectorDef` properties to the module class.
*/
export function compileNgModuleDefs(moduleType: Type<any>, ngModule: NgModule): void {
ngDevMode && assertDefined(moduleType, 'Required value moduleType');
ngDevMode && assertDefined(ngModule, 'Required value ngModule');
const declarations: Type<any>[] = flatten(ngModule.declarations || EMPTY_ARRAY);
let ngModuleDef: any = null;

View File

@ -13,7 +13,7 @@ import {executeHooks} from './hooks';
import {TElementNode, TNode, TNodeFlags, TViewNode} from './interfaces/node';
import {LQueries} from './interfaces/query';
import {Renderer3, RendererFactory3} from './interfaces/renderer';
import {BINDING_INDEX, CLEANUP, CONTEXT, DECLARATION_VIEW, FLAGS, HOST_NODE, LViewData, LViewFlags, OpaqueViewState, QUERIES, RENDERER, SANITIZER, TVIEW, TView} from './interfaces/view';
import {BINDING_INDEX, CLEANUP, CONTEXT, DECLARATION_VIEW, FLAGS, HOST_NODE, LViewData, LViewFlags, OpaqueViewState, QUERIES, RENDERER, RENDERER_FACTORY, SANITIZER, TVIEW, TView} from './interfaces/view';
import {assertDataInRangeInternal, isContentQueryHost} from './util';
/**
@ -51,10 +51,6 @@ export function getRendererFactory(): RendererFactory3 {
return rendererFactory;
}
export function setRendererFactory(factory: RendererFactory3): void {
rendererFactory = factory;
}
export function getCurrentSanitizer(): Sanitizer|null {
return viewData && viewData[SANITIZER];
}
@ -357,6 +353,7 @@ export function enterView(
creationMode = newView && (newView[FLAGS] & LViewFlags.CreationMode) === LViewFlags.CreationMode;
firstTemplatePass = newView && tView.firstTemplatePass;
bindingRootIndex = newView && tView.bindingStartIndex;
rendererFactory = newView && newView[RENDERER_FACTORY];
renderer = newView && newView[RENDERER];
previousOrParentTNode = hostTNode !;

View File

@ -13,7 +13,7 @@ import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, InternalViewRef as viewEn
import {checkNoChanges, checkNoChangesInRootView, detectChanges, detectChangesInRootView, markViewDirty, storeCleanupFn, viewAttached} from './instructions';
import {TNode, TNodeType, TViewNode} from './interfaces/node';
import {FLAGS, HOST, HOST_NODE, LViewData, LViewFlags, PARENT} from './interfaces/view';
import {FLAGS, HOST, HOST_NODE, LViewData, LViewFlags, PARENT, RENDERER_FACTORY} from './interfaces/view';
import {destroyLView} from './node_manipulation';
import {getRendererFactory} from './state';
import {getNativeByTNode} from './util';
@ -241,7 +241,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
* See {@link ChangeDetectorRef#detach detach} for more information.
*/
detectChanges(): void {
const rendererFactory = getRendererFactory();
const rendererFactory = this._view[RENDERER_FACTORY];
if (rendererFactory.begin) {
rendererFactory.begin();
}

View File

@ -60,7 +60,7 @@ export interface TrustedUrlString extends TrustedString { [BRAND]: BypassType.Ur
export interface TrustedResourceUrlString extends TrustedString { [BRAND]: BypassType.ResourceUrl; }
export function allowSanitizationBypass(value: any, type: BypassType): boolean {
return (value instanceof String && (value as TrustedStyleString)[BRAND] === type) ? true : false;
return (value instanceof String && (value as TrustedStyleString)[BRAND] === type);
}
/**

View File

@ -6,13 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {DebugElement, DebugNode, EventListener, getDebugNode, indexDebugNode, removeDebugNodeFromIndex} from '../debug/debug_node';
import {DebugElement__PRE_R3__, DebugNode__PRE_R3__, EventListener, getDebugNode, indexDebugNode, removeDebugNodeFromIndex} from '../debug/debug_node';
import {Injector} from '../di';
import {InjectableDef, getInjectableDef} from '../di/defs';
import {InjectableType} from '../di/injectable';
import {ErrorHandler} from '../error_handler';
import {isDevMode} from '../is_dev_mode';
import {ivyEnabled} from '../ivy_switch';
import {ComponentFactory} from '../linker/component_factory';
import {NgModuleRef} from '../linker/ng_module_factory';
import {Renderer2, RendererFactory2, RendererStyleFlags2, RendererType2} from '../render/api';
@ -700,8 +699,8 @@ export class DebugRenderer2 implements Renderer2 {
const el = this.delegate.createElement(name, namespace);
const debugCtx = this.createDebugContext(el);
if (debugCtx) {
const debugEl = new DebugElement(el, null, debugCtx);
debugEl.name = name;
const debugEl = new DebugElement__PRE_R3__(el, null, debugCtx);
(debugEl as{name: string}).name = name;
indexDebugNode(debugEl);
}
return el;
@ -711,7 +710,7 @@ export class DebugRenderer2 implements Renderer2 {
const comment = this.delegate.createComment(value);
const debugCtx = this.createDebugContext(comment);
if (debugCtx) {
indexDebugNode(new DebugNode(comment, null, debugCtx));
indexDebugNode(new DebugNode__PRE_R3__(comment, null, debugCtx));
}
return comment;
}
@ -720,7 +719,7 @@ export class DebugRenderer2 implements Renderer2 {
const text = this.delegate.createText(value);
const debugCtx = this.createDebugContext(text);
if (debugCtx) {
indexDebugNode(new DebugNode(text, null, debugCtx));
indexDebugNode(new DebugNode__PRE_R3__(text, null, debugCtx));
}
return text;
}
@ -728,7 +727,7 @@ export class DebugRenderer2 implements Renderer2 {
appendChild(parent: any, newChild: any): void {
const debugEl = getDebugNode(parent);
const debugChildEl = getDebugNode(newChild);
if (debugEl && debugChildEl && debugEl instanceof DebugElement) {
if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
debugEl.addChild(debugChildEl);
}
this.delegate.appendChild(parent, newChild);
@ -738,7 +737,7 @@ export class DebugRenderer2 implements Renderer2 {
const debugEl = getDebugNode(parent);
const debugChildEl = getDebugNode(newChild);
const debugRefEl = getDebugNode(refChild) !;
if (debugEl && debugChildEl && debugEl instanceof DebugElement) {
if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
debugEl.insertBefore(debugRefEl, debugChildEl);
}
@ -748,7 +747,7 @@ export class DebugRenderer2 implements Renderer2 {
removeChild(parent: any, oldChild: any): void {
const debugEl = getDebugNode(parent);
const debugChildEl = getDebugNode(oldChild);
if (debugEl && debugChildEl && debugEl instanceof DebugElement) {
if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
debugEl.removeChild(debugChildEl);
}
this.delegate.removeChild(parent, oldChild);
@ -756,16 +755,16 @@ export class DebugRenderer2 implements Renderer2 {
selectRootElement(selectorOrNode: string|any, preserveContent?: boolean): any {
const el = this.delegate.selectRootElement(selectorOrNode, preserveContent);
const debugCtx = getCurrentDebugContext() || (ivyEnabled ? this.createDebugContext(el) : null);
const debugCtx = getCurrentDebugContext();
if (debugCtx) {
indexDebugNode(new DebugElement(el, null, debugCtx));
indexDebugNode(new DebugElement__PRE_R3__(el, null, debugCtx));
}
return el;
}
setAttribute(el: any, name: string, value: string, namespace?: string): void {
const debugEl = getDebugNode(el);
if (debugEl && debugEl instanceof DebugElement) {
if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
const fullName = namespace ? namespace + ':' + name : name;
debugEl.attributes[fullName] = value;
}
@ -774,7 +773,7 @@ export class DebugRenderer2 implements Renderer2 {
removeAttribute(el: any, name: string, namespace?: string): void {
const debugEl = getDebugNode(el);
if (debugEl && debugEl instanceof DebugElement) {
if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
const fullName = namespace ? namespace + ':' + name : name;
debugEl.attributes[fullName] = null;
}
@ -783,7 +782,7 @@ export class DebugRenderer2 implements Renderer2 {
addClass(el: any, name: string): void {
const debugEl = getDebugNode(el);
if (debugEl && debugEl instanceof DebugElement) {
if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
debugEl.classes[name] = true;
}
this.delegate.addClass(el, name);
@ -791,7 +790,7 @@ export class DebugRenderer2 implements Renderer2 {
removeClass(el: any, name: string): void {
const debugEl = getDebugNode(el);
if (debugEl && debugEl instanceof DebugElement) {
if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
debugEl.classes[name] = false;
}
this.delegate.removeClass(el, name);
@ -799,7 +798,7 @@ export class DebugRenderer2 implements Renderer2 {
setStyle(el: any, style: string, value: any, flags: RendererStyleFlags2): void {
const debugEl = getDebugNode(el);
if (debugEl && debugEl instanceof DebugElement) {
if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
debugEl.styles[style] = value;
}
this.delegate.setStyle(el, style, value, flags);
@ -807,7 +806,7 @@ export class DebugRenderer2 implements Renderer2 {
removeStyle(el: any, style: string, flags: RendererStyleFlags2): void {
const debugEl = getDebugNode(el);
if (debugEl && debugEl instanceof DebugElement) {
if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
debugEl.styles[style] = null;
}
this.delegate.removeStyle(el, style, flags);
@ -815,7 +814,7 @@ export class DebugRenderer2 implements Renderer2 {
setProperty(el: any, name: string, value: any): void {
const debugEl = getDebugNode(el);
if (debugEl && debugEl instanceof DebugElement) {
if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
debugEl.properties[name] = value;
}
this.delegate.setProperty(el, name, value);

View File

@ -176,6 +176,9 @@
{
"name": "RENDERER"
},
{
"name": "RENDERER_FACTORY"
},
{
"name": "RENDER_PARENT"
},
@ -611,9 +614,6 @@
{
"name": "getCurrentQueries"
},
{
"name": "getCurrentSanitizer"
},
{
"name": "getDirectiveDef"
},
@ -1145,9 +1145,6 @@
{
"name": "setProp"
},
{
"name": "setRendererFactory"
},
{
"name": "setStyle"
},

View File

@ -107,6 +107,9 @@
{
"name": "RENDERER"
},
{
"name": "RENDERER_FACTORY"
},
{
"name": "RENDER_PARENT"
},
@ -320,9 +323,6 @@
{
"name": "getRenderer"
},
{
"name": "getRendererFactory"
},
{
"name": "getRootContext"
},
@ -458,9 +458,6 @@
{
"name": "setPreviousOrParentTNode"
},
{
"name": "setRendererFactory"
},
{
"name": "setTNodeAndViewData"
},

View File

@ -356,6 +356,9 @@
{
"name": "RENDERER"
},
{
"name": "RENDERER_FACTORY"
},
{
"name": "RENDER_PARENT"
},
@ -392,6 +395,9 @@
{
"name": "SafeSubscriber"
},
{
"name": "Sanitizer"
},
{
"name": "Self"
},
@ -455,9 +461,6 @@
{
"name": "ViewEncapsulation"
},
{
"name": "WRAP_RENDERER_FACTORY2"
},
{
"name": "_CLEAN_PROMISE"
},
@ -548,6 +551,9 @@
{
"name": "_enable_super_gross_mode_that_will_cause_bad_things"
},
{
"name": "_getViewData"
},
{
"name": "_global"
},
@ -950,9 +956,6 @@
{
"name": "getRenderer"
},
{
"name": "getRendererFactory"
},
{
"name": "getRootContext"
},
@ -1322,9 +1325,6 @@
{
"name": "setPreviousOrParentTNode"
},
{
"name": "setRendererFactory"
},
{
"name": "setRootDomAdapter"
},

View File

@ -170,6 +170,9 @@
{
"name": "RENDERER"
},
{
"name": "RENDERER_FACTORY"
},
{
"name": "RENDER_PARENT"
},
@ -659,9 +662,6 @@
{
"name": "getCurrentQueries"
},
{
"name": "getCurrentSanitizer"
},
{
"name": "getCurrentView"
},
@ -1166,9 +1166,6 @@
{
"name": "setProp"
},
{
"name": "setRendererFactory"
},
{
"name": "setStyle"
},

View File

@ -137,6 +137,24 @@
{
"name": "Compiler"
},
{
"name": "Compiler_compileModuleAndAllComponentsAsync"
},
{
"name": "Compiler_compileModuleAndAllComponentsSync"
},
{
"name": "Compiler_compileModuleAndAllComponentsSync__POST_R3__"
},
{
"name": "Compiler_compileModuleAsync"
},
{
"name": "Compiler_compileModuleSync"
},
{
"name": "Compiler_compileModuleSync__POST_R3__"
},
{
"name": "ComponentFactory"
},
@ -209,6 +227,12 @@
{
"name": "DateType"
},
{
"name": "DebugElement__POST_R3__"
},
{
"name": "DebugNode__POST_R3__"
},
{
"name": "DecimalPipe"
},
@ -446,6 +470,9 @@
{
"name": "MergeMapSubscriber"
},
{
"name": "ModuleWithComponentFactories"
},
{
"name": "MulticastOperator"
},
@ -698,6 +725,9 @@
{
"name": "RENDERER"
},
{
"name": "RENDERER_FACTORY"
},
{
"name": "RENDER_PARENT"
},
@ -950,9 +980,6 @@
{
"name": "ViewRef"
},
{
"name": "WRAP_RENDERER_FACTORY2"
},
{
"name": "WrappedValue"
},
@ -1136,6 +1163,9 @@
{
"name": "_enable_super_gross_mode_that_will_cause_bad_things"
},
{
"name": "_getViewData"
},
{
"name": "_global"
},
@ -1151,9 +1181,6 @@
{
"name": "_localeFactory"
},
{
"name": "_nativeNodeToDebugNode"
},
{
"name": "_ngProbeTokensToMap"
},
@ -1163,6 +1190,9 @@
{
"name": "_promiseStrategy"
},
{
"name": "_queryNodeChildrenR3"
},
{
"name": "_randomChar"
},
@ -1184,9 +1214,6 @@
{
"name": "_testabilityGetter"
},
{
"name": "_throwError"
},
{
"name": "addComponentLogic"
},
@ -1481,6 +1508,9 @@
{
"name": "directiveInject"
},
{
"name": "discoverLocalRefs"
},
{
"name": "domRendererFactory3"
},
@ -1565,6 +1595,12 @@
{
"name": "findViaComponent"
},
{
"name": "findViaDirective"
},
{
"name": "findViaNativeElement"
},
{
"name": "firstTemplatePass"
},
@ -1646,6 +1682,12 @@
{
"name": "getClosureSafeProperty"
},
{
"name": "getComponent"
},
{
"name": "getComponentAtNodeIndex"
},
{
"name": "getComponentDef"
},
@ -1658,6 +1700,9 @@
{
"name": "getContainerRenderParent"
},
{
"name": "getContext"
},
{
"name": "getContextViewData"
},
@ -1670,9 +1715,6 @@
{
"name": "getCurrentQueries"
},
{
"name": "getCurrentSanitizer"
},
{
"name": "getCurrentView"
},
@ -1694,9 +1736,21 @@
{
"name": "getDebugNode"
},
{
"name": "getDebugNode__POST_R3__"
},
{
"name": "getDirectiveDef"
},
{
"name": "getDirectiveEndIndex"
},
{
"name": "getDirectiveStartIndex"
},
{
"name": "getDirectivesAtNodeIndex"
},
{
"name": "getElementDepthCount"
},
@ -1727,6 +1781,9 @@
{
"name": "getInjectableDef"
},
{
"name": "getInjector"
},
{
"name": "getInjectorDef"
},
@ -1745,6 +1802,9 @@
{
"name": "getLastDefinedValue"
},
{
"name": "getLocalRefs"
},
{
"name": "getLocaleCurrencies"
},
@ -2075,6 +2135,9 @@
{
"name": "isComponentDef"
},
{
"name": "isComponentInstance"
},
{
"name": "isContextDirty"
},
@ -2093,6 +2156,12 @@
{
"name": "isDifferent"
},
{
"name": "isDirectiveDefHack"
},
{
"name": "isDirectiveInstance"
},
{
"name": "isDirty"
},
@ -2195,6 +2264,9 @@
{
"name": "listener"
},
{
"name": "loadContext"
},
{
"name": "loadInternal"
},
@ -2288,6 +2360,9 @@
{
"name": "noopScope"
},
{
"name": "notImplemented"
},
{
"name": "observable"
},
@ -2531,9 +2606,6 @@
{
"name": "setProp"
},
{
"name": "setRendererFactory"
},
{
"name": "setRootDomAdapter"
},
@ -2660,6 +2732,9 @@
{
"name": "trackByIdentity"
},
{
"name": "traverseNextElement"
},
{
"name": "tryCatch"
},

View File

@ -940,17 +940,19 @@ function declareTests(config?: {useJit: boolean}) {
expect(getDOM().getProperty(tc.nativeElement, 'id')).toEqual('newId');
});
fixmeIvy('FW-681: not possible to retrieve host property bindings from TView') &&
it('should not use template variables for expressions in hostProperties', () => {
@Directive({selector: '[host-properties]', host: {'[id]': 'id', '[title]': 'unknownProp'}})
@Directive(
{selector: '[host-properties]', host: {'[id]': 'id', '[title]': 'unknownProp'}})
class DirectiveWithHostProps {
id = 'one';
}
const fixture =
TestBed.configureTestingModule({declarations: [MyComp, DirectiveWithHostProps]})
.overrideComponent(
MyComp,
{set: {template: `<div *ngFor="let id of ['forId']" host-properties></div>`}})
.overrideComponent(MyComp, {
set: {template: `<div *ngFor="let id of ['forId']" host-properties></div>`}
})
.createComponent(MyComp);
fixture.detectChanges();
@ -1113,7 +1115,7 @@ function declareTests(config?: {useJit: boolean}) {
.toHaveText('dynamic greet');
}));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-707: TestBed: No LViewData in getParentInjectorLocation') &&
it('should create a component that has been freshly compiled', () => {
@Component({template: ''})
class RootComp {
@ -1153,7 +1155,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(compRef.instance.someToken).toBe('someRootValue');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-707: TestBed: No LViewData in getParentInjectorLocation') &&
it('should create a component with the passed NgModuleRef', () => {
@Component({template: ''})
class RootComp {
@ -1194,7 +1196,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(compRef.instance.someToken).toBe('someValue');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-707: TestBed: No LViewData in getParentInjectorLocation') &&
it('should create a component with the NgModuleRef of the ComponentFactoryResolver',
() => {
@Component({template: ''})

View File

@ -142,8 +142,8 @@ function declareTests(config?: {useJit: boolean}) {
return new ComponentFixture(comp, null !, false);
}
fixmeIvy('FW-682: Compiler error handling') && //
describe('errors', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should error when exporting a directive that was neither declared nor imported', () => {
@NgModule({exports: [SomeDirective]})
class SomeModule {
@ -154,7 +154,6 @@ function declareTests(config?: {useJit: boolean}) {
`Can't export directive ${stringify(SomeDirective)} from ${stringify(SomeModule)} as it was neither declared nor imported!`);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should error when exporting a pipe that was neither declared nor imported', () => {
@NgModule({exports: [SomePipe]})
class SomeModule {
@ -165,7 +164,6 @@ function declareTests(config?: {useJit: boolean}) {
`Can't export pipe ${stringify(SomePipe)} from ${stringify(SomeModule)} as it was neither declared nor imported!`);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should error if a directive is declared in more than 1 module', () => {
@NgModule({declarations: [SomeDirective]})
class Module1 {
@ -184,7 +182,6 @@ function declareTests(config?: {useJit: boolean}) {
`You can also create a new NgModule that exports and includes ${stringify(SomeDirective)} then import that NgModule in ${stringify(Module1)} and ${stringify(Module2)}.`);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should error if a directive is declared in more than 1 module also if the module declaring it is imported',
() => {
@NgModule({declarations: [SomeDirective], exports: [SomeDirective]})
@ -202,7 +199,6 @@ function declareTests(config?: {useJit: boolean}) {
`You can also create a new NgModule that exports and includes ${stringify(SomeDirective)} then import that NgModule in ${stringify(Module1)} and ${stringify(Module2)}.`);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should error if a pipe is declared in more than 1 module', () => {
@NgModule({declarations: [SomePipe]})
class Module1 {
@ -221,7 +217,6 @@ function declareTests(config?: {useJit: boolean}) {
`You can also create a new NgModule that exports and includes ${stringify(SomePipe)} then import that NgModule in ${stringify(Module1)} and ${stringify(Module2)}.`);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should error if a pipe is declared in more than 1 module also if the module declaring it is imported',
() => {
@NgModule({declarations: [SomePipe], exports: [SomePipe]})
@ -242,7 +237,7 @@ function declareTests(config?: {useJit: boolean}) {
});
describe('schemas', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should error on unknown bound properties on custom elements by default', () => {
@Component({template: '<some-element [someUnknownProp]="true"></some-element>'})
class ComponentUsingInvalidProperty {
@ -255,17 +250,14 @@ function declareTests(config?: {useJit: boolean}) {
expect(() => createModule(SomeModule)).toThrowError(/Can't bind to 'someUnknownProp'/);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should not error on unknown bound properties on custom elements when using the CUSTOM_ELEMENTS_SCHEMA',
() => {
@Component({template: '<some-element [someUnknownProp]="true"></some-element>'})
class ComponentUsingInvalidProperty {
}
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [ComponentUsingInvalidProperty]
})
@NgModule(
{schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [ComponentUsingInvalidProperty]})
class SomeModule {
}
@ -284,7 +276,7 @@ function declareTests(config?: {useJit: boolean}) {
afterEach(() => clearModulesForTest());
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-740: missing global registry of NgModules by id') &&
it('should register loaded modules', () => {
createModule(SomeModule);
const factory = getModuleFactory(token);
@ -292,7 +284,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(factory.moduleType).toBe(SomeModule);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should throw when registering a duplicate module', () => {
createModule(SomeModule);
expect(() => createModule(SomeOtherModule)).toThrowError(/Duplicate module registered/);
@ -300,15 +292,13 @@ function declareTests(config?: {useJit: boolean}) {
});
describe('entryComponents', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should create ComponentFactories in root modules', () => {
@NgModule({declarations: [SomeComp], entryComponents: [SomeComp]})
class SomeModule {
}
const ngModule = createModule(SomeModule);
expect(
ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
expect(ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
.toBe(SomeComp);
expect(ngModule.injector.get(ComponentFactoryResolver)
.resolveComponentFactory(SomeComp)
@ -316,7 +306,7 @@ function declareTests(config?: {useJit: boolean}) {
.toBe(SomeComp);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should throw if we cannot find a module associated with a module-level entryComponent',
() => {
@Component({template: ''})
@ -332,7 +322,7 @@ function declareTests(config?: {useJit: boolean}) {
'Component SomeCompWithEntryComponents is not part of any NgModule or the module has not been imported into your module.');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should throw if we cannot find a module associated with a component-level entryComponent',
() => {
@Component({template: '', entryComponents: [SomeComp]})
@ -348,7 +338,6 @@ function declareTests(config?: {useJit: boolean}) {
'Component SomeComp is not part of any NgModule or the module has not been imported into your module.');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should create ComponentFactories via ANALYZE_FOR_ENTRY_COMPONENTS', () => {
@NgModule({
declarations: [SomeComp],
@ -362,8 +351,7 @@ function declareTests(config?: {useJit: boolean}) {
}
const ngModule = createModule(SomeModule);
expect(
ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
expect(ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
.toBe(SomeComp);
expect(ngModule.injector.get(ComponentFactoryResolver)
.resolveComponentFactory(SomeComp)
@ -371,7 +359,6 @@ function declareTests(config?: {useJit: boolean}) {
.toBe(SomeComp);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should create ComponentFactories in imported modules', () => {
@NgModule({declarations: [SomeComp], entryComponents: [SomeComp]})
class SomeImportedModule {
@ -382,8 +369,7 @@ function declareTests(config?: {useJit: boolean}) {
}
const ngModule = createModule(SomeModule);
expect(
ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
expect(ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
.toBe(SomeComp);
expect(ngModule.injector.get(ComponentFactoryResolver)
.resolveComponentFactory(SomeComp)
@ -391,7 +377,6 @@ function declareTests(config?: {useJit: boolean}) {
.toBe(SomeComp);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should create ComponentFactories if the component was imported', () => {
@NgModule({declarations: [SomeComp], exports: [SomeComp]})
class SomeImportedModule {
@ -402,8 +387,7 @@ function declareTests(config?: {useJit: boolean}) {
}
const ngModule = createModule(SomeModule);
expect(
ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
expect(ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
.toBe(SomeComp);
expect(ngModule.injector.get(ComponentFactoryResolver)
.resolveComponentFactory(SomeComp)
@ -414,19 +398,16 @@ function declareTests(config?: {useJit: boolean}) {
});
describe('bootstrap components', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should create ComponentFactories', () => {
@NgModule({declarations: [SomeComp], bootstrap: [SomeComp]})
class SomeModule {
}
const ngModule = createModule(SomeModule);
expect(
ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
expect(ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp) !.componentType)
.toBe(SomeComp);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should store the ComponentFactories in the NgModuleInjector', () => {
@NgModule({declarations: [SomeComp], bootstrap: [SomeComp]})
class SomeModule {
@ -440,8 +421,8 @@ function declareTests(config?: {useJit: boolean}) {
});
describe('directives and pipes', () => {
fixmeIvy('FW-681: not possible to retrieve host property bindings from TView') &&
describe('declarations', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should be supported in root modules', () => {
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe, SomeDirective, SomePipe],
@ -457,7 +438,6 @@ function declareTests(config?: {useJit: boolean}) {
.toBe('transformed someValue');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should be supported in imported modules', () => {
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe, SomeDirective, SomePipe],
@ -477,7 +457,6 @@ function declareTests(config?: {useJit: boolean}) {
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should be supported in nested components', () => {
@Component({
selector: 'parent',
@ -505,7 +484,7 @@ function declareTests(config?: {useJit: boolean}) {
describe('import/export', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('Pipe with name \'somePipe\' not found!') &&
it('should support exported directives and pipes', () => {
@NgModule(
{declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
@ -527,7 +506,7 @@ function declareTests(config?: {useJit: boolean}) {
.toBe('transformed someValue');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('Pipe with name \'somePipe\' not found!') &&
it('should support exported directives and pipes if the module is wrapped into an `ModuleWithProviders`',
() => {
@NgModule(
@ -550,7 +529,7 @@ function declareTests(config?: {useJit: boolean}) {
.toBe('transformed someValue');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('Pipe with name \'somePipe\' not found!') &&
it('should support reexported modules', () => {
@NgModule(
{declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
@ -575,7 +554,7 @@ function declareTests(config?: {useJit: boolean}) {
.toBe('transformed someValue');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('Pipe with name \'somePipe\' not found!') &&
it('should support exporting individual directives of an imported module', () => {
@NgModule(
{declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
@ -600,7 +579,7 @@ function declareTests(config?: {useJit: boolean}) {
.toBe('transformed someValue');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should not use non exported pipes of an imported module', () => {
@NgModule({
declarations: [SomePipe],
@ -620,7 +599,7 @@ function declareTests(config?: {useJit: boolean}) {
.toThrowError(/The pipe 'somePipe' could not be found/);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should not use non exported directives of an imported module', () => {
@NgModule({
declarations: [SomeDirective],
@ -657,11 +636,9 @@ function declareTests(config?: {useJit: boolean}) {
return createModule(SomeModule, parent).injector;
}
fixmeIvy('FW-561: Runtime compiler is not loaded') && it('should provide the module', () => {
expect(createInjector([]).get(moduleType)).toBeAnInstanceOf(moduleType);
});
it('should provide the module',
() => { expect(createInjector([]).get(moduleType)).toBeAnInstanceOf(moduleType); });
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should instantiate a class without dependencies', () => {
const injector = createInjector([Engine]);
const engine = injector.get(Engine);
@ -669,7 +646,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(engine).toBeAnInstanceOf(Engine);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should resolve dependencies based on type information', () => {
const injector = createInjector([Engine, Car]);
const car = injector.get(Car);
@ -678,7 +654,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(car.engine).toBeAnInstanceOf(Engine);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should resolve dependencies based on @Inject annotation', () => {
const injector = createInjector([TurboEngine, Engine, CarWithInject]);
const car = injector.get(CarWithInject);
@ -687,19 +662,19 @@ function declareTests(config?: {useJit: boolean}) {
expect(car.engine).toBeAnInstanceOf(TurboEngine);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should throw when no type and not @Inject (class case)', () => {
expect(() => createInjector([NoAnnotations]))
.toThrowError('Can\'t resolve all parameters for NoAnnotations: (?).');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should throw when no type and not @Inject (factory case)', () => {
expect(() => createInjector([{provide: 'someToken', useFactory: factoryFn}]))
.toThrowError('Can\'t resolve all parameters for factoryFn: (?).');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') && it('should cache instances', () => {
it('should cache instances', () => {
const injector = createInjector([Engine]);
const e1 = injector.get(Engine);
@ -708,33 +683,31 @@ function declareTests(config?: {useJit: boolean}) {
expect(e1).toBe(e2);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') && it('should provide to a value', () => {
it('should provide to a value', () => {
const injector = createInjector([{provide: Engine, useValue: 'fake engine'}]);
const engine = injector.get(Engine);
expect(engine).toEqual('fake engine');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should provide to a factory', () => {
function sportsCarFactory(e: Engine) { return new SportsCar(e); }
const injector = createInjector(
[Engine, {provide: Car, useFactory: sportsCarFactory, deps: [Engine]}]);
const injector =
createInjector([Engine, {provide: Car, useFactory: sportsCarFactory, deps: [Engine]}]);
const car = injector.get(Car);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car.engine).toBeAnInstanceOf(Engine);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should supporting provider to null', () => {
const injector = createInjector([{provide: Engine, useValue: null}]);
const engine = injector.get(Engine);
expect(engine).toBeNull();
});
fixmeIvy('FW-561: Runtime compiler is not loaded') && it('should provide to an alias', () => {
it('should provide to an alias', () => {
const injector = createInjector([
Engine, {provide: SportsCar, useClass: SportsCar},
{provide: Car, useExisting: SportsCar}
@ -746,7 +719,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(car).toBe(sportsCar);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should support multiProviders', () => {
const injector = createInjector([
Engine, {provide: CARS, useClass: SportsCar, multi: true},
@ -759,7 +731,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(cars[1]).toBeAnInstanceOf(CarWithOptionalEngine);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should support multiProviders that are created using useExisting', () => {
const injector = createInjector(
[Engine, SportsCar, {provide: CARS, useExisting: SportsCar, multi: true}]);
@ -769,14 +740,13 @@ function declareTests(config?: {useJit: boolean}) {
expect(cars[0]).toBe(injector.get(SportsCar));
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should throw when the aliased provider does not exist', () => {
const injector = createInjector([{provide: 'car', useExisting: SportsCar}]);
const e = `NullInjectorError: No provider for ${stringify(SportsCar)}!`;
expect(() => injector.get('car')).toThrowError(e);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should handle forwardRef in useExisting', () => {
const injector = createInjector([
{provide: 'originalEngine', useClass: forwardRef(() => Engine)},
@ -785,18 +755,15 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('aliasedEngine')).toBeAnInstanceOf(Engine);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should support overriding factory dependencies', () => {
const injector = createInjector([
Engine, {provide: Car, useFactory: (e: Engine) => new SportsCar(e), deps: [Engine]}
]);
const injector = createInjector(
[Engine, {provide: Car, useFactory: (e: Engine) => new SportsCar(e), deps: [Engine]}]);
const car = injector.get(Car);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car.engine).toBeAnInstanceOf(Engine);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should support optional dependencies', () => {
const injector = createInjector([CarWithOptionalEngine]);
@ -804,7 +771,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(car.engine).toBeNull();
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should flatten passed-in providers', () => {
const injector = createInjector([[[Engine, Car]]]);
@ -812,43 +778,40 @@ function declareTests(config?: {useJit: boolean}) {
expect(car).toBeAnInstanceOf(Car);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should use the last provider when there are multiple providers for same token',
() => {
it('should use the last provider when there are multiple providers for same token', () => {
const injector = createInjector(
[{provide: Engine, useClass: Engine}, {provide: Engine, useClass: TurboEngine}]);
expect(injector.get(Engine)).toBeAnInstanceOf(TurboEngine);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') && it('should use non-type tokens', () => {
it('should use non-type tokens', () => {
const injector = createInjector([{provide: 'token', useValue: 'value'}]);
expect(injector.get('token')).toEqual('value');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should throw when given invalid providers', () => {
expect(() => createInjector(<any>['blah']))
.toThrowError(
`Invalid provider for the NgModule 'SomeModule' - only instances of Provider and Type are allowed, got: [?blah?]`);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should throw when given blank providers', () => {
fixmeIvy('FW-682: Compiler error handling') && it('should throw when given blank providers', () => {
expect(() => createInjector(<any>[null, {provide: 'token', useValue: 'value'}]))
.toThrowError(
`Invalid provider for the NgModule 'SomeModule' - only instances of Provider and Type are allowed, got: [?null?, ...]`);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') && it('should provide itself', () => {
it('should provide itself', () => {
const parent = createInjector([]);
const child = createInjector([], parent);
expect(child.get(Injector)).toBe(child);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') && it('should provide undefined', () => {
it('should provide undefined', () => {
let factoryCounter = 0;
const injector = createInjector([{
@ -866,7 +829,6 @@ function declareTests(config?: {useJit: boolean}) {
describe('injecting lazy providers into an eager provider via Injector.get', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should inject providers that were declared before it', () => {
@NgModule({
providers: [
@ -886,7 +848,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(createModule(MyModule).injector.get('eager')).toBe('eagerValue: lazyValue');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should inject providers that were declared after it', () => {
@NgModule({
providers: [
@ -909,7 +870,6 @@ function declareTests(config?: {useJit: boolean}) {
describe('injecting eager providers into an eager provider via Injector.get', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should inject providers that were declared before it', () => {
@NgModule({
providers: [
@ -929,7 +889,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(createModule(MyModule).injector.get('eager2')).toBe('v2: v1');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should inject providers that were declared after it', () => {
@NgModule({
providers: [
@ -949,7 +908,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(createModule(MyModule).injector.get('eager1')).toBe('v1: v2');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('eager providers should get initialized only once', () => {
@Injectable()
class MyService1 {
@ -980,27 +938,25 @@ function declareTests(config?: {useJit: boolean}) {
});
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should throw when no provider defined', () => {
const injector = createInjector([]);
expect(() => injector.get('NonExisting'))
.toThrowError('NullInjectorError: No provider for NonExisting!');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should throw when trying to instantiate a cyclic dependency', () => {
expect(() => createInjector([Car, {provide: Engine, useClass: CyclicEngine}]))
.toThrowError(/Cannot instantiate cyclic dependency! Car/g);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') && it('should support null values', () => {
it('should support null values', () => {
const injector = createInjector([{provide: 'null', useValue: null}]);
expect(injector.get('null')).toBe(null);
});
describe('child', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should load instances from parent injector', () => {
const parent = createInjector([Engine]);
const child = createInjector([], parent);
@ -1011,7 +967,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(engineFromChild).toBe(engineFromParent);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should not use the child providers when resolving the dependencies of a parent provider',
() => {
const parent = createInjector([Car, Engine]);
@ -1021,7 +976,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(carFromChild.engine).toBeAnInstanceOf(Engine);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should create new instance in a child injector', () => {
const parent = createInjector([Engine]);
const child = createInjector([{provide: Engine, useClass: TurboEngine}], parent);
@ -1037,14 +991,10 @@ function declareTests(config?: {useJit: boolean}) {
describe('depedency resolution', () => {
describe('@Self()', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should return a dependency from self', () => {
const inj = createInjector([
Engine, {
provide: Car,
useFactory: (e: Engine) => new Car(e),
deps: [[Engine, new Self()]]
}
Engine,
{provide: Car, useFactory: (e: Engine) => new Car(e), deps: [[Engine, new Self()]]}
]);
expect(inj.get(Car)).toBeAnInstanceOf(Car);
@ -1052,7 +1002,7 @@ function declareTests(config?: {useJit: boolean}) {
});
describe('default', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') && it('should not skip self', () => {
it('should not skip self', () => {
const parent = createInjector([Engine]);
const child = createInjector(
[
@ -1067,7 +1017,7 @@ function declareTests(config?: {useJit: boolean}) {
});
describe('lifecycle', () => {
fixmeIvy('unknown') && it('should instantiate modules eagerly', () => {
it('should instantiate modules eagerly', () => {
let created = false;
@NgModule()
@ -1084,7 +1034,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(created).toBe(true);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should instantiate providers that are not used by a module lazily', () => {
let created = false;
@ -1099,7 +1048,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(created).toBe(false);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('ngOnDestroy not running') &&
it('should support ngOnDestroy on any provider', () => {
let destroyed = false;
@ -1119,7 +1068,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(destroyed).toBe(true);
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('ngOnDestroy not running') &&
it('should support ngOnDestroy for lazy providers', () => {
let created = false;
let destroyed = false;
@ -1151,7 +1100,6 @@ function declareTests(config?: {useJit: boolean}) {
});
describe('imported and exported modules', () => {
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should add the providers of imported modules', () => {
@NgModule({providers: [{provide: 'token1', useValue: 'imported'}]})
class ImportedModule {
@ -1168,17 +1116,16 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('imported');
});
fixmeIvy('unknown') &&
it('should add the providers of imported ModuleWithProviders', () => {
@NgModule()
class ImportedModule {
}
@NgModule({
imports: [{
ngModule: ImportedModule,
providers: [{provide: 'token1', useValue: 'imported'}]
}]
imports: [
{ngModule: ImportedModule, providers: [{provide: 'token1', useValue: 'imported'}]}
]
})
class SomeModule {
}
@ -1190,7 +1137,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('imported');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should overwrite the providers of imported modules', () => {
@NgModule({providers: [{provide: 'token1', useValue: 'imported'}]})
class ImportedModule {
@ -1205,7 +1151,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('direct');
});
fixmeIvy('unknown') &&
it('should overwrite the providers of imported ModuleWithProviders', () => {
@NgModule()
class ImportedModule {
@ -1213,10 +1159,9 @@ function declareTests(config?: {useJit: boolean}) {
@NgModule({
providers: [{provide: 'token1', useValue: 'direct'}],
imports: [{
ngModule: ImportedModule,
providers: [{provide: 'token1', useValue: 'imported'}]
}]
imports: [
{ngModule: ImportedModule, providers: [{provide: 'token1', useValue: 'imported'}]}
]
})
class SomeModule {
}
@ -1225,9 +1170,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('direct');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should overwrite the providers of imported modules on the second import level',
() => {
it('should overwrite the providers of imported modules on the second import level', () => {
@NgModule({providers: [{provide: 'token1', useValue: 'imported'}]})
class ImportedModuleLevel2 {
}
@ -1247,7 +1190,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('direct');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should add the providers of exported modules', () => {
@NgModule({providers: [{provide: 'token1', useValue: 'exported'}]})
class ExportedValue {
@ -1264,7 +1206,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('exported');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should overwrite the providers of exported modules', () => {
@NgModule({providers: [{provide: 'token1', useValue: 'exported'}]})
class ExportedModule {
@ -1279,7 +1220,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('direct');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should overwrite the providers of imported modules by following imported modules',
() => {
@NgModule({providers: [{provide: 'token1', useValue: 'imported1'}]})
@ -1298,7 +1238,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('imported2');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should overwrite the providers of exported modules by following exported modules',
() => {
@NgModule({providers: [{provide: 'token1', useValue: 'exported1'}]})
@ -1317,7 +1256,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('exported2');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should overwrite the providers of imported modules by exported modules', () => {
@NgModule({providers: [{provide: 'token1', useValue: 'imported'}]})
class ImportedModule {
@ -1335,7 +1273,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('exported');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should not overwrite the providers if a module was already used on the same level',
() => {
@NgModule({providers: [{provide: 'token1', useValue: 'imported1'}]})
@ -1354,7 +1291,6 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('imported2');
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should not overwrite the providers if a module was already used on a child level',
() => {
@NgModule({providers: [{provide: 'token1', useValue: 'imported1'}]})
@ -1377,7 +1313,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(injector.get('token1')).toBe('imported2');
});
fixmeIvy('unknown') &&
fixmeIvy('FW-682: Compiler error handling') &&
it('should throw when given invalid providers in an imported ModuleWithProviders', () => {
@NgModule()
class ImportedModule1 {
@ -1394,7 +1330,7 @@ function declareTests(config?: {useJit: boolean}) {
});
describe('tree shakable providers', () => {
fixmeIvy('unknown') &&
fixmeIvy('providersByKey is not defined') &&
it('definition should not persist across NgModuleRef instances', () => {
@NgModule()
class SomeModule {

View File

@ -10,7 +10,7 @@ import {defineComponent} from '../../src/render3/definition';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, text, textBinding} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {ComponentFixture, TemplateFixture, createComponent, renderToHtml} from './render_util';
import {ComponentFixture, TemplateFixture, createComponent} from './render_util';
describe('JS control flow', () => {
it('should work with if block', () => {

View File

@ -2021,8 +2021,8 @@ describe('di', () => {
describe('getOrCreateNodeInjector', () => {
it('should handle initial undefined state', () => {
const contentView = createLViewData(
null, null !, createTView(-1, null, 1, 0, null, null, null), null,
LViewFlags.CheckAlways);
null, createTView(-1, null, 1, 0, null, null, null), null, LViewFlags.CheckAlways,
{} as any, {} as any);
const oldView = enterView(contentView, null);
try {
const parentTNode = createNodeAtIndex(0, TNodeType.Element, null, null, null);

View File

@ -33,8 +33,8 @@ describe('style and class based bindings', () => {
const rootContext =
createRootContext(requestAnimationFrame.bind(window), playerHandler || null);
const lViewData = createLViewData(
null, domRendererFactory3.createRenderer(element, null),
createTView(-1, null, 1, 0, null, null, null), rootContext, LViewFlags.IsRoot);
null, createTView(-1, null, 1, 0, null, null, null), rootContext, LViewFlags.IsRoot,
domRendererFactory3, domRendererFactory3.createRenderer(element, null));
return lViewData;
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Component, Directive, Injector, NgModule, NgZone, Pipe, PlatformRef, Provider, RendererFactory2, SchemaMetadata, Type, ɵInjectableDef as InjectableDef, ɵNgModuleDef as NgModuleDef, ɵNgModuleTransitiveScopes as NgModuleTransitiveScopes, ɵRender3ComponentFactory as ComponentFactory, ɵRender3DebugRendererFactory2 as Render3DebugRendererFactory2, ɵRender3NgModuleRef as NgModuleRef, ɵWRAP_RENDERER_FACTORY2 as WRAP_RENDERER_FACTORY2, ɵcompileComponent as compileComponent, ɵcompileDirective as compileDirective, ɵcompileNgModuleDefs as compileNgModuleDefs, ɵcompilePipe as compilePipe, ɵgetInjectableDef as getInjectableDef, ɵpatchComponentDefWithScope as patchComponentDefWithScope, ɵstringify as stringify} from '@angular/core';
import {Component, Directive, Injector, NgModule, NgZone, Pipe, PlatformRef, Provider, RendererFactory2, SchemaMetadata, Type, ɵInjectableDef as InjectableDef, ɵNgModuleDef as NgModuleDef, ɵNgModuleTransitiveScopes as NgModuleTransitiveScopes, ɵRender3ComponentFactory as ComponentFactory, ɵRender3NgModuleRef as NgModuleRef, ɵcompileComponent as compileComponent, ɵcompileDirective as compileDirective, ɵcompileNgModuleDefs as compileNgModuleDefs, ɵcompilePipe as compilePipe, ɵgetInjectableDef as getInjectableDef, ɵpatchComponentDefWithScope as patchComponentDefWithScope, ɵstringify as stringify} from '@angular/core';
import {ComponentFixture} from './component_fixture';
import {MetadataOverride} from './metadata_override';
@ -423,13 +423,8 @@ export class TestBedRender3 implements Injector, TestBed {
private _createTestModule(): Type<any> {
const rootProviderOverrides = this._rootProviderOverrides;
const rendererFactoryWrapper = {
provide: WRAP_RENDERER_FACTORY2,
useFactory: () => (rf: RendererFactory2) => new Render3DebugRendererFactory2(rf),
};
@NgModule({
providers: [...rootProviderOverrides, rendererFactoryWrapper],
providers: [...rootProviderOverrides],
jit: true,
})
class RootScopeModule {

View File

@ -9,7 +9,7 @@
import {CommonModule, Location} from '@angular/common';
import {SpyLocation} from '@angular/common/testing';
import {ChangeDetectionStrategy, Component, Injectable, NgModule, NgModuleFactoryLoader, NgModuleRef, NgZone, OnDestroy, ɵConsole as Console, ɵNoopNgZone as NoopNgZone} from '@angular/core';
import {ComponentFixture, TestBed, fakeAsync, flush, inject, tick} from '@angular/core/testing';
import {ComponentFixture, TestBed, fakeAsync, inject, tick} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {fixmeIvy} from '@angular/private/testing';
@ -2482,6 +2482,7 @@ describe('Integration', () => {
expect(canceledStatus).toEqual(false);
})));
fixmeIvy('unknown') &&
it('works with componentless routes',
fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
const fixture = createRoot(router, RootCmp);
@ -2823,7 +2824,7 @@ describe('Integration', () => {
})));
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('unknown') &&
it('should find the guard provided in lazy loaded module',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -2892,7 +2893,6 @@ describe('Integration', () => {
});
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should not load children when CanLoad returns false',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -2904,8 +2904,8 @@ describe('Integration', () => {
@NgModule({
declarations: [LazyLoadedComponent],
imports: [RouterModule.forChild(
[{path: 'loaded', component: LazyLoadedComponent}])]
imports:
[RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])]
})
class LoadedModule {
}
@ -2997,7 +2997,6 @@ describe('Integration', () => {
// Regression where navigateByUrl with false CanLoad no longer resolved `false` value on
// navigateByUrl promise: https://github.com/angular/angular/issues/26284
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should resolve navigateByUrl promise after CanLoad executes',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3009,8 +3008,8 @@ describe('Integration', () => {
@NgModule({
declarations: [LazyLoadedComponent],
imports: [RouterModule.forChild(
[{path: 'loaded', component: LazyLoadedComponent}])]
imports:
[RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])]
})
class LazyLoadedModule {
}
@ -3035,7 +3034,6 @@ describe('Integration', () => {
})));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should execute CanLoad only once',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3047,8 +3045,8 @@ describe('Integration', () => {
@NgModule({
declarations: [LazyLoadedComponent],
imports: [RouterModule.forChild(
[{path: 'loaded', component: LazyLoadedComponent}])]
imports:
[RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])]
})
class LazyLoadedModule {
}
@ -3056,8 +3054,7 @@ describe('Integration', () => {
loader.stubbedModules = {lazy: LazyLoadedModule};
const fixture = createRoot(router, RootCmp);
router.resetConfig(
[{path: 'lazy', canLoad: ['alwaysTrue'], loadChildren: 'lazy'}]);
router.resetConfig([{path: 'lazy', canLoad: ['alwaysTrue'], loadChildren: 'lazy'}]);
router.navigateByUrl('/lazy/loaded');
advance(fixture);
@ -3389,7 +3386,8 @@ describe('Integration', () => {
});
fixmeIvy('FW-561: Runtime compiler is not loaded') && describe('lazy loading', () => {
describe('lazy loading', () => {
fixmeIvy('unknown') &&
it('works',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3430,7 +3428,7 @@ describe('Integration', () => {
expect(fixture.nativeElement).toHaveText('lazy-loaded-parent [lazy-loaded-child]');
})));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('timeout') &&
it('should have 2 injector trees: module and element',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3520,7 +3518,7 @@ describe('Integration', () => {
})));
// https://github.com/angular/angular/issues/12889
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('unknown') &&
it('should create a single instance of lazy-loaded modules',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3559,7 +3557,7 @@ describe('Integration', () => {
})));
// https://github.com/angular/angular/issues/13870
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('timeout') &&
it('should create a single instance of guards for lazy-loaded modules',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3611,7 +3609,6 @@ describe('Integration', () => {
})));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should emit RouteConfigLoadStart and RouteConfigLoadEnd event when route is lazy loaded',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3658,7 +3655,6 @@ describe('Integration', () => {
expect(events[1].toString()).toEqual('RouteConfigLoadEnd(path: lazy)');
})));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('throws an error when forRoot() is used in a lazy context',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3669,8 +3665,7 @@ describe('Integration', () => {
@NgModule({
declarations: [LazyLoadedComponent],
imports:
[RouterModule.forRoot([{path: 'loaded', component: LazyLoadedComponent}])]
imports: [RouterModule.forRoot([{path: 'loaded', component: LazyLoadedComponent}])]
})
class LoadedModule {
}
@ -3689,7 +3684,6 @@ describe('Integration', () => {
`RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.`);
})));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should combine routes from multiple modules into a single configuration',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3719,10 +3713,7 @@ describe('Integration', () => {
class LoadedModule {
}
loader.stubbedModules = {
expected1: LoadedModule,
expected2: SiblingOfLoadedModule
};
loader.stubbedModules = {expected1: LoadedModule, expected2: SiblingOfLoadedModule};
const fixture = createRoot(router, RootCmp);
@ -3740,7 +3731,7 @@ describe('Integration', () => {
expect(location.path()).toEqual('/lazy2/loaded');
})));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('unknown') &&
it('should allow lazy loaded module in named outlet',
fakeAsync(inject(
[Router, NgModuleFactoryLoader],
@ -3783,9 +3774,11 @@ describe('Integration', () => {
.toHaveText('team 22 [ user john, right: lazy-loaded ]');
})));
fixmeIvy('unknown') &&
it('should allow componentless named outlet to render children',
fakeAsync(inject(
[Router, NgModuleFactoryLoader], (router: Router, loader: SpyNgModuleFactoryLoader) => {
[Router, NgModuleFactoryLoader],
(router: Router, loader: SpyNgModuleFactoryLoader) => {
const fixture = createRoot(router, RootCmp);
@ -3794,7 +3787,11 @@ describe('Integration', () => {
component: TeamCmp,
children: [
{path: 'user/:name', component: UserCmp},
{path: 'simple', outlet: 'right', children: [{path: '', component: SimpleCmp}]},
{
path: 'simple',
outlet: 'right',
children: [{path: '', component: SimpleCmp}]
},
]
}]);
@ -3869,7 +3866,7 @@ describe('Integration', () => {
});
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('timeout') &&
it('should use the injector of the lazily-loaded configuration',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3892,7 +3889,6 @@ describe('Integration', () => {
})));
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('works when given a callback',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader], (router: Router, location: Location) => {
@ -3902,8 +3898,7 @@ describe('Integration', () => {
@NgModule({
declarations: [LazyLoadedComponent],
imports:
[RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])],
imports: [RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])],
})
class LoadedModule {
}
@ -3943,7 +3938,6 @@ describe('Integration', () => {
]);
})));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should work with complex redirect rules',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -3954,8 +3948,7 @@ describe('Integration', () => {
@NgModule({
declarations: [LazyLoadedComponent],
imports:
[RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])],
imports: [RouterModule.forChild([{path: 'loaded', component: LazyLoadedComponent}])],
})
class LoadedModule {
}
@ -3972,7 +3965,6 @@ describe('Integration', () => {
expect(location.path()).toEqual('/lazy/loaded');
})));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should work with wildcard route',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -4008,7 +4000,6 @@ describe('Integration', () => {
preloader.setUpPreloading();
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should work',
fakeAsync(inject(
[Router, Location, NgModuleFactoryLoader],
@ -4026,8 +4017,8 @@ describe('Integration', () => {
}
@NgModule({
imports: [RouterModule.forChild(
[{path: 'LoadedModule1', loadChildren: 'expected2'}])]
imports:
[RouterModule.forChild([{path: 'LoadedModule1', loadChildren: 'expected2'}])]
})
class LoadedModule1 {
}
@ -4037,8 +4028,7 @@ describe('Integration', () => {
const fixture = createRoot(router, RootCmp);
router.resetConfig([
{path: 'blank', component: BlankCmp},
{path: 'lazy', loadChildren: 'expected'}
{path: 'blank', component: BlankCmp}, {path: 'lazy', loadChildren: 'expected'}
]);
router.navigateByUrl('/blank');
@ -4097,6 +4087,7 @@ describe('Integration', () => {
{providers: [{provide: UrlHandlingStrategy, useClass: CustomUrlHandlingStrategy}]});
});
fixmeIvy('unknown') &&
it('should work',
fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
const fixture = createRoot(router, RootCmp);
@ -4105,7 +4096,8 @@ describe('Integration', () => {
path: 'include',
component: TeamCmp,
children: [
{path: 'user/:name', component: UserCmp}, {path: 'simple', component: SimpleCmp}
{path: 'user/:name', component: UserCmp},
{path: 'simple', component: SimpleCmp}
]
}]);
@ -4219,7 +4211,6 @@ describe('Integration', () => {
class LazyLoadedModule {
}
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should not ignore empty path when in legacy mode',
fakeAsync(inject(
[Router, NgModuleFactoryLoader],
@ -4238,7 +4229,6 @@ describe('Integration', () => {
expect(link.getAttribute('href')).toEqual('/lazy/foo/bar/simple');
})));
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should ignore empty path when in corrected mode',
fakeAsync(inject(
[Router, NgModuleFactoryLoader],

View File

@ -36,7 +36,7 @@ describe('RouterPreloader', () => {
});
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should work',
fakeAsync(inject(
[NgModuleFactoryLoader, RouterPreloader, Router],
@ -60,7 +60,8 @@ describe('RouterPreloader', () => {
});
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
fixmeIvy('unknown') &&
it('should work',
fakeAsync(inject(
[NgModuleFactoryLoader, RouterPreloader, Router, NgModuleRef],
@ -200,7 +201,7 @@ describe('RouterPreloader', () => {
});
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should work',
fakeAsync(inject(
[NgModuleFactoryLoader, RouterPreloader, Router],
@ -230,7 +231,7 @@ describe('RouterPreloader', () => {
});
});
fixmeIvy('FW-561: Runtime compiler is not loaded') &&
it('should work',
fakeAsync(inject(
[NgModuleFactoryLoader, RouterPreloader, Router],

View File

@ -76,12 +76,12 @@ export interface CollectionChangeRecord<V> extends IterableChangeRecord<V> {
}
export declare class Compiler {
compileModuleAndAllComponentsAsync: <T>(moduleType: Type<T>) => Promise<ModuleWithComponentFactories<T>>;
compileModuleAndAllComponentsSync: <T>(moduleType: Type<T>) => ModuleWithComponentFactories<T>;
compileModuleAsync: <T>(moduleType: Type<T>) => Promise<NgModuleFactory<T>>;
compileModuleSync: <T>(moduleType: Type<T>) => NgModuleFactory<T>;
clearCache(): void;
clearCacheFor(type: Type<any>): void;
compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>): Promise<ModuleWithComponentFactories<T>>;
compileModuleAndAllComponentsSync<T>(moduleType: Type<T>): ModuleWithComponentFactories<T>;
compileModuleAsync<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>>;
compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T>;
getModuleId(moduleType: Type<any>): string | undefined;
}
@ -188,48 +188,50 @@ export declare function createPlatformFactory(parentPlatformFactory: ((extraProv
export declare const CUSTOM_ELEMENTS_SCHEMA: SchemaMetadata;
export declare class DebugElement extends DebugNode {
attributes: {
export interface DebugElement extends DebugNode {
readonly attributes: {
[key: string]: string | null;
};
childNodes: DebugNode[];
readonly childNodes: DebugNode[];
readonly children: DebugElement[];
classes: {
readonly classes: {
[key: string]: boolean;
};
name: string;
nativeElement: any;
properties: {
readonly name: string;
readonly nativeElement: any;
readonly properties: {
[key: string]: any;
};
styles: {
readonly styles: {
[key: string]: string | null;
};
constructor(nativeNode: any, parent: any, _debugContext: DebugContext);
addChild(child: DebugNode): void;
insertBefore(refChild: DebugNode, newChild: DebugNode): void;
insertChildrenAfter(child: DebugNode, newChildren: DebugNode[]): void;
query(predicate: Predicate<DebugElement>): DebugElement;
queryAll(predicate: Predicate<DebugElement>): DebugElement[];
queryAllNodes(predicate: Predicate<DebugNode>): DebugNode[];
removeChild(child: DebugNode): void;
triggerEventHandler(eventName: string, eventObj: any): void;
}
export declare class DebugNode {
export declare const DebugElement: {
new (...args: any[]): DebugElement;
};
export interface DebugNode {
readonly componentInstance: any;
readonly context: any;
readonly injector: Injector;
listeners: EventListener[];
nativeNode: any;
parent: DebugElement | null;
readonly listeners: EventListener[];
readonly nativeNode: any;
readonly parent: DebugElement | null;
readonly providerTokens: any[];
readonly references: {
[key: string]: any;
};
constructor(nativeNode: any, parent: DebugNode | null, _debugContext: DebugContext);
}
export declare const DebugNode: {
new (...args: any[]): DebugNode;
};
/** @deprecated */
export declare class DefaultIterableDiffer<V> implements IterableDiffer<V>, IterableChanges<V> {
readonly collection: V[] | Iterable<V> | null;
@ -330,7 +332,7 @@ export interface ForwardRefFn {
(): any;
}
export declare function getDebugNode(nativeNode: any): DebugNode | null;
export declare const getDebugNode: (nativeNode: any) => DebugNode | null;
export declare function getModuleFactory(id: string): NgModuleFactory<any>;