refactor(ivy): run the compiler compliance tests against ngtsc (#24862)

This commit moves the compiler compliance tests into compiler-cli,
and uses ngtsc to run them instead of the custom compilation
pipeline used before. Testing against ngtsc allows for validation
of the real compiler output.

This commit also fixes a few small issues that prevented the tests
from passing.

PR Close #24862
This commit is contained in:
Alex Rickabaugh 2018-07-12 15:10:55 -07:00 committed by Victor Berchet
parent b7bbc82e3e
commit 9fd70c9715
17 changed files with 529 additions and 652 deletions

View File

@ -73,6 +73,7 @@ module.exports = function(config) {
'dist/all/@angular/benchpress/**',
'dist/all/@angular/compiler-cli/**',
'dist/all/@angular/compiler-cli/src/ngtsc/**',
'dist/all/@angular/compiler-cli/test/compliance/**',
'dist/all/@angular/compiler-cli/test/ngtsc/**',
'dist/all/@angular/compiler/test/aot/**',
'dist/all/@angular/compiler/test/render3/**',

View File

@ -0,0 +1,35 @@
load("//tools:defaults.bzl", "ts_library")
load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test")
ts_library(
name = "test_lib",
testonly = 1,
srcs = glob(
["**/*.ts"],
),
deps = [
"//packages:types",
"//packages/compiler",
"//packages/compiler-cli",
"//packages/compiler/test:test_utils",
"//packages/compiler/testing",
"//packages/core",
],
)
jasmine_node_test(
name = "compliance",
bootstrap = ["angular/tools/testing/init_node_spec.js"],
data = [
"//packages/common:npm_package",
"//packages/core:npm_package",
],
tags = [
"ivy-local",
"ivy-only",
],
deps = [
":test_lib",
"//tools/testing:node",
],
)

View File

@ -0,0 +1 @@
Tests in this directory are excluded from running in the browser and only run in node.

View File

@ -0,0 +1,178 @@
/**
* @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 {AotCompilerOptions} from '@angular/compiler';
import {escapeRegExp} from '@angular/compiler/src/util';
import {MockCompilerHost, MockData, MockDirectory, arrayToMockDir, settings, toMockFileArray} from '@angular/compiler/test/aot/test_util';
import * as ts from 'typescript';
import {NgtscProgram} from '../../src/ngtsc/program';
const IDENTIFIER = /[A-Za-z_$ɵ][A-Za-z0-9_$]*/;
const OPERATOR =
/!|%|\*|\/|\^|&&?|\|\|?|\(|\)|\{|\}|\[|\]|:|;|<=?|>=?|={1,3}|!==?|=>|\+\+?|--?|@|,|\.|\.\.\./;
const STRING = /'[^']*'|"[^"]*"|`[\s\S]*?`/;
const NUMBER = /\d+/;
const ELLIPSIS = '…';
const TOKEN = new RegExp(
`\\s*((${IDENTIFIER.source})|(${OPERATOR.source})|(${STRING.source})|${NUMBER.source}|${ELLIPSIS})`,
'y');
type Piece = string | RegExp;
const SKIP = /(?:.|\n|\r)*/;
const ERROR_CONTEXT_WIDTH = 30;
// Transform the expected output to set of tokens
function tokenize(text: string): Piece[] {
TOKEN.lastIndex = 0;
let match: RegExpMatchArray|null;
const pieces: Piece[] = [];
while ((match = TOKEN.exec(text)) !== null) {
const token = match[1];
if (token === 'IDENT') {
pieces.push(IDENTIFIER);
} else if (token === ELLIPSIS) {
pieces.push(SKIP);
} else {
pieces.push(token);
}
}
if (pieces.length === 0 || TOKEN.lastIndex !== 0) {
const from = TOKEN.lastIndex;
const to = from + ERROR_CONTEXT_WIDTH;
throw Error(`Invalid test, no token found for '${text.substr(from, to)}...'`);
}
return pieces;
}
export function expectEmit(
source: string, expected: string, description: string,
assertIdentifiers?: {[name: string]: RegExp}) {
// turns `// ...` into `…`
// remove `// TODO` comment lines
expected = expected.replace(/\/\/\s*\.\.\./g, ELLIPSIS).replace(/\/\/\s*TODO.*?\n/g, '');
const pieces = tokenize(expected);
const {regexp, groups} = buildMatcher(pieces);
const matches = source.match(regexp);
if (matches === null) {
let last: number = 0;
for (let i = 1; i < pieces.length; i++) {
const {regexp} = buildMatcher(pieces.slice(0, i));
const m = source.match(regexp);
const expectedPiece = pieces[i - 1] == IDENTIFIER ? '<IDENT>' : pieces[i - 1];
if (!m) {
fail(
`${description}: Expected to find ${expectedPiece} '${source.substr(0,last)}[<---HERE expected "${expectedPiece}"]${source.substr(last)}'`);
return;
} else {
last = (m.index || 0) + m[0].length;
}
}
fail(
`Test helper failure: Expected expression failed but the reporting logic could not find where it failed in: ${source}`);
} else {
if (assertIdentifiers) {
// It might be possible to add the constraints in the original regexp (see `buildMatcher`)
// by transforming the assertion regexps when using anchoring, grouping, back references,
// flags, ...
//
// Checking identifiers after they have matched allows for a simple and flexible
// implementation.
// The overall performance are not impacted when `assertIdentifiers` is empty.
const ids = Object.keys(assertIdentifiers);
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
if (groups.has(id)) {
const name = matches[groups.get(id) as number];
const regexp = assertIdentifiers[id];
if (!regexp.test(name)) {
throw Error(
`${description}: The matching identifier "${id}" is "${name}" which doesn't match ${regexp}`);
}
}
}
}
}
}
const IDENT_LIKE = /^[a-z][A-Z]/;
const MATCHING_IDENT = /^\$.*\$$/;
/*
* Builds a regexp that matches the given `pieces`
*
* It returns:
* - the `regexp` to be used to match the generated code,
* - the `groups` which maps `$...$` identifier to their position in the regexp matches.
*/
function buildMatcher(pieces: (string | RegExp)[]): {regexp: RegExp, groups: Map<string, number>} {
const results: string[] = [];
let first = true;
let group = 0;
const groups = new Map<string, number>();
for (const piece of pieces) {
if (!first)
results.push(`\\s${typeof piece === 'string' && IDENT_LIKE.test(piece) ? '+' : '*'}`);
first = false;
if (typeof piece === 'string') {
if (MATCHING_IDENT.test(piece)) {
const matchGroup = groups.get(piece);
if (!matchGroup) {
results.push('(' + IDENTIFIER.source + ')');
const newGroup = ++group;
groups.set(piece, newGroup);
} else {
results.push(`\\${matchGroup}`);
}
} else {
results.push(escapeRegExp(piece));
}
} else {
results.push('(?:' + piece.source + ')');
}
}
return {
regexp: new RegExp(results.join('')),
groups,
};
}
export function compile(
data: MockDirectory, angularFiles: MockData, options: AotCompilerOptions = {},
errorCollector: (error: any, fileName?: string) => void = error => { throw error;}): {
source: string,
} {
const testFiles = toMockFileArray(data);
const scripts = testFiles.map(entry => entry.fileName);
const angularFilesArray = toMockFileArray(angularFiles);
const files = arrayToMockDir([...testFiles, ...angularFilesArray]);
const mockCompilerHost = new MockCompilerHost(scripts, files);
const program = new NgtscProgram(
scripts, {
target: ts.ScriptTarget.ES2015,
module: ts.ModuleKind.ES2015,
moduleResolution: ts.ModuleResolutionKind.NodeJs, ...options,
},
mockCompilerHost);
program.emit();
const source =
scripts.map(script => mockCompilerHost.readFile(script.replace(/\.ts$/, '.js'))).join('\n');
return {source};
}

View File

@ -7,7 +7,7 @@
*/
import {MockDirectory, setup} from '../aot/test_util';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
describe('mock_compiler', () => {
@ -47,9 +47,6 @@ describe('mock_compiler', () => {
// result.source contains just the emitted factory declarations regardless of the original
// module.
expect(result.source).toContain('Hello');
// The output context is also returned if the actual output ast is needed.
expect(result.outputContext.statements.length).toBeGreaterThan(0);
});
});
@ -143,7 +140,7 @@ describe('mock_compiler', () => {
expectEmit(
result.source, `
// TODO: this comment should not be taken into account
$r3$.ɵT(0, 'Hello!');
$r3$.ɵT(0, "Hello!");
// TODO: this comment should not be taken into account
`,
'todo comments should be ignored');

View File

@ -6,9 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {InitialStylingFlags} from '../../src/core';
import {MockDirectory, setup} from '../aot/test_util';
import {InitialStylingFlags} from '@angular/compiler/src/core';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
@ -47,21 +46,21 @@ describe('compiler compliance', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
const $c1$ = ['title', 'Hello'];
const $c2$ = ['my-app', ${InitialStylingFlags.VALUES_MODE}, 'my-app', true];
const $c3$ = ['cx', '20', 'cy', '30', 'r', '50'];
const $c1$ = ["title", "Hello"];
const $c2$ = ["my-app", ${InitialStylingFlags.VALUES_MODE}, "my-app", true];
const $c3$ = ["cx", "20", "cy", "30", "r", "50"];
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $c1$);
$r3$.ɵs((null as any), $c2$);
$r3$.ɵE(0, "div", $c1$);
$r3$.ɵs(null, $c2$);
$r3$.ɵNS();
$r3$.ɵE(1, 'svg');
$r3$.ɵEe(2, 'circle', $c3$);
$r3$.ɵE(1, "svg");
$r3$.ɵEe(2, "circle", $c3$);
$r3$.ɵe();
$r3$.ɵNH();
$r3$.ɵE(3, 'p');
$r3$.ɵT(4, 'test');
$r3$.ɵE(3, "p");
$r3$.ɵT(4, "test");
$r3$.ɵe();
$r3$.ɵe();
}
@ -98,20 +97,20 @@ describe('compiler compliance', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
const $c1$ = ['title', 'Hello'];
const $c2$ = ['my-app', ${InitialStylingFlags.VALUES_MODE}, 'my-app', true];
const $c1$ = ["title", "Hello"];
const $c2$ = ["my-app", ${InitialStylingFlags.VALUES_MODE}, "my-app", true];
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $c1$);
$r3$.ɵs((null as any), $c2$);
$r3$.ɵE(0, "div", $c1$);
$r3$.ɵs(null, $c2$);
$r3$.ɵNM();
$r3$.ɵE(1, 'math');
$r3$.ɵEe(2, 'infinity');
$r3$.ɵE(1, "math");
$r3$.ɵEe(2, "infinity");
$r3$.ɵe();
$r3$.ɵNH();
$r3$.ɵE(3, 'p');
$r3$.ɵT(4, 'test');
$r3$.ɵE(3, "p");
$r3$.ɵT(4, "test");
$r3$.ɵe();
$r3$.ɵe();
}
@ -148,18 +147,18 @@ describe('compiler compliance', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
const $c1$ = ['title', 'Hello'];
const $c2$ = ['my-app', ${InitialStylingFlags.VALUES_MODE}, 'my-app', true];
const $c1$ = ["title", "Hello"];
const $c2$ = ["my-app", ${InitialStylingFlags.VALUES_MODE}, "my-app", true];
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $c1$);
$r3$.ɵs((null as any), $c2$);
$r3$.ɵT(1, 'Hello ');
$r3$.ɵE(2, 'b');
$r3$.ɵT(3, 'World');
$r3$.ɵE(0, "div", $c1$);
$r3$.ɵs(null, $c2$);
$r3$.ɵT(1, "Hello ");
$r3$.ɵE(2, "b");
$r3$.ɵT(3, "World");
$r3$.ɵe();
$r3$.ɵT(4, '!');
$r3$.ɵT(4, "!");
$r3$.ɵe();
}
}
@ -197,16 +196,16 @@ describe('compiler compliance', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
const $c1$ = ['class', 'my-app', 0, 'http://someuri/foo', 'foo:bar', 'baz', 'title', 'Hello', 0, 'http://someuri/foo', 'foo:qux', 'quacks'];
const $c1$ = ["class", "my-app", 0, "http://someuri/foo", "foo:bar", "baz", "title", "Hello", 0, "http://someuri/foo", "foo:qux", "quacks"];
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $e0_attrs$);
$r3$.ɵT(1, 'Hello ');
$r3$.ɵE(2, 'b');
$r3$.ɵT(3, 'World');
$r3$.ɵE(0, "div", $e0_attrs$);
$r3$.ɵT(1, "Hello ");
$r3$.ɵE(2, "b");
$r3$.ɵT(3, "World");
$r3$.ɵe();
$r3$.ɵT(4, '!');
$r3$.ɵT(4, "!");
$r3$.ɵe();
}
}
@ -241,12 +240,12 @@ describe('compiler compliance', () => {
const factory = 'factory: function MyComponent_Factory() { return new MyComponent(); }';
const template = `
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'div');
$r3$.ɵEe(0, "div");
}
if (rf & 2) {
$r3$.ɵp(0, 'id', $r3$.ɵb(ctx.id));
$r3$.ɵp(0, "id", $r3$.ɵb(ctx.id));
}
}
`;
@ -285,17 +284,17 @@ describe('compiler compliance', () => {
const factory = 'factory: function MyComponent_Factory() { return new MyComponent(); }';
const template = `
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'div');
$r3$.ɵPp(1,'pipe');
$r3$.ɵEe(0, "div");
$r3$.ɵPp(1,"pipe");
$r3$.ɵrS(10);
}
if (rf & 2) {
$r3$.ɵp(0, 'ternary', $r3$.ɵb((ctx.cond ? $r3$.ɵf1(2, _c0, ctx.a): _c1)));
$r3$.ɵp(0, 'pipe', $r3$.ɵb($r3$.ɵpb3(6, 1, ctx.value, 1, 2)));
$r3$.ɵp(0, 'and', $r3$.ɵb((ctx.cond && $r3$.ɵf1(4, _c0, ctx.b))));
$r3$.ɵp(0, 'or', $r3$.ɵb((ctx.cond || $r3$.ɵf1(6, _c0, ctx.c))));
$r3$.ɵp(0, "ternary", $r3$.ɵb((ctx.cond ? $r3$.ɵf1(2, _c0, ctx.a): _c1)));
$r3$.ɵp(0, "pipe", $r3$.ɵb($r3$.ɵpb3(6, 1, ctx.value, 1, 2)));
$r3$.ɵp(0, "and", $r3$.ɵb((ctx.cond && $r3$.ɵf1(4, _c0, ctx.b))));
$r3$.ɵp(0, "or", $r3$.ɵb((ctx.cond || $r3$.ɵf1(6, _c0, ctx.c))));
}
}
`;
@ -330,24 +329,25 @@ describe('compiler compliance', () => {
const factory = 'factory: function MyComponent_Factory() { return new MyComponent(); }';
const template = `
const _c0 = ['background-color'];
const _c1 = ['error'];
class MyComponent {
static ngComponentDef = i0.ɵdefineComponent({type:MyComponent,selectors:[['my-component']],
factory:function MyComponent_Factory(){
return new MyComponent();
},template:function MyComponent_Template(rf:number,ctx:any){
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵs(_c0, _c1);
$r3$.ɵe();
}
if (rf & 2) {
$r3$.ɵsp(0, 0, ctx.color);
$r3$.ɵcp(0, 0, ctx.error);
$r3$.ɵsa(0);
}
const _c0 = ["background-color"];
const _c1 = ["error"];
MyComponent.ngComponentDef = i0.ɵdefineComponent({type:MyComponent,selectors:[["my-component"]],
factory:function MyComponent_Factory(){
return new MyComponent();
},template:function MyComponent_Template(rf,ctx){
if (rf & 1) {
$r3$.ɵE(0, "div");
$r3$.ɵs(_c0, _c1);
$r3$.ɵe();
}
if (rf & 2) {
$r3$.ɵsp(0, 0, ctx.color);
$r3$.ɵcp(0, 0, ctx.error);
$r3$.ɵsa(0);
}
}
});
`;
@ -383,38 +383,38 @@ describe('compiler compliance', () => {
// ChildComponent definition should be:
const ChildComponentDefinition = `
static ngComponentDef = $r3$.ɵdefineComponent({
ChildComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: ChildComponent,
selectors: [['child']],
selectors: [["child"]],
factory: function ChildComponent_Factory() { return new ChildComponent(); },
template: function ChildComponent_Template(rf: IDENT, ctx: IDENT) {
template: function ChildComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵT(0, 'child-view');
$r3$.ɵT(0, "child-view");
}
}
});`;
// SomeDirective definition should be:
const SomeDirectiveDefinition = `
static ngDirectiveDef = $r3$.ɵdefineDirective({
SomeDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: SomeDirective,
selectors: [['', 'some-directive', '']],
selectors: [["", "some-directive", ""]],
factory: function SomeDirective_Factory() {return new SomeDirective(); }
});
`;
// MyComponent definition should be:
const MyComponentDefinition = `
const $c1$ = ['some-directive', ''];
const $c1$ = ["some-directive", ""];
static ngComponentDef = $r3$.ɵdefineComponent({
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selectors: [['my-component']],
selectors: [["my-component"]],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'child', $c1$);
$r3$.ɵT(1, '!');
$r3$.ɵEe(0, "child", $c1$);
$r3$.ɵT(1, "!");
}
},
directives: [ChildComponent, SomeDirective]
@ -450,18 +450,18 @@ describe('compiler compliance', () => {
// SomeDirective definition should be:
const SomeDirectiveDefinition = `
static ngDirectiveDef = $r3$.ɵdefineDirective({
SomeDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: SomeDirective,
selectors: [['div', 'some-directive', '', 8, 'foo', 3, 'title', '', 9, 'baz']],
selectors: [["div", "some-directive", "", 8, "foo", 3, "title", "", 9, "baz"]],
factory: function SomeDirective_Factory() {return new SomeDirective(); }
});
`;
// OtherDirective definition should be:
const OtherDirectiveDefinition = `
static ngDirectiveDef = $r3$.ɵdefineDirective({
OtherDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: OtherDirective,
selectors: [['', 5, 'span', 'title', '', 9, 'baz']],
selectors: [["", 5, "span", "title", "", 9, "baz"]],
factory: function OtherDirective_Factory() {return new OtherDirective(); }
});
`;
@ -491,13 +491,12 @@ describe('compiler compliance', () => {
};
const HostBindingDirDeclaration = `
static ngDirectiveDef = $r3$.ɵdefineDirective({
HostBindingDir.ngDirectiveDef = $r3$.ɵdefineDirective({
type: HostBindingDir,
selectors: [['', 'hostBindingDir', '']],
selectors: [["", "hostBindingDir", ""]],
factory: function HostBindingDir_Factory() { return new HostBindingDir(); },
hostBindings: function HostBindingDir_HostBindings(
dirIndex: $number$, elIndex: $number$) {
$r3$.ɵp(elIndex, 'id', $r3$.ɵb($r3$.ɵd(dirIndex).dirId));
hostBindings: function HostBindingDir_HostBindings(dirIndex, elIndex) {
$r3$.ɵp(elIndex, "id", $r3$.ɵb($r3$.ɵd(dirIndex).dirId));
}
});
`;
@ -534,34 +533,34 @@ describe('compiler compliance', () => {
};
const IfDirectiveDefinition = `
static ngDirectiveDef = $r3$.ɵdefineDirective({
IfDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: IfDirective,
selectors: [['', 'if', '']],
selectors: [["", "if", ""]],
factory: function IfDirective_Factory() { return new IfDirective($r3$.ɵinjectTemplateRef()); }
});`;
const MyComponentDefinition = `
const $c1$ = ['foo', ''];
const $c2$ = ['if', ''];
const $c1$ = ["foo", ""];
const $c2$ = ["if", ""];
static ngComponentDef = $r3$.ɵdefineComponent({
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selectors: [['my-component']],
selectors: [["my-component"]],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵE(0, 'ul', null, $c1$);
$r3$.ɵE(0, "ul", null, $c1$);
$r3$.ɵC(2, MyComponent_li_Template_2, null, $c2$);
$r3$.ɵe();
}
const $foo$ = $r3$.ɵld(1);
function MyComponent_li_Template_2(rf: IDENT, ctx0: IDENT) {
function MyComponent_li_Template_2(rf, ctx0) {
if (rf & 1) {
$r3$.ɵE(0, 'li');
$r3$.ɵE(0, "li");
$r3$.ɵT(1);
$r3$.ɵe();
}
if (rf & 2) {
$r3$.ɵt(1, $r3$.ɵi2('', ctx.salutation, ' ', $foo$, ''));
$r3$.ɵt(1, $r3$.ɵi2("", ctx.salutation, " ", $foo$, ""));
}
}
},
@ -611,19 +610,19 @@ describe('compiler compliance', () => {
};
const MyAppDeclaration = `
const $e0_ff$ = ($v$: any) => { return ['Nancy', $v$]; };
const $e0_ff$ = function ($v$) { return ["Nancy", $v$]; };
static ngComponentDef = $r3$.ɵdefineComponent({
MyApp.ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selectors: [['my-app']],
selectors: [["my-app"]],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
template: function MyApp_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'my-comp');
$r3$.ɵEe(0, "my-comp");
$r3$.ɵrS(2);
}
if (rf & 2) {
$r3$.ɵp(0, 'names', $r3$.ɵb($r3$.ɵf1(2, $e0_ff$, ctx.customName)));
$r3$.ɵp(0, "names", $r3$.ɵb($r3$.ɵf1(2, $e0_ff$, ctx.customName)));
}
},
directives: [MyComp]
@ -688,22 +687,22 @@ describe('compiler compliance', () => {
};
const MyAppDefinition = `
const $e0_ff$ = ($v0$: $any$, $v1$: $any$, $v2$: $any$, $v3$: $any$, $v4$: $any$, $v5$: $any$, $v6$: $any$, $v7$: $any$, $v8$: $any$) => {
return ['start-', $v0$, $v1$, $v2$, $v3$, $v4$, '-middle-', $v5$, $v6$, $v7$, $v8$, '-end'];
const $e0_ff$ = function ($v0$, $v1$, $v2$, $v3$, $v4$, $v5$, $v6$, $v7$, $v8$) {
return ["start-", $v0$, $v1$, $v2$, $v3$, $v4$, "-middle-", $v5$, $v6$, $v7$, $v8$, "-end"];
}
static ngComponentDef = $r3$.ɵdefineComponent({
MyApp.ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selectors: [['my-app']],
selectors: [["my-app"]],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
template: function MyApp_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'my-comp');
$r3$.ɵEe(0, "my-comp");
$r3$.ɵrS(10);
}
if (rf & 2) {
$r3$.ɵp(
0, 'names',
0, "names",
$r3$.ɵb($r3$.ɵfV(10, $e0_ff$, [ctx.n0, ctx.n1, ctx.n2, ctx.n3, ctx.n4, ctx.n5, ctx.n6, ctx.n7, ctx.n8])));
}
},
@ -751,19 +750,19 @@ describe('compiler compliance', () => {
};
const MyAppDefinition = `
const $e0_ff$ = ($v$: any) => { return {'duration': 500, animation: $v$}; };
const $e0_ff$ = function ($v$) { return {"duration": 500, animation: $v$}; };
static ngComponentDef = $r3$.ɵdefineComponent({
MyApp.ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selectors: [['my-app']],
selectors: [["my-app"]],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
template: function MyApp_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'object-comp');
$r3$.ɵEe(0, "object-comp");
$r3$.ɵrS(2);
}
if (rf & 2) {
$r3$.ɵp(0, 'config', $r3$.ɵb($r3$.ɵf1(2, $e0_ff$, ctx.name)));
$r3$.ɵp(0, "config", $r3$.ɵb($r3$.ɵf1(2, $e0_ff$, ctx.name)));
}
},
directives: [ObjectComp]
@ -814,22 +813,22 @@ describe('compiler compliance', () => {
const MyAppDefinition = `
const $c0$ = {opacity: 0, duration: 0};
const $e0_ff$ = ($v$: any) => { return {opacity: 1, duration: $v$}; };
const $e0_ff_1$ = ($v$: any) => { return [$c0$, $v$]; };
const $e0_ff_2$ = ($v1$: any, $v2$: any) => { return {animation: $v1$, actions: $v2$}; };
const $e0_ff$ = function ($v$) { return {opacity: 1, duration: $v$}; };
const $e0_ff_1$ = function ($v$) { return [$c0$, $v$]; };
const $e0_ff_2$ = function ($v1$, $v2$) { return {animation: $v1$, actions: $v2$}; };
static ngComponentDef = $r3$.ɵdefineComponent({
MyApp.ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selectors: [['my-app']],
selectors: [["my-app"]],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
template: function MyApp_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'nested-comp');
$r3$.ɵEe(0, "nested-comp");
$r3$.ɵrS(7);
}
if (rf & 2) {
$r3$.ɵp(
0, 'config',
0, "config",
$r3$.ɵb($r3$.ɵf2(7, $e0_ff_2$, ctx.name, $r3$.ɵf1(4, $e0_ff_1$, $r3$.ɵf1(2, $e0_ff$, ctx.duration)))));
}
},
@ -875,14 +874,14 @@ describe('compiler compliance', () => {
};
const SimpleComponentDefinition = `
static ngComponentDef = $r3$.ɵdefineComponent({
SimpleComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: SimpleComponent,
selectors: [['simple']],
selectors: [["simple"]],
factory: function SimpleComponent_Factory() { return new SimpleComponent(); },
template: function SimpleComponent_Template(rf: IDENT, ctx: IDENT) {
template: function SimpleComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵpD();
$r3$.ɵE(0, 'div');
$r3$.ɵE(0, "div");
$r3$.ɵP(1);
$r3$.ɵe();
}
@ -890,22 +889,22 @@ describe('compiler compliance', () => {
});`;
const ComplexComponentDefinition = `
const $c1$ = [[['span', 'title', 'tofirst']], [['span', 'title', 'tosecond']]];
const $c2$ = ['span[title=toFirst]', 'span[title=toSecond]'];
const $c3$ = ['id','first'];
const $c4$ = ['id','second'];
const $c1$ = [[["span", "title", "tofirst"]], [["span", "title", "tosecond"]]];
const $c2$ = ["span[title=toFirst]", "span[title=toSecond]"];
const $c3$ = ["id","first"];
const $c4$ = ["id","second"];
static ngComponentDef = $r3$.ɵdefineComponent({
ComplexComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: ComplexComponent,
selectors: [['complex']],
selectors: [["complex"]],
factory: function ComplexComponent_Factory() { return new ComplexComponent(); },
template: function ComplexComponent_Template(rf: IDENT, ctx: IDENT) {
template: function ComplexComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵpD($c1$, $c2$);
$r3$.ɵE(0, 'div', $c3$);
$r3$.ɵE(0, "div", $c3$);
$r3$.ɵP(1, 1);
$r3$.ɵe();
$r3$.ɵE(2, 'div', $c4$);
$r3$.ɵE(2, "div", $c4$);
$r3$.ɵP(3, 2);
$r3$.ɵe();
}
@ -958,17 +957,17 @@ describe('compiler compliance', () => {
};
const ViewQueryComponentDefinition = `
const $e0_attrs$ = ['someDir',''];
const $e0_attrs$ = ["someDir",""];
static ngComponentDef = $r3$.ɵdefineComponent({
ViewQueryComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: ViewQueryComponent,
selectors: [['view-query-component']],
selectors: [["view-query-component"]],
factory: function ViewQueryComponent_Factory() { return new ViewQueryComponent(); },
template: function ViewQueryComponent_Template(rf: $RenderFlags$, ctx: $ViewQueryComponent$) {
var $tmp$: $any$;
template: function ViewQueryComponent_Template(rf, ctx) {
var $tmp$;
if (rf & 1) {
$r3$.ɵQ(0, SomeDirective, true);
$r3$.ɵEe(1, 'div', $e0_attrs$);
$r3$.ɵEe(1, "div", $e0_attrs$);
}
if (rf & 2) {
($r3$.ɵqR(($tmp$ = $r3$.ɵld(0))) && (ctx.someDir = $tmp$.first));
@ -1018,22 +1017,20 @@ describe('compiler compliance', () => {
};
const ContentQueryComponentDefinition = `
static ngComponentDef = $r3$.ɵdefineComponent({
ContentQueryComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: ContentQueryComponent,
selectors: [['content-query-component']],
selectors: [["content-query-component"]],
factory: function ContentQueryComponent_Factory() {
return [new ContentQueryComponent(), $r3$.ɵQ(null, SomeDirective, true)];
},
hostBindings: function ContentQueryComponent_HostBindings(
dirIndex: $number$, elIndex: $number$) {
var $tmp$: $any$;
hostBindings: function ContentQueryComponent_HostBindings(dirIndex, elIndex) {
var $tmp$;
($r3$.ɵqR(($tmp$ = $r3$.ɵd(dirIndex)[1])) && ($r3$.ɵd(dirIndex)[0].someDir = $tmp$.first));
},
template: function ContentQueryComponent_Template(
rf: $RenderFlags$, ctx: $ContentQueryComponent$) {
template: function ContentQueryComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵpD();
$r3$.ɵE(0, 'div');
$r3$.ɵE(0, "div");
$r3$.ɵP(1);
$r3$.ɵe();
}
@ -1089,41 +1086,41 @@ describe('compiler compliance', () => {
it('should render pipes', () => {
const MyPipeDefinition = `
static ngPipeDef = $r3$.ɵdefinePipe(
{name: 'myPipe', type: MyPipe, factory: function MyPipe_Factory() { return new MyPipe(); }, pure: false});
MyPipe.ngPipeDef = $r3$.ɵdefinePipe(
{name: "myPipe", type: MyPipe, factory: function MyPipe_Factory() { return new MyPipe(); }, pure: false});
`;
const MyPurePipeDefinition = `
static ngPipeDef = $r3$.ɵdefinePipe({
name: 'myPurePipe',
MyPurePipe.ngPipeDef = $r3$.ɵdefinePipe({
name: "myPurePipe",
type: MyPurePipe,
factory: function MyPurePipe_Factory() { return new MyPurePipe(); },
pure: true
});`;
const MyAppDefinition = `
const $c0$ = ($a0$: any) => {
const $c0$ = function ($a0$) {
return [$a0$, 1, 2, 3, 4, 5];
};
// ...
static ngComponentDef = $r3$.ɵdefineComponent({
MyApp.ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp,
selectors: [['my-app']],
selectors: [["my-app"]],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(rf: IDENT, ctx: IDENT) {
template: function MyApp_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵT(0);
$r3$.ɵPp(1, 'myPurePipe');
$r3$.ɵPp(2, 'myPipe');
$r3$.ɵE(3, 'p');
$r3$.ɵPp(1, "myPurePipe");
$r3$.ɵPp(2, "myPipe");
$r3$.ɵE(3, "p");
$r3$.ɵT(4);
$r3$.ɵPp(5, 'myPipe');
$r3$.ɵPp(5, "myPipe");
$r3$.ɵe();
$r3$.ɵrS(15);
}
if (rf & 2) {
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, 3, $r3$.ɵpb2(2, 6, ctx.name, ctx.size), ctx.size), ''));
$r3$.ɵt(4, $r3$.ɵi1('', $r3$.ɵpbV(5, 13 , $r3$.ɵf1(15, $c0$, ctx.name)), ''));
$r3$.ɵt(0, $r3$.ɵi1("", $r3$.ɵpb2(1, 3, $r3$.ɵpb2(2, 6, ctx.name, ctx.size), ctx.size), ""));
$r3$.ɵt(4, $r3$.ɵi1("", $r3$.ɵpbV(5, 13 , $r3$.ɵf1(15, $c0$, ctx.name)), ""));
}
},
pipes: [MyPurePipe, MyPipe]
@ -1154,20 +1151,20 @@ describe('compiler compliance', () => {
};
const MyComponentDefinition = `
const $c1$ = ['user', ''];
const $c1$ = ["user", ""];
static ngComponentDef = $r3$.ɵdefineComponent({
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selectors: [['my-component']],
selectors: [["my-component"]],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'input', null, $c1$);
$r3$.ɵEe(0, "input", null, $c1$);
$r3$.ɵT(2);
}
const $user$ = $r3$.ɵld(1);
if (rf & 2) {
$r3$.ɵt(2, $r3$.ɵi1('Hello ', $user$.value, '!'));
$r3$.ɵt(2, $r3$.ɵi1("Hello ", $user$.value, "!"));
}
}
});
@ -1225,28 +1222,28 @@ describe('compiler compliance', () => {
it('should gen hooks with a few simple components', () => {
const LifecycleCompDefinition = `
static ngComponentDef = $r3$.ɵdefineComponent({
LifecycleComp.ngComponentDef = $r3$.ɵdefineComponent({
type: LifecycleComp,
selectors: [['lifecycle-comp']],
selectors: [["lifecycle-comp"]],
factory: function LifecycleComp_Factory() { return new LifecycleComp(); },
inputs: {nameMin: 'name'},
inputs: {nameMin: "name"},
features: [$r3$.ɵNgOnChangesFeature],
template: function LifecycleComp_Template(rf: IDENT, ctx: IDENT) {}
template: function LifecycleComp_Template(rf, ctx) {}
});`;
const SimpleLayoutDefinition = `
static ngComponentDef = $r3$.ɵdefineComponent({
SimpleLayout.ngComponentDef = $r3$.ɵdefineComponent({
type: SimpleLayout,
selectors: [['simple-layout']],
selectors: [["simple-layout"]],
factory: function SimpleLayout_Factory() { return new SimpleLayout(); },
template: function SimpleLayout_Template(rf: IDENT, ctx: IDENT) {
template: function SimpleLayout_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'lifecycle-comp');
$r3$.ɵEe(1, 'lifecycle-comp');
$r3$.ɵEe(0, "lifecycle-comp");
$r3$.ɵEe(1, "lifecycle-comp");
}
if (rf & 2) {
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1));
$r3$.ɵp(1, 'name', $r3$.ɵb(ctx.name2));
$r3$.ɵp(0, "name", $r3$.ɵb(ctx.name1));
$r3$.ɵp(1, "name", $r3$.ɵb(ctx.name2));
}
},
directives: [LifecycleComp]
@ -1340,37 +1337,37 @@ describe('compiler compliance', () => {
// TODO(benlesh): Enforce this when the directives are specified
const ForDirectiveDefinition = `
static ngDirectiveDef = $r3$.ɵdefineDirective({
ForOfDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: ForOfDirective,
selectors: [['', 'forOf', '']],
selectors: [["", "forOf", ""]],
factory: function ForOfDirective_Factory() {
return new ForOfDirective($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef());
},
features: [$r3$.ɵNgOnChangesFeature],
inputs: {forOf: 'forOf'}
inputs: {forOf: "forOf"}
});
`;
const MyComponentDefinition = `
const $_c0$ = ['for','','forOf',''];
const $_c0$ = ["for","","forOf",""];
static ngComponentDef = $r3$.ɵdefineComponent({
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selectors: [['my-component']],
selectors: [["my-component"]],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(rf:IDENT,ctx:IDENT){
template: function MyComponent_Template(rf, ctx){
if (rf & 1) {
$r3$.ɵNS();
$r3$.ɵE(0,'svg');
$r3$.ɵE(0,"svg");
$r3$.ɵC(1,MyComponent__svg_g_Template_1,null,$_c0$);
$r3$.ɵe();
}
if (rf & 2) { $r3$.ɵp(1,'forOf',$r3$.ɵb(ctx.items)); }
function MyComponent__svg_g_Template_1(rf:IDENT,ctx0:IDENT) {
if (rf & 2) { $r3$.ɵp(1,"forOf",$r3$.ɵb(ctx.items)); }
function MyComponent__svg_g_Template_1(rf, ctx0) {
if (rf & 1) {
$r3$.ɵNS();
$r3$.ɵE(0,'g');
$r3$.ɵEe(1,'circle');
$r3$.ɵE(0,"g");
$r3$.ɵEe(1,"circle");
$r3$.ɵe();
}
}
@ -1413,43 +1410,43 @@ describe('compiler compliance', () => {
// TODO(chuckj): Enforce this when the directives are specified
const ForDirectiveDefinition = `
static ngDirectiveDef = $r3$.ɵdefineDirective({
ForOfDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: ForOfDirective,
selectors: [['', 'forOf', '']],
selectors: [["", "forOf", ""]],
factory: function ForOfDirective_Factory() {
return new ForOfDirective($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef());
},
features: [$r3$.ɵNgOnChangesFeature],
inputs: {forOf: 'forOf'}
inputs: {forOf: "forOf"}
});
`;
const MyComponentDefinition = `
const $_c0$ = ['for','','forOf',''];
const $_c0$ = ["for","","forOf",""];
static ngComponentDef = $r3$.ɵdefineComponent({
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selectors: [['my-component']],
selectors: [["my-component"]],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵE(0, 'ul');
$r3$.ɵE(0, "ul");
$r3$.ɵC(1, MyComponent_li_Template_1, null, $_c0$);
$r3$.ɵe();
}
if (rf & 2) {
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
$r3$.ɵp(1, "forOf", $r3$.ɵb(ctx.items));
}
function MyComponent_li_Template_1(rf: IDENT, ctx0: IDENT) {
function MyComponent_li_Template_1(rf, ctx0) {
if (rf & 1) {
$r3$.ɵE(0, 'li');
$r3$.ɵE(0, "li");
$r3$.ɵT(1);
$r3$.ɵe();
}
if (rf & 2) {
const $item$ = ctx0.$implicit;
$r3$.ɵt(1, $r3$.ɵi1('', $item$.name, ''));
$r3$.ɵt(1, $r3$.ɵi1("", $item$.name, ""));
}
}
},
@ -1503,49 +1500,49 @@ describe('compiler compliance', () => {
};
const MyComponentDefinition = `
const $c1$ = ['for', '', 'forOf', ''];
const $c1$ = ["for", "", "forOf", ""];
static ngComponentDef = $r3$.ɵdefineComponent({
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selectors: [['my-component']],
selectors: [["my-component"]],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵE(0, 'ul');
$r3$.ɵE(0, "ul");
$r3$.ɵC(1, MyComponent_li_Template_1, null, $c1$);
$r3$.ɵe();
}
if (rf & 2) {
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
$r3$.ɵp(1, "forOf", $r3$.ɵb(ctx.items));
}
function MyComponent_li_Template_1(rf: IDENT, ctx0: IDENT) {
function MyComponent_li_Template_1(rf, ctx0) {
if (rf & 1) {
$r3$.ɵE(0, 'li');
$r3$.ɵE(1, 'div');
$r3$.ɵE(0, "li");
$r3$.ɵE(1, "div");
$r3$.ɵT(2);
$r3$.ɵe();
$r3$.ɵE(3, 'ul');
$r3$.ɵE(3, "ul");
$r3$.ɵC(4, MyComponent_li_li_Template_4, null, $c1$);
$r3$.ɵe();
$r3$.ɵe();
}
if (rf & 2) {
const $item$ = ctx0.$implicit;
$r3$.ɵt(2, $r3$.ɵi1('', IDENT.name, ''));
$r3$.ɵp(4, 'forOf', $r3$.ɵb(IDENT.infos));
$r3$.ɵt(2, $r3$.ɵi1("", IDENT.name, ""));
$r3$.ɵp(4, "forOf", $r3$.ɵb(IDENT.infos));
}
function MyComponent_li_li_Template_4(rf: IDENT, ctx1: IDENT) {
function MyComponent_li_li_Template_4(rf, ctx1) {
if (rf & 1) {
$r3$.ɵE(0, 'li');
$r3$.ɵE(0, "li");
$r3$.ɵT(1);
$r3$.ɵe();
}
if (rf & 2) {
const $item$ = ctx0.$implicit;
const $info$ = ctx1.$implicit;
$r3$.ɵt(1, $r3$.ɵi2(' ', $item$.name, ': ', $info$.description, ' '));
$r3$.ɵt(1, $r3$.ɵi2(" ", $item$.name, ": ", $info$.description, " "));
}
}
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {MockDirectory, setup} from '../aot/test_util';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
describe('compiler compliance: bindings', () => {
@ -37,14 +37,14 @@ describe('compiler compliance: bindings', () => {
};
const template = `
template:function MyComponent_Template(rf: IDENT, $ctx$: IDENT){
template:function MyComponent_Template(rf, $ctx$){
if (rf & 1) {
$i0$.ɵE(0, 'div');
$i0$.ɵE(0, "div");
$i0$.ɵT(1);
$i0$.ɵe();
}
if (rf & 2) {
$i0$.ɵt(1, $i0$.ɵi1('Hello ', $ctx$.name, ''));
$i0$.ɵt(1, $i0$.ɵi1("Hello ", $ctx$.name, ""));
}
}`;
const result = compile(files, angularFiles);
@ -73,12 +73,12 @@ describe('compiler compliance: bindings', () => {
};
const template = `
template:function MyComponent_Template(rf: IDENT, $ctx$: IDENT){
template:function MyComponent_Template(rf, $ctx$){
if (rf & 1) {
$i0$.ɵEe(0, 'a');
$i0$.ɵEe(0, "a");
}
if (rf & 2) {
$i0$.ɵp(0, 'title', $i0$.ɵb($ctx$.title));
$i0$.ɵp(0, "title", $i0$.ɵb($ctx$.title));
}
}`;
const result = compile(files, angularFiles);
@ -105,12 +105,12 @@ describe('compiler compliance: bindings', () => {
};
const template = `
template:function MyComponent_Template(rf: IDENT, $ctx$: IDENT){
template:function MyComponent_Template(rf, $ctx$){
if (rf & 1) {
$i0$.ɵEe(0, 'a');
$i0$.ɵEe(0, "a");
}
if (rf & 2) {
$i0$.ɵp(0, 'title', $i0$.ɵi1('Hello ', $ctx$.name, ''));
$i0$.ɵp(0, "title", $i0$.ɵi1("Hello ", $ctx$.name, ""));
}
}`;
const result = compile(files, angularFiles);

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {MockDirectory, setup} from '../aot/test_util';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
describe('compiler compliance: dependency injection', () => {

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {setup} from '../aot/test_util';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
const TRANSLATION_NAME_REGEXP = /^MSG_[A-Z0-9]+/;
@ -43,15 +43,15 @@ describe('i18n support in the view compiler', () => {
};
const template = `
const $msg_1$ = goog.getMsg('Hello world');
const $msg_2$ = goog.getMsg('farewell');
const $msg_1$ = goog.getMsg("Hello world");
const $msg_2$ = goog.getMsg("farewell");
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵT(1, $msg_1$);
$r3$.ɵT(3,'&');
$r3$.ɵT(3,"&");
$r3$.ɵT(5, $msg_2$);
@ -92,18 +92,18 @@ describe('i18n support in the view compiler', () => {
/**
* @desc desc
*/
const $msg_1$ = goog.getMsg('introduction');
const $c1$ = ['title', $msg_1$];
const $msg_1$ = goog.getMsg("introduction");
const $c1$ = ["title", $msg_1$];
/**
* @desc desc
* @meaning meaning
*/
const $msg_2$ = goog.getMsg('Hello world');
const $msg_2$ = goog.getMsg("Hello world");
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $c1$);
$r3$.ɵE(0, "div", $c1$);
$r3$.ɵT(1, $msg_2$);
$r3$.ɵe();
}
@ -143,12 +143,12 @@ describe('i18n support in the view compiler', () => {
* @desc d
* @meaning m
*/
const $msg_1$ = goog.getMsg('introduction');
const $c1$ = ['id', 'static', 'title', $msg_1$];
const $msg_1$ = goog.getMsg("introduction");
const $c1$ = ["id", "static", "title", $msg_1$];
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵEe(0, 'div', $c1$);
$r3$.ɵEe(0, "div", $c1$);
}
}
`;
@ -186,8 +186,8 @@ describe('i18n support in the view compiler', () => {
};
const template = `
const $r1$ = {'b':[2], 'i':[4, 6]};
const $r2$ = {'i':[13]};
const $r1$ = {"b":[2], "i":[4, 6]};
const $r2$ = {"i":[13]};
`;
const result = compile(files, angularFiles);

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {MockDirectory, setup} from '../aot/test_util';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
describe('compiler compliance: listen()', () => {
@ -52,29 +52,29 @@ describe('compiler compliance: listen()', () => {
};
const componentDef = `
static ngComponentDef = IDENT.ɵdefineComponent({
MyComponent.ngComponentDef = IDENT.ɵdefineComponent({
inputs:{
componentInput: 'componentInput',
originalComponentInput: 'renamedComponentInput'
componentInput: "componentInput",
originalComponentInput: "renamedComponentInput"
},
outputs: {
componentOutput: 'componentOutput',
originalComponentOutput: 'renamedComponentOutput'
componentOutput: "componentOutput",
originalComponentOutput: "renamedComponentOutput"
}
});`;
const directiveDef = `
static ngDirectiveDef = IDENT.ɵdefineDirective({
MyDirective.ngDirectiveDef = IDENT.ɵdefineDirective({
inputs:{
directiveInput: 'directiveInput',
originalDirectiveInput: 'renamedDirectiveInput'
directiveInput: "directiveInput",
originalDirectiveInput: "renamedDirectiveInput"
},
outputs: {
directiveOutput: 'directiveOutput',
originalDirectiveOutput: 'renamedDirectiveOutput'
directiveOutput: "directiveOutput",
originalDirectiveOutput: "renamedDirectiveOutput"
}
});`;

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {MockDirectory, setup} from '../aot/test_util';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
/* These tests are codified version of the tests in compiler_canonical_spec.ts. Every
@ -41,10 +41,10 @@ describe('compiler compliance: listen()', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵL('click', function MyComponent_Template_div_click_listener($event: $any$) {
$r3$.ɵE(0, "div");
$r3$.ɵL("click", function MyComponent_Template_div_click_listener($event) {
ctx.onClick($event);
return (1 == 2);
});

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {MockDirectory, setup} from '../aot/test_util';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
describe('r3_view_compiler', () => {
@ -114,9 +114,9 @@ describe('r3_view_compiler', () => {
}
};
const bV_call = `$r3$.ɵiV([' ',ctx.list[0],' ',ctx.list[1],' ',ctx.list[2],' ',ctx.list[3],
' ',ctx.list[4],' ',ctx.list[5],' ',ctx.list[6],' ',ctx.list[7],' ',ctx.list[8],
' '])`;
const bV_call = `$r3$.ɵiV([" ",ctx.list[0]," ",ctx.list[1]," ",ctx.list[2]," ",ctx.list[3],
" ",ctx.list[4]," ",ctx.list[5]," ",ctx.list[6]," ",ctx.list[7]," ",ctx.list[8],
" "])`;
const result = compile(files, angularFiles);
expectEmit(result.source, bV_call, 'Incorrect bV call');
});

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {InitialStylingFlags} from '../../src/core';
import {MockDirectory, setup} from '../aot/test_util';
import {InitialStylingFlags} from '@angular/compiler/src/core';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
@ -40,9 +40,9 @@ describe('compiler compliance: styling', () => {
};
const template = `
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵE(0, "div");
$r3$.ɵs();
$r3$.ɵe();
}
@ -85,17 +85,17 @@ describe('compiler compliance: styling', () => {
};
const template = `
const _c0 = ['opacity','width','height',${InitialStylingFlags.VALUES_MODE},'opacity','1'];
class MyComponent {
static ngComponentDef = i0.ɵdefineComponent({
const _c0 = ["opacity","width","height",${InitialStylingFlags.VALUES_MODE},"opacity","1"];
MyComponent.ngComponentDef = i0.ɵdefineComponent({
type: MyComponent,
selectors:[['my-component']],
selectors:[["my-component"]],
factory:function MyComponent_Factory(){
return new MyComponent();
},
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵE(0, "div");
$r3$.ɵs(_c0);
$r3$.ɵe();
}
@ -104,7 +104,7 @@ describe('compiler compliance: styling', () => {
$r3$.ɵsp(0, 1, $ctx$.myWidth);
$r3$.ɵsp(0, 2, $ctx$.myHeight);
$r3$.ɵsa(0);
$r3$.ɵa(0, 'style', $r3$.ɵb('border-width: 10px'));
$r3$.ɵa(0, "style", $r3$.ɵb("border-width: 10px"));
}
}
});
@ -137,14 +137,14 @@ describe('compiler compliance: styling', () => {
};
const template = `
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵE(0, "div");
$r3$.ɵs();
$r3$.ɵe();
}
if (rf & 2) {
$r3$.ɵsm(0,(null as any),$ctx$.myClassExp);
$r3$.ɵsm(0,null,$ctx$.myClassExp);
$r3$.ɵsa(0);
}
}
@ -182,26 +182,26 @@ describe('compiler compliance: styling', () => {
};
const template = `
const _c0 = ['grape','apple','orange',${InitialStylingFlags.VALUES_MODE},'grape',true];
class MyComponent {
static ngComponentDef = i0.ɵdefineComponent({
const _c0 = ["grape","apple","orange",${InitialStylingFlags.VALUES_MODE},"grape",true];
MyComponent.ngComponentDef = i0.ɵdefineComponent({
type: MyComponent,
selectors:[['my-component']],
selectors:[["my-component"]],
factory:function MyComponent_Factory(){
return new MyComponent();
},
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵs((null as any), _c0);
$r3$.ɵE(0, "div");
$r3$.ɵs(null, _c0);
$r3$.ɵe();
}
if (rf & 2) {
$r3$.ɵsm(0, (null as any), $ctx$.myClassExp);
$r3$.ɵsm(0, null, $ctx$.myClassExp);
$r3$.ɵcp(0, 1, $ctx$.yesToApple);
$r3$.ɵcp(0, 2, $ctx$.yesToOrange);
$r3$.ɵsa(0);
$r3$.ɵa(0, 'class', $r3$.ɵb('banana'));
$r3$.ɵa(0, "class", $r3$.ɵb("banana"));
}
}
});
@ -234,24 +234,24 @@ describe('compiler compliance: styling', () => {
};
const template = `
const _c0 = ['width',${InitialStylingFlags.VALUES_MODE},'width','100px'];
const _c1 = ['foo',${InitialStylingFlags.VALUES_MODE},'foo',true];
class MyComponent {
static ngComponentDef = i0.ɵdefineComponent({
const _c0 = ["width",${InitialStylingFlags.VALUES_MODE},"width","100px"];
const _c1 = ["foo",${InitialStylingFlags.VALUES_MODE},"foo",true];
MyComponent.ngComponentDef = i0.ɵdefineComponent({
type: MyComponent,
selectors:[['my-component']],
selectors:[["my-component"]],
factory:function MyComponent_Factory(){
return new MyComponent();
},
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵE(0, "div");
$r3$.ɵs(_c0, _c1);
$r3$.ɵe();
}
if (rf & 2) {
$r3$.ɵa(0, 'class', $r3$.ɵb('round'));
$r3$.ɵa(0, 'style', $r3$.ɵb('height:100px'));
$r3$.ɵa(0, "class", $r3$.ɵb("round"));
$r3$.ɵa(0, "style", $r3$.ɵb("height:100px"));
}
}
});

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {MockDirectory, setup} from '../aot/test_util';
import {MockDirectory, setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
describe('compiler compliance: template', () => {
@ -51,39 +51,39 @@ describe('compiler compliance: template', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
const $c0$ = ['ngFor','','ngForOf',''];
const $c0$ = ["ngFor","","ngForOf",""];
// ...
template:function MyComponent_Template(rf: IDENT, $ctx$: IDENT){
template:function MyComponent_Template(rf, $ctx$){
if (rf & 1) {
$i0$.ɵC(0, MyComponent_ul_Template_0, null, _c0);
}
if (rf & 2) {
$i0$.ɵp(0, 'ngForOf', $i0$.ɵb($ctx$.items));
$i0$.ɵp(0, "ngForOf", $i0$.ɵb($ctx$.items));
}
function MyComponent_ul_Template_0(rf: IDENT, $ctx0$: IDENT) {
function MyComponent_ul_Template_0(rf, $ctx0$) {
if (rf & 1) {
$i0$.ɵE(0, 'ul');
$i0$.ɵE(0, "ul");
$i0$.ɵC(1, MyComponent_ul_li_Template_1, null, _c0);
$i0$.ɵe();
}
if (rf & 2) {
const $outer$ = $ctx0$.$implicit;
$i0$.ɵp(1, 'ngForOf', $i0$.ɵb($outer$.items));
$i0$.ɵp(1, "ngForOf", $i0$.ɵb($outer$.items));
}
function MyComponent_ul_li_Template_1(rf: IDENT, $ctx1$: IDENT) {
function MyComponent_ul_li_Template_1(rf, $ctx1$) {
if (rf & 1) {
$i0$.ɵE(0, 'li');
$i0$.ɵE(0, "li");
$i0$.ɵC(1, MyComponent_ul_li_div_Template_1, null, _c0);
$i0$.ɵe();
}
if (rf & 2) {
$i0$.ɵp(1, 'ngForOf', $i0$.ɵb($ctx$.items));
$i0$.ɵp(1, "ngForOf", $i0$.ɵb($ctx$.items));
}
function MyComponent_ul_li_div_Template_1(rf: IDENT, $ctx2$: IDENT) {
function MyComponent_ul_li_div_Template_1(rf, $ctx2$) {
if (rf & 1) {
$i0$.ɵE(0, 'div');
$i0$.ɵL('click', function MyComponent_ul_li_div_Template_1_div_click_listener($event:any){
$i0$.ɵE(0, "div");
$i0$.ɵL("click", function MyComponent_ul_li_div_Template_1_div_click_listener($event){
const $outer$ = $ctx0$.$implicit;
const $middle$ = $ctx1$.$implicit;
const $inner$ = $ctx2$.$implicit;
@ -96,8 +96,8 @@ describe('compiler compliance: template', () => {
const $outer$ = $ctx0$.$implicit;
const $middle$ = $ctx1$.$implicit;
const $inner$ = $ctx2$.$implicit;
$i0$.ɵp(0, 'title', $i0$.ɵb(ctx.format($outer$, $middle$, $inner$, $ctx$.component)));
$i0$.ɵt(1, $i0$.ɵi1(' ', ctx.format($outer$, $middle$, $inner$, $ctx$.component), ' '));
$i0$.ɵp(0, "title", $i0$.ɵb(ctx.format($outer$, $middle$, $inner$, $ctx$.component)));
$i0$.ɵt(1, $i0$.ɵi1(" ", ctx.format($outer$, $middle$, $inner$, $ctx$.component), " "));
}
}
}

View File

@ -20,10 +20,6 @@ ts_library(
jasmine_node_test(
name = "test",
bootstrap = ["angular/tools/testing/init_node_spec.js"],
data = [
"//packages/common:npm_package",
"//packages/core:npm_package",
],
deps = [
":test_lib",
"//tools/testing:node",

View File

@ -1,329 +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 {AotCompilerOptions, AotSummaryResolver, CompileMetadataResolver, CompilerConfig, DEFAULT_INTERPOLATION_CONFIG, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, HtmlParser, Lexer, NgModuleResolver, ParseError, Parser, PipeResolver, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, TemplateParser, TypeScriptEmitter, analyzeNgModules, createAotUrlResolver} from '@angular/compiler';
import {ViewEncapsulation} from '@angular/core';
import * as ts from 'typescript';
import {NgAnalyzedModules} from '../../src/aot/compiler';
import {ConstantPool} from '../../src/constant_pool';
import * as html from '../../src/ml_parser/ast';
import {removeWhitespaces} from '../../src/ml_parser/html_whitespaces';
import * as o from '../../src/output/output_ast';
import {compilePipeFromRender2} from '../../src/render3/r3_pipe_compiler';
import {htmlAstToRender3Ast} from '../../src/render3/r3_template_transform';
import {compileComponentFromRender2, compileDirectiveFromRender2} from '../../src/render3/view/compiler';
import {BindingParser} from '../../src/template_parser/binding_parser';
import {OutputContext, escapeRegExp} from '../../src/util';
import {MockAotCompilerHost, MockCompilerHost, MockData, MockDirectory, arrayToMockDir, expectNoDiagnostics, settings, toMockFileArray} from '../aot/test_util';
const IDENTIFIER = /[A-Za-z_$ɵ][A-Za-z0-9_$]*/;
const OPERATOR =
/!|%|\*|\/|\^|&&?|\|\|?|\(|\)|\{|\}|\[|\]|:|;|<=?|>=?|={1,3}|!==?|=>|\+\+?|--?|@|,|\.|\.\.\./;
const STRING = /'[^']*'|"[^"]*"|`[\s\S]*?`/;
const NUMBER = /\d+/;
const ELLIPSIS = '…';
const TOKEN = new RegExp(
`\\s*((${IDENTIFIER.source})|(${OPERATOR.source})|(${STRING.source})|${NUMBER.source}|${ELLIPSIS})`,
'y');
type Piece = string | RegExp;
const SKIP = /(?:.|\n|\r)*/;
const ERROR_CONTEXT_WIDTH = 30;
// Transform the expected output to set of tokens
function tokenize(text: string): Piece[] {
TOKEN.lastIndex = 0;
let match: RegExpMatchArray|null;
const pieces: Piece[] = [];
while ((match = TOKEN.exec(text)) !== null) {
const token = match[1];
if (token === 'IDENT') {
pieces.push(IDENTIFIER);
} else if (token === ELLIPSIS) {
pieces.push(SKIP);
} else {
pieces.push(token);
}
}
if (pieces.length === 0 || TOKEN.lastIndex !== 0) {
const from = TOKEN.lastIndex;
const to = from + ERROR_CONTEXT_WIDTH;
throw Error(`Invalid test, no token found for '${text.substr(from, to)}...'`);
}
return pieces;
}
export function expectEmit(
source: string, expected: string, description: string,
assertIdentifiers?: {[name: string]: RegExp}) {
// turns `// ...` into `…`
// remove `// TODO` comment lines
expected = expected.replace(/\/\/\s*\.\.\./g, ELLIPSIS).replace(/\/\/\s*TODO.*?\n/g, '');
const pieces = tokenize(expected);
const {regexp, groups} = buildMatcher(pieces);
const matches = source.match(regexp);
if (matches === null) {
let last: number = 0;
for (let i = 1; i < pieces.length; i++) {
const {regexp} = buildMatcher(pieces.slice(0, i));
const m = source.match(regexp);
const expectedPiece = pieces[i - 1] == IDENTIFIER ? '<IDENT>' : pieces[i - 1];
if (!m) {
fail(
`${description}: Expected to find ${expectedPiece} '${source.substr(0,last)}[<---HERE expected "${expectedPiece}"]${source.substr(last)}'`);
return;
} else {
last = (m.index || 0) + m[0].length;
}
}
fail(
`Test helper failure: Expected expression failed but the reporting logic could not find where it failed in: ${source}`);
} else {
if (assertIdentifiers) {
// It might be possible to add the constraints in the original regexp (see `buildMatcher`)
// by transforming the assertion regexps when using anchoring, grouping, back references,
// flags, ...
//
// Checking identifiers after they have matched allows for a simple and flexible
// implementation.
// The overall performance are not impacted when `assertIdentifiers` is empty.
const ids = Object.keys(assertIdentifiers);
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
if (groups.has(id)) {
const name = matches[groups.get(id) as number];
const regexp = assertIdentifiers[id];
if (!regexp.test(name)) {
throw Error(
`${description}: The matching identifier "${id}" is "${name}" which doesn't match ${regexp}`);
}
}
}
}
}
}
const IDENT_LIKE = /^[a-z][A-Z]/;
const MATCHING_IDENT = /^\$.*\$$/;
/*
* Builds a regexp that matches the given `pieces`
*
* It returns:
* - the `regexp` to be used to match the generated code,
* - the `groups` which maps `$...$` identifier to their position in the regexp matches.
*/
function buildMatcher(pieces: (string | RegExp)[]): {regexp: RegExp, groups: Map<string, number>} {
const results: string[] = [];
let first = true;
let group = 0;
const groups = new Map<string, number>();
for (const piece of pieces) {
if (!first)
results.push(`\\s${typeof piece === 'string' && IDENT_LIKE.test(piece) ? '+' : '*'}`);
first = false;
if (typeof piece === 'string') {
if (MATCHING_IDENT.test(piece)) {
const matchGroup = groups.get(piece);
if (!matchGroup) {
results.push('(' + IDENTIFIER.source + ')');
const newGroup = ++group;
groups.set(piece, newGroup);
} else {
results.push(`\\${matchGroup}`);
}
} else {
results.push(escapeRegExp(piece));
}
} else {
results.push('(?:' + piece.source + ')');
}
}
return {
regexp: new RegExp(results.join('')),
groups,
};
}
function doCompile(
data: MockDirectory, angularFiles: MockData, options: AotCompilerOptions = {},
errorCollector: (error: any, fileName?: string) => void = error => { throw error; },
compileAction: (
outputCtx: OutputContext, analyzedModules: NgAnalyzedModules,
resolver: CompileMetadataResolver, htmlParser: HtmlParser, templateParser: TemplateParser,
hostBindingParser: BindingParser, reflector: StaticReflector) => void) {
const testFiles = toMockFileArray(data);
const scripts = testFiles.map(entry => entry.fileName);
const angularFilesArray = toMockFileArray(angularFiles);
const files = arrayToMockDir([...testFiles, ...angularFilesArray]);
const mockCompilerHost = new MockCompilerHost(scripts, files);
const compilerHost = new MockAotCompilerHost(mockCompilerHost);
const program = ts.createProgram(scripts, {...settings}, mockCompilerHost);
expectNoDiagnostics(program);
// TODO(chuckj): Replace with a variant of createAotCompiler() when the r3_view_compiler is
// integrated
const urlResolver = createAotUrlResolver(compilerHost);
const symbolCache = new StaticSymbolCache();
const summaryResolver = new AotSummaryResolver(compilerHost, symbolCache);
const symbolResolver = new StaticSymbolResolver(compilerHost, symbolCache, summaryResolver);
const staticReflector =
new StaticReflector(summaryResolver, symbolResolver, [], [], errorCollector);
const htmlParser = new HtmlParser();
const config = new CompilerConfig({
defaultEncapsulation: ViewEncapsulation.Emulated,
useJit: false,
missingTranslation: options.missingTranslation,
preserveWhitespaces: options.preserveWhitespaces,
strictInjectionParameters: options.strictInjectionParameters,
});
const normalizer = new DirectiveNormalizer(
{get: (url: string) => compilerHost.loadResource(url)}, urlResolver, htmlParser, config);
const expressionParser = new Parser(new Lexer());
const elementSchemaRegistry = new DomElementSchemaRegistry();
const templateParser = new TemplateParser(
config, staticReflector, expressionParser, elementSchemaRegistry, htmlParser, console, []);
const resolver = new CompileMetadataResolver(
config, htmlParser, new NgModuleResolver(staticReflector),
new DirectiveResolver(staticReflector), new PipeResolver(staticReflector), summaryResolver,
elementSchemaRegistry, normalizer, console, symbolCache, staticReflector, errorCollector);
// Create the TypeScript program
const sourceFiles = program.getSourceFiles().map(sf => sf.fileName);
// Analyze the modules
// TODO(chuckj): Eventually this should not be necessary as the ts.SourceFile should be sufficient
// to generate a template definition.
const analyzedModules = analyzeNgModules(sourceFiles, compilerHost, symbolResolver, resolver);
const pipesOrDirectives = Array.from(analyzedModules.ngModuleByPipeOrDirective.keys());
const fakeOutputContext: OutputContext = {
genFilePath: 'fakeFactory.ts',
statements: [],
importExpr(symbol: StaticSymbol, typeParams: o.Type[]) {
if (!(symbol instanceof StaticSymbol)) {
if (!symbol) {
throw new Error('Invalid: undefined passed to as a symbol');
}
throw new Error(`Invalid: ${(symbol as any).constructor.name} is not a symbol`);
}
return (symbol.members || [])
.reduce(
(expr, member) => expr.prop(member),
<o.Expression>o.importExpr(new o.ExternalReference(symbol.filePath, symbol.name)));
},
constantPool: new ConstantPool()
};
const errors: ParseError[] = [];
const hostBindingParser = new BindingParser(
expressionParser, DEFAULT_INTERPOLATION_CONFIG, elementSchemaRegistry, null, errors);
// Load all directives and pipes
for (const pipeOrDirective of pipesOrDirectives) {
const module = analyzedModules.ngModuleByPipeOrDirective.get(pipeOrDirective) !;
resolver.loadNgModuleDirectiveAndPipeMetadata(module.type.reference, true);
}
compileAction(
fakeOutputContext, analyzedModules, resolver, htmlParser, templateParser, hostBindingParser,
staticReflector);
fakeOutputContext.statements.unshift(...fakeOutputContext.constantPool.statements);
const emitter = new TypeScriptEmitter();
const result = emitter.emitStatementsAndContext(
fakeOutputContext.genFilePath, fakeOutputContext.statements, '', false,
/* referenceFilter */ undefined,
/* importFilter */ e => e.moduleName != null && e.moduleName.startsWith('/app'));
if (errors.length) {
throw new Error('Unexpected errors:' + errors.map(e => e.toString()).join(', '));
}
return {source: result.sourceText, outputContext: fakeOutputContext};
}
export function compile(
data: MockDirectory, angularFiles: MockData, options: AotCompilerOptions = {},
errorCollector: (error: any, fileName?: string) => void = error => { throw error;}) {
return doCompile(
data, angularFiles, options, errorCollector,
(outputCtx: OutputContext, analyzedModules: NgAnalyzedModules,
resolver: CompileMetadataResolver, htmlParser: HtmlParser, templateParser: TemplateParser,
hostBindingParser: BindingParser, reflector: StaticReflector) => {
const pipesOrDirectives = Array.from(analyzedModules.ngModuleByPipeOrDirective.keys());
for (const pipeOrDirective of pipesOrDirectives) {
const module = analyzedModules.ngModuleByPipeOrDirective.get(pipeOrDirective);
if (!module || !module.type.reference.filePath.startsWith('/app')) {
continue;
}
if (resolver.isDirective(pipeOrDirective)) {
const directive = resolver.getDirectiveMetadata(pipeOrDirective);
if (directive.isComponent) {
const fakeUrl = 'ng://fake-template-url.html';
let htmlAst = htmlParser.parse(directive.template !.template !, fakeUrl);
// Map of StaticType by directive selectors
const directiveTypeBySel = new Map<string, any>();
const directives = module.transitiveModule.directives.map(
dir => resolver.getDirectiveSummary(dir.reference));
directives.forEach(directive => {
if (directive.selector) {
directiveTypeBySel.set(directive.selector, directive.type.reference);
}
});
// Map of StaticType by pipe names
const pipeTypeByName = new Map<string, any>();
const pipes = module.transitiveModule.pipes.map(
pipe => resolver.getPipeSummary(pipe.reference));
pipes.forEach(pipe => { pipeTypeByName.set(pipe.name, pipe.type.reference); });
const preserveWhitespaces = directive.template !.preserveWhitespaces;
if (!preserveWhitespaces) {
htmlAst = removeWhitespaces(htmlAst);
}
const render3Ast = htmlAstToRender3Ast(htmlAst.rootNodes, hostBindingParser);
compileComponentFromRender2(
outputCtx, directive, render3Ast, reflector, hostBindingParser,
directiveTypeBySel, pipeTypeByName);
} else {
compileDirectiveFromRender2(outputCtx, directive, reflector, hostBindingParser);
}
} else if (resolver.isPipe(pipeOrDirective)) {
const metadata = resolver.getPipeMetadata(pipeOrDirective);
if (metadata) {
compilePipeFromRender2(outputCtx, metadata, reflector);
}
}
}
});
}

View File

@ -58,6 +58,7 @@ const specFiles =
'@angular/_testing_init/**',
'@angular/compiler/test/aot/**',
'@angular/compiler/test/render3/**',
'@angular/compiler-cli/test/compliance/**',
'@angular/core/test/bundling/**',
'@angular/core/test/fake_async_spec.*',
'@angular/core/test/render3/**',