diff --git a/karma-js.conf.js b/karma-js.conf.js index 48b8a555fd..910a13bab3 100644 --- a/karma-js.conf.js +++ b/karma-js.conf.js @@ -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/**', diff --git a/packages/compiler-cli/test/compliance/BUILD.bazel b/packages/compiler-cli/test/compliance/BUILD.bazel new file mode 100644 index 0000000000..365b20bc3d --- /dev/null +++ b/packages/compiler-cli/test/compliance/BUILD.bazel @@ -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", + ], +) diff --git a/packages/compiler-cli/test/compliance/README.md b/packages/compiler-cli/test/compliance/README.md new file mode 100644 index 0000000000..7c522a1396 --- /dev/null +++ b/packages/compiler-cli/test/compliance/README.md @@ -0,0 +1 @@ +Tests in this directory are excluded from running in the browser and only run in node. \ No newline at end of file diff --git a/packages/compiler-cli/test/compliance/mock_compile.ts b/packages/compiler-cli/test/compliance/mock_compile.ts new file mode 100644 index 0000000000..e258951271 --- /dev/null +++ b/packages/compiler-cli/test/compliance/mock_compile.ts @@ -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 ? '' : 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} { + const results: string[] = []; + let first = true; + let group = 0; + + const groups = new Map(); + 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}; +} diff --git a/packages/compiler/test/render3/mock_compiler_spec.ts b/packages/compiler-cli/test/compliance/mock_compiler_spec.ts similarity index 96% rename from packages/compiler/test/render3/mock_compiler_spec.ts rename to packages/compiler-cli/test/compliance/mock_compiler_spec.ts index 3b7ceffa87..128890af0e 100644 --- a/packages/compiler/test/render3/mock_compiler_spec.ts +++ b/packages/compiler-cli/test/compliance/mock_compiler_spec.ts @@ -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'); diff --git a/packages/compiler/test/render3/r3_compiler_compliance_spec.ts b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts similarity index 77% rename from packages/compiler/test/render3/r3_compiler_compliance_spec.ts rename to packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts index 007c103bc4..33bf098b7f 100644 --- a/packages/compiler/test/render3/r3_compiler_compliance_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts @@ -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, " ")); } } } diff --git a/packages/compiler/test/render3/r3_view_compiler_binding_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_binding_spec.ts similarity index 84% rename from packages/compiler/test/render3/r3_view_compiler_binding_spec.ts rename to packages/compiler-cli/test/compliance/r3_view_compiler_binding_spec.ts index a9f4f3672e..4b6d9b474b 100644 --- a/packages/compiler/test/render3/r3_view_compiler_binding_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_binding_spec.ts @@ -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); diff --git a/packages/compiler/test/render3/r3_view_compiler_di_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_di_spec.ts similarity index 96% rename from packages/compiler/test/render3/r3_view_compiler_di_spec.ts rename to packages/compiler-cli/test/compliance/r3_view_compiler_di_spec.ts index 11912e0ee6..455569a0a5 100644 --- a/packages/compiler/test/render3/r3_view_compiler_di_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_di_spec.ts @@ -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', () => { diff --git a/packages/compiler/test/render3/r3_view_compiler_i18n_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts similarity index 87% rename from packages/compiler/test/render3/r3_view_compiler_i18n_spec.ts rename to packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts index 1065b3acb9..f3af5b9a3b 100644 --- a/packages/compiler/test/render3/r3_view_compiler_i18n_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts @@ -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); diff --git a/packages/compiler/test/render3/r3_view_compiler_input_outputs_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_input_outputs_spec.ts similarity index 76% rename from packages/compiler/test/render3/r3_view_compiler_input_outputs_spec.ts rename to packages/compiler-cli/test/compliance/r3_view_compiler_input_outputs_spec.ts index bfdbc3ab87..6b8adb4abf 100644 --- a/packages/compiler/test/render3/r3_view_compiler_input_outputs_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_input_outputs_spec.ts @@ -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" } … });`; diff --git a/packages/compiler/test/render3/r3_view_compiler_listener_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_listener_spec.ts similarity index 85% rename from packages/compiler/test/render3/r3_view_compiler_listener_spec.ts rename to packages/compiler-cli/test/compliance/r3_view_compiler_listener_spec.ts index 7dbf578df2..2fc273996e 100644 --- a/packages/compiler/test/render3/r3_view_compiler_listener_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_listener_spec.ts @@ -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); }); diff --git a/packages/compiler/test/render3/r3_view_compiler_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_spec.ts similarity index 91% rename from packages/compiler/test/render3/r3_view_compiler_spec.ts rename to packages/compiler-cli/test/compliance/r3_view_compiler_spec.ts index 192aee4b0b..c67dfb1efe 100644 --- a/packages/compiler/test/render3/r3_view_compiler_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_spec.ts @@ -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'); }); diff --git a/packages/compiler/test/render3/r3_view_compiler_styling_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts similarity index 78% rename from packages/compiler/test/render3/r3_view_compiler_styling_spec.ts rename to packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts index 63b29ae47a..24ddf9447d 100644 --- a/packages/compiler/test/render3/r3_view_compiler_styling_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts @@ -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")); } } }); diff --git a/packages/compiler/test/render3/r3_view_compiler_template_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts similarity index 75% rename from packages/compiler/test/render3/r3_view_compiler_template_spec.ts rename to packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts index 12041faec4..8c7d522ce8 100644 --- a/packages/compiler/test/render3/r3_view_compiler_template_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts @@ -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), " ")); } } } diff --git a/packages/compiler/test/render3/BUILD.bazel b/packages/compiler/test/render3/BUILD.bazel index 27bd131ce3..48af3bc592 100644 --- a/packages/compiler/test/render3/BUILD.bazel +++ b/packages/compiler/test/render3/BUILD.bazel @@ -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", diff --git a/packages/compiler/test/render3/mock_compile.ts b/packages/compiler/test/render3/mock_compile.ts deleted file mode 100644 index 441a53c942..0000000000 --- a/packages/compiler/test/render3/mock_compile.ts +++ /dev/null @@ -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 ? '' : 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} { - const results: string[] = []; - let first = true; - let group = 0; - - const groups = new Map(); - 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.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(); - - 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(); - - 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); - } - } - } - - }); -} diff --git a/tools/cjs-jasmine/index.ts b/tools/cjs-jasmine/index.ts index 2527b28d3f..8b06bad1d6 100644 --- a/tools/cjs-jasmine/index.ts +++ b/tools/cjs-jasmine/index.ts @@ -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/**',