fix(core): Remove static dependency from @angular/core to @angular/compiler (#26734)

PR Close #26734
This commit is contained in:
Misko Hevery 2018-10-24 16:02:25 -07:00 committed by Matias Niemelä
parent 5d740785a9
commit d042c4afe0
46 changed files with 923 additions and 551 deletions

View File

@ -332,8 +332,9 @@ function parseFieldToPropertyMapping(
*/
function parseDecoratedFields(
fields: {member: ClassMember, decorators: Decorator[]}[], reflector: ReflectionHost,
checker: ts.TypeChecker, mapValueResolver: (publicName: string, internalName: string) =>
string | string[]): {[field: string]: string | string[]} {
checker: ts.TypeChecker,
mapValueResolver: (publicName: string, internalName: string) =>
string | [string, string]): {[field: string]: string | [string, string]} {
return fields.reduce(
(results, field) => {
const fieldName = field.member.name;
@ -356,10 +357,10 @@ function parseDecoratedFields(
});
return results;
},
{} as{[field: string]: string | string[]});
{} as{[field: string]: string | [string, string]});
}
function resolveInput(publicName: string, internalName: string) {
function resolveInput(publicName: string, internalName: string): [string, string] {
return [publicName, internalName];
}

View File

@ -22,5 +22,5 @@
"ng-update": {
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
},
"sideEffects": false
"sideEffects": true
}

View File

@ -6,6 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/
//////////////////////////////////////
// THIS FILE HAS GLOBAL SIDE EFFECT //
// (see bottom of file) //
//////////////////////////////////////
/**
* @module
* @description
@ -23,6 +28,8 @@
*/
import * as core from './core';
import {publishFacade} from './jit_compiler_facade';
import {global} from './util';
export {core};
@ -91,4 +98,9 @@ export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compile
export {makeBindingParser, parseTemplate} from './render3/view/template';
export {R3Reference} from './render3/util';
export {compileBaseDefFromMetadata, R3BaseRefMetaData, compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings} from './render3/view/compiler';
export {publishFacade} from './jit_compiler_facade';
// This file only reexports content of the `src` folder. Keep it that way.
// This function call has a global side effects and publishes the compiler into global namespace for
// the late binding of the Compiler to the @angular/core for jit compilation.
publishFacade(global);

View File

@ -0,0 +1,145 @@
/**
* @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
*/
/**
* A set of interfaces which are shared between `@angular/core` and `@angular/compiler` to allow
* for late binding of `@angular/compiler` for JIT purposes.
*
* This file has two copies. Please ensure that they are in sync:
* - packages/compiler/src/compiler_facade_interface.ts (master)
* - packages/core/src/render3/jit/compiler_facade_interface.ts (copy)
*
* Please ensure that the two files are in sync using this command:
* ```
* cp packages/compiler/src/compiler_facade_interface.ts \
* packages/core/src/render3/jit/compiler_facade_interface.ts
* ```
*/
export interface ExportedCompilerFacade { ɵcompilerFacade: CompilerFacade; }
export interface CompilerFacade {
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3PipeMetadataFacade):
any;
compileInjectable(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectableMetadataFacade): any;
compileInjector(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectorMetadataFacade): any;
compileNgModule(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3NgModuleMetadataFacade): any;
compileDirective(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3DirectiveMetadataFacade): any;
compileComponent(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any;
R3ResolvedDependencyType: typeof R3ResolvedDependencyType;
}
export interface CoreEnvironment { [name: string]: Function; }
export type StringMap = {
[key: string]: string;
};
export type StringMapWithRename = {
[key: string]: string | [string, string];
};
export type Provider = any;
export enum R3ResolvedDependencyType {
Token = 0,
Attribute = 1,
}
export interface R3DependencyMetadataFacade {
token: any;
resolved: R3ResolvedDependencyType;
host: boolean;
optional: boolean;
self: boolean;
skipSelf: boolean;
}
export interface R3PipeMetadataFacade {
name: string;
type: any;
pipeName: string;
deps: R3DependencyMetadataFacade[]|null;
pure: boolean;
}
export interface R3InjectableMetadataFacade {
name: string;
type: any;
ctorDeps: R3DependencyMetadataFacade[]|null;
providedIn: any;
useClass?: any;
useFactory?: any;
useExisting?: any;
useValue?: any;
userDeps?: R3DependencyMetadataFacade[];
}
export interface R3NgModuleMetadataFacade {
type: any;
bootstrap: Function[];
declarations: Function[];
imports: Function[];
exports: Function[];
emitInline: boolean;
}
export interface R3InjectorMetadataFacade {
name: string;
type: any;
deps: R3DependencyMetadataFacade[]|null;
providers: any;
imports: any;
}
export interface R3DirectiveMetadataFacade {
name: string;
type: any;
typeArgumentCount: number;
typeSourceSpan: null;
deps: R3DependencyMetadataFacade[]|null;
selector: string|null;
queries: R3QueryMetadataFacade[];
host: {[key: string]: string};
propMetadata: {[key: string]: any[]};
lifecycle: {usesOnChanges: boolean;};
inputs: string[];
outputs: string[];
usesInheritance: boolean;
exportAs: string|null;
providers: Provider[]|null;
}
export interface R3ComponentMetadataFacade extends R3DirectiveMetadataFacade {
template: string;
preserveWhitespaces: boolean;
animations: any[]|undefined;
viewQueries: R3QueryMetadataFacade[];
pipes: Map<string, any>;
directives: Map<string, any>;
styles: string[];
encapsulation: ViewEncapsulation;
viewProviders: Provider[]|null;
}
export type ViewEncapsulation = number;
export interface R3QueryMetadataFacade {
propertyName: string;
first: boolean;
predicate: any|string[];
descendants: boolean;
read: any|null;
}

View File

@ -0,0 +1,294 @@
/**
* @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 {CompilerFacade, CoreEnvironment, ExportedCompilerFacade, R3ComponentMetadataFacade, R3DependencyMetadataFacade, R3DirectiveMetadataFacade, R3InjectableMetadataFacade, R3InjectorMetadataFacade, R3NgModuleMetadataFacade, R3PipeMetadataFacade, R3QueryMetadataFacade, StringMap, StringMapWithRename} from './compiler_facade_interface';
import {ConstantPool} from './constant_pool';
import {HostBinding, HostListener, Input, Output, Type} from './core';
import {compileInjectable} from './injectable_compiler_2';
import {Expression, LiteralExpr, WrappedNodeExpr} from './output/output_ast';
import {R3DependencyMetadata, R3ResolvedDependencyType} from './render3/r3_factory';
import {jitExpression} from './render3/r3_jit';
import {R3InjectorMetadata, R3NgModuleMetadata, compileInjector, compileNgModule} from './render3/r3_module_compiler';
import {compilePipeFromMetadata} from './render3/r3_pipe_compiler';
import {R3Reference} from './render3/util';
import {R3DirectiveMetadata, R3QueryMetadata} from './render3/view/api';
import {compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings} from './render3/view/compiler';
import {makeBindingParser, parseTemplate} from './render3/view/template';
export class CompilerFacadeImpl implements CompilerFacade {
R3ResolvedDependencyType = R3ResolvedDependencyType as any;
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, facade: R3PipeMetadataFacade):
any {
const res = compilePipeFromMetadata({
name: facade.name,
type: new WrappedNodeExpr(facade.type),
deps: convertR3DependencyMetadataArray(facade.deps),
pipeName: facade.pipeName,
pure: facade.pure,
});
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
}
compileInjectable(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
facade: R3InjectableMetadataFacade): any {
const {expression, statements} = compileInjectable({
name: facade.name,
type: new WrappedNodeExpr(facade.type),
providedIn: computeProvidedIn(facade.providedIn),
useClass: wrapExpression(facade, USE_CLASS),
useFactory: wrapExpression(facade, USE_FACTORY),
useValue: wrapExpression(facade, USE_VALUE),
useExisting: wrapExpression(facade, USE_EXISTING),
ctorDeps: convertR3DependencyMetadataArray(facade.ctorDeps),
userDeps: convertR3DependencyMetadataArray(facade.userDeps) || undefined,
});
return jitExpression(expression, angularCoreEnv, sourceMapUrl, statements);
}
compileInjector(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
facade: R3InjectorMetadataFacade): any {
const meta: R3InjectorMetadata = {
name: facade.name,
type: new WrappedNodeExpr(facade.type),
deps: convertR3DependencyMetadataArray(facade.deps),
providers: new WrappedNodeExpr(facade.providers),
imports: new WrappedNodeExpr(facade.imports),
};
const res = compileInjector(meta);
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
}
compileNgModule(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
facade: R3NgModuleMetadataFacade): any {
const meta: R3NgModuleMetadata = {
type: new WrappedNodeExpr(facade.type),
bootstrap: facade.bootstrap.map(wrapReference),
declarations: facade.declarations.map(wrapReference),
imports: facade.imports.map(wrapReference),
exports: facade.exports.map(wrapReference),
emitInline: true,
};
const res = compileNgModule(meta);
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
}
compileDirective(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
facade: R3DirectiveMetadataFacade): any {
const constantPool = new ConstantPool();
const bindingParser = makeBindingParser();
const meta: R3DirectiveMetadata = convertDirectiveFacadeToMetadata(facade);
const res = compileDirectiveFromMetadata(meta, constantPool, bindingParser);
const preStatements = [...constantPool.statements, ...res.statements];
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
}
compileComponent(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
facade: R3ComponentMetadataFacade): any {
// The ConstantPool is a requirement of the JIT'er.
const constantPool = new ConstantPool();
// Parse the template and check for errors.
const template = parseTemplate(
facade.template, sourceMapUrl, {
preserveWhitespaces: facade.preserveWhitespaces || false,
},
'');
if (template.errors !== undefined) {
const errors = template.errors.map(err => err.toString()).join(', ');
throw new Error(`Errors during JIT compilation of template for ${facade.name}: ${errors}`);
}
// Compile the component metadata, including template, into an expression.
// TODO(alxhub): implement inputs, outputs, queries, etc.
const res = compileComponentFromMetadata(
{
...facade as R3ComponentMetadataFacadeNoPropAndWhitespace,
...convertDirectiveFacadeToMetadata(facade),
template,
viewQueries: facade.viewQueries.map(convertToR3QueryMetadata),
wrapDirectivesAndPipesInClosure: false,
styles: facade.styles || [],
encapsulation: facade.encapsulation as any,
animations: facade.animations != null ? new WrappedNodeExpr(facade.animations) : null,
viewProviders: facade.viewProviders != null ? new WrappedNodeExpr(facade.viewProviders) :
null,
},
constantPool, makeBindingParser());
const preStatements = [...constantPool.statements, ...res.statements];
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
}
}
// This seems to be needed to placate TS v3.0 only
type R3ComponentMetadataFacadeNoPropAndWhitespace = Pick<
R3ComponentMetadataFacade,
Exclude<Exclude<keyof R3ComponentMetadataFacade, 'preserveWhitespaces'>, 'propMetadata'>>;
const USE_CLASS = Object.keys({useClass: null})[0];
const USE_FACTORY = Object.keys({useFactory: null})[0];
const USE_VALUE = Object.keys({useValue: null})[0];
const USE_EXISTING = Object.keys({useExisting: null})[0];
const wrapReference = function(value: Type): R3Reference {
const wrapped = new WrappedNodeExpr(value);
return {value: wrapped, type: wrapped};
};
function convertToR3QueryMetadata(facade: R3QueryMetadataFacade): R3QueryMetadata {
return {
...facade,
predicate: Array.isArray(facade.predicate) ? facade.predicate :
new WrappedNodeExpr(facade.predicate),
read: facade.read ? new WrappedNodeExpr(facade.read) : null,
};
}
function convertDirectiveFacadeToMetadata(facade: R3DirectiveMetadataFacade): R3DirectiveMetadata {
const inputsFromMetadata = parseInputOutputs(facade.inputs || []);
const outputsFromMetadata = parseInputOutputs(facade.outputs || []);
const propMetadata = facade.propMetadata;
const inputsFromType: StringMapWithRename = {};
const outputsFromType: StringMap = {};
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
if (isInput(ann)) {
inputsFromType[field] =
ann.bindingPropertyName ? [ann.bindingPropertyName, field] : field;
} else if (isOutput(ann)) {
outputsFromType[field] = ann.bindingPropertyName || field;
}
});
}
}
return {
...facade as R3DirectiveMetadataFacadeNoPropAndWhitespace,
typeSourceSpan: null !,
type: new WrappedNodeExpr(facade.type),
deps: convertR3DependencyMetadataArray(facade.deps),
host: extractHostBindings(facade.host, facade.propMetadata),
inputs: {...inputsFromMetadata, ...inputsFromType},
outputs: {...outputsFromMetadata, ...outputsFromType},
providers: facade.providers != null ? new WrappedNodeExpr(facade.providers) : null,
};
}
// This seems to be needed to placate TS v3.0 only
type R3DirectiveMetadataFacadeNoPropAndWhitespace =
Pick<R3DirectiveMetadataFacade, Exclude<keyof R3DirectiveMetadataFacade, 'propMetadata'>>;
function wrapExpression(obj: any, property: string): WrappedNodeExpr<any>|undefined {
if (obj.hasOwnProperty(property)) {
return new WrappedNodeExpr(obj[property]);
} else {
return undefined;
}
}
function computeProvidedIn(providedIn: Type | string | null | undefined): Expression {
if (providedIn == null || typeof providedIn === 'string') {
return new LiteralExpr(providedIn);
} else {
return new WrappedNodeExpr(providedIn);
}
}
function convertR3DependencyMetadata(facade: R3DependencyMetadataFacade): R3DependencyMetadata {
let tokenExpr;
if (facade.token === null) {
tokenExpr = new LiteralExpr(null);
} else if (facade.resolved === R3ResolvedDependencyType.Attribute) {
tokenExpr = new LiteralExpr(facade.token);
} else {
tokenExpr = new WrappedNodeExpr(facade.token);
}
return {
token: tokenExpr,
resolved: facade.resolved,
host: facade.host,
optional: facade.optional,
self: facade.self,
skipSelf: facade.skipSelf
};
}
function convertR3DependencyMetadataArray(facades: R3DependencyMetadataFacade[] | null | undefined):
R3DependencyMetadata[]|null {
return facades == null ? null : facades.map(convertR3DependencyMetadata);
}
function extractHostBindings(host: {[key: string]: string}, propMetadata: {[key: string]: any[]}): {
attributes: StringMap,
listeners: StringMap,
properties: StringMap,
} {
// First parse the declarations from the metadata.
const {attributes, listeners, properties, animations} = parseHostBindings(host || {});
if (Object.keys(animations).length > 0) {
throw new Error(`Animation bindings are as-of-yet unsupported in Ivy`);
}
// Next, loop over the properties of the object, looking for @HostBinding and @HostListener.
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
if (isHostBinding(ann)) {
properties[ann.hostPropertyName || field] = field;
} else if (isHostListener(ann)) {
listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
}
});
}
}
return {attributes, listeners, properties};
}
function isHostBinding(value: any): value is HostBinding {
return value.ngMetadataName === 'HostBinding';
}
function isHostListener(value: any): value is HostListener {
return value.ngMetadataName === 'HostListener';
}
function isInput(value: any): value is Input {
return value.ngMetadataName === 'Input';
}
function isOutput(value: any): value is Output {
return value.ngMetadataName === 'Output';
}
function parseInputOutputs(values: string[]): StringMap {
return values.reduce(
(map, value) => {
const [field, property] = value.split(',').map(piece => piece.trim());
map[field] = property || field;
return map;
},
{} as StringMap);
}
export function publishFacade(global: any) {
const ng: ExportedCompilerFacade = global.ng || (global.ng = {});
ng.ɵcompilerFacade = new CompilerFacadeImpl();
}

View File

@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {StaticSymbol} from '../aot/static_symbol';
import {CompileShallowModuleMetadata, identifierName} from '../compile_metadata';
import {InjectableCompiler} from '../injectable_compiler';
import {mapLiteral} from '../output/map_util';

View File

@ -86,7 +86,7 @@ export interface R3DirectiveMetadata {
/**
* A mapping of input field names to the property names.
*/
inputs: {[field: string]: string | string[]};
inputs: {[field: string]: string | [string, string]};
/**
* A mapping of output field names to the property names.

View File

@ -44,7 +44,7 @@ export interface DirectiveMeta {
*
* Goes from property names to field names.
*/
inputs: {[property: string]: string | string[]};
inputs: {[property: string]: string | [string, string]};
/**
* Set of outputs which this directive claims.

View File

@ -233,3 +233,19 @@ export interface Console {
log(message: string): void;
warn(message: string): void;
}
declare var WorkerGlobalScope: any;
// CommonJS / Node have global context exposed as "global" variable.
// We don't want to include the whole node.d.ts this this compilation unit so we'll just fake
// the global "global" var for now.
declare var global: any;
const __window = typeof window !== 'undefined' && window;
const __self = typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' &&
self instanceof WorkerGlobalScope && self;
const __global = typeof global !== 'undefined' && global;
// Check __global first, because in Node tests both __global and __window may be defined and _global
// should be __global in that case.
const _global: {[name: string]: any} = __global || __window || __self;
export {_global as global};

View File

@ -0,0 +1,100 @@
/**
* @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 * as core from '../../core/src/render3/jit/compiler_facade_interface';
import {R3ResolvedDependencyType} from '../public_api';
import * as compiler from '../src/compiler_facade_interface';
/**
* This file is compiler level file which asserts that the set of interfaces in `@angular/core` and
* `@angular/compiler` match. (Build time failure.)
*
* If this file fails to compile it means these two files when out of sync:
* - packages/compiler/src/compiler_facade_interface.ts (master)
* - packages/core/src/render3/jit/compiler_facade_interface.ts (copy)
*
* Please ensure that the two files are in sync using this command:
* ```
* cp packages/compiler/src/compiler_facade_interface.ts \
* packages/core/src/render3/jit/compiler_facade_interface.ts
* ```
*/
const coreExportedCompilerFacade1: core.ExportedCompilerFacade =
null !as compiler.ExportedCompilerFacade;
const compilerExportedCompilerFacade2: compiler.ExportedCompilerFacade =
null !as core.ExportedCompilerFacade;
const coreCompilerFacade: core.CompilerFacade = null !as compiler.CompilerFacade;
const compilerCompilerFacade: compiler.CompilerFacade = null !as core.CompilerFacade;
const coreCoreEnvironment: core.CoreEnvironment = null !as compiler.CoreEnvironment;
const compilerCoreEnvironment: compiler.CoreEnvironment = null !as core.CoreEnvironment;
const coreStringMap: core.StringMap = null !as compiler.StringMap;
const compilerStringMap: compiler.StringMap = null !as core.StringMap;
const coreProvider: core.Provider = null !as compiler.Provider;
const compilerProvider: compiler.Provider = null !as core.Provider;
const coreR3ResolvedDependencyType: core.R3ResolvedDependencyType =
null !as compiler.R3ResolvedDependencyType;
const compilerR3ResolvedDependencyType: compiler.R3ResolvedDependencyType =
null !as core.R3ResolvedDependencyType;
const coreR3ResolvedDependencyType2: R3ResolvedDependencyType =
null !as core.R3ResolvedDependencyType;
const compilerR3ResolvedDependencyType2: R3ResolvedDependencyType =
null !as core.R3ResolvedDependencyType;
const coreR3ResolvedDependencyType3: core.R3ResolvedDependencyType =
null !as R3ResolvedDependencyType;
const compilerR3ResolvedDependencyType3: compiler.R3ResolvedDependencyType =
null !as R3ResolvedDependencyType;
const coreR3DependencyMetadataFacade: core.R3DependencyMetadataFacade =
null !as compiler.R3DependencyMetadataFacade;
const compilerR3DependencyMetadataFacade: compiler.R3DependencyMetadataFacade =
null !as core.R3DependencyMetadataFacade;
const coreR3PipeMetadataFacade: core.R3PipeMetadataFacade = null !as compiler.R3PipeMetadataFacade;
const compilerR3PipeMetadataFacade: compiler.R3PipeMetadataFacade =
null !as core.R3PipeMetadataFacade;
const coreR3InjectableMetadataFacade: core.R3InjectableMetadataFacade =
null !as compiler.R3InjectableMetadataFacade;
const compilerR3InjectableMetadataFacade: compiler.R3InjectableMetadataFacade =
null !as core.R3InjectableMetadataFacade;
const coreR3NgModuleMetadataFacade: core.R3NgModuleMetadataFacade =
null !as compiler.R3NgModuleMetadataFacade;
const compilerR3NgModuleMetadataFacade: compiler.R3NgModuleMetadataFacade =
null !as core.R3NgModuleMetadataFacade;
const coreR3InjectorMetadataFacade: core.R3InjectorMetadataFacade =
null !as compiler.R3InjectorMetadataFacade;
const compilerR3InjectorMetadataFacade: compiler.R3InjectorMetadataFacade =
null !as core.R3InjectorMetadataFacade;
const coreR3DirectiveMetadataFacade: core.R3DirectiveMetadataFacade =
null !as compiler.R3DirectiveMetadataFacade;
const compilerR3DirectiveMetadataFacade: compiler.R3DirectiveMetadataFacade =
null !as core.R3DirectiveMetadataFacade;
const coreR3ComponentMetadataFacade: core.R3ComponentMetadataFacade =
null !as compiler.R3ComponentMetadataFacade;
const compilerR3ComponentMetadataFacade: compiler.R3ComponentMetadataFacade =
null !as core.R3ComponentMetadataFacade;
const coreViewEncapsulation: core.ViewEncapsulation = null !as compiler.ViewEncapsulation;
const compilerViewEncapsulation: compiler.ViewEncapsulation = null !as core.ViewEncapsulation;
const coreR3QueryMetadataFacade: core.R3QueryMetadataFacade =
null !as compiler.R3QueryMetadataFacade;
const compilerR3QueryMetadataFacade: compiler.R3QueryMetadataFacade =
null !as core.R3QueryMetadataFacade;

View File

@ -13,7 +13,6 @@ ng_module(
module_name = "@angular/core",
deps = [
"//packages:types",
"//packages/compiler",
"@ngdeps//zone.js",
"@rxjs",
"@rxjs//operators",

View File

@ -16,7 +16,6 @@
"tslib": "^1.9.0"
},
"peerDependencies": {
"@angular/compiler": "0.0.0-PLACEHOLDER",
"rxjs": "^6.0.0",
"zone.js": "~0.8.26"
},

View File

@ -480,6 +480,7 @@ export function getNodeInjectable(
*/
export function bloomHashBitOrFactory(token: Type<any>| InjectionToken<any>): number|Function|
undefined {
ngDevMode && assertDefined(token, 'token must be defined');
const tokenId: number|undefined = (token as any)[NG_ELEMENT_ID];
return typeof tokenId === 'number' ? tokenId & BLOOM_MASK : tokenId;
}

View File

@ -0,0 +1,22 @@
/**
* @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 {global} from '../../util';
import {CompilerFacade, ExportedCompilerFacade} from './compiler_facade_interface';
export * from './compiler_facade_interface';
export function getCompilerFacade(): CompilerFacade {
const globalNg: ExportedCompilerFacade = global.ng;
if (!globalNg || !globalNg.ɵcompilerFacade) {
throw new Error(
`Angular JIT compilation failed: '@angular/compiler' not loaded!\n` +
` - JIT compilation is discouraged for production use-cases! Consider AOT mode instead.\n` +
` - Did you bootstrap using '@angular/platform-browser-dynamic' or '@angular/platform-server'?\n` +
` - Alternatively provide the compiler with 'import "@angular/compiler";' before bootstrapping.`);
}
return globalNg.ɵcompilerFacade;
}

View File

@ -0,0 +1,145 @@
/**
* @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
*/
/**
* A set of interfaces which are shared between `@angular/core` and `@angular/compiler` to allow
* for late binding of `@angular/compiler` for JIT purposes.
*
* This file has two copies. Please ensure that they are in sync:
* - packages/compiler/src/compiler_facade_interface.ts (master)
* - packages/core/src/render3/jit/compiler_facade_interface.ts (copy)
*
* Please ensure that the two files are in sync using this command:
* ```
* cp packages/compiler/src/compiler_facade_interface.ts \
* packages/core/src/render3/jit/compiler_facade_interface.ts
* ```
*/
export interface ExportedCompilerFacade { ɵcompilerFacade: CompilerFacade; }
export interface CompilerFacade {
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3PipeMetadataFacade):
any;
compileInjectable(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectableMetadataFacade): any;
compileInjector(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectorMetadataFacade): any;
compileNgModule(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3NgModuleMetadataFacade): any;
compileDirective(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3DirectiveMetadataFacade): any;
compileComponent(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any;
R3ResolvedDependencyType: typeof R3ResolvedDependencyType;
}
export interface CoreEnvironment { [name: string]: Function; }
export type StringMap = {
[key: string]: string;
};
export type StringMapWithRename = {
[key: string]: string | [string, string];
};
export type Provider = any;
export enum R3ResolvedDependencyType {
Token = 0,
Attribute = 1,
}
export interface R3DependencyMetadataFacade {
token: any;
resolved: R3ResolvedDependencyType;
host: boolean;
optional: boolean;
self: boolean;
skipSelf: boolean;
}
export interface R3PipeMetadataFacade {
name: string;
type: any;
pipeName: string;
deps: R3DependencyMetadataFacade[]|null;
pure: boolean;
}
export interface R3InjectableMetadataFacade {
name: string;
type: any;
ctorDeps: R3DependencyMetadataFacade[]|null;
providedIn: any;
useClass?: any;
useFactory?: any;
useExisting?: any;
useValue?: any;
userDeps?: R3DependencyMetadataFacade[];
}
export interface R3NgModuleMetadataFacade {
type: any;
bootstrap: Function[];
declarations: Function[];
imports: Function[];
exports: Function[];
emitInline: boolean;
}
export interface R3InjectorMetadataFacade {
name: string;
type: any;
deps: R3DependencyMetadataFacade[]|null;
providers: any;
imports: any;
}
export interface R3DirectiveMetadataFacade {
name: string;
type: any;
typeArgumentCount: number;
typeSourceSpan: null;
deps: R3DependencyMetadataFacade[]|null;
selector: string|null;
queries: R3QueryMetadataFacade[];
host: {[key: string]: string};
propMetadata: {[key: string]: any[]};
lifecycle: {usesOnChanges: boolean;};
inputs: string[];
outputs: string[];
usesInheritance: boolean;
exportAs: string|null;
providers: Provider[]|null;
}
export interface R3ComponentMetadataFacade extends R3DirectiveMetadataFacade {
template: string;
preserveWhitespaces: boolean;
animations: any[]|undefined;
viewQueries: R3QueryMetadataFacade[];
pipes: Map<string, any>;
directives: Map<string, any>;
styles: string[];
encapsulation: ViewEncapsulation;
viewProviders: Provider[]|null;
}
export type ViewEncapsulation = number;
export interface R3QueryMetadataFacade {
propertyName: string;
first: boolean;
predicate: any|string[];
descendants: boolean;
read: any|null;
}

View File

@ -6,23 +6,22 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ConstantPool, Expression, R3DirectiveMetadata, R3QueryMetadata, WrappedNodeExpr, compileComponentFromMetadata as compileR3Component, compileDirectiveFromMetadata as compileR3Directive, jitExpression, makeBindingParser, parseHostBindings, parseTemplate} from '@angular/compiler';
import {Query} from '../../metadata/di';
import {Component, Directive, HostBinding, HostListener, Input, Output} from '../../metadata/directives';
import {Component, Directive} from '../../metadata/directives';
import {componentNeedsResolution, maybeQueueResolutionOfComponentResources} from '../../metadata/resource_loading';
import {ViewEncapsulation} from '../../metadata/view';
import {Type} from '../../type';
import {stringify} from '../../util';
import {EMPTY_ARRAY} from '../definition';
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF} from '../fields';
import {R3DirectiveMetadataFacade, getCompilerFacade} from './compiler_facade';
import {R3ComponentMetadataFacade, R3QueryMetadataFacade} from './compiler_facade_interface';
import {angularCoreEnv} from './environment';
import {patchComponentDefWithScope, transitiveScopesFor} from './module';
import {getReflect, reflectDependencies} from './util';
type StringMap = {
[key: string]: string
};
/**
* Compile an Angular component according to its decorator metadata, and patch the resulting
@ -39,6 +38,7 @@ export function compileComponent(type: Type<any>, metadata: Component): void {
maybeQueueResolutionOfComponentResources(metadata);
Object.defineProperty(type, NG_COMPONENT_DEF, {
get: () => {
const compiler = getCompilerFacade();
if (ngComponentDef === null) {
if (componentNeedsResolution(metadata)) {
const error = [`Component '${stringify(type)}' is not resolved:`];
@ -51,43 +51,20 @@ export function compileComponent(type: Type<any>, metadata: Component): void {
error.push(`Did you run and wait for 'resolveComponentResources()'?`);
throw new Error(error.join('\n'));
}
// The ConstantPool is a requirement of the JIT'er.
const constantPool = new ConstantPool();
// Parse the template and check for errors.
const template = parseTemplate(
metadata.template !, `ng://${stringify(type)}/template.html`, {
preserveWhitespaces: metadata.preserveWhitespaces || false,
},
'');
if (template.errors !== undefined) {
const errors = template.errors.map(err => err.toString()).join(', ');
throw new Error(
`Errors during JIT compilation of template for ${stringify(type)}: ${errors}`);
}
const animations =
metadata.animations !== null ? new WrappedNodeExpr(metadata.animations) : null;
// Compile the component metadata, including template, into an expression.
const res = compileR3Component(
{
const meta: R3ComponentMetadataFacade = {
...directiveMetadata(type, metadata),
template,
template: metadata.template || '',
preserveWhitespaces: metadata.preserveWhitespaces || false,
styles: metadata.styles || EMPTY_ARRAY,
animations: metadata.animations,
viewQueries: extractQueriesMetadata(getReflect().propMetadata(type), isViewQuery),
directives: new Map(),
pipes: new Map(),
viewQueries: extractQueriesMetadata(getReflect().propMetadata(type), isViewQuery),
wrapDirectivesAndPipesInClosure: false,
styles: metadata.styles || [],
encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated, animations,
viewProviders: metadata.viewProviders ? new WrappedNodeExpr(metadata.viewProviders) :
null
},
constantPool, makeBindingParser());
const preStatements = [...constantPool.statements, ...res.statements];
ngComponentDef = jitExpression(
res.expression, angularCoreEnv, `ng://${type.name}/ngComponentDef.js`, preStatements);
encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated,
viewProviders: metadata.viewProviders || null,
};
ngComponentDef = compiler.compileComponent(
angularCoreEnv, `ng://${stringify(type)}/template.html`, meta);
// If component compilation is async, then the @NgModule annotation which declares the
// component may execute and set an ngSelectorScope property on the component type. This
@ -122,12 +99,9 @@ export function compileDirective(type: Type<any>, directive: Directive): void {
Object.defineProperty(type, NG_DIRECTIVE_DEF, {
get: () => {
if (ngDirectiveDef === null) {
const constantPool = new ConstantPool();
const sourceMapUrl = `ng://${type && type.name}/ngDirectiveDef.js`;
const res = compileR3Directive(
directiveMetadata(type, directive), constantPool, makeBindingParser());
const preStatements = [...constantPool.statements, ...res.statements];
ngDirectiveDef = jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
const facade = directiveMetadata(type, directive);
ngDirectiveDef = getCompilerFacade().compileDirective(
angularCoreEnv, `ng://${type && type.name}/ngDirectiveDef.js`, facade);
}
return ngDirectiveDef;
},
@ -144,38 +118,20 @@ export function extendsDirectlyFromObject(type: Type<any>): boolean {
* Extract the `R3DirectiveMetadata` for a particular directive (either a `Directive` or a
* `Component`).
*/
function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMetadata {
function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMetadataFacade {
// Reflect inputs and outputs.
const propMetadata = getReflect().propMetadata(type);
const host = extractHostBindings(metadata, propMetadata);
const inputsFromMetadata = parseInputOutputs(metadata.inputs || []);
const outputsFromMetadata = parseInputOutputs(metadata.outputs || []);
const inputsFromType: {[key: string]: string | string[]} = {};
const outputsFromType: StringMap = {};
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
if (isInput(ann)) {
inputsFromType[field] =
ann.bindingPropertyName ? [ann.bindingPropertyName, field] : field;
} else if (isOutput(ann)) {
outputsFromType[field] = ann.bindingPropertyName || field;
}
});
}
}
return {
name: type.name,
type: new WrappedNodeExpr(type),
type: type,
typeArgumentCount: 0,
selector: metadata.selector !,
deps: reflectDependencies(type), host,
inputs: {...inputsFromMetadata, ...inputsFromType},
outputs: {...outputsFromMetadata, ...outputsFromType},
deps: reflectDependencies(type),
host: metadata.host || EMPTY_OBJ,
propMetadata: propMetadata,
inputs: metadata.inputs || EMPTY_ARRAY,
outputs: metadata.outputs || EMPTY_ARRAY,
queries: extractQueriesMetadata(propMetadata, isContentQuery),
lifecycle: {
usesOnChanges: type.prototype.ngOnChanges !== undefined,
@ -183,57 +139,29 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
typeSourceSpan: null !,
usesInheritance: !extendsDirectlyFromObject(type),
exportAs: metadata.exportAs || null,
providers: metadata.providers ? new WrappedNodeExpr(metadata.providers) : null
providers: metadata.providers || null,
};
}
function extractHostBindings(metadata: Directive, propMetadata: {[key: string]: any[]}): {
attributes: StringMap,
listeners: StringMap,
properties: StringMap,
} {
// First parse the declarations from the metadata.
const {attributes, listeners, properties, animations} = parseHostBindings(metadata.host || {});
const EMPTY_OBJ = {};
if (Object.keys(animations).length > 0) {
throw new Error(`Animation bindings are as-of-yet unsupported in Ivy`);
}
// Next, loop over the properties of the object, looking for @HostBinding and @HostListener.
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
if (isHostBinding(ann)) {
properties[ann.hostPropertyName || field] = field;
} else if (isHostListener(ann)) {
listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
}
});
}
}
return {attributes, listeners, properties};
function convertToR3QueryPredicate(selector: any): any|string[] {
return typeof selector === 'string' ? splitByComma(selector) : selector;
}
function convertToR3QueryPredicate(selector: any): Expression|string[] {
return typeof selector === 'string' ? splitByComma(selector) : new WrappedNodeExpr(selector);
}
export function convertToR3QueryMetadata(propertyName: string, ann: Query): R3QueryMetadata {
export function convertToR3QueryMetadata(propertyName: string, ann: Query): R3QueryMetadataFacade {
return {
propertyName: propertyName,
predicate: convertToR3QueryPredicate(ann.selector),
descendants: ann.descendants,
first: ann.first,
read: ann.read ? new WrappedNodeExpr(ann.read) : null
read: ann.read ? ann.read : null
};
}
function extractQueriesMetadata(
propMetadata: {[key: string]: any[]},
isQueryAnn: (ann: any) => ann is Query): R3QueryMetadata[] {
const queriesMeta: R3QueryMetadata[] = [];
isQueryAnn: (ann: any) => ann is Query): R3QueryMetadataFacade[] {
const queriesMeta: R3QueryMetadataFacade[] = [];
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
@ -243,26 +171,9 @@ function extractQueriesMetadata(
});
}
}
return queriesMeta;
}
function isInput(value: any): value is Input {
return value.ngMetadataName === 'Input';
}
function isOutput(value: any): value is Output {
return value.ngMetadataName === 'Output';
}
function isHostBinding(value: any): value is HostBinding {
return value.ngMetadataName === 'HostBinding';
}
function isHostListener(value: any): value is HostListener {
return value.ngMetadataName === 'HostListener';
}
function isContentQuery(value: any): value is Query {
const name = value.ngMetadataName;
return name === 'ContentChild' || name === 'ContentChildren';
@ -276,13 +187,3 @@ function isViewQuery(value: any): value is Query {
function splitByComma(value: string): string[] {
return value.split(',').map(piece => piece.trim());
}
function parseInputOutputs(values: string[]): StringMap {
return values.reduce(
(map, value) => {
const [field, property] = splitByComma(value);
map[field] = property || field;
return map;
},
{} as StringMap);
}

View File

@ -6,14 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Expression, LiteralExpr, R3DependencyMetadata, R3InjectableMetadata, WrappedNodeExpr, compileInjectable as compileR3Injectable, jitExpression} from '@angular/compiler';
import {Injectable} from '../../di/injectable';
import {ClassSansProvider, ExistingSansProvider, FactorySansProvider, StaticClassSansProvider, ValueProvider, ValueSansProvider} from '../../di/provider';
import {ClassSansProvider, ExistingSansProvider, FactorySansProvider, ValueProvider, ValueSansProvider} from '../../di/provider';
import {Type} from '../../type';
import {getClosureSafeProperty} from '../../util/property';
import {NG_INJECTABLE_DEF} from '../fields';
import {R3InjectableMetadataFacade, getCompilerFacade} from './compiler_facade';
import {angularCoreEnv} from './environment';
import {convertDependencies, reflectDependencies} from './util';
@ -31,84 +30,60 @@ export function compileInjectable(type: Type<any>, srcMeta?: Injectable): void {
Object.defineProperty(type, NG_INJECTABLE_DEF, {
get: () => {
if (def === null) {
// Check whether the injectable metadata includes a provider specification.
const meta: Injectable = srcMeta || {providedIn: null};
const hasAProvider = isUseClassProvider(meta) || isUseFactoryProvider(meta) ||
isUseValueProvider(meta) || isUseExistingProvider(meta);
const ctorDeps = reflectDependencies(type);
let userDeps: R3DependencyMetadata[]|undefined = undefined;
const compilerMeta: R3InjectableMetadataFacade = {
name: type.name,
type: type,
providedIn: meta.providedIn,
ctorDeps: reflectDependencies(type),
userDeps: undefined
};
if ((isUseClassProvider(meta) || isUseFactoryProvider(meta)) && meta.deps !== undefined) {
userDeps = convertDependencies(meta.deps);
compilerMeta.userDeps = convertDependencies(meta.deps);
}
// Decide which flavor of factory to generate, based on the provider specified.
// Only one of the use* fields should be set.
let useClass: Expression|undefined = undefined;
let useFactory: Expression|undefined = undefined;
let useValue: Expression|undefined = undefined;
let useExisting: Expression|undefined = undefined;
if (!hasAProvider) {
// In the case the user specifies a type provider, treat it as {provide: X, useClass: X}.
// The deps will have been reflected above, causing the factory to create the class by
// calling
// its constructor with injected deps.
useClass = new WrappedNodeExpr(type);
compilerMeta.useClass = type;
} else if (isUseClassProvider(meta)) {
// The user explicitly specified useClass, and may or may not have provided deps.
useClass = new WrappedNodeExpr(meta.useClass);
compilerMeta.useClass = meta.useClass;
} else if (isUseValueProvider(meta)) {
// The user explicitly specified useValue.
useValue = new WrappedNodeExpr(meta.useValue);
compilerMeta.useValue = meta.useValue;
} else if (isUseFactoryProvider(meta)) {
// The user explicitly specified useFactory.
useFactory = new WrappedNodeExpr(meta.useFactory);
compilerMeta.useFactory = meta.useFactory;
} else if (isUseExistingProvider(meta)) {
// The user explicitly specified useExisting.
useExisting = new WrappedNodeExpr(meta.useExisting);
compilerMeta.useExisting = meta.useExisting;
} else {
// Can't happen - either hasAProvider will be false, or one of the providers will be set.
throw new Error(`Unreachable state.`);
}
const {expression, statements} = compileR3Injectable({
name: type.name,
type: new WrappedNodeExpr(type),
providedIn: computeProvidedIn(meta.providedIn),
useClass,
useFactory,
useValue,
useExisting,
ctorDeps,
userDeps,
});
def = jitExpression(
expression, angularCoreEnv, `ng://${type.name}/ngInjectableDef.js`, statements);
def = getCompilerFacade().compileInjectable(
angularCoreEnv, `ng://${type.name}/ngInjectableDef.js`, compilerMeta);
}
return def;
},
});
}
function computeProvidedIn(providedIn: Type<any>| string | null | undefined): Expression {
if (providedIn == null || typeof providedIn === 'string') {
return new LiteralExpr(providedIn);
} else {
return new WrappedNodeExpr(providedIn);
}
}
type UseClassProvider = Injectable & ClassSansProvider & {deps?: any[]};
const USE_VALUE =
getClosureSafeProperty<ValueProvider>({provide: String, useValue: getClosureSafeProperty});
function isUseClassProvider(meta: Injectable): meta is UseClassProvider {
return (meta as UseClassProvider).useClass !== undefined;
}
const USE_VALUE =
getClosureSafeProperty<ValueProvider>({provide: String, useValue: getClosureSafeProperty});
function isUseValueProvider(meta: Injectable): meta is Injectable&ValueSansProvider {
return USE_VALUE in meta;
}

View File

@ -6,14 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Expression, R3InjectorMetadata, R3NgModuleMetadata, R3Reference, WrappedNodeExpr, compileInjector, compileNgModule as compileR3NgModule, jitExpression} from '@angular/compiler';
import {ModuleWithProviders, NgModule, NgModuleDef, NgModuleTransitiveScopes} from '../../metadata/ng_module';
import {Type} from '../../type';
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';
import {R3InjectorMetadataFacade, getCompilerFacade} from './compiler_facade';
import {angularCoreEnv} from './environment';
import {reflectDependencies} from './util';
@ -37,48 +36,39 @@ export function compileNgModuleDefs(moduleType: Type<any>, ngModule: NgModule):
let ngModuleDef: any = null;
Object.defineProperty(moduleType, NG_MODULE_DEF, {
configurable: true,
get: () => {
if (ngModuleDef === null) {
const meta: R3NgModuleMetadata = {
type: wrap(moduleType),
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(wrapReference),
declarations: declarations.map(wrapReference),
imports: flatten(ngModule.imports || EMPTY_ARRAY)
.map(expandModuleWithProviders)
.map(wrapReference),
exports: flatten(ngModule.exports || EMPTY_ARRAY)
.map(expandModuleWithProviders)
.map(wrapReference),
ngModuleDef = getCompilerFacade().compileNgModule(
angularCoreEnv, `ng://${moduleType.name}/ngModuleDef.js`, {
type: moduleType,
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY),
declarations: declarations,
imports: flatten(ngModule.imports || EMPTY_ARRAY).map(expandModuleWithProviders),
exports: flatten(ngModule.exports || EMPTY_ARRAY).map(expandModuleWithProviders),
emitInline: true,
};
const res = compileR3NgModule(meta);
ngModuleDef = jitExpression(
res.expression, angularCoreEnv, `ng://${moduleType.name}/ngModuleDef.js`, []);
});
}
return ngModuleDef;
},
// Make the property configurable in dev mode to allow overriding in tests
configurable: !!ngDevMode,
}
});
let ngInjectorDef: any = null;
Object.defineProperty(moduleType, NG_INJECTOR_DEF, {
get: () => {
if (ngInjectorDef === null) {
const meta: R3InjectorMetadata = {
const meta: R3InjectorMetadataFacade = {
name: moduleType.name,
type: wrap(moduleType),
type: moduleType,
deps: reflectDependencies(moduleType),
providers: new WrappedNodeExpr(ngModule.providers || EMPTY_ARRAY),
imports: new WrappedNodeExpr([
providers: ngModule.providers || EMPTY_ARRAY,
imports: [
ngModule.imports || EMPTY_ARRAY,
ngModule.exports || EMPTY_ARRAY,
]),
],
};
const res = compileInjector(meta);
ngInjectorDef = jitExpression(
res.expression, angularCoreEnv, `ng://${moduleType.name}/ngInjectorDef.js`,
res.statements);
ngInjectorDef = getCompilerFacade().compileInjector(
angularCoreEnv, `ng://${moduleType.name}/ngInjectorDef.js`, meta);
}
return ngInjectorDef;
},
@ -235,15 +225,6 @@ function expandModuleWithProviders(value: Type<any>| ModuleWithProviders<{}>): T
return value;
}
function wrap(value: Type<any>): Expression {
return new WrappedNodeExpr(value);
}
function wrapReference(value: Type<any>): R3Reference {
const wrapped = wrap(value);
return {value: wrapped, type: wrapped};
}
function isModuleWithProviders(value: any): value is ModuleWithProviders<{}> {
return (value as{ngModule?: any}).ngModule !== undefined;
}

View File

@ -6,13 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {WrappedNodeExpr, compilePipeFromMetadata, jitExpression} from '@angular/compiler';
import {Pipe} from '../../metadata/directives';
import {Type} from '../../type';
import {NG_PIPE_DEF} from '../fields';
import {stringify} from '../util';
import {getCompilerFacade} from './compiler_facade';
import {angularCoreEnv} from './environment';
import {reflectDependencies} from './util';
@ -21,18 +20,14 @@ export function compilePipe(type: Type<any>, meta: Pipe): void {
Object.defineProperty(type, NG_PIPE_DEF, {
get: () => {
if (ngPipeDef === null) {
const sourceMapUrl = `ng://${stringify(type)}/ngPipeDef.js`;
const name = type.name;
const res = compilePipeFromMetadata({
name,
type: new WrappedNodeExpr(type),
ngPipeDef = getCompilerFacade().compilePipe(
angularCoreEnv, `ng://${stringify(type)}/ngPipeDef.js`, {
type: type,
name: type.name,
deps: reflectDependencies(type),
pipeName: meta.name,
pure: meta.pure !== undefined ? meta.pure : true,
pure: meta.pure !== undefined ? meta.pure : true
});
ngPipeDef = jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
}
return ngPipeDef;
},

View File

@ -6,44 +6,41 @@
* found in the LICENSE file at https://angular.io/license
*/
import {LiteralExpr, R3DependencyMetadata, R3ResolvedDependencyType, WrappedNodeExpr} from '@angular/compiler';
import {Injector} from '../../di/injector';
import {Host, Inject, Optional, Self, SkipSelf} from '../../di/metadata';
import {ElementRef} from '../../linker/element_ref';
import {TemplateRef} from '../../linker/template_ref';
import {ViewContainerRef} from '../../linker/view_container_ref';
import {Attribute} from '../../metadata/di';
import {ReflectionCapabilities} from '../../reflection/reflection_capabilities';
import {Type} from '../../type';
import {CompilerFacade, R3DependencyMetadataFacade, getCompilerFacade} from './compiler_facade';
let _reflect: ReflectionCapabilities|null = null;
export function getReflect(): ReflectionCapabilities {
return (_reflect = _reflect || new ReflectionCapabilities());
}
export function reflectDependencies(type: Type<any>): R3DependencyMetadata[] {
export function reflectDependencies(type: Type<any>): R3DependencyMetadataFacade[] {
return convertDependencies(getReflect().parameters(type));
}
export function convertDependencies(deps: any[]): R3DependencyMetadata[] {
return deps.map(dep => reflectDependency(dep));
export function convertDependencies(deps: any[]): R3DependencyMetadataFacade[] {
const compiler = getCompilerFacade();
return deps.map(dep => reflectDependency(compiler, dep));
}
function reflectDependency(dep: any | any[]): R3DependencyMetadata {
const meta: R3DependencyMetadata = {
token: new LiteralExpr(null),
function reflectDependency(compiler: CompilerFacade, dep: any | any[]): R3DependencyMetadataFacade {
const meta: R3DependencyMetadataFacade = {
token: null,
host: false,
optional: false,
resolved: R3ResolvedDependencyType.Token,
resolved: compiler.R3ResolvedDependencyType.Token,
self: false,
skipSelf: false,
};
function setTokenAndResolvedType(token: any): void {
meta.resolved = R3ResolvedDependencyType.Token;
meta.token = new WrappedNodeExpr(token);
meta.resolved = compiler.R3ResolvedDependencyType.Token;
meta.token = token;
}
if (Array.isArray(dep)) {
@ -61,13 +58,13 @@ function reflectDependency(dep: any | any[]): R3DependencyMetadata {
} else if (param instanceof Host || param.__proto__.ngMetadataName === 'Host') {
meta.host = true;
} else if (param instanceof Inject) {
meta.token = new WrappedNodeExpr(param.token);
meta.token = param.token;
} else if (param instanceof Attribute) {
if (param.attributeName === undefined) {
throw new Error(`Attribute name must be defined.`);
}
meta.token = new LiteralExpr(param.attributeName);
meta.resolved = R3ResolvedDependencyType.Attribute;
meta.token = param.attributeName;
meta.resolved = compiler.R3ResolvedDependencyType.Attribute;
} else {
setTokenAndResolvedType(param);
}

View File

@ -54,7 +54,7 @@
"name": "EMPTY_ARR"
},
{
"name": "EMPTY_ARRAY$1"
"name": "EMPTY_ARRAY"
},
{
"name": "EMPTY_OBJ"
@ -216,7 +216,7 @@
"name": "ViewContainerRef"
},
{
"name": "ViewEncapsulation$1"
"name": "ViewEncapsulation"
},
{
"name": "ViewRef"
@ -396,7 +396,7 @@
"name": "createNodeAtIndex"
},
{
"name": "createOutput$1"
"name": "createOutput"
},
{
"name": "createRootComponent"
@ -1122,10 +1122,10 @@
"name": "storeCleanupWithContext"
},
{
"name": "stringify$1"
"name": "stringify"
},
{
"name": "stringify$2"
"name": "stringify$1"
},
{
"name": "swapMultiContextEntries"

View File

@ -45,6 +45,7 @@ ts_library(
],
deps = [
"//packages:types",
"//packages/compiler",
"//packages/core/testing",
"//packages/private/testing",
],

View File

@ -27,7 +27,7 @@
"name": "EMPTY"
},
{
"name": "EMPTY_ARRAY$1"
"name": "EMPTY_ARRAY"
},
{
"name": "EmptyErrorImpl"
@ -117,7 +117,7 @@
"name": "VIEWS"
},
{
"name": "ViewEncapsulation$1"
"name": "ViewEncapsulation"
},
{
"name": "_renderCompCount"
@ -438,7 +438,7 @@
"name": "setUpAttributes"
},
{
"name": "stringify$2"
"name": "stringify$1"
},
{
"name": "syncViewWithBlueprint"

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import '@angular/compiler';
import {withBody} from '@angular/private/testing';
import * as fs from 'fs';
import * as path from 'path';

View File

@ -47,6 +47,7 @@ ts_library(
],
deps = [
"//packages:types",
"//packages/compiler",
"//packages/core/testing",
"//packages/private/testing",
],

View File

@ -240,7 +240,7 @@
"name": "BINDING_INDEX"
},
{
"name": "BIND_NAME_REGEXP"
"name": "BIND_NAME_REGEXP$1"
},
{
"name": "BLOCK_PLACEHOLDER"
@ -813,16 +813,16 @@
"name": "IDENT"
},
{
"name": "IDENT_BANANA_BOX_IDX"
"name": "IDENT_BANANA_BOX_IDX$1"
},
{
"name": "IDENT_EVENT_IDX"
"name": "IDENT_EVENT_IDX$1"
},
{
"name": "IDENT_KW_IDX"
"name": "IDENT_KW_IDX$1"
},
{
"name": "IDENT_PROPERTY_IDX"
"name": "IDENT_PROPERTY_IDX$1"
},
{
"name": "ID_SEPARATOR"
@ -939,22 +939,22 @@
"name": "KEY_CONTEXT"
},
{
"name": "KW_AT_IDX"
"name": "KW_AT_IDX$1"
},
{
"name": "KW_BINDON_IDX"
"name": "KW_BINDON_IDX$1"
},
{
"name": "KW_BIND_IDX"
"name": "KW_BIND_IDX$1"
},
{
"name": "KW_LET_IDX"
"name": "KW_LET_IDX$1"
},
{
"name": "KW_ON_IDX"
"name": "KW_ON_IDX$1"
},
{
"name": "KW_REF_IDX"
"name": "KW_REF_IDX$1"
},
{
"name": "KeyVisitor"
@ -1116,7 +1116,7 @@
"name": "NG_TOKEN_PATH"
},
{
"name": "NON_BINDABLE_VISITOR"
"name": "NON_BINDABLE_VISITOR$1"
},
{
"name": "NOOP"
@ -1209,7 +1209,7 @@
"name": "NodeInjectorFactory"
},
{
"name": "NonBindableVisitor"
"name": "NonBindableVisitor$1"
},
{
"name": "NonNullAssert"
@ -1410,7 +1410,7 @@
"name": "RecurseVisitor"
},
{
"name": "RecursiveAstVisitor"
"name": "RecursiveAstVisitor$1"
},
{
"name": "RefCountOperator"
@ -1629,7 +1629,7 @@
"name": "TAIL"
},
{
"name": "TEMPLATE_ATTR_PREFIX"
"name": "TEMPLATE_ATTR_PREFIX$1"
},
{
"name": "TEXT_CSS_SELECTOR"
@ -1704,10 +1704,10 @@
"name": "Text"
},
{
"name": "Text$1"
"name": "Text$2"
},
{
"name": "Text$2"
"name": "Text$3"
},
{
"name": "TextAst"
@ -1770,7 +1770,7 @@
"name": "URL_WITH_SCHEMA_REGEXP"
},
{
"name": "USE_VALUE$1"
"name": "USE_VALUE$2"
},
{
"name": "UnsubscriptionError"
@ -1782,7 +1782,7 @@
"name": "UrlResolver"
},
{
"name": "VERSION$1"
"name": "VERSION"
},
{
"name": "VERSION$2"
@ -2151,7 +2151,7 @@
"name": "__read"
},
{
"name": "__self"
"name": "__self$1"
},
{
"name": "__spread"
@ -2163,7 +2163,7 @@
"name": "__values"
},
{
"name": "__window"
"name": "__window$1"
},
{
"name": "_addDebugContext"
@ -2283,7 +2283,7 @@
"name": "_getViewQueries"
},
{
"name": "_global"
"name": "_global$1"
},
{
"name": "_isClosingComment"

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import '@angular/compiler';
import * as fs from 'fs';
import * as path from 'path';

View File

@ -48,6 +48,7 @@ ts_library(
deps = [
":injection",
"//packages:types",
"//packages/compiler",
"//packages/core/testing",
"//packages/private/testing",
],

View File

@ -6,7 +6,7 @@
"name": "CIRCULAR$1"
},
{
"name": "EMPTY_ARRAY$2"
"name": "EMPTY_ARRAY$1"
},
{
"name": "EmptyErrorImpl"
@ -60,7 +60,7 @@
"name": "THROW_IF_NOT_FOUND"
},
{
"name": "USE_VALUE$1"
"name": "USE_VALUE"
},
{
"name": "UnsubscriptionErrorImpl"
@ -159,12 +159,12 @@
"name": "providerToRecord"
},
{
"name": "resolveForwardRef$1"
"name": "resolveForwardRef"
},
{
"name": "setCurrentInjector"
},
{
"name": "stringify$1"
"name": "stringify"
}
]

View File

@ -6,15 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as fs from 'fs';
import * as path from 'path';
import '@angular/compiler';
import {INJECTOR, ScopedService} from './usage';
const UTF8 = {
encoding: 'utf-8'
};
const PACKAGE = 'angular/packages/core/test/bundling/hello_world';
describe('functional test for injection system bundling', () => {
it('should be able to inject the scoped service',

View File

@ -50,6 +50,7 @@ ts_library(
],
deps = [
"//packages:types",
"//packages/compiler",
"//packages/core",
"//packages/core/testing",
"//packages/private/testing",

View File

@ -45,7 +45,7 @@
"name": "EMPTY"
},
{
"name": "EMPTY_ARRAY$1"
"name": "EMPTY_ARRAY"
},
{
"name": "ElementRef"
@ -231,7 +231,7 @@
"name": "ViewContainerRef"
},
{
"name": "ViewEncapsulation$1"
"name": "ViewEncapsulation"
},
{
"name": "ViewRef"
@ -453,7 +453,7 @@
"name": "createNodeAtIndex"
},
{
"name": "createOutput$1"
"name": "createOutput"
},
{
"name": "createRootComponent"
@ -1143,10 +1143,10 @@
"name": "storeCleanupWithContext"
},
{
"name": "stringify$1"
"name": "stringify"
},
{
"name": "stringify$2"
"name": "stringify$1"
},
{
"name": "syncViewWithBlueprint"

View File

@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import '@angular/compiler';
import {ɵwhenRendered as whenRendered} from '@angular/core';
import {withBody} from '@angular/private/testing';
import * as fs from 'fs';
import * as path from 'path';
const UTF8 = {

View File

@ -54,6 +54,7 @@ ts_library(
],
deps = [
"//packages:types",
"//packages/compiler",
"//packages/core",
"//packages/core/testing",
"//packages/platform-browser",

View File

@ -99,13 +99,13 @@
"name": "COMPONENT_REGEX"
},
{
"name": "COMPONENT_VARIABLE$1"
"name": "COMPONENT_VARIABLE"
},
{
"name": "CONTAINER_INDEX"
},
{
"name": "CONTENT_ATTR$1"
"name": "CONTENT_ATTR"
},
{
"name": "CONTEXT"
@ -252,10 +252,10 @@
"name": "EMPTY$1"
},
{
"name": "EMPTY_ARRAY$1"
"name": "EMPTY_ARRAY"
},
{
"name": "EMPTY_ARRAY$2"
"name": "EMPTY_ARRAY$1"
},
{
"name": "EMPTY_PAYLOAD"
@ -330,7 +330,7 @@
"name": "HOST"
},
{
"name": "HOST_ATTR$1"
"name": "HOST_ATTR"
},
{
"name": "HOST_NODE"
@ -792,7 +792,7 @@
"name": "SanitizingHtmlSerializer"
},
{
"name": "SecurityContext$1"
"name": "SecurityContext"
},
{
"name": "Self"
@ -906,7 +906,7 @@
"name": "URL_RE"
},
{
"name": "USE_VALUE$1"
"name": "USE_VALUE"
},
{
"name": "UnsubscriptionError"
@ -930,13 +930,13 @@
"name": "VOID_ELEMENTS"
},
{
"name": "Version$1"
"name": "Version"
},
{
"name": "ViewContainerRef"
},
{
"name": "ViewEncapsulation$1"
"name": "ViewEncapsulation"
},
{
"name": "ViewRef"
@ -1341,7 +1341,7 @@
"name": "createNodeAtIndex"
},
{
"name": "createOutput$1"
"name": "createOutput"
},
{
"name": "createPlatform"
@ -2118,10 +2118,10 @@
"name": "isProceduralRenderer"
},
{
"name": "isPromise$1"
"name": "isPromise"
},
{
"name": "isPromise$2"
"name": "isPromise$1"
},
{
"name": "isRootView"
@ -2244,10 +2244,10 @@
"name": "noSideEffects"
},
{
"name": "noop$2"
"name": "noop$1"
},
{
"name": "noop$3"
"name": "noop$2"
},
{
"name": "noopScope"
@ -2274,7 +2274,7 @@
"name": "parseCookieValue"
},
{
"name": "parseIntAutoRadix$1"
"name": "parseIntAutoRadix"
},
{
"name": "parseNumber"
@ -2400,7 +2400,7 @@
"name": "resolveDirectives"
},
{
"name": "resolveForwardRef$1"
"name": "resolveForwardRef"
},
{
"name": "resolveProvider"
@ -2550,10 +2550,10 @@
"name": "strToNumber"
},
{
"name": "stringify$1"
"name": "stringify"
},
{
"name": "stringify$2"
"name": "stringify$1"
},
{
"name": "subscribeTo"

View File

@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import '@angular/compiler';
import {ɵwhenRendered as whenRendered} from '@angular/core';
import {withBody} from '@angular/private/testing';
import * as fs from 'fs';
import * as path from 'path';
const UTF8 = {

View File

@ -38,6 +38,7 @@ ts_library(
"load_domino.ts",
],
deps = [
"//packages/compiler",
"//packages/platform-browser",
"//packages/platform-server",
"@ngdeps//zone.js",

View File

@ -1,138 +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 {Component, ContentChild, Directive, Injectable, Injector, Input, NgModule, NgModuleFactory, NgModuleRef, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef, defineInjector} from '../../../src/core';
import * as r3 from '../../../src/render3/index';
const details_elided = {
type: Object,
} as any;
export type $ComponentDef$ = any;
///////////
// Lib A - Compiled pre-Ivy
// "enableIvy": false
//////////
// BEGIN FILE: node_modules/libA/module.ts (Compiled without Ivy)
@Component({})
export class LibAComponent {
}
@NgModule({declarations: [LibAComponent], imports: []})
export class LibAModule {
}
// END FILE: node_modules/libA/module.ts
// BEGIN FILE: node_modules/libA/module.metadata.json
// Abridged version of metadata
const node_modules_libA_module_metadata = {
'LibAModule': {
refs: ['LibAComponent'],
constructorDes: [],
},
'LibAComponent': {
constructorDes: [],
}
};
// END FILE: node_modules/libA/module.metadata.json
///////////
// Lib B - Compiled with Ivy
// "enableIvy": true
//////////
// BEGIN FILE: node_modules/libB/module.ts (Compiled with Ivy)
@Component({})
export class LibBComponent {
// COMPILER GENERATED
static ngComponentDef: $ComponentDef$ = r3.defineComponent(details_elided);
}
@NgModule({declarations: [LibAComponent], imports: []})
export class LibBModule {
// COMPILER GENERATED
static ngInjectorDef = defineInjector(details_elided);
}
// END FILE: node_modules/libB/module.ts
// BEGIN FILE: node_modules/libB/module.metadata.json
// Abridged version of metadata
// Must still generate metadata in case it should be consumed with non-ivy application
// Must mark the metadata with `hasNgDef: true` so that Ivy knows to ignore it.
const node_modules_libB_module_metadata = {
'LibBModule': {refs: ['LibBComponent'], constructorDes: [], hasNgDef: true},
'LibBComponent': {constructorDes: [], hasNgDef: true}
};
// END FILE: node_modules/libA/module.metadata.json
///////////
// Lib B - Compiled with Ivy
// "enableIvy": true
// "enableIvyBackPatch": true
//////////
// BEGIN FILE: src/app.ts (Compiled with Ivy)
@Component({})
export class AppComponent {
// COMPILER GENERATED
static ngComponentDef: $ComponentDef$ = r3.defineComponent(details_elided);
}
@NgModule({declarations: [LibAComponent], imports: []})
export class AppModule {
// COMPILER GENERATED
static ngInjectorDef = defineInjector(details_elided);
}
// END FILE: src/app.ts
// BEGIN FILE: src/main.ts
// platformBrowserDynamic().bootstrapModule(AppModule);
// CLI rewrites it later to:
// platformBrowser().bootstrapModuleFactory(AppModuleFactory);
// END FILE: src/main.ts
// BEGIN FILE: src/app.ngfactory.ts
function ngBackPatch_node_modules_libB_module() {
ngBackPatch_node_modules_libB_module_LibAComponent();
ngBackPatch_node_modules_libB_module_LibAModule();
}
function ngBackPatch_node_modules_libB_module_LibAComponent() {
(LibAComponent as any).ngComponentDef = r3.defineComponent(details_elided);
}
function ngBackPatch_node_modules_libB_module_LibAModule() {
(LibAModule as any).ngInjectorDef = defineInjector(details_elided);
}
export const AppModuleFactory: NgModuleFactory<AppModule>&{patchedDeps: boolean} = {
moduleType: AppModule,
patchedDeps: false, create(parentInjector: Injector | null): NgModuleRef<AppModule>{
if (!this.patchedDeps) {
ngBackPatch_node_modules_libB_module();
this.patchedDeps = true;
} return details_elided;
}
};
// BEGIN FILE: src/app.ngfactory.ts
// ISSUE: I don't think this works. The issue is that multiple modules get flattened into single
// module and hence we can't patch transitively.
// ISSUE: can non-ivy @NgModule import Ivy @NgModule? I assume no, since the flattening of modules
// happens during compilation.
// BEGIN FILE: src/main.ts
// platformBrowserDynamic().bootstrapModule(AppModule);
// CLI rewrites it to:
// platformBrowser().bootstrapModuleFactory(AppModuleFactory);
// END FILE: src/main.ts

View File

@ -1,78 +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 {Component, ContentChild, Directive, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef, defineInjectable, defineInjector} from '../../../src/core';
import * as r3 from '../../../src/render3/index';
/**
* GOALS:
* - Patch types in tree shakable way
* - Generate these types for files which have `metadata.json` (since those are the files which
* have not been compiled with Ivy)
* - Have build optimizer hoist the patch functions into corresponding types to allow tree-shaking.
*/
// File: node_modules/some_library/path/public.ts
// Implies metadata: node_modules/some_library/path/public.metadata.json
// Assume: node_modules/some_library/index.js re-exports ./path/public.ts#ThirdPartyClass
@Injectable()
class ThirdPartyClass {
}
@Injectable()
class CompiledWithIvy {
// NORMATIVE
static ngInjectableDef = defineInjectable(
{factory: function CompileWithIvy_Factory() { return new CompiledWithIvy(); }});
// /NORMATIVE
}
// import { CompiledWithIvy } from 'some_library';
@NgModule({providers: [ThirdPartyClass, CompiledWithIvy]})
class CompiledWithIvyModule {
// NORMATIVE
static ngInjectorDef = defineInjector({
providers: [ThirdPartyClass, CompiledWithIvy],
factory: function CompiledWithIvyModule_Factory() { return new CompiledWithIvyModule(); }
});
// /NORMATIVE
}
/**
* Below is a function which should be generated right next to the `@NgModule` which
* imports types which have `.metadata.json` files.
*
* # JIT Mode
* - Because the `ngPatch_CompiledWithIvyModule` is invoked all parts get patched.
*
* # AOT Mode
* - Build Optimizer detects `@__BUILD_OPTIMIZER_COLOCATE__` annotation and moves the
* code from the current location to the destination.
* - The resulting `ngPatch_CompiledWithIvyModule` becomes empty and eligible for tree-shaking.
* - Uglify removes the `ngPatch_CompiledWithIvyModule` since it is empty.
*
* # AOT Closure Mode
* - Option A: not supported. (Preferred option)
* - Externally very few people use closure they will just have to wait until all of their
* libraries are Ivy.
* - Internally (g3) we build from source hence everyone switches to Ivy at the same time.
* - Option B: Write a closure pass similar to Build Optimizer which would move the code.
*/
// NORMATIVE
ngPatch_depsOf_CompiledWithIvyModule();
function ngPatch_depsOf_CompiledWithIvyModule() {
ngPatch_node_modules_some_library_path_public_CompileWithIvy();
}
function ngPatch_node_modules_some_library_path_public_CompileWithIvy() {
/** @__BUILD_OPTIMIZER_COLOCATE__ */
(ThirdPartyClass as any).ngInjectableDef = defineInjectable(
{factory: function CompileWithIvy_Factory() { return new ThirdPartyClass(); }});
}
// /NORMATIVE

View File

@ -109,7 +109,7 @@ class ToDoAppComponent {
selector: 'todo',
template: `
<div [class.done]="todo.done">
<input type="checkbox" [value]="todo.done" (click)="onCheckboxClick()"></input>
<input type="checkbox" [value]="todo.done" (click)="onCheckboxClick()">
<span>{{todo.text}}</span>
<button (click)="onArchiveClick()">archive</button>
</div>

View File

@ -5,7 +5,6 @@
* 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 'reflect-metadata';
import {ElementRef, QueryList} from '@angular/core';

View File

@ -88,8 +88,8 @@ describe('jit directive helper functions', () => {
read: Directive
});
expect(converted.predicate).toEqual(jasmine.any(WrappedNodeExpr));
expect(converted.read).toEqual(jasmine.any(WrappedNodeExpr));
expect(converted.predicate).toEqual(Directive);
expect(converted.read).toEqual(Directive);
});
});

View File

@ -9,6 +9,7 @@
// Needed to run animation tests
require('zone.js/dist/zone-node.js');
import '@angular/compiler'; // For JIT mode. Must be in front of any other @angular/* imports.
import {DominoAdapter} from '@angular/platform-server/src/domino_adapter';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';

View File

@ -7,6 +7,7 @@ ts_library(
testonly = 1,
srcs = ["init_browser_spec.ts"],
deps = [
"//packages/compiler",
"//packages/core/testing",
"//packages/platform-browser-dynamic/testing",
"//packages/platform-browser/animations",
@ -18,6 +19,7 @@ ts_library(
testonly = 1,
srcs = ["init_node_spec.ts"],
deps = [
"//packages/compiler",
"//packages/core/testing",
"//packages/platform-server",
"//packages/platform-server/testing",

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import '@angular/compiler'; // For JIT mode. Must be in front of any other @angular/* imports.
import {TestBed} from '@angular/core/testing';
import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';

View File

@ -36,6 +36,7 @@ import 'zone.js/dist/jasmine-patch.js';
(global as any).isNode = true;
(global as any).isBrowser = false;
import '@angular/compiler'; // For JIT mode. Must be in front of any other @angular/* imports.
// Init TestBed
import {TestBed} from '@angular/core/testing';
import {ServerTestingModule, platformServerTesting} from '@angular/platform-server/testing/src/server';