Compare commits
130 Commits
7.2.2
...
backup-7.2
Author | SHA1 | Date | |
---|---|---|---|
279c57f38d | |||
35ec2dc9bc | |||
332dcb2d47 | |||
2c3b084817 | |||
918d906a1e | |||
12e3b71740 | |||
9faad4b2b0 | |||
42ccea547e | |||
67e6b63165 | |||
88d415515a | |||
3bc02a3652 | |||
a3f72d92f2 | |||
f86eb9a133 | |||
ac3c9c1e6e | |||
c9f213c0ea | |||
23d8edb263 | |||
23e2127cee | |||
0af5b8eb7a | |||
17403a2b1d | |||
325bf558ba | |||
21a9fe64d6 | |||
961d55395d | |||
c7fe8de182 | |||
7928356a62 | |||
0316fda529 | |||
6650e525ec | |||
2558e6843c | |||
1b2ba78090 | |||
5f0d845ca9 | |||
5f616ca613 | |||
b47ea97a48 | |||
f8101804a2 | |||
5a8c14b6d7 | |||
31556fa7b0 | |||
01d475d6f3 | |||
3c08b86e27 | |||
b102835294 | |||
0465dc6637 | |||
937a856b47 | |||
eeb4c87dc0 | |||
a82ba5d4dc | |||
28c6e9d684 | |||
9ea8f7197f | |||
0d9afd85f1 | |||
d2eea769f6 | |||
7bafe180fb | |||
457781906b | |||
2530c9d2dd | |||
c18c46a976 | |||
9447b852a4 | |||
11d184aaae | |||
d4b476fb45 | |||
a64a7a4041 | |||
9bda4460fa | |||
acb69e8341 | |||
69ca7cd381 | |||
e5f5ad34a2 | |||
51f8892d9b | |||
a06469c2f5 | |||
eb3345b950 | |||
ecc304adac | |||
49138bd114 | |||
aa7f2c8dc7 | |||
84857a267c | |||
e0ed78c2d0 | |||
b00efa3399 | |||
cdfca90053 | |||
0edca7997f | |||
2ce90323b8 | |||
7227b4aa62 | |||
5a7dd73b2c | |||
e1538fdd63 | |||
81da0fe91f | |||
fa377b350f | |||
097af5ae2b | |||
f1c3eab1e0 | |||
1edb8af20f | |||
0f34e3ac15 | |||
1cca9cc9d1 | |||
575cf3da0f | |||
11dfdf7f57 | |||
0bb03aaab1 | |||
df2704dc12 | |||
7714998869 | |||
c9c06a014f | |||
204b675ea4 | |||
23c666bdf5 | |||
9202a4de81 | |||
8c51e83a46 | |||
cbc45fd59b | |||
11fe52b805 | |||
50fadfaca3 | |||
9e04284bb3 | |||
216bbd09ef | |||
0c683a73e2 | |||
998bb8382e | |||
f893e2e502 | |||
bbe656e634 | |||
17825e8f55 | |||
7242551213 | |||
1ad88e0e59 | |||
6cc864a771 | |||
3fc02ce60b | |||
0a54825b29 | |||
970e3a0f79 | |||
791d8656fd | |||
7e98eedf5e | |||
5aecb2d43d | |||
9a15a42f29 | |||
fdd8b0402c | |||
d8aeb59c1c | |||
679235a44a | |||
e9de47c969 | |||
061615c16e | |||
213e01bd38 | |||
92d3942691 | |||
4ad7e21ce8 | |||
4b78c23c65 | |||
70c184b4bd | |||
98a617e415 | |||
0ae1e93eed | |||
dd59e9a343 | |||
89fd1822d4 | |||
4ae1880642 | |||
c51b0b9564 | |||
7bb760f6ff | |||
2013ef7ed0 | |||
6a13c107cf | |||
a3debf6a72 | |||
b1560f7357 |
12
.bazelrc
12
.bazelrc
@ -22,18 +22,12 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test
|
||||
# Filesystem interactions #
|
||||
###############################
|
||||
|
||||
# Create symlinks in the project:
|
||||
# - dist/bin for outputs
|
||||
# - dist/testlogs, dist/genfiles
|
||||
# - bazel-out
|
||||
# NB: bazel-out should be excluded from the editor configuration.
|
||||
# The checked-in /.vscode/settings.json does this for VSCode.
|
||||
# Other editors may require manual config to ignore this directory.
|
||||
# In the past, we say a problem where VSCode traversed a massive tree, opening file handles and
|
||||
# Don't create symlinks like bazel-out in the project.
|
||||
# These cause VSCode to traverse a massive tree, opening file handles and
|
||||
# eventually a surprising failure with auto-discovery of the C++ toolchain in
|
||||
# MacOS High Sierra.
|
||||
# See https://github.com/bazelbuild/bazel/issues/4603
|
||||
build --symlink_prefix=dist/
|
||||
build --symlink_prefix=/
|
||||
|
||||
# Performance: avoid stat'ing input files
|
||||
build --watchfs
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,7 +1,7 @@
|
||||
.DS_STORE
|
||||
|
||||
/dist/
|
||||
/bazel-out/
|
||||
/bazel-*
|
||||
/integration/bazel/bazel-*
|
||||
e2e_test.*
|
||||
node_modules
|
||||
@ -13,9 +13,9 @@ pubspec.lock
|
||||
.c9
|
||||
.idea/
|
||||
.settings/
|
||||
.vscode/launch.json
|
||||
*.swo
|
||||
modules/.settings
|
||||
.vscode
|
||||
modules/.vscode
|
||||
|
||||
# Don't check in secret files
|
||||
|
15
.vscode/settings.json
vendored
15
.vscode/settings.json
vendored
@ -1,15 +0,0 @@
|
||||
{
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/.git/subtree-cache/**": true,
|
||||
"**/node_modules/**": true,
|
||||
"**/bazel-out/**": true,
|
||||
"**/dist/**": true,
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/bower_components": true,
|
||||
"**/bazel-out": true,
|
||||
"**/dist": true,
|
||||
},
|
||||
}
|
44
CHANGELOG.md
44
CHANGELOG.md
@ -1,47 +1,3 @@
|
||||
<a name="7.2.2"></a>
|
||||
## [7.2.2](https://github.com/angular/angular/compare/7.2.1...7.2.2) (2019-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** Fix integration test after v8 bump ([#28194](https://github.com/angular/angular/issues/28194)) ([7b772e9](https://github.com/angular/angular/commit/7b772e9)), closes [#28142](https://github.com/angular/angular/issues/28142)
|
||||
* **router:** `skipLocationChange` with named outlets ([#28301](https://github.com/angular/angular/issues/28301)) ([32737a6](https://github.com/angular/angular/commit/32737a6)), closes [#27680](https://github.com/angular/angular/issues/27680) [#28200](https://github.com/angular/angular/issues/28200)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **bazel:** Add support for SASS ([#28167](https://github.com/angular/angular/issues/28167)) ([a4d9192](https://github.com/angular/angular/commit/a4d9192))
|
||||
* **compiler-cli:** resolve generated Sass/Less files to .css inputs ([#28166](https://github.com/angular/angular/issues/28166)) ([4c00059](https://github.com/angular/angular/commit/4c00059))
|
||||
|
||||
|
||||
|
||||
<a name="7.2.1"></a>
|
||||
## [7.2.1](https://github.com/angular/angular/compare/7.2.0...7.2.1) (2019-01-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** Add [@bazel](https://github.com/bazel)/bazel to dev deps ([#28032](https://github.com/angular/angular/issues/28032)) ([21093b9](https://github.com/angular/angular/commit/21093b9))
|
||||
* **bazel:** Add /bazel-out to .gitignore ([#27874](https://github.com/angular/angular/issues/27874)) ([e4fc8ba](https://github.com/angular/angular/commit/e4fc8ba))
|
||||
* **bazel:** Add ibazel to deps of Bazel project ([#28090](https://github.com/angular/angular/issues/28090)) ([28d34b6](https://github.com/angular/angular/commit/28d34b6))
|
||||
* **bazel:** Bazel schematics should add router package ([#28141](https://github.com/angular/angular/issues/28141)) ([02a852a](https://github.com/angular/angular/commit/02a852a))
|
||||
* **bazel:** flat module misses AMD module name on windows ([#27839](https://github.com/angular/angular/issues/27839)) ([c3d8e28](https://github.com/angular/angular/commit/c3d8e28))
|
||||
* **bazel:** incorrectly always uses ngc-wrapped from "npm" workspace ([#28137](https://github.com/angular/angular/issues/28137)) ([ca3965a](https://github.com/angular/angular/commit/ca3965a))
|
||||
* **bazel:** ng_package creates invalid typings reexport on windows ([#27829](https://github.com/angular/angular/issues/27829)) ([6b394f6](https://github.com/angular/angular/commit/6b394f6))
|
||||
* **bazel:** packager not properly removing amd directives on windows ([#27829](https://github.com/angular/angular/issues/27829)) ([fad4145](https://github.com/angular/angular/commit/fad4145))
|
||||
* **bazel:** protractor rule does not run spec files with underscore ([#28022](https://github.com/angular/angular/issues/28022)) ([f05c5f8](https://github.com/angular/angular/commit/f05c5f8))
|
||||
* **bazel:** protractor utils cannot start server on windows ([#27915](https://github.com/angular/angular/issues/27915)) ([0be8487](https://github.com/angular/angular/commit/0be8487))
|
||||
* **bazel:** replay compilation uses wrong compiler for building esm5 ([#28053](https://github.com/angular/angular/issues/28053)) ([fbbdaaa](https://github.com/angular/angular/commit/fbbdaaa))
|
||||
* **router:** ensure URL is updated after second redirect with UrlUpdateStrategy="eager" ([#27680](https://github.com/angular/angular/issues/27680)) ([6ae7aee](https://github.com/angular/angular/commit/6ae7aee)), closes [#27116](https://github.com/angular/angular/issues/27116)
|
||||
* **service-worker:** navigation urls backwards compatibility ([#27244](https://github.com/angular/angular/issues/27244)) ([585e871](https://github.com/angular/angular/commit/585e871))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **platform-server:** use shared `DomElementSchemaRegistry` instance ([#28150](https://github.com/angular/angular/issues/28150)) ([#28151](https://github.com/angular/angular/issues/28151)) ([6851581](https://github.com/angular/angular/commit/6851581))
|
||||
|
||||
|
||||
|
||||
<a name="7.2.0"></a>
|
||||
# [7.2.0](https://github.com/angular/angular/compare/7.1.4...7.2.0) (2019-01-07)
|
||||
|
||||
|
@ -26,8 +26,8 @@ ARG AIO_GITHUB_ORGANIZATION=angular
|
||||
ARG TEST_AIO_GITHUB_ORGANIZATION=test-org
|
||||
ARG AIO_GITHUB_REPO=angular
|
||||
ARG TEST_AIO_GITHUB_REPO=test-repo
|
||||
ARG AIO_GITHUB_TEAM_SLUGS=aio-contributors
|
||||
ARG TEST_AIO_GITHUB_TEAM_SLUGS=aio-contributors
|
||||
ARG AIO_GITHUB_TEAM_SLUGS=team,aio-contributors
|
||||
ARG TEST_AIO_GITHUB_TEAM_SLUGS=team,aio-contributors
|
||||
ARG AIO_NGINX_HOSTNAME=$AIO_DOMAIN_NAME
|
||||
ARG TEST_AIO_NGINX_HOSTNAME=$TEST_AIO_DOMAIN_NAME
|
||||
ARG AIO_NGINX_PORT_HTTP=80
|
||||
|
@ -16,7 +16,7 @@ const ITEMS: Item[] = [
|
||||
|
||||
const FETCH_LATENCY = 500;
|
||||
|
||||
/** Simulate a data service that retrieves items from a server */
|
||||
/** Simulate a data service that retrieves crises from a server */
|
||||
@Injectable()
|
||||
export class ItemService implements OnDestroy {
|
||||
|
||||
|
@ -3796,7 +3796,7 @@ The relevant *Crisis Center* code for this milestone follows.
|
||||
|
||||
</code-pane>
|
||||
|
||||
<code-pane header="crisis-detail.component.ts" path="router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts">
|
||||
<code-pane header="crisis-detail.component.html" path="router/src/app/crisis-center/crisis-detail/crisis-detail.component.html">
|
||||
|
||||
</code-pane>
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
<div class="feature-section">
|
||||
<div class="feature-header">
|
||||
<div class="text-headline">Cross Platform</div>
|
||||
<img src="generated/images/marketing/features/feature-icon.svg" height="70px" alt="">
|
||||
<img src="generated/images/marketing/features/feature-icon.svg" height="70px">
|
||||
</div>
|
||||
<div class="feature-row">
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
<div class="feature-section">
|
||||
<div class="feature-header">
|
||||
<div class="text-headline">Speed and Performance</div>
|
||||
<img src="generated/images/marketing/features/feature-icon.svg" height="70px" alt="">
|
||||
<img src="generated/images/marketing/features/feature-icon.svg" height="70px">
|
||||
</div>
|
||||
<div class="feature-row">
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
<div class="feature-section">
|
||||
<div class="feature-header">
|
||||
<div class="text-headline">Productivity</div>
|
||||
<img src="generated/images/marketing/features/feature-icon.svg" height="70px" alt="">
|
||||
<img src="generated/images/marketing/features/feature-icon.svg" height="70px">
|
||||
</div>
|
||||
<div class="feature-row">
|
||||
|
||||
@ -84,7 +84,7 @@
|
||||
<div class="feature-section">
|
||||
<div class="feature-header">
|
||||
<div class="text-headline">Full Development Story</div>
|
||||
<img src="generated/images/marketing/features/feature-icon.svg" height="70px" alt="">
|
||||
<img src="generated/images/marketing/features/feature-icon.svg" height="70px">
|
||||
</div>
|
||||
<div class="feature-row">
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
<!-- LOGO -->
|
||||
<div class="hero-logo">
|
||||
<img src="assets/images/logos/angular/angular.svg" alt="Angular"/>
|
||||
<img src="assets/images/logos/angular/angular.svg"/>
|
||||
</div>
|
||||
|
||||
<!-- CONTAINER -->
|
||||
@ -104,7 +104,7 @@
|
||||
<div layout="row" layout-xs="column" class="home-row">
|
||||
<a href="guide/quickstart">
|
||||
<div class="card">
|
||||
<img src="generated/images/marketing/home/code-icon.svg" height="70px" alt="Angular quickstart">
|
||||
<img src="generated/images/marketing/home/code-icon.svg" height="70px">
|
||||
<div class="card-text-container">
|
||||
<div class="text-headline">Get Started</div>
|
||||
<p>Start building your Angular application.</p>
|
||||
|
@ -20,7 +20,7 @@
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/angular/angular.svg" alt="Full color logo Angular">
|
||||
<img src="assets/images/logos/angular/angular.svg" alt="Angular">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">FULL COLOR LOGO</h3>
|
||||
@ -40,7 +40,7 @@
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<div>
|
||||
<img src="assets/images/logos/angular/angular_solidBlack.svg" alt="Black logo Angular">
|
||||
<img src="assets/images/logos/angular/angular_solidBlack.svg">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
@ -61,7 +61,7 @@
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<div>
|
||||
<img src="assets/images/logos/angular/angular_whiteTransparent.svg" class="transparent-img-bg" alt="Transparent logo Angular">
|
||||
<img src="assets/images/logos/angular/angular_whiteTransparent.svg" class="transparent-img-bg">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
<mat-sidenav-container class="sidenav-container mat-drawer-container mat-sidenav-container" role="main">
|
||||
<mat-sidenav-content class="mat-drawer-content mat-sidenav-content">
|
||||
<section class="sidenav-content" role="article">
|
||||
<section class="sidenav-content" role="content">
|
||||
<aio-doc-viewer>
|
||||
<div class="content">
|
||||
<div class="nf-container l-flex-wrap flex-center">
|
||||
|
@ -52,7 +52,7 @@
|
||||
</div>
|
||||
</mat-sidenav>
|
||||
|
||||
<main class="sidenav-content" [id]="pageId" role="main">
|
||||
<section class="sidenav-content" [id]="pageId" role="content">
|
||||
<aio-mode-banner [mode]="deployment.mode" [version]="versionInfo"></aio-mode-banner>
|
||||
<aio-doc-viewer [class.no-animations]="isStarting"
|
||||
[doc]="currentDocument"
|
||||
@ -62,7 +62,7 @@
|
||||
(docRendered)="onDocRendered()">
|
||||
</aio-doc-viewer>
|
||||
<aio-dt [on]="dtOn" [(doc)]="currentDocument"></aio-dt>
|
||||
</main>
|
||||
</section>
|
||||
|
||||
</mat-sidenav-container>
|
||||
|
||||
|
@ -52,7 +52,7 @@ describe('AppComponent', () => {
|
||||
await newDocPromise; // Wait for the new document to be fetched.
|
||||
fixture.detectChanges(); // Propagate document change to the view (i.e to `DocViewer`).
|
||||
await docRenderedPromise; // Wait for the `docRendered` event.
|
||||
}
|
||||
};
|
||||
|
||||
function initializeTest(waitForDoc = true) {
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
@ -73,7 +73,7 @@ describe('AppComponent', () => {
|
||||
tocService = de.injector.get<TocService>(TocService);
|
||||
|
||||
return waitForDoc && awaitDocRendered();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
describe('with proper DocViewer', () => {
|
||||
@ -1071,7 +1071,7 @@ describe('AppComponent', () => {
|
||||
|
||||
it('should set the id of the doc viewer container based on the current doc', () => {
|
||||
initializeTest(false);
|
||||
const container = fixture.debugElement.query(By.css('main.sidenav-content'));
|
||||
const container = fixture.debugElement.query(By.css('section.sidenav-content'));
|
||||
|
||||
navigateTo('guide/pipes');
|
||||
expect(component.pageId).toEqual('guide-pipes');
|
||||
@ -1088,7 +1088,7 @@ describe('AppComponent', () => {
|
||||
|
||||
it('should not be affected by changes to the query', () => {
|
||||
initializeTest(false);
|
||||
const container = fixture.debugElement.query(By.css('main.sidenav-content'));
|
||||
const container = fixture.debugElement.query(By.css('section.sidenav-content'));
|
||||
|
||||
navigateTo('guide/pipes');
|
||||
navigateTo('guide/other?search=http');
|
||||
|
@ -46,7 +46,7 @@ export interface Announcement {
|
||||
template: `
|
||||
<div class="homepage-container" *ngIf="announcement">
|
||||
<div class="announcement-bar">
|
||||
<img [src]="announcement.imageUrl" alt="">
|
||||
<img [src]="announcement.imageUrl">
|
||||
<p [innerHTML]="announcement.message"></p>
|
||||
<a class="button" [href]="announcement.linkUrl">Learn More</a>
|
||||
</div>
|
||||
|
@ -125,7 +125,7 @@ export class ApiListComponent implements OnInit {
|
||||
return status === 'all' ||
|
||||
status === item.stability ||
|
||||
(status === 'security-risk' && item.securityRisk);
|
||||
}
|
||||
};
|
||||
|
||||
function matchesType() {
|
||||
return type === 'all' || type === item.docType;
|
||||
|
@ -54,7 +54,7 @@ export class ApiService implements OnDestroy {
|
||||
section.items.every(item => item.stability === 'deprecated');
|
||||
});
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
constructor(private http: HttpClient, private logger: Logger) { }
|
||||
|
||||
|
@ -79,7 +79,7 @@ describe('ContributorListComponent', () => {
|
||||
return comp;
|
||||
}
|
||||
|
||||
interface SearchResult { [index: string]: string; }
|
||||
interface SearchResult { [index: string]: string; };
|
||||
|
||||
class TestLocationService {
|
||||
searchResult: SearchResult = {};
|
||||
|
@ -245,7 +245,7 @@ class FakeComponentFactory extends ComponentFactory<any> {
|
||||
rootSelectorOrNode?: string | any,
|
||||
ngModule?: NgModuleRef<any>): ComponentRef<any> {
|
||||
return jasmine.createSpy('ComponentRef') as any;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class FakeComponentFactoryResolver extends ComponentFactoryResolver {
|
||||
|
@ -37,6 +37,6 @@ describe('Getting Started NgFor Component', () => {
|
||||
|
||||
component.parseError$.subscribe(error => {
|
||||
expect(error).toBeTruthy();
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
@ -46,6 +46,6 @@ describe('Getting Started NgIf Component', () => {
|
||||
|
||||
component.parseError$.subscribe(error => {
|
||||
expect(error).toBeTruthy();
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
@ -26,7 +26,7 @@ export class ResourceService {
|
||||
|
||||
(categories as ConnectableObservable<Category[]>).connect();
|
||||
return categories;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Extract sorted Category[] from resource JSON data
|
||||
|
@ -100,10 +100,9 @@ export class DocViewerComponent implements OnDestroy {
|
||||
if (needsToc && !embeddedToc) {
|
||||
// Add an embedded ToC if it's needed and there isn't one in the content already.
|
||||
titleEl!.insertAdjacentHTML('afterend', '<aio-toc class="embedded"></aio-toc>');
|
||||
} else if (!needsToc && embeddedToc && embeddedToc.parentNode !== null) {
|
||||
} else if (!needsToc && embeddedToc) {
|
||||
// Remove the embedded Toc if it's there and not needed.
|
||||
// We cannot use ChildNode.remove() because of IE11
|
||||
embeddedToc.parentNode.removeChild(embeddedToc);
|
||||
embeddedToc.remove();
|
||||
}
|
||||
|
||||
return () => {
|
||||
|
@ -14,4 +14,4 @@ export class Deployment {
|
||||
mode: string = this.location.search()['mode'] || environment.mode;
|
||||
|
||||
constructor(private location: LocationService) {}
|
||||
}
|
||||
};
|
||||
|
@ -68,10 +68,7 @@ export class TocService {
|
||||
}
|
||||
}
|
||||
// now remove the anchor
|
||||
if (anchorLink.parentNode !== null) {
|
||||
// We cannot use ChildNode.remove() because of IE11
|
||||
anchorLink.parentNode.removeChild(anchorLink);
|
||||
}
|
||||
anchorLink.remove();
|
||||
}
|
||||
// security: the document element which provides this heading content
|
||||
// is always authored by the documentation team and is considered to be safe
|
||||
|
@ -93,7 +93,7 @@
|
||||
<div class="background-sky hero"></div>
|
||||
<section id="intro" style="text-shadow: 1px 1px #1976d2;">
|
||||
<div class="hero-logo">
|
||||
<img src="assets/images/logos/angular/angular.svg" width="250" height="250" alt="Angular">
|
||||
<img src="assets/images/logos/angular/angular.svg" width="250" height="250">
|
||||
</div>
|
||||
<div class="homepage-container">
|
||||
<div class="hero-headline">One framework.<br>Mobile & desktop.</div>
|
||||
|
@ -268,13 +268,13 @@ section#intro {
|
||||
|
||||
aio-shell {
|
||||
&.page-resources, &.page-events, &.page-features, &.page-presskit, &.page-contribute {
|
||||
main {
|
||||
section {
|
||||
padding: 0rem 0rem 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.page-home {
|
||||
main {
|
||||
section {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ aio-notification {
|
||||
}
|
||||
|
||||
&.page-home, &.page-resources, &.page-events, &.page-features, &.page-presskit, &.page-contribute {
|
||||
main {
|
||||
section {
|
||||
padding-top: $notificationHeight;
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,6 @@
|
||||
],
|
||||
"radix": true,
|
||||
"semicolon": [
|
||||
true,
|
||||
"always"
|
||||
],
|
||||
"triple-equals": [
|
||||
|
@ -8,15 +8,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli-hello-world-ivy": {
|
||||
"master": {
|
||||
"uncompressed": {
|
||||
"runtime": 1440,
|
||||
"main": 507677,
|
||||
"polyfills": 38390
|
||||
}
|
||||
}
|
||||
},
|
||||
"hello_world__closure": {
|
||||
"master": {
|
||||
"uncompressed": {
|
||||
|
@ -13,6 +13,3 @@ build --local_resources=14336,8.0,1.0
|
||||
|
||||
# Use the Angular 6 compiler
|
||||
build --define=compile=legacy
|
||||
|
||||
# Don't create symlinks
|
||||
build --symlink_prefix=/
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Editor configuration, see https://editorconfig.org
|
||||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
|
@ -1,6 +1,6 @@
|
||||
# CliHelloWorldIvy
|
||||
# CliHelloWorld
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.2.0-rc.0.
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.6.6.
|
||||
|
||||
## Development server
|
||||
|
||||
@ -12,7 +12,7 @@ Run `ng generate component component-name` to generate a new component. You can
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
|
@ -1,17 +1,14 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json",
|
||||
"version": 1,
|
||||
"cli": {
|
||||
"packageManager": "yarn"
|
||||
},
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"cli-hello-world-ivy": {
|
||||
"cli-hello-world": {
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"schematics": {},
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
@ -22,36 +19,47 @@
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.app.json",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
{
|
||||
"glob": "assets",
|
||||
"input": "/src",
|
||||
"output": "/"
|
||||
},
|
||||
{
|
||||
"glob": "favicon.ico",
|
||||
"input": "/src",
|
||||
"output": "/"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
{
|
||||
"input": "src/styles.css"
|
||||
}
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"dev": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
"from": "src/environments/environment.ts",
|
||||
"to": "dist/environments/environment.ts"
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"production": {
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"sourceMap": true,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
"fileReplacements": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
"src": "src/environments/environment.ts",
|
||||
"replaceWith": "src/environments/environment.prod.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -60,17 +68,20 @@
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "cli-hello-world-ivy:build"
|
||||
"browserTarget": "cli-hello-world:build"
|
||||
},
|
||||
"configurations": {
|
||||
"dev": {
|
||||
"browserTarget": "cli-hello-world:build:dev"
|
||||
},
|
||||
"production": {
|
||||
"browserTarget": "cli-hello-world-ivy:build:production"
|
||||
"browserTarget": "cli-hello-world:build:production"
|
||||
},
|
||||
"ci": {
|
||||
"progress": false
|
||||
},
|
||||
"ci-production": {
|
||||
"browserTarget": "cli-hello-world-ivy:build:production",
|
||||
"browserTarget": "cli-hello-world:build:production",
|
||||
"progress": false
|
||||
}
|
||||
}
|
||||
@ -78,7 +89,7 @@
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "cli-hello-world-ivy:build"
|
||||
"browserTarget": "cli-hello-world:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
@ -86,15 +97,25 @@
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"karmaConfig": "./karma.conf.js",
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"karmaConfig": "src/karma.conf.js",
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
],
|
||||
"scripts": [],
|
||||
"styles": [
|
||||
{
|
||||
"input": "src/styles.css"
|
||||
}
|
||||
],
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
{
|
||||
"glob": "assets",
|
||||
"input": "/src",
|
||||
"output": "/"
|
||||
},
|
||||
{
|
||||
"glob": "favicon.ico",
|
||||
"input": "/src",
|
||||
"output": "/"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -112,33 +133,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli-hello-world-ivy-e2e": {
|
||||
"root": "e2e/",
|
||||
"cli-hello-world-e2e": {
|
||||
"root": "",
|
||||
"projectType": "application",
|
||||
"prefix": "",
|
||||
"cli": {},
|
||||
"schematics": {},
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "cli-hello-world-ivy:serve"
|
||||
"protractorConfig": "./protractor.conf.js",
|
||||
"devServerTarget": "cli-hello-world:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "cli-hello-world-ivy:serve:production"
|
||||
"devServerTarget": "cli-hello-world:serve:production"
|
||||
},
|
||||
"ci": {
|
||||
"devServerTarget": "cli-hello-world-ivy:serve:ci"
|
||||
"devServerTarget": "cli-hello-world:serve:ci"
|
||||
},
|
||||
"ci-production": {
|
||||
"devServerTarget": "cli-hello-world-ivy:serve:ci-production"
|
||||
"devServerTarget": "cli-hello-world:serve:ci-production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": "e2e/tsconfig.e2e.json",
|
||||
"tsConfig": [
|
||||
"e2e/tsconfig.e2e.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
@ -147,5 +171,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "cli-hello-world-ivy"
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"prefix": "app",
|
||||
"styleext": "css"
|
||||
},
|
||||
"@schematics/angular:directive": {
|
||||
"prefix": "app"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ describe('cli-hello-world App', () => {
|
||||
|
||||
it('should display welcome message', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getParagraphText()).toEqual('Welcome to cli-hello-world-ivy!');
|
||||
expect(page.getParagraphText()).toEqual('Welcome to app!');
|
||||
});
|
||||
|
||||
it('the percent pipe should work', () => {
|
@ -1,7 +1,8 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/app",
|
||||
"outDir": "../out-tsc/e2e",
|
||||
"baseUrl": "./",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
@ -10,4 +11,4 @@
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,14 +12,16 @@ module.exports = function (config) {
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
client:{
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, 'coverage'),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
angularCli: {
|
||||
environment: 'dev'
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "cli-hello-world-ivy",
|
||||
"name": "cli-hello-world",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@ -29,24 +29,24 @@
|
||||
"zone.js": "file:../../node_modules/zone.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.12.0-rc.0",
|
||||
"@angular/cli": "file:../../node_modules/@angular/cli",
|
||||
"@angular-devkit/build-angular": "~0.10.3",
|
||||
"@angular/cli": "7.0.3",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
"@angular/language-service": "file:../../dist/packages-dist/language-service",
|
||||
"@types/node": "~8.9.4",
|
||||
"@types/jasmine": "~2.8.8",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"codelyzer": "~4.5.0",
|
||||
"jasmine-core": "~2.99.1",
|
||||
"@types/jasmine": "~2.8.3",
|
||||
"@types/jasminewd2": "~2.0.4",
|
||||
"@types/node": "~6.0.60",
|
||||
"codelyzer": "^4.3.0",
|
||||
"jasmine-core": "~2.8.0",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~3.1.1",
|
||||
"karma": "~2.0.0",
|
||||
"karma-chrome-launcher": "~2.2.0",
|
||||
"karma-coverage-istanbul-reporter": "~2.0.1",
|
||||
"karma-jasmine": "~1.1.2",
|
||||
"karma-coverage-istanbul-reporter": "^1.2.1",
|
||||
"karma-jasmine": "~1.1.0",
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"protractor": "file:../../node_modules/protractor",
|
||||
"ts-node": "~7.0.0",
|
||||
"tslint": "~5.11.0",
|
||||
"ts-node": "~4.1.0",
|
||||
"tslint": "~5.9.1",
|
||||
"typescript": "file:../../node_modules/typescript"
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
'./src/**/*.e2e-spec.ts'
|
||||
'./e2e/**/*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
browserName: 'chrome',
|
||||
@ -25,7 +25,7 @@ exports.config = {
|
||||
},
|
||||
onPrepare() {
|
||||
require('ts-node').register({
|
||||
project: require('path').join(__dirname, './tsconfig.e2e.json')
|
||||
project: 'e2e/tsconfig.e2e.json'
|
||||
});
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
|
||||
</li>
|
||||
<li>
|
||||
<h2><a target="_blank" rel="noopener" href="https://angular.io/cli">CLI Documentation</a></h2>
|
||||
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
|
||||
</li>
|
||||
<li>
|
||||
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@ -9,23 +8,20 @@ describe('AppComponent', () => {
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
it('should create the app', () => {
|
||||
it('should create the app', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'cli-hello-world-ivy'`, () => {
|
||||
}));
|
||||
it(`should have as title 'app'`, async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app.title).toEqual('cli-hello-world-ivy');
|
||||
});
|
||||
|
||||
it('should render title in a h1 tag', () => {
|
||||
expect(app.title).toEqual('app');
|
||||
}));
|
||||
it('should render title in a h1 tag', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to cli-hello-world-ivy!');
|
||||
});
|
||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
||||
}));
|
||||
});
|
||||
|
@ -6,5 +6,5 @@ import { Component } from '@angular/core';
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'cli-hello-world-ivy';
|
||||
title = 'app';
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
#
|
||||
# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
|
||||
|
||||
> 0.5%
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 9-11
|
@ -1,16 +1,8 @@
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
// The file contents for the current environment will overwrite these during build.
|
||||
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
|
||||
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
|
||||
// The list of which env maps to which file can be found in `.angular-cli.json`.
|
||||
|
||||
export const environment = {
|
||||
production: false
|
||||
};
|
||||
|
||||
/*
|
||||
* For easier debugging in development mode, you can import the following file
|
||||
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||||
*
|
||||
* This import should be commented out in production mode because it will have a negative impact
|
||||
* on performance if an error is thrown.
|
||||
*/
|
||||
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
||||
|
@ -2,11 +2,12 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CliHelloWorldIvy</title>
|
||||
<title>CliHelloWorld</title>
|
||||
<base href="/">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<script>window['ngDevMode'] = true;</script>
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
|
@ -9,4 +9,4 @@ if (environment.production) {
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
||||
.catch(err => console.log(err));
|
||||
|
@ -11,17 +11,14 @@
|
||||
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||||
*
|
||||
* Learn more in https://angular.io/guide/browser-support
|
||||
* Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
* BROWSER POLYFILLS
|
||||
*/
|
||||
|
||||
/** IE9, IE10, IE11, and Chrome <55 requires all of the following polyfills.
|
||||
* This also includes Android Emulators with older versions of Chrome and Google Search/Googlebot
|
||||
*/
|
||||
|
||||
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
|
||||
// import 'core-js/es6/symbol';
|
||||
// import 'core-js/es6/object';
|
||||
// import 'core-js/es6/function';
|
||||
@ -43,36 +40,19 @@
|
||||
/** IE10 and IE11 requires the following for the Reflect API. */
|
||||
// import 'core-js/es6/reflect';
|
||||
|
||||
/**
|
||||
* Web Animations `@angular/platform-browser/animations`
|
||||
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
||||
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
||||
*/
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
/** Evergreen browsers require these. **/
|
||||
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
|
||||
import 'core-js/es7/reflect';
|
||||
|
||||
|
||||
/**
|
||||
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||||
* because those flags need to be set before `zone.js` being loaded, and webpack
|
||||
* will put import in the top of bundle, so user need to create a separate file
|
||||
* in this directory (for example: zone-flags.ts), and put the following flags
|
||||
* into that file, and then add the following code before importing zone.js.
|
||||
* import './zone-flags.ts';
|
||||
*
|
||||
* The flags allowed in zone-flags.ts are listed here.
|
||||
*
|
||||
* The following flags will work for all browsers.
|
||||
*
|
||||
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
|
||||
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||||
* (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
|
||||
*
|
||||
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||||
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||||
*
|
||||
* (window as any).__Zone_enable_cross_context_check = true;
|
||||
*
|
||||
*/
|
||||
* Required to support Web Animations `@angular/platform-browser/animations`.
|
||||
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
|
||||
**/
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
* Zone JS is required by default for Angular itself.
|
||||
@ -80,6 +60,7 @@
|
||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
||||
|
@ -2,13 +2,12 @@
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/app",
|
||||
"baseUrl": "./",
|
||||
"module": "es2015",
|
||||
"types": []
|
||||
},
|
||||
"exclude": [
|
||||
"test.ts",
|
||||
"**/*.spec.ts"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"enableIvy": "ngtsc"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/spec",
|
||||
"baseUrl": "./",
|
||||
"module": "commonjs",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"node"
|
||||
@ -15,4 +17,4 @@
|
||||
"**/*.spec.ts",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"extends": "../tslint.json",
|
||||
"rules": {
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"app",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"app",
|
||||
"kebab-case"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
{
|
||||
"angularCompilerOptions": {
|
||||
"enableIvy": "ngtsc",
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"outDir": "./dist/out-tsc",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"target": "es5",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
],
|
||||
"lib": [
|
||||
"es2018",
|
||||
"es2017",
|
||||
"dom"
|
||||
]
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"rulesDirectory": [
|
||||
"codelyzer"
|
||||
"node_modules/codelyzer"
|
||||
],
|
||||
"rules": {
|
||||
"arrow-return-shorthand": true,
|
||||
@ -18,6 +18,7 @@
|
||||
"forin": true,
|
||||
"import-blacklist": [
|
||||
true,
|
||||
"rxjs",
|
||||
"rxjs/Rx"
|
||||
],
|
||||
"import-spacing": true,
|
||||
@ -65,7 +66,6 @@
|
||||
],
|
||||
"no-misused-new": true,
|
||||
"no-non-null-assertion": true,
|
||||
"no-redundant-jsdoc": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-string-literal": false,
|
||||
"no-string-throw": true,
|
||||
@ -117,6 +117,18 @@
|
||||
"check-separator",
|
||||
"check-type"
|
||||
],
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"app",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"app",
|
||||
"kebab-case"
|
||||
],
|
||||
"no-output-on-prefix": true,
|
||||
"use-input-property-decorator": true,
|
||||
"use-output-property-decorator": true,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.10.3",
|
||||
"@angular/cli": "file:../../node_modules/@angular/cli",
|
||||
"@angular/cli": "7.0.3",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
"@angular/language-service": "file:../../dist/packages-dist/language-service",
|
||||
"@types/jasmine": "~2.8.3",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,10 @@
|
||||
import nodeResolve from 'rollup-plugin-node-resolve';
|
||||
|
||||
export default {
|
||||
input: 'dist/src/main.js',
|
||||
output: {
|
||||
sourceMap: true,
|
||||
},
|
||||
entry: 'dist/src/main.js',
|
||||
sourceMap: true,
|
||||
treeshake: true,
|
||||
moduleName: 'main',
|
||||
plugins: [
|
||||
nodeResolve()
|
||||
]
|
||||
|
@ -4,11 +4,10 @@ import commonjs from 'rollup-plugin-commonjs';
|
||||
// a real app should make a common bundle for libraries instead of bundling them
|
||||
// in both the main module & the lazy module, but we don't care about size here
|
||||
export default {
|
||||
input: 'dist/src/lazy.module.js',
|
||||
output: {
|
||||
sourceMap: true,
|
||||
},
|
||||
entry: 'dist/src/lazy.module.js',
|
||||
sourceMap: true,
|
||||
treeshake: true,
|
||||
moduleName: 'lazy',
|
||||
plugins: [
|
||||
nodeResolve()
|
||||
]
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -61,9 +61,9 @@ for testDir in ${TEST_DIRS}; do
|
||||
yarn install --cache-folder ../$cache
|
||||
yarn test || exit 1
|
||||
|
||||
# Track payload size for cli-hello-world, cli-hello-world-ivy and hello_world__closure
|
||||
if $CI && ([[ $testDir == cli-hello-world ]] || [[ $testDir == cli-hello-world-ivy ]] || [[ $testDir == hello_world__closure ]]); then
|
||||
if ([[ $testDir == cli-hello-world ]] || [[ $testDir == cli-hello-world-ivy ]]); then
|
||||
# Track payload size for cli-hello-world and hello_world__closure and the render3 tests
|
||||
if $CI && ([[ $testDir == cli-hello-world ]] || [[ $testDir == hello_world__closure ]]); then
|
||||
if [[ $testDir == cli-hello-world ]]; then
|
||||
yarn build
|
||||
fi
|
||||
|
||||
|
13
package.json
13
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "7.2.2",
|
||||
"version": "7.2.0",
|
||||
"private": true,
|
||||
"branchPattern": "2.0.*",
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
@ -32,7 +32,6 @@
|
||||
"// 1": "dependencies are used locally and by bazel",
|
||||
"dependencies": {
|
||||
"@angular-devkit/architect": "^0.10.6",
|
||||
"@angular-devkit/build-optimizer": "^0.12.2",
|
||||
"@angular-devkit/core": "^7.0.4",
|
||||
"@angular-devkit/schematics": "^7.0.4",
|
||||
"@bazel/karma": "~0.22.1",
|
||||
@ -74,9 +73,6 @@
|
||||
"node-uuid": "1.4.8",
|
||||
"protractor": "^5.4.2",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
"rollup": "^1.1.0",
|
||||
"rollup-plugin-node-resolve": "^4.0.0",
|
||||
"rollup-plugin-sourcemaps": "^0.4.2",
|
||||
"selenium-webdriver": "3.5.0",
|
||||
"shelljs": "^0.8.1",
|
||||
"source-map": "^0.6.1",
|
||||
@ -133,7 +129,10 @@
|
||||
"madge": "0.5.0",
|
||||
"mutation-observer": "^1.0.3",
|
||||
"rewire": "2.5.2",
|
||||
"rollup": "0.47.4",
|
||||
"rollup-plugin-commonjs": "8.1.0",
|
||||
"rollup-plugin-node-resolve": "3.0.0",
|
||||
"rollup-plugin-sourcemaps": "0.4.2",
|
||||
"rxjs": "^6.3.0",
|
||||
"sauce-connect": "https://saucelabs.com/downloads/sc-4.5.2-linux.tar.gz",
|
||||
"semver": "5.4.1",
|
||||
@ -146,9 +145,5 @@
|
||||
"vlq": "0.2.2",
|
||||
"vrsource-tslint-rules": "5.1.1",
|
||||
"webpack": "1.12.9"
|
||||
},
|
||||
"// 4": "natives is needed for gulp to work with node >= 10.13, see #28213",
|
||||
"resolutions": {
|
||||
"natives": "1.1.6"
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export function supportsAnimationEventCreation() {
|
||||
try {
|
||||
makeAnimationEvent('end', 'test', 0);
|
||||
supported = true;
|
||||
} catch {
|
||||
} catch (e) {
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
@ -53,6 +53,19 @@ def rules_angular_dev_dependencies():
|
||||
shorter.
|
||||
"""
|
||||
|
||||
# We have a source dependency on the Devkit repository, because it's built with
|
||||
# Bazel.
|
||||
# This allows us to edit sources and have the effect appear immediately without
|
||||
# re-packaging or "npm link"ing.
|
||||
# Even better, things like aspects will visit the entire graph including
|
||||
# ts_library rules in the devkit repository.
|
||||
http_archive(
|
||||
name = "angular_cli",
|
||||
sha256 = "8cf320ea58c321e103f39087376feea502f20eaf79c61a4fdb05c7286c8684fd",
|
||||
strip_prefix = "angular-cli-6.1.0-rc.0",
|
||||
url = "https://github.com/angular/angular-cli/archive/v6.1.0-rc.0.zip",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "org_brotli",
|
||||
sha256 = "774b893a0700b0692a76e2e5b7e7610dbbe330ffbe3fe864b4b52ca718061d5a",
|
||||
|
@ -13,15 +13,13 @@ load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
|
||||
|
||||
nodejs_binary(
|
||||
name = "rollup_with_build_optimizer",
|
||||
data = [
|
||||
"@ngdeps//@angular-devkit/build-optimizer",
|
||||
"@ngdeps//is-builtin-module",
|
||||
"@ngdeps//rollup",
|
||||
"@ngdeps//rollup-plugin-node-resolve",
|
||||
"@ngdeps//rollup-plugin-sourcemaps",
|
||||
],
|
||||
entry_point = "ngdeps/node_modules/rollup/bin/rollup",
|
||||
data = ["@angular_cli//packages/angular_devkit/build_optimizer:lib"],
|
||||
# Since our rule extends the one in rules_nodejs, we use the same runtime
|
||||
# dependency @build_bazel_rules_nodejs_rollup_deps. We don't need any
|
||||
# additional npm dependencies when we run rollup or uglify.
|
||||
entry_point = "build_bazel_rules_nodejs_rollup_deps/node_modules/rollup/bin/rollup",
|
||||
install_source_map_support = False,
|
||||
node_modules = "@build_bazel_rules_nodejs_rollup_deps//:node_modules",
|
||||
)
|
||||
|
||||
nodejs_binary(
|
||||
|
@ -31,7 +31,7 @@ PACKAGES = ["packages/core/src", "packages/common/src", "packages/compiler/src",
|
||||
PLUGIN_CONFIG = "{sideEffectFreeModules: [\n%s]}" % ",\n".join(
|
||||
[" '.esm5/{0}'".format(p) for p in PACKAGES],
|
||||
)
|
||||
BO_ROLLUP = "ngdeps/node_modules/@angular-devkit/build-optimizer/src/build-optimizer/rollup-plugin.js"
|
||||
BO_ROLLUP = "angular_cli/packages/angular_devkit/build_optimizer/src/build-optimizer/rollup-plugin.js"
|
||||
BO_PLUGIN = "require('%s').default(%s)" % (BO_ROLLUP, PLUGIN_CONFIG)
|
||||
|
||||
def _use_plain_rollup(ctx):
|
||||
|
@ -41,7 +41,7 @@ http_archive(
|
||||
url = "https://registry.yarnpkg.com/rxjs/-/rxjs-%s.tgz" % RXJS_VERSION,
|
||||
strip_prefix = "package/src",
|
||||
)
|
||||
<% if (sass) { %>
|
||||
|
||||
# Rules for compiling sass
|
||||
RULES_SASS_VERSION = "<%= RULES_SASS_VERSION %>"
|
||||
http_archive(
|
||||
@ -49,7 +49,7 @@ http_archive(
|
||||
url = "https://github.com/bazelbuild/rules_sass/archive/%s.zip" % RULES_SASS_VERSION,
|
||||
strip_prefix = "rules_sass-%s" % RULES_SASS_VERSION,
|
||||
)
|
||||
<% } %>
|
||||
|
||||
####################################
|
||||
# Load and install our dependencies downloaded above.
|
||||
|
||||
@ -85,9 +85,9 @@ browser_repositories(
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
||||
ts_setup_workspace()
|
||||
<% if (sass) { %>
|
||||
|
||||
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
||||
sass_repositories()
|
||||
<% } %>
|
||||
|
||||
load("@angular//:index.bzl", "ng_setup_workspace")
|
||||
ng_setup_workspace()
|
||||
|
@ -5,17 +5,7 @@ load("@build_bazel_rules_typescript//:defs.bzl", "ts_library", "ts_web_test_suit
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle", "history_server")
|
||||
load("@build_bazel_rules_nodejs//internal/web_package:web_package.bzl", "web_package")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver")
|
||||
<% if (sass) { %>load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
|
||||
|
||||
[
|
||||
sass_binary(
|
||||
name = "style_" + x,
|
||||
src = x,
|
||||
deps = [],
|
||||
)
|
||||
for x in glob(["**/*.scss"])
|
||||
]
|
||||
<% } %>
|
||||
ng_module(
|
||||
name = "src",
|
||||
srcs = glob(
|
||||
@ -30,7 +20,7 @@ ng_module(
|
||||
assets = glob([
|
||||
"**/*.css",
|
||||
"**/*.html",
|
||||
])<% if (sass) { %> + [":style_" + x for x in glob(["**/*.scss"])]<% } %>,
|
||||
]),
|
||||
deps = [
|
||||
"@angular//packages/core",
|
||||
"@angular//packages/platform-browser",<% if (routing) { %>
|
||||
|
@ -60,16 +60,6 @@ function hasRoutingModule(host: Tree) {
|
||||
return hasRouting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if project uses SASS stylesheets, false otherwise.
|
||||
*/
|
||||
function hasSassStylesheet(host: Tree) {
|
||||
let hasSass = false;
|
||||
// The proper extension for SASS is .scss
|
||||
host.visit((file: string) => { hasSass = hasSass || file.endsWith('.scss'); });
|
||||
return hasSass;
|
||||
}
|
||||
|
||||
export default function(options: BazelWorkspaceOptions): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
if (!options.name) {
|
||||
@ -113,7 +103,6 @@ export default function(options: BazelWorkspaceOptions): Rule {
|
||||
...options,
|
||||
'dot': '.', ...workspaceVersions,
|
||||
routing: hasRoutingModule(host),
|
||||
sass: hasSassStylesheet(host),
|
||||
}),
|
||||
move(appDir),
|
||||
]));
|
||||
|
@ -12,7 +12,7 @@ import {clean} from './index';
|
||||
|
||||
describe('Bazel-workspace Schematic', () => {
|
||||
const schematicRunner =
|
||||
new SchematicTestRunner('@angular/bazel', require.resolve('../collection.json'));
|
||||
new SchematicTestRunner('@angular/bazel', require.resolve('../collection.json'), );
|
||||
const defaultOptions = {
|
||||
name: 'demo',
|
||||
};
|
||||
@ -79,46 +79,6 @@ describe('Bazel-workspace Schematic', () => {
|
||||
expect(content).toContain('workspace(name = "demo_project"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('SASS', () => {
|
||||
let host = new UnitTestTree(new HostTree);
|
||||
beforeAll(() => {
|
||||
host.create('/demo/src/app/app.component.scss', '');
|
||||
expect(host.files).toContain('/demo/src/app/app.component.scss');
|
||||
const options = {...defaultOptions};
|
||||
host = schematicRunner.runSchematic('bazel-workspace', options, host);
|
||||
expect(host.files).toContain('/demo/WORKSPACE');
|
||||
expect(host.files).toContain('/demo/src/BUILD.bazel');
|
||||
});
|
||||
|
||||
it('should download rules_sass in WORKSPACE', () => {
|
||||
const content = host.readContent('/demo/WORKSPACE');
|
||||
expect(content).toContain('RULES_SASS_VERSION');
|
||||
expect(content).toContain('io_bazel_rules_sass');
|
||||
});
|
||||
|
||||
it('should load sass_repositories in WORKSPACE', () => {
|
||||
const content = host.readContent('/demo/WORKSPACE');
|
||||
expect(content).toContain(
|
||||
'load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")');
|
||||
expect(content).toContain('sass_repositories()');
|
||||
});
|
||||
|
||||
it('should add sass_binary rules in src/BUILD', () => {
|
||||
const content = host.readContent('/demo/src/BUILD.bazel');
|
||||
expect(content).toContain('load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")');
|
||||
expect(content).toMatch(/sass_binary\((.*\n)+\)/);
|
||||
});
|
||||
|
||||
it('should add SASS targets to assets of ng_module in src/BUILD', () => {
|
||||
const content = host.readContent('/demo/src/BUILD.bazel');
|
||||
expect(content).toContain(`
|
||||
assets = glob([
|
||||
"**/*.css",
|
||||
"**/*.html",
|
||||
]) + [":style_" + x for x in glob(["**/*.scss"])],`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('clean', () => {
|
||||
|
@ -149,7 +149,7 @@ export class NgForOf<T> implements DoCheck {
|
||||
if (!this._differ && value) {
|
||||
try {
|
||||
this._differ = this._differs.find(value).create(this.ngForTrackBy);
|
||||
} catch {
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Cannot find a differ supporting object '${value}' of type '${getTypeNameForDebugging(value)}'. NgFor only supports binding to Iterables such as Arrays.`);
|
||||
}
|
||||
|
@ -12,35 +12,21 @@ import {Directive, DoCheck, ElementRef, Input, KeyValueChanges, KeyValueDiffer,
|
||||
* @ngModule CommonModule
|
||||
*
|
||||
* @usageNotes
|
||||
*
|
||||
* Set the font of the containing element to the result of an expression.
|
||||
*
|
||||
* ```
|
||||
* <some-element [ngStyle]="{'font-style': styleExp}">...</some-element>
|
||||
* ```
|
||||
*
|
||||
* Set the width of the containing element to a pixel value returned by an expression.
|
||||
*
|
||||
* ```
|
||||
* <some-element [ngStyle]="{'max-width.px': widthExp}">...</some-element>
|
||||
* ```
|
||||
*
|
||||
* Set a collection of style values using an expression that returns key-value pairs.
|
||||
*
|
||||
* ```
|
||||
* <some-element [ngStyle]="objExp">...</some-element>
|
||||
* ```
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* An attribute directive that updates styles for the containing HTML element.
|
||||
* Sets one or more style properties, specified as colon-separated key-value pairs.
|
||||
* The key is a style name, with an optional `.<unit>` suffix
|
||||
* (such as 'top.px', 'font-style.em').
|
||||
* The value is an expression to be evaluated.
|
||||
* The resulting non-null value, expressed in the given unit,
|
||||
* is assigned to the given style property.
|
||||
* If the result of evaluation is null, the corresponding style is removed.
|
||||
* Update an HTML element styles.
|
||||
*
|
||||
* The styles are updated according to the value of the expression evaluation:
|
||||
* - keys are style names with an optional `.<unit>` suffix (ie 'top.px', 'font-style.em'),
|
||||
* - values are the values assigned to those properties (expressed in the given unit).
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
@ -55,24 +41,13 @@ export class NgStyle implements DoCheck {
|
||||
private _differs: KeyValueDiffers, private _ngEl: ElementRef, private _renderer: Renderer2) {}
|
||||
|
||||
@Input()
|
||||
set ngStyle(
|
||||
/**
|
||||
* A map of style properties, specified as colon-separated
|
||||
* key-value pairs.
|
||||
* * The key is a style name, with an optional `.<unit>` suffix
|
||||
* (such as 'top.px', 'font-style.em').
|
||||
* * The value is an expression to be evaluated.
|
||||
*/
|
||||
values: {[key: string]: string}) {
|
||||
set ngStyle(values: {[key: string]: string}) {
|
||||
this._ngStyle = values;
|
||||
if (!this._differ && values) {
|
||||
this._differ = this._differs.find(values).create();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the new styles if needed.
|
||||
*/
|
||||
ngDoCheck() {
|
||||
if (this._differ) {
|
||||
const changes = this._differ.diff(this._ngStyle);
|
||||
|
@ -150,7 +150,7 @@ export class BrowserViewportScroller implements ViewportScroller {
|
||||
private supportScrollRestoration(): boolean {
|
||||
try {
|
||||
return !!this.window && !!this.window.scrollTo;
|
||||
} catch {
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ ts_library(
|
||||
"//packages/platform-browser",
|
||||
"//packages/platform-browser-dynamic",
|
||||
"//packages/platform-browser/testing",
|
||||
"//packages/private/testing",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -11,7 +11,6 @@ import {NgComponentOutlet} from '@angular/common/src/directives/ng_component_out
|
||||
import {Compiler, Component, ComponentRef, Inject, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory, Optional, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
|
||||
import {TestBed, async} from '@angular/core/testing';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
import {modifiedInIvy} from '@angular/private/testing';
|
||||
|
||||
describe('insert/remove', () => {
|
||||
|
||||
@ -107,20 +106,17 @@ describe('insert/remove', () => {
|
||||
|
||||
}));
|
||||
|
||||
it('should resolve a with injector', async(() => {
|
||||
let fixture = TestBed.createComponent(TestComponent);
|
||||
|
||||
modifiedInIvy('Static ViewChild and ContentChild queries are resolved in update mode')
|
||||
.it('should resolve with an injector', async(() => {
|
||||
let fixture = TestBed.createComponent(TestComponent);
|
||||
|
||||
// We are accessing a ViewChild (ngComponentOutlet) before change detection has run
|
||||
fixture.componentInstance.cmpRef = null;
|
||||
fixture.componentInstance.currentComponent = InjectedComponent;
|
||||
fixture.detectChanges();
|
||||
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !;
|
||||
expect(cmpRef).toBeAnInstanceOf(ComponentRef);
|
||||
expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent);
|
||||
expect(cmpRef.instance.testToken).toBeNull();
|
||||
}));
|
||||
fixture.componentInstance.cmpRef = null;
|
||||
fixture.componentInstance.currentComponent = InjectedComponent;
|
||||
fixture.detectChanges();
|
||||
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !;
|
||||
expect(cmpRef).toBeAnInstanceOf(ComponentRef);
|
||||
expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent);
|
||||
expect(cmpRef.instance.testToken).toBeNull();
|
||||
}));
|
||||
|
||||
it('should render projectable nodes, if supplied', async(() => {
|
||||
const template = `<ng-template>projected foo</ng-template>${TEST_CMP_TEMPLATE}`;
|
||||
|
@ -22,7 +22,7 @@ import {performWatchCompilation, createPerformWatchHost} from './perform_watch'
|
||||
|
||||
export function main(
|
||||
args: string[], consoleError: (s: string) => void = console.error,
|
||||
config?: NgcParsedConfiguration, customTransformers?: api.CustomTransformers): number {
|
||||
config?: NgcParsedConfiguration): number {
|
||||
let {project, rootNames, options, errors: configErrors, watch, emitFlags} =
|
||||
config || readNgcCommandLineAndConfiguration(args);
|
||||
if (configErrors.length) {
|
||||
@ -32,12 +32,8 @@ export function main(
|
||||
const result = watchMode(project, options, consoleError);
|
||||
return reportErrorsAndExit(result.firstCompileResult, options, consoleError);
|
||||
}
|
||||
const {diagnostics: compileDiags} = performCompilation({
|
||||
rootNames,
|
||||
options,
|
||||
emitFlags,
|
||||
emitCallback: createEmitCallback(options), customTransformers
|
||||
});
|
||||
const {diagnostics: compileDiags} = performCompilation(
|
||||
{rootNames, options, emitFlags, emitCallback: createEmitCallback(options)});
|
||||
return reportErrorsAndExit(compileDiags, options, consoleError);
|
||||
}
|
||||
|
||||
|
@ -1,118 +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 * as ts from 'typescript';
|
||||
|
||||
import {ReferencesRegistry} from '../../../ngtsc/annotations';
|
||||
import {Declaration} from '../../../ngtsc/host';
|
||||
import {ResolvedReference} from '../../../ngtsc/metadata';
|
||||
import {NgccReflectionHost} from '../host/ngcc_host';
|
||||
import {isDefined} from '../utils';
|
||||
|
||||
export interface ModuleWithProvidersInfo {
|
||||
/**
|
||||
* The declaration (in the .d.ts file) of the function that returns
|
||||
* a `ModuleWithProviders object, but has a signature that needs
|
||||
* a type parameter adding.
|
||||
*/
|
||||
declaration: ts.MethodDeclaration|ts.FunctionDeclaration;
|
||||
/**
|
||||
* The NgModule class declaration (in the .d.ts file) to add as a type parameter.
|
||||
*/
|
||||
ngModule: Declaration;
|
||||
}
|
||||
|
||||
export type ModuleWithProvidersAnalyses = Map<ts.SourceFile, ModuleWithProvidersInfo[]>;
|
||||
export const ModuleWithProvidersAnalyses = Map;
|
||||
|
||||
export class ModuleWithProvidersAnalyzer {
|
||||
constructor(private host: NgccReflectionHost, private referencesRegistry: ReferencesRegistry) {}
|
||||
|
||||
analyzeProgram(program: ts.Program): ModuleWithProvidersAnalyses {
|
||||
const analyses = new ModuleWithProvidersAnalyses();
|
||||
const rootFiles = this.getRootFiles(program);
|
||||
rootFiles.forEach(f => {
|
||||
const fns = this.host.getModuleWithProvidersFunctions(f);
|
||||
fns && fns.forEach(fn => {
|
||||
const dtsFn = this.getDtsDeclaration(fn.declaration);
|
||||
const typeParam = dtsFn.type && ts.isTypeReferenceNode(dtsFn.type) &&
|
||||
dtsFn.type.typeArguments && dtsFn.type.typeArguments[0] ||
|
||||
null;
|
||||
if (!typeParam || isAnyKeyword(typeParam)) {
|
||||
// Either we do not have a parameterized type or the type is `any`.
|
||||
let ngModule = this.host.getDeclarationOfIdentifier(fn.ngModule);
|
||||
if (!ngModule) {
|
||||
throw new Error(
|
||||
`Cannot find a declaration for NgModule ${fn.ngModule.text} referenced in ${fn.declaration.getText()}`);
|
||||
}
|
||||
// For internal (non-library) module references, redirect the module's value declaration
|
||||
// to its type declaration.
|
||||
if (ngModule.viaModule === null) {
|
||||
const dtsNgModule = this.host.getDtsDeclaration(ngModule.node);
|
||||
if (!dtsNgModule) {
|
||||
throw new Error(
|
||||
`No typings declaration can be found for the referenced NgModule class in ${fn.declaration.getText()}.`);
|
||||
}
|
||||
if (!ts.isClassDeclaration(dtsNgModule)) {
|
||||
throw new Error(
|
||||
`The referenced NgModule in ${fn.declaration.getText()} is not a class declaration in the typings program; instead we get ${dtsNgModule.getText()}`);
|
||||
}
|
||||
// Record the usage of the internal module as it needs to become an exported symbol
|
||||
this.referencesRegistry.add(new ResolvedReference(ngModule.node, fn.ngModule));
|
||||
|
||||
ngModule = {node: dtsNgModule, viaModule: null};
|
||||
}
|
||||
const dtsFile = dtsFn.getSourceFile();
|
||||
const analysis = analyses.get(dtsFile) || [];
|
||||
analysis.push({declaration: dtsFn, ngModule});
|
||||
analyses.set(dtsFile, analysis);
|
||||
}
|
||||
});
|
||||
});
|
||||
return analyses;
|
||||
}
|
||||
|
||||
private getRootFiles(program: ts.Program): ts.SourceFile[] {
|
||||
return program.getRootFileNames().map(f => program.getSourceFile(f)).filter(isDefined);
|
||||
}
|
||||
|
||||
private getDtsDeclaration(fn: ts.SignatureDeclaration) {
|
||||
let dtsFn: ts.Declaration|null = null;
|
||||
const containerClass = this.host.getClassSymbol(fn.parent);
|
||||
const fnName = fn.name && ts.isIdentifier(fn.name) && fn.name.text;
|
||||
if (containerClass && fnName) {
|
||||
const dtsClass = this.host.getDtsDeclaration(containerClass.valueDeclaration);
|
||||
// Get the declaration of the matching static method
|
||||
dtsFn = dtsClass && ts.isClassDeclaration(dtsClass) ?
|
||||
dtsClass.members
|
||||
.find(
|
||||
member => ts.isMethodDeclaration(member) && ts.isIdentifier(member.name) &&
|
||||
member.name.text === fnName) as ts.Declaration :
|
||||
null;
|
||||
} else {
|
||||
dtsFn = this.host.getDtsDeclaration(fn);
|
||||
}
|
||||
if (!dtsFn) {
|
||||
throw new Error(`Matching type declaration for ${fn.getText()} is missing`);
|
||||
}
|
||||
if (!isFunctionOrMethod(dtsFn)) {
|
||||
throw new Error(
|
||||
`Matching type declaration for ${fn.getText()} is not a function: ${dtsFn.getText()}`);
|
||||
}
|
||||
return dtsFn;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function isFunctionOrMethod(declaration: ts.Declaration): declaration is ts.FunctionDeclaration|
|
||||
ts.MethodDeclaration {
|
||||
return ts.isFunctionDeclaration(declaration) || ts.isMethodDeclaration(declaration);
|
||||
}
|
||||
|
||||
function isAnyKeyword(typeParam: ts.TypeNode): typeParam is ts.KeywordTypeNode {
|
||||
return typeParam.kind === ts.SyntaxKind.AnyKeyword;
|
||||
}
|
@ -15,7 +15,7 @@ import {hasNameIdentifier, isDefined} from '../utils';
|
||||
export interface ExportInfo {
|
||||
identifier: string;
|
||||
from: string;
|
||||
dtsFrom?: string|null;
|
||||
dtsFrom: string|null;
|
||||
}
|
||||
export type PrivateDeclarationsAnalyses = ExportInfo[];
|
||||
|
||||
@ -52,7 +52,7 @@ export class PrivateDeclarationsAnalyzer {
|
||||
return Array.from(privateDeclarations.keys()).map(id => {
|
||||
const from = id.getSourceFile().fileName;
|
||||
const declaration = privateDeclarations.get(id) !;
|
||||
const dtsDeclaration = this.host.getDtsDeclaration(declaration.node);
|
||||
const dtsDeclaration = this.host.getDtsDeclarationOfClass(declaration.node);
|
||||
const dtsFrom = dtsDeclaration && dtsDeclaration.getSourceFile().fileName;
|
||||
return {identifier: id.text, from, dtsFrom};
|
||||
});
|
||||
|
@ -14,7 +14,7 @@ import {BundleProgram} from '../packages/bundle_program';
|
||||
import {findAll, getNameText, isDefined} from '../utils';
|
||||
|
||||
import {DecoratedClass} from './decorated_class';
|
||||
import {ModuleWithProvidersFunction, NgccReflectionHost, PRE_R3_MARKER, SwitchableVariableDeclaration, isSwitchableVariableDeclaration} from './ngcc_host';
|
||||
import {NgccReflectionHost, PRE_R3_MARKER, SwitchableVariableDeclaration, isSwitchableVariableDeclaration} from './ngcc_host';
|
||||
|
||||
export const DECORATORS = 'decorators' as ts.__String;
|
||||
export const PROP_DECORATORS = 'propDecorators' as ts.__String;
|
||||
@ -49,10 +49,10 @@ export const CONSTRUCTOR_PARAMS = 'ctorParameters' as ts.__String;
|
||||
* a static method called `ctorParameters`.
|
||||
*/
|
||||
export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements NgccReflectionHost {
|
||||
protected dtsDeclarationMap: Map<string, ts.Declaration>|null;
|
||||
protected dtsClassMap: Map<string, ts.ClassDeclaration>|null;
|
||||
constructor(protected isCore: boolean, checker: ts.TypeChecker, dts?: BundleProgram|null) {
|
||||
super(checker);
|
||||
this.dtsDeclarationMap = dts && this.computeDtsDeclarationMap(dts.path, dts.program) || null;
|
||||
this.dtsClassMap = dts && this.computeDtsClassMap(dts.path, dts.program) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -327,15 +327,15 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
* is not a class or has an unknown number of type parameters.
|
||||
*/
|
||||
getGenericArityOfClass(clazz: ts.Declaration): number|null {
|
||||
const dtsDeclaration = this.getDtsDeclaration(clazz);
|
||||
if (dtsDeclaration && ts.isClassDeclaration(dtsDeclaration)) {
|
||||
return dtsDeclaration.typeParameters ? dtsDeclaration.typeParameters.length : 0;
|
||||
const dtsClass = this.getDtsDeclarationOfClass(clazz);
|
||||
if (dtsClass) {
|
||||
return dtsClass.typeParameters ? dtsClass.typeParameters.length : 0;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take an exported declaration of a class (maybe down-leveled to a variable) and look up the
|
||||
* Take an exported declaration of a class (maybe downleveled to a variable) and look up the
|
||||
* declaration of its type in a separate .d.ts tree.
|
||||
*
|
||||
* This function is allowed to return `null` if the current compilation unit does not have a
|
||||
@ -346,47 +346,19 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
* Note that the `ts.ClassDeclaration` returned from this function may not be from the same
|
||||
* `ts.Program` as the input declaration.
|
||||
*/
|
||||
getDtsDeclaration(declaration: ts.Declaration): ts.Declaration|null {
|
||||
if (!this.dtsDeclarationMap) {
|
||||
return null;
|
||||
getDtsDeclarationOfClass(declaration: ts.Declaration): ts.ClassDeclaration|null {
|
||||
if (this.dtsClassMap) {
|
||||
if (ts.isClassDeclaration(declaration)) {
|
||||
if (!declaration.name || !ts.isIdentifier(declaration.name)) {
|
||||
throw new Error(
|
||||
`Cannot get the dts file for a class declaration that has no indetifier: ${declaration.getText()} in ${declaration.getSourceFile().fileName}`);
|
||||
}
|
||||
return this.dtsClassMap.get(declaration.name.text) || null;
|
||||
}
|
||||
}
|
||||
if (!isNamedDeclaration(declaration)) {
|
||||
throw new Error(
|
||||
`Cannot get the dts file for a declaration that has no name: ${declaration.getText()} in ${declaration.getSourceFile().fileName}`);
|
||||
}
|
||||
return this.dtsDeclarationMap.get(declaration.name.text) || null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the given source file for exported functions and static class methods that return
|
||||
* ModuleWithProviders objects.
|
||||
* @param f The source file to search for these functions
|
||||
* @returns An array of function declarations that look like they return ModuleWithProviders
|
||||
* objects.
|
||||
*/
|
||||
getModuleWithProvidersFunctions(f: ts.SourceFile): ModuleWithProvidersFunction[] {
|
||||
const exports = this.getExportsOfModule(f);
|
||||
if (!exports) return [];
|
||||
const infos: ModuleWithProvidersFunction[] = [];
|
||||
exports.forEach((declaration, name) => {
|
||||
if (this.isClass(declaration.node)) {
|
||||
this.getMembersOfClass(declaration.node).forEach(member => {
|
||||
if (member.isStatic) {
|
||||
const info = this.parseForModuleWithProviders(member.node);
|
||||
if (info) {
|
||||
infos.push(info);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const info = this.parseForModuleWithProviders(declaration.node);
|
||||
if (info) {
|
||||
infos.push(info);
|
||||
}
|
||||
}
|
||||
});
|
||||
return infos;
|
||||
}
|
||||
|
||||
///////////// Protected Helpers /////////////
|
||||
|
||||
@ -766,7 +738,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
if (isNamedDeclaration(node)) {
|
||||
if (isNamedDeclaration(node) && node.name && ts.isIdentifier(node.name)) {
|
||||
name = node.name.text;
|
||||
nameNode = node.name;
|
||||
} else {
|
||||
@ -874,8 +846,8 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parameter type and decorators for a class where the information is stored via
|
||||
* calls to `__decorate` helpers.
|
||||
* Get the parameter type and decorators for a class where the information is stored on
|
||||
* in calls to `__decorate` helpers.
|
||||
*
|
||||
* Reflect over the helpers to find the decorators and types about each of
|
||||
* the class's constructor parameters.
|
||||
@ -1030,9 +1002,9 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
* @param dtsProgram The program containing all the typings files.
|
||||
* @returns a map of class names to class declarations.
|
||||
*/
|
||||
protected computeDtsDeclarationMap(dtsRootFileName: string, dtsProgram: ts.Program):
|
||||
Map<string, ts.Declaration> {
|
||||
const dtsDeclarationMap = new Map<string, ts.Declaration>();
|
||||
protected computeDtsClassMap(dtsRootFileName: string, dtsProgram: ts.Program):
|
||||
Map<string, ts.ClassDeclaration> {
|
||||
const dtsClassMap = new Map<string, ts.ClassDeclaration>();
|
||||
const checker = dtsProgram.getTypeChecker();
|
||||
|
||||
// First add all the classes that are publicly exported from the entry-point
|
||||
@ -1040,38 +1012,13 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
if (!rootFile) {
|
||||
throw new Error(`The given file ${dtsRootFileName} is not part of the typings program.`);
|
||||
}
|
||||
collectExportedDeclarations(checker, dtsDeclarationMap, rootFile);
|
||||
collectExportedClasses(checker, dtsClassMap, rootFile);
|
||||
|
||||
// Now add any additional classes that are exported from individual dts files,
|
||||
// but are not publicly exported from the entry-point.
|
||||
dtsProgram.getSourceFiles().forEach(
|
||||
sourceFile => { collectExportedDeclarations(checker, dtsDeclarationMap, sourceFile); });
|
||||
return dtsDeclarationMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given node, to see if it is a function that returns a `ModuleWithProviders` object.
|
||||
* @param node a node to check to see if it is a function that returns a `ModuleWithProviders`
|
||||
* object.
|
||||
* @returns info about the function if it does return a `ModuleWithProviders` object; `null`
|
||||
* otherwise.
|
||||
*/
|
||||
protected parseForModuleWithProviders(node: ts.Node|null): ModuleWithProvidersFunction|null {
|
||||
const declaration =
|
||||
node && (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) ? node : null;
|
||||
const body = declaration ? this.getDefinitionOfFunction(declaration).body : null;
|
||||
const lastStatement = body && body[body.length - 1];
|
||||
const returnExpression =
|
||||
lastStatement && ts.isReturnStatement(lastStatement) && lastStatement.expression || null;
|
||||
const ngModuleProperty = returnExpression && ts.isObjectLiteralExpression(returnExpression) &&
|
||||
returnExpression.properties.find(
|
||||
prop =>
|
||||
!!prop.name && ts.isIdentifier(prop.name) && prop.name.text === 'ngModule') ||
|
||||
null;
|
||||
const ngModule = ngModuleProperty && ts.isPropertyAssignment(ngModuleProperty) &&
|
||||
ts.isIdentifier(ngModuleProperty.initializer) && ngModuleProperty.initializer ||
|
||||
null;
|
||||
return ngModule && declaration && {ngModule, declaration};
|
||||
sourceFile => { collectExportedClasses(checker, dtsClassMap, sourceFile); });
|
||||
return dtsClassMap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1182,10 +1129,8 @@ function isThisAssignment(node: ts.Declaration): node is ts.BinaryExpression&
|
||||
node.left.expression.kind === ts.SyntaxKind.ThisKeyword;
|
||||
}
|
||||
|
||||
function isNamedDeclaration(node: ts.Declaration): node is ts.NamedDeclaration&
|
||||
{name: ts.Identifier} {
|
||||
const anyNode: any = node;
|
||||
return !!anyNode.name && ts.isIdentifier(anyNode.name);
|
||||
function isNamedDeclaration(node: ts.Declaration): node is ts.NamedDeclaration {
|
||||
return !!(node as any).name;
|
||||
}
|
||||
|
||||
|
||||
@ -1208,11 +1153,13 @@ function getFarLeftIdentifier(propertyAccess: ts.PropertyAccessExpression): ts.I
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect mappings between exported declarations in a source file and its associated
|
||||
* declaration in the typings program.
|
||||
* Search a source file for exported classes, storing them in the provided `dtsClassMap`.
|
||||
* @param checker The typechecker for the source program.
|
||||
* @param dtsClassMap The map in which to store the collected exported classes.
|
||||
* @param srcFile The source file to search for exported classes.
|
||||
*/
|
||||
function collectExportedDeclarations(
|
||||
checker: ts.TypeChecker, dtsDeclarationMap: Map<string, ts.Declaration>,
|
||||
function collectExportedClasses(
|
||||
checker: ts.TypeChecker, dtsClassMap: Map<string, ts.ClassDeclaration>,
|
||||
srcFile: ts.SourceFile): void {
|
||||
const srcModule = srcFile && checker.getSymbolAtLocation(srcFile);
|
||||
const moduleExports = srcModule && checker.getExportsOfModule(srcModule);
|
||||
@ -1223,8 +1170,8 @@ function collectExportedDeclarations(
|
||||
}
|
||||
const declaration = exportedSymbol.valueDeclaration;
|
||||
const name = exportedSymbol.name;
|
||||
if (declaration && !dtsDeclarationMap.has(name)) {
|
||||
dtsDeclarationMap.set(name, declaration);
|
||||
if (declaration && ts.isClassDeclaration(declaration) && !dtsClassMap.has(name)) {
|
||||
dtsClassMap.set(name, declaration);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -19,21 +19,6 @@ export function isSwitchableVariableDeclaration(node: ts.Node):
|
||||
ts.isIdentifier(node.initializer) && node.initializer.text.endsWith(PRE_R3_MARKER);
|
||||
}
|
||||
|
||||
/**
|
||||
* A structure returned from `getModuleWithProviderInfo` that describes functions
|
||||
* that return ModuleWithProviders objects.
|
||||
*/
|
||||
export interface ModuleWithProvidersFunction {
|
||||
/**
|
||||
* The declaration of the function that returns the `ModuleWithProviders` object.
|
||||
*/
|
||||
declaration: ts.SignatureDeclaration;
|
||||
/**
|
||||
* The identifier of the `ngModule` property on the `ModuleWithProviders` object.
|
||||
*/
|
||||
ngModule: ts.Identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* A reflection host that has extra methods for looking at non-Typescript package formats
|
||||
*/
|
||||
@ -60,13 +45,4 @@ export interface NgccReflectionHost extends ReflectionHost {
|
||||
* @returns An array of decorated classes.
|
||||
*/
|
||||
findDecoratedClasses(sourceFile: ts.SourceFile): DecoratedClass[];
|
||||
|
||||
/**
|
||||
* Search the given source file for exported functions and static class methods that return
|
||||
* ModuleWithProviders objects.
|
||||
* @param f The source file to search for these functions
|
||||
* @returns An array of info items about each of the functions that return ModuleWithProviders
|
||||
* objects.
|
||||
*/
|
||||
getModuleWithProvidersFunctions(f: ts.SourceFile): ModuleWithProvidersFunction[];
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import {mkdir, mv} from 'shelljs';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {CompiledFile, DecorationAnalyzer} from '../analysis/decoration_analyzer';
|
||||
import {ModuleWithProvidersAnalyses, ModuleWithProvidersAnalyzer} from '../analysis/module_with_providers_analyzer';
|
||||
import {NgccReferencesRegistry} from '../analysis/ngcc_references_registry';
|
||||
import {ExportInfo, PrivateDeclarationsAnalyzer} from '../analysis/private_declarations_analyzer';
|
||||
import {SwitchMarkerAnalyses, SwitchMarkerAnalyzer} from '../analysis/switch_marker_analyzer';
|
||||
@ -26,7 +25,6 @@ import {EntryPoint} from './entry_point';
|
||||
import {EntryPointBundle} from './entry_point_bundle';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A Package is stored in a directory on disk and that directory can contain one or more package
|
||||
* formats - e.g. fesm2015, UMD, etc. Additionally, each package provides typings (`.d.ts` files).
|
||||
@ -61,14 +59,13 @@ export class Transformer {
|
||||
const reflectionHost = this.getHost(isCore, bundle);
|
||||
|
||||
// Parse and analyze the files.
|
||||
const {decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} = this.analyzeProgram(reflectionHost, isCore, bundle);
|
||||
const {decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
this.analyzeProgram(reflectionHost, isCore, bundle);
|
||||
|
||||
// Transform the source files and source maps.
|
||||
const renderer = this.getRenderer(reflectionHost, isCore, bundle);
|
||||
const renderedFiles = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
|
||||
// Write out all the transformed files.
|
||||
renderedFiles.forEach(file => this.writeFile(file));
|
||||
@ -105,26 +102,16 @@ export class Transformer {
|
||||
ProgramAnalyses {
|
||||
const typeChecker = bundle.src.program.getTypeChecker();
|
||||
const referencesRegistry = new NgccReferencesRegistry(reflectionHost);
|
||||
|
||||
const switchMarkerAnalyzer = new SwitchMarkerAnalyzer(reflectionHost);
|
||||
const switchMarkerAnalyses = switchMarkerAnalyzer.analyzeProgram(bundle.src.program);
|
||||
|
||||
const decorationAnalyzer = new DecorationAnalyzer(
|
||||
typeChecker, reflectionHost, referencesRegistry, bundle.rootDirs, isCore);
|
||||
const decorationAnalyses = decorationAnalyzer.analyzeProgram(bundle.src.program);
|
||||
|
||||
const moduleWithProvidersAnalyzer =
|
||||
bundle.dts && new ModuleWithProvidersAnalyzer(reflectionHost, referencesRegistry);
|
||||
const moduleWithProvidersAnalyses = moduleWithProvidersAnalyzer &&
|
||||
moduleWithProvidersAnalyzer.analyzeProgram(bundle.src.program);
|
||||
|
||||
const switchMarkerAnalyzer = new SwitchMarkerAnalyzer(reflectionHost);
|
||||
const privateDeclarationsAnalyzer =
|
||||
new PrivateDeclarationsAnalyzer(reflectionHost, referencesRegistry);
|
||||
const decorationAnalyses = decorationAnalyzer.analyzeProgram(bundle.src.program);
|
||||
const switchMarkerAnalyses = switchMarkerAnalyzer.analyzeProgram(bundle.src.program);
|
||||
const privateDeclarationsAnalyses =
|
||||
privateDeclarationsAnalyzer.analyzeProgram(bundle.src.program);
|
||||
|
||||
return {decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses};
|
||||
return {decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses};
|
||||
}
|
||||
|
||||
writeFile(file: FileInfo): void {
|
||||
@ -142,5 +129,4 @@ interface ProgramAnalyses {
|
||||
decorationAnalyses: Map<ts.SourceFile, CompiledFile>;
|
||||
switchMarkerAnalyses: SwitchMarkerAnalyses;
|
||||
privateDeclarationsAnalyses: ExportInfo[];
|
||||
moduleWithProvidersAnalyses: ModuleWithProvidersAnalyses|null;
|
||||
}
|
||||
|
@ -15,10 +15,9 @@ import * as ts from 'typescript';
|
||||
|
||||
import {Decorator} from '../../../ngtsc/host';
|
||||
import {CompileResult} from '@angular/compiler-cli/src/ngtsc/transform';
|
||||
import {translateStatement, translateType, ImportManager} from '../../../ngtsc/translator';
|
||||
import {translateStatement, translateType} from '../../../ngtsc/translator';
|
||||
import {NgccImportManager} from './ngcc_import_manager';
|
||||
import {CompiledClass, CompiledFile, DecorationAnalyses} from '../analysis/decoration_analyzer';
|
||||
import {ModuleWithProvidersInfo, ModuleWithProvidersAnalyses} from '../analysis/module_with_providers_analyzer';
|
||||
import {PrivateDeclarationsAnalyses, ExportInfo} from '../analysis/private_declarations_analyzer';
|
||||
import {SwitchMarkerAnalyses, SwitchMarkerAnalysis} from '../analysis/switch_marker_analyzer';
|
||||
import {IMPORT_PREFIX} from '../constants';
|
||||
@ -50,20 +49,6 @@ interface DtsClassInfo {
|
||||
compilation: CompileResult[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A structure that captures information about what needs to be rendered
|
||||
* in a typings file.
|
||||
*
|
||||
* It is created as a result of processing the analysis passed to the renderer.
|
||||
*
|
||||
* The `renderDtsFile()` method consumes it when rendering a typings file.
|
||||
*/
|
||||
class DtsRenderInfo {
|
||||
classInfo: DtsClassInfo[] = [];
|
||||
moduleWithProviders: ModuleWithProvidersInfo[] = [];
|
||||
privateExports: ExportInfo[] = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* The collected decorators that have become redundant after the compilation
|
||||
* of Ivy static fields. The map is keyed by the container node, such that we
|
||||
@ -86,8 +71,7 @@ export abstract class Renderer {
|
||||
|
||||
renderProgram(
|
||||
decorationAnalyses: DecorationAnalyses, switchMarkerAnalyses: SwitchMarkerAnalyses,
|
||||
privateDeclarationsAnalyses: PrivateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses: ModuleWithProvidersAnalyses|null): FileInfo[] {
|
||||
privateDeclarationsAnalyses: PrivateDeclarationsAnalyses): FileInfo[] {
|
||||
const renderedFiles: FileInfo[] = [];
|
||||
|
||||
// Transform the source files.
|
||||
@ -103,16 +87,16 @@ export abstract class Renderer {
|
||||
|
||||
// Transform the .d.ts files
|
||||
if (this.bundle.dts) {
|
||||
const dtsFiles = this.getTypingsFilesToRender(
|
||||
decorationAnalyses, privateDeclarationsAnalyses, moduleWithProvidersAnalyses);
|
||||
const dtsFiles = this.getTypingsFilesToRender(decorationAnalyses);
|
||||
|
||||
// If the dts entry-point is not already there (it did not have compiled classes)
|
||||
// then add it now, to ensure it gets its extra exports rendered.
|
||||
if (!dtsFiles.has(this.bundle.dts.file)) {
|
||||
dtsFiles.set(this.bundle.dts.file, new DtsRenderInfo());
|
||||
dtsFiles.set(this.bundle.dts.file, []);
|
||||
}
|
||||
dtsFiles.forEach(
|
||||
(renderInfo, file) => renderedFiles.push(...this.renderDtsFile(file, renderInfo)));
|
||||
(classes, file) => renderedFiles.push(
|
||||
...this.renderDtsFile(file, classes, privateDeclarationsAnalyses)));
|
||||
}
|
||||
|
||||
return renderedFiles;
|
||||
@ -167,12 +151,14 @@ export abstract class Renderer {
|
||||
return this.renderSourceAndMap(sourceFile, input, outputText);
|
||||
}
|
||||
|
||||
renderDtsFile(dtsFile: ts.SourceFile, renderInfo: DtsRenderInfo): FileInfo[] {
|
||||
renderDtsFile(
|
||||
dtsFile: ts.SourceFile, dtsClasses: DtsClassInfo[],
|
||||
privateDeclarationsAnalyses: PrivateDeclarationsAnalyses): FileInfo[] {
|
||||
const input = this.extractSourceMap(dtsFile);
|
||||
const outputText = new MagicString(input.source);
|
||||
const importManager = new NgccImportManager(false, this.isCore, IMPORT_PREFIX);
|
||||
|
||||
renderInfo.classInfo.forEach(dtsClass => {
|
||||
dtsClasses.forEach(dtsClass => {
|
||||
const endOfClass = dtsClass.dtsDeclaration.getEnd();
|
||||
dtsClass.compilation.forEach(declaration => {
|
||||
const type = translateType(declaration.type, importManager);
|
||||
@ -181,67 +167,26 @@ export abstract class Renderer {
|
||||
});
|
||||
});
|
||||
|
||||
this.addModuleWithProvidersParams(outputText, renderInfo.moduleWithProviders, importManager);
|
||||
this.addImports(
|
||||
outputText, importManager.getAllImports(dtsFile.fileName, this.bundle.dts !.r3SymbolsFile));
|
||||
|
||||
this.addExports(outputText, dtsFile.fileName, renderInfo.privateExports);
|
||||
|
||||
if (dtsFile === this.bundle.dts !.file) {
|
||||
const dtsExports = privateDeclarationsAnalyses.map(e => {
|
||||
if (!e.dtsFrom) {
|
||||
throw new Error(
|
||||
`There is no typings path for ${e.identifier} in ${e.from}.\n` +
|
||||
`We need to add an export for this class to a .d.ts typings file because ` +
|
||||
`Angular compiler needs to be able to reference this class in compiled code, such as templates.\n` +
|
||||
`The simplest fix for this is to ensure that this class is exported from the package's entry-point.`);
|
||||
}
|
||||
return {identifier: e.identifier, from: e.dtsFrom};
|
||||
});
|
||||
this.addExports(outputText, dtsFile.fileName, dtsExports);
|
||||
}
|
||||
|
||||
return this.renderSourceAndMap(dtsFile, input, outputText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the type parameters to the appropriate functions that return `ModuleWithProviders`
|
||||
* structures.
|
||||
*
|
||||
* This function only gets called on typings files, so it doesn't need different implementations
|
||||
* for each bundle format.
|
||||
*/
|
||||
protected addModuleWithProvidersParams(
|
||||
outputText: MagicString, moduleWithProviders: ModuleWithProvidersInfo[],
|
||||
importManager: NgccImportManager): void {
|
||||
moduleWithProviders.forEach(info => {
|
||||
const ngModuleName = (info.ngModule.node as ts.ClassDeclaration).name !.text;
|
||||
const declarationFile = info.declaration.getSourceFile().fileName;
|
||||
const ngModuleFile = info.ngModule.node.getSourceFile().fileName;
|
||||
const importPath = info.ngModule.viaModule ||
|
||||
(declarationFile !== ngModuleFile ?
|
||||
stripExtension(`./${relative(dirname(declarationFile), ngModuleFile)}`) :
|
||||
null);
|
||||
const ngModule = getImportString(importManager, importPath, ngModuleName);
|
||||
|
||||
if (info.declaration.type) {
|
||||
const typeName = info.declaration.type && ts.isTypeReferenceNode(info.declaration.type) ?
|
||||
info.declaration.type.typeName :
|
||||
null;
|
||||
if (this.isCoreModuleWithProvidersType(typeName)) {
|
||||
// The declaration already returns `ModuleWithProvider` but it needs the `NgModule` type
|
||||
// parameter adding.
|
||||
outputText.overwrite(
|
||||
info.declaration.type.getStart(), info.declaration.type.getEnd(),
|
||||
`ModuleWithProviders<${ngModule}>`);
|
||||
} else {
|
||||
// The declaration returns an unknown type so we need to convert it to a union that
|
||||
// includes the ngModule property.
|
||||
const originalTypeString = info.declaration.type.getText();
|
||||
outputText.overwrite(
|
||||
info.declaration.type.getStart(), info.declaration.type.getEnd(),
|
||||
`(${originalTypeString})&{ngModule:${ngModule}}`);
|
||||
}
|
||||
} else {
|
||||
// The declaration has no return type so provide one.
|
||||
const lastToken = info.declaration.getLastToken();
|
||||
const insertPoint = lastToken && lastToken.kind === ts.SyntaxKind.SemicolonToken ?
|
||||
lastToken.getStart() :
|
||||
info.declaration.getEnd();
|
||||
outputText.appendLeft(
|
||||
insertPoint,
|
||||
`: ${getImportString(importManager, '@angular/core', 'ModuleWithProviders')}<${ngModule}>`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract addConstants(output: MagicString, constants: string, file: ts.SourceFile):
|
||||
void;
|
||||
protected abstract addImports(output: MagicString, imports: {name: string, as: string}[]): void;
|
||||
@ -357,67 +302,22 @@ export abstract class Renderer {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected getTypingsFilesToRender(
|
||||
decorationAnalyses: DecorationAnalyses,
|
||||
privateDeclarationsAnalyses: PrivateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses: ModuleWithProvidersAnalyses|
|
||||
null): Map<ts.SourceFile, DtsRenderInfo> {
|
||||
const dtsMap = new Map<ts.SourceFile, DtsRenderInfo>();
|
||||
|
||||
// Capture the rendering info from the decoration analyses
|
||||
decorationAnalyses.forEach(compiledFile => {
|
||||
protected getTypingsFilesToRender(analyses: DecorationAnalyses):
|
||||
Map<ts.SourceFile, DtsClassInfo[]> {
|
||||
const dtsMap = new Map<ts.SourceFile, DtsClassInfo[]>();
|
||||
analyses.forEach(compiledFile => {
|
||||
compiledFile.compiledClasses.forEach(compiledClass => {
|
||||
const dtsDeclaration = this.host.getDtsDeclaration(compiledClass.declaration);
|
||||
const dtsDeclaration = this.host.getDtsDeclarationOfClass(compiledClass.declaration);
|
||||
if (dtsDeclaration) {
|
||||
const dtsFile = dtsDeclaration.getSourceFile();
|
||||
const renderInfo = dtsMap.get(dtsFile) || new DtsRenderInfo();
|
||||
renderInfo.classInfo.push({dtsDeclaration, compilation: compiledClass.compilation});
|
||||
dtsMap.set(dtsFile, renderInfo);
|
||||
const classes = dtsMap.get(dtsFile) || [];
|
||||
classes.push({dtsDeclaration, compilation: compiledClass.compilation});
|
||||
dtsMap.set(dtsFile, classes);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Capture the ModuleWithProviders functions/methods that need updating
|
||||
if (moduleWithProvidersAnalyses !== null) {
|
||||
moduleWithProvidersAnalyses.forEach((moduleWithProvidersToFix, dtsFile) => {
|
||||
const renderInfo = dtsMap.get(dtsFile) || new DtsRenderInfo();
|
||||
renderInfo.moduleWithProviders = moduleWithProvidersToFix;
|
||||
dtsMap.set(dtsFile, renderInfo);
|
||||
});
|
||||
}
|
||||
|
||||
// Capture the private declarations that need to be re-exported
|
||||
if (privateDeclarationsAnalyses.length) {
|
||||
const dtsExports = privateDeclarationsAnalyses.map(e => {
|
||||
if (!e.dtsFrom) {
|
||||
throw new Error(
|
||||
`There is no typings path for ${e.identifier} in ${e.from}.\n` +
|
||||
`We need to add an export for this class to a .d.ts typings file because ` +
|
||||
`Angular compiler needs to be able to reference this class in compiled code, such as templates.\n` +
|
||||
`The simplest fix for this is to ensure that this class is exported from the package's entry-point.`);
|
||||
}
|
||||
return {identifier: e.identifier, from: e.dtsFrom};
|
||||
});
|
||||
const dtsEntryPoint = this.bundle.dts !.file;
|
||||
const renderInfo = dtsMap.get(dtsEntryPoint) || new DtsRenderInfo();
|
||||
renderInfo.privateExports = dtsExports;
|
||||
dtsMap.set(dtsEntryPoint, renderInfo);
|
||||
}
|
||||
|
||||
return dtsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given type is the core Angular `ModuleWithProviders` interface.
|
||||
* @param typeName The type to check.
|
||||
* @returns true if the type is the core Angular `ModuleWithProviders` interface.
|
||||
*/
|
||||
private isCoreModuleWithProvidersType(typeName: ts.EntityName|null) {
|
||||
const id =
|
||||
typeName && ts.isIdentifier(typeName) ? this.host.getImportOfIdentifier(typeName) : null;
|
||||
return (
|
||||
id && id.name === 'ModuleWithProviders' && (this.isCore || id.from === '@angular/core'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -486,7 +386,7 @@ export function renderDefinitions(
|
||||
}
|
||||
|
||||
export function stripExtension(filePath: string): string {
|
||||
return filePath.replace(/\.(js|d\.ts)$/, '');
|
||||
return filePath.replace(/\.(js|d\.ts$)/, '');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -499,9 +399,3 @@ function createAssignmentStatement(
|
||||
const receiver = new WrappedNodeExpr(receiverName);
|
||||
return new WritePropExpr(receiver, propName, initializer).toStmt();
|
||||
}
|
||||
|
||||
function getImportString(
|
||||
importManager: ImportManager, importPath: string | null, importName: string) {
|
||||
const importAs = importPath ? importManager.generateNamedImport(importPath, importName) : null;
|
||||
return importAs ? `${importAs.moduleImport}.${importAs.symbol}` : `${importName}`;
|
||||
}
|
||||
|
@ -1,401 +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 * as ts from 'typescript';
|
||||
|
||||
import {ModuleWithProvidersAnalyses, ModuleWithProvidersAnalyzer} from '../../src/analysis/module_with_providers_analyzer';
|
||||
import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry';
|
||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||
import {BundleProgram} from '../../src/packages/bundle_program';
|
||||
import {getDeclaration, makeTestBundleProgram, makeTestProgram} from '../helpers/utils';
|
||||
|
||||
const TEST_PROGRAM = [
|
||||
{
|
||||
name: '/src/entry-point.js',
|
||||
contents: `
|
||||
export * from './explicit';
|
||||
export * from './any';
|
||||
export * from './implicit';
|
||||
export * from './no-providers';
|
||||
export * from './module';
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/src/explicit.js',
|
||||
contents: `
|
||||
import {ExternalModule} from './module';
|
||||
import {LibraryModule} from 'some-library';
|
||||
export class ExplicitInternalModule {}
|
||||
export function explicitInternalFunction() {
|
||||
return {
|
||||
ngModule: ExplicitInternalModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
export function explicitExternalFunction() {
|
||||
return {
|
||||
ngModule: ExternalModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
export function explicitLibraryFunction() {
|
||||
return {
|
||||
ngModule: LibraryModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
export class ExplicitClass {
|
||||
static explicitInternalMethod() {
|
||||
return {
|
||||
ngModule: ExplicitInternalModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
static explicitExternalMethod() {
|
||||
return {
|
||||
ngModule: ExternalModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
static explicitLibraryMethod() {
|
||||
return {
|
||||
ngModule: LibraryModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/src/any.js',
|
||||
contents: `
|
||||
import {ExternalModule} from './module';
|
||||
import {LibraryModule} from 'some-library';
|
||||
export class AnyInternalModule {}
|
||||
export function anyInternalFunction() {
|
||||
return {
|
||||
ngModule: AnyInternalModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
export function anyExternalFunction() {
|
||||
return {
|
||||
ngModule: ExternalModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
export function anyLibraryFunction() {
|
||||
return {
|
||||
ngModule: LibraryModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
export class AnyClass {
|
||||
static anyInternalMethod() {
|
||||
return {
|
||||
ngModule: AnyInternalModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
static anyExternalMethod() {
|
||||
return {
|
||||
ngModule: ExternalModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
static anyLibraryMethod() {
|
||||
return {
|
||||
ngModule: LibraryModule,
|
||||
providers: []
|
||||
};
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/src/implicit.js',
|
||||
contents: `
|
||||
import {ExternalModule} from './module';
|
||||
import {LibraryModule} from 'some-library';
|
||||
export class ImplicitInternalModule {}
|
||||
export function implicitInternalFunction() {
|
||||
return {
|
||||
ngModule: ImplicitInternalModule,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
export function implicitExternalFunction() {
|
||||
return {
|
||||
ngModule: ExternalModule,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
export function implicitLibraryFunction() {
|
||||
return {
|
||||
ngModule: LibraryModule,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
export class ImplicitClass {
|
||||
static implicitInternalMethod() {
|
||||
return {
|
||||
ngModule: ImplicitInternalModule,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
static implicitExternalMethod() {
|
||||
return {
|
||||
ngModule: ExternalModule,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
static implicitLibraryMethod() {
|
||||
return {
|
||||
ngModule: LibraryModule,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/src/no-providers.js',
|
||||
contents: `
|
||||
import {ExternalModule} from './module';
|
||||
import {LibraryModule} from 'some-library';
|
||||
export class NoProvidersInternalModule {}
|
||||
export function noProvExplicitInternalFunction() {
|
||||
return {ngModule: NoProvidersInternalModule};
|
||||
}
|
||||
export function noProvExplicitExternalFunction() {
|
||||
return {ngModule: ExternalModule};
|
||||
}
|
||||
export function noProvExplicitLibraryFunction() {
|
||||
return {ngModule: LibraryModule};
|
||||
}
|
||||
export function noProvAnyInternalFunction() {
|
||||
return {ngModule: NoProvidersInternalModule};
|
||||
}
|
||||
export function noProvAnyExternalFunction() {
|
||||
return {ngModule: ExternalModule};
|
||||
}
|
||||
export function noProvAnyLibraryFunction() {
|
||||
return {ngModule: LibraryModule};
|
||||
}
|
||||
export function noProvImplicitInternalFunction() {
|
||||
return {ngModule: NoProvidersInternalModule};
|
||||
}
|
||||
export function noProvImplicitExternalFunction() {
|
||||
return {ngModule: ExternalModule};
|
||||
}
|
||||
export function noProvImplicitLibraryFunction() {
|
||||
return {ngModule: LibraryModule};
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/src/module.js',
|
||||
contents: `
|
||||
export class ExternalModule {}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/node_modules/some-library/index.d.ts',
|
||||
contents: 'export declare class LibraryModule {}'
|
||||
},
|
||||
];
|
||||
const TEST_DTS_PROGRAM = [
|
||||
{
|
||||
name: '/typings/entry-point.d.ts',
|
||||
contents: `
|
||||
export * from './explicit';
|
||||
export * from './any';
|
||||
export * from './implicit';
|
||||
export * from './no-providers';
|
||||
export * from './module';
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/typings/explicit.d.ts',
|
||||
contents: `
|
||||
import {ModuleWithProviders} from './core';
|
||||
import {ExternalModule} from './module';
|
||||
import {LibraryModule} from 'some-library';
|
||||
export declare class ExplicitInternalModule {}
|
||||
export declare function explicitInternalFunction(): ModuleWithProviders<ExplicitInternalModule>;
|
||||
export declare function explicitExternalFunction(): ModuleWithProviders<ExternalModule>;
|
||||
export declare function explicitLibraryFunction(): ModuleWithProviders<LibraryModule>;
|
||||
export declare class ExplicitClass {
|
||||
static explicitInternalMethod(): ModuleWithProviders<ExplicitInternalModule>;
|
||||
static explicitExternalMethod(): ModuleWithProviders<ExternalModule>;
|
||||
static explicitLibraryMethod(): ModuleWithProviders<LibraryModule>;
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/typings/any.d.ts',
|
||||
contents: `
|
||||
import {ModuleWithProviders} from './core';
|
||||
export declare class AnyInternalModule {}
|
||||
export declare function anyInternalFunction(): ModuleWithProviders<any>;
|
||||
export declare function anyExternalFunction(): ModuleWithProviders<any>;
|
||||
export declare function anyLibraryFunction(): ModuleWithProviders<any>;
|
||||
export declare class AnyClass {
|
||||
static anyInternalMethod(): ModuleWithProviders<any>;
|
||||
static anyExternalMethod(): ModuleWithProviders<any>;
|
||||
static anyLibraryMethod(): ModuleWithProviders<any>;
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/typings/implicit.d.ts',
|
||||
contents: `
|
||||
import {ExternalModule} from './module';
|
||||
import {LibraryModule} from 'some-library';
|
||||
export declare class ImplicitInternalModule {}
|
||||
export declare function implicitInternalFunction(): { ngModule: typeof ImplicitInternalModule; providers: never[]; };
|
||||
export declare function implicitExternalFunction(): { ngModule: typeof ExternalModule; providers: never[]; };
|
||||
export declare function implicitLibraryFunction(): { ngModule: typeof LibraryModule; providers: never[]; };
|
||||
export declare class ImplicitClass {
|
||||
static implicitInternalMethod(): { ngModule: typeof ImplicitInternalModule; providers: never[]; };
|
||||
static implicitExternalMethod(): { ngModule: typeof ExternalModule; providers: never[]; };
|
||||
static implicitLibraryMethod(): { ngModule: typeof LibraryModule; providers: never[]; };
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/typings/no-providers.d.ts',
|
||||
contents: `
|
||||
import {ModuleWithProviders} from './core';
|
||||
import {ExternalModule} from './module';
|
||||
import {LibraryModule} from 'some-library';
|
||||
export declare class NoProvidersInternalModule {}
|
||||
export declare function noProvExplicitInternalFunction(): ModuleWithProviders<NoProvidersInternalModule>;
|
||||
export declare function noProvExplicitExternalFunction(): ModuleWithProviders<ExternalModule>;
|
||||
export declare function noProvExplicitLibraryFunction(): ModuleWithProviders<LibraryModule>;
|
||||
export declare function noProvAnyInternalFunction(): ModuleWithProviders<any>;
|
||||
export declare function noProvAnyExternalFunction(): ModuleWithProviders<any>;
|
||||
export declare function noProvAnyLibraryFunction(): ModuleWithProviders<any>;
|
||||
export declare function noProvImplicitInternalFunction(): { ngModule: typeof NoProvidersInternalModule; };
|
||||
export declare function noProvImplicitExternalFunction(): { ngModule: typeof ExternalModule; };
|
||||
export declare function noProvImplicitLibraryFunction(): { ngModule: typeof LibraryModule; };
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/typings/module.d.ts',
|
||||
contents: `
|
||||
export declare class ExternalModule {}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/typings/core.d.ts',
|
||||
contents: `
|
||||
|
||||
export declare interface Type<T> {
|
||||
new (...args: any[]): T
|
||||
}
|
||||
export declare type Provider = any;
|
||||
export declare interface ModuleWithProviders<T> {
|
||||
ngModule: Type<T>
|
||||
providers?: Provider[]
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/node_modules/some-library/index.d.ts',
|
||||
contents: 'export declare class LibraryModule {}'
|
||||
},
|
||||
];
|
||||
|
||||
describe('ModuleWithProvidersAnalyzer', () => {
|
||||
describe('analyzeProgram()', () => {
|
||||
let analyses: ModuleWithProvidersAnalyses;
|
||||
let program: ts.Program;
|
||||
let dtsProgram: BundleProgram;
|
||||
let referencesRegistry: NgccReferencesRegistry;
|
||||
|
||||
beforeAll(() => {
|
||||
program = makeTestProgram(...TEST_PROGRAM);
|
||||
dtsProgram = makeTestBundleProgram(TEST_DTS_PROGRAM);
|
||||
const host = new Esm2015ReflectionHost(false, program.getTypeChecker(), dtsProgram);
|
||||
referencesRegistry = new NgccReferencesRegistry(host);
|
||||
|
||||
const analyzer = new ModuleWithProvidersAnalyzer(host, referencesRegistry);
|
||||
analyses = analyzer.analyzeProgram(program);
|
||||
});
|
||||
|
||||
it('should ignore declarations that already have explicit NgModule type params',
|
||||
() => { expect(getAnalysisDescription(analyses, '/typings/explicit.d.ts')).toEqual([]); });
|
||||
|
||||
it('should find declarations that use `any` for the NgModule type param', () => {
|
||||
const anyAnalysis = getAnalysisDescription(analyses, '/typings/any.d.ts');
|
||||
expect(anyAnalysis).toContain(['anyInternalFunction', 'AnyInternalModule', null]);
|
||||
expect(anyAnalysis).toContain(['anyExternalFunction', 'ExternalModule', null]);
|
||||
expect(anyAnalysis).toContain(['anyLibraryFunction', 'LibraryModule', 'some-library']);
|
||||
expect(anyAnalysis).toContain(['anyInternalMethod', 'AnyInternalModule', null]);
|
||||
expect(anyAnalysis).toContain(['anyExternalMethod', 'ExternalModule', null]);
|
||||
expect(anyAnalysis).toContain(['anyLibraryMethod', 'LibraryModule', 'some-library']);
|
||||
});
|
||||
|
||||
it('should track internal module references in the references registry', () => {
|
||||
const declarations = referencesRegistry.getDeclarationMap();
|
||||
const externalModuleDeclaration =
|
||||
getDeclaration(program, '/src/module.js', 'ExternalModule', ts.isClassDeclaration);
|
||||
const libraryModuleDeclaration = getDeclaration(
|
||||
program, '/node_modules/some-library/index.d.ts', 'LibraryModule', ts.isClassDeclaration);
|
||||
expect(declarations.has(externalModuleDeclaration.name !)).toBe(true);
|
||||
expect(declarations.has(libraryModuleDeclaration.name !)).toBe(false);
|
||||
});
|
||||
|
||||
it('should find declarations that have implicit return types', () => {
|
||||
const anyAnalysis = getAnalysisDescription(analyses, '/typings/implicit.d.ts');
|
||||
expect(anyAnalysis).toContain(['implicitInternalFunction', 'ImplicitInternalModule', null]);
|
||||
expect(anyAnalysis).toContain(['implicitExternalFunction', 'ExternalModule', null]);
|
||||
expect(anyAnalysis).toContain(['implicitLibraryFunction', 'LibraryModule', 'some-library']);
|
||||
expect(anyAnalysis).toContain(['implicitInternalMethod', 'ImplicitInternalModule', null]);
|
||||
expect(anyAnalysis).toContain(['implicitExternalMethod', 'ExternalModule', null]);
|
||||
expect(anyAnalysis).toContain(['implicitLibraryMethod', 'LibraryModule', 'some-library']);
|
||||
});
|
||||
|
||||
it('should find declarations that do not specify a `providers` property in the return type',
|
||||
() => {
|
||||
const anyAnalysis = getAnalysisDescription(analyses, '/typings/no-providers.d.ts');
|
||||
expect(anyAnalysis).not.toContain([
|
||||
'noProvExplicitInternalFunction', 'NoProvidersInternalModule'
|
||||
]);
|
||||
expect(anyAnalysis).not.toContain([
|
||||
'noProvExplicitExternalFunction', 'ExternalModule', null
|
||||
]);
|
||||
expect(anyAnalysis).toContain([
|
||||
'noProvAnyInternalFunction', 'NoProvidersInternalModule', null
|
||||
]);
|
||||
expect(anyAnalysis).toContain(['noProvAnyExternalFunction', 'ExternalModule', null]);
|
||||
expect(anyAnalysis).toContain([
|
||||
'noProvAnyLibraryFunction', 'LibraryModule', 'some-library'
|
||||
]);
|
||||
expect(anyAnalysis).toContain([
|
||||
'noProvImplicitInternalFunction', 'NoProvidersInternalModule', null
|
||||
]);
|
||||
expect(anyAnalysis).toContain(['noProvImplicitExternalFunction', 'ExternalModule', null]);
|
||||
expect(anyAnalysis).toContain([
|
||||
'noProvImplicitLibraryFunction', 'LibraryModule', 'some-library'
|
||||
]);
|
||||
});
|
||||
|
||||
function getAnalysisDescription(analyses: ModuleWithProvidersAnalyses, fileName: string) {
|
||||
const file = dtsProgram.program.getSourceFile(fileName) !;
|
||||
const analysis = analyses.get(file);
|
||||
return analysis ?
|
||||
analysis.map(
|
||||
info =>
|
||||
[info.declaration.name !.getText(),
|
||||
(info.ngModule.node as ts.ClassDeclaration).name !.getText(),
|
||||
info.ngModule.viaModule]) :
|
||||
[];
|
||||
}
|
||||
});
|
||||
});
|
@ -84,8 +84,6 @@ export function getFakeCore() {
|
||||
export class InjectionToken {
|
||||
constructor(name: string) {}
|
||||
}
|
||||
|
||||
export interface ModuleWithProviders<T = any> {}
|
||||
`
|
||||
};
|
||||
}
|
||||
|
@ -453,7 +453,6 @@ const TYPINGS_SRC_FILES = [
|
||||
},
|
||||
{name: '/src/class1.js', contents: 'export class Class1 {}\nexport class MissingClass1 {}'},
|
||||
{name: '/src/class2.js', contents: 'export class Class2 {}'},
|
||||
{name: '/src/func1.js', contents: 'export function mooFn() {}'},
|
||||
{name: '/src/internal.js', contents: 'export class InternalClass {}\nexport class Class2 {}'},
|
||||
{name: '/src/missing-class.js', contents: 'export class MissingClass2 {}'}, {
|
||||
name: '/src/flat-file.js',
|
||||
@ -477,7 +476,6 @@ const TYPINGS_DTS_FILES = [
|
||||
contents:
|
||||
`export declare class Class2 {}\nexport declare interface SomeInterface {}\nexport {Class3 as xClass3} from './class3';`
|
||||
},
|
||||
{name: '/typings/func1.d.ts', contents: 'export declare function mooFn(): void;'},
|
||||
{
|
||||
name: '/typings/internal.d.ts',
|
||||
contents: `export declare class InternalClass {}\nexport declare class Class2 {}`
|
||||
@ -485,54 +483,6 @@ const TYPINGS_DTS_FILES = [
|
||||
{name: '/typings/class3.d.ts', contents: `export declare class Class3 {}`},
|
||||
];
|
||||
|
||||
const MODULE_WITH_PROVIDERS_PROGRAM = [
|
||||
{
|
||||
name: '/src/functions.js',
|
||||
contents: `
|
||||
import {ExternalModule} from './module';
|
||||
export class SomeService {}
|
||||
export class InternalModule {}
|
||||
export function aNumber() { return 42; }
|
||||
export function aString() { return 'foo'; }
|
||||
export function emptyObject() { return {}; }
|
||||
export function ngModuleIdentifier() { return { ngModule: InternalModule }; }
|
||||
export function ngModuleWithEmptyProviders() { return { ngModule: InternalModule, providers: [] }; }
|
||||
export function ngModuleWithProviders() { return { ngModule: InternalModule, providers: [SomeService] }; }
|
||||
export function onlyProviders() { return { providers: [SomeService] }; }
|
||||
export function ngModuleNumber() { return { ngModule: 42 }; }
|
||||
export function ngModuleString() { return { ngModule: 'foo' }; }
|
||||
export function ngModuleObject() { return { ngModule: { foo: 42 } }; }
|
||||
export function externalNgModule() { return { ngModule: ExternalModule }; }
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '/src/methods.js',
|
||||
contents: `
|
||||
import {ExternalModule} from './module';
|
||||
export class SomeService {}
|
||||
export class InternalModule {
|
||||
static aNumber() { return 42; }
|
||||
static aString() { return 'foo'; }
|
||||
static emptyObject() { return {}; }
|
||||
static ngModuleIdentifier() { return { ngModule: InternalModule }; }
|
||||
static ngModuleWithEmptyProviders() { return { ngModule: InternalModule, providers: [] }; }
|
||||
static ngModuleWithProviders() { return { ngModule: InternalModule, providers: [SomeService] }; }
|
||||
static onlyProviders() { return { providers: [SomeService] }; }
|
||||
static ngModuleNumber() { return { ngModule: 42 }; }
|
||||
static ngModuleString() { return { ngModule: 'foo' }; }
|
||||
static ngModuleObject() { return { ngModule: { foo: 42 } }; }
|
||||
static externalNgModule() { return { ngModule: ExternalModule }; }
|
||||
|
||||
instanceNgModuleIdentifier() { return { ngModule: InternalModule }; }
|
||||
instanceNgModuleWithEmptyProviders() { return { ngModule: InternalModule, providers: [] }; }
|
||||
instanceNgModuleWithProviders() { return { ngModule: InternalModule, providers: [SomeService] }; }
|
||||
instanceExternalNgModule() { return { ngModule: ExternalModule }; }
|
||||
}
|
||||
`
|
||||
},
|
||||
{name: '/src/module', contents: 'export class ExternalModule {}'},
|
||||
];
|
||||
|
||||
describe('Fesm2015ReflectionHost', () => {
|
||||
|
||||
describe('getDecoratorsOfDeclaration()', () => {
|
||||
@ -1336,20 +1286,10 @@ describe('Fesm2015ReflectionHost', () => {
|
||||
const class1 = getDeclaration(srcProgram, '/src/class1.js', 'Class1', ts.isClassDeclaration);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker(), dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class1);
|
||||
const dtsDeclaration = host.getDtsDeclarationOfClass(class1);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual('/typings/class1.d.ts');
|
||||
});
|
||||
|
||||
it('should find the dts declaration for exported functions', () => {
|
||||
const srcProgram = makeTestProgram(...TYPINGS_SRC_FILES);
|
||||
const dtsProgram = makeTestBundleProgram(TYPINGS_DTS_FILES);
|
||||
const mooFn = getDeclaration(srcProgram, '/src/func1.js', 'mooFn', ts.isFunctionDeclaration);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker(), dtsProgram);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(mooFn);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual('/typings/func1.d.ts');
|
||||
});
|
||||
|
||||
it('should return null if there is no matching class in the matching dts file', () => {
|
||||
const srcProgram = makeTestProgram(...TYPINGS_SRC_FILES);
|
||||
const dts = makeTestBundleProgram(TYPINGS_DTS_FILES);
|
||||
@ -1357,7 +1297,7 @@ describe('Fesm2015ReflectionHost', () => {
|
||||
getDeclaration(srcProgram, '/src/class1.js', 'MissingClass1', ts.isClassDeclaration);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker(), dts);
|
||||
|
||||
expect(host.getDtsDeclaration(missingClass)).toBe(null);
|
||||
expect(host.getDtsDeclarationOfClass(missingClass)).toBe(null);
|
||||
});
|
||||
|
||||
it('should return null if there is no matching dts file', () => {
|
||||
@ -1367,7 +1307,7 @@ describe('Fesm2015ReflectionHost', () => {
|
||||
srcProgram, '/src/missing-class.js', 'MissingClass2', ts.isClassDeclaration);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker(), dts);
|
||||
|
||||
expect(host.getDtsDeclaration(missingClass)).toBe(null);
|
||||
expect(host.getDtsDeclarationOfClass(missingClass)).toBe(null);
|
||||
});
|
||||
|
||||
it('should find the dts file that contains a matching class declaration, even if the source files do not match',
|
||||
@ -1378,7 +1318,7 @@ describe('Fesm2015ReflectionHost', () => {
|
||||
getDeclaration(srcProgram, '/src/flat-file.js', 'Class1', ts.isClassDeclaration);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker(), dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class1);
|
||||
const dtsDeclaration = host.getDtsDeclarationOfClass(class1);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual('/typings/class1.d.ts');
|
||||
});
|
||||
|
||||
@ -1389,7 +1329,7 @@ describe('Fesm2015ReflectionHost', () => {
|
||||
getDeclaration(srcProgram, '/src/flat-file.js', 'Class3', ts.isClassDeclaration);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker(), dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class3);
|
||||
const dtsDeclaration = host.getDtsDeclarationOfClass(class3);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual('/typings/class3.d.ts');
|
||||
});
|
||||
|
||||
@ -1401,7 +1341,7 @@ describe('Fesm2015ReflectionHost', () => {
|
||||
getDeclaration(srcProgram, '/src/internal.js', 'InternalClass', ts.isClassDeclaration);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker(), dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(internalClass);
|
||||
const dtsDeclaration = host.getDtsDeclarationOfClass(internalClass);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual('/typings/internal.d.ts');
|
||||
});
|
||||
|
||||
@ -1415,42 +1355,12 @@ describe('Fesm2015ReflectionHost', () => {
|
||||
getDeclaration(srcProgram, '/src/internal.js', 'Class2', ts.isClassDeclaration);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker(), dts);
|
||||
|
||||
const class2DtsDeclaration = host.getDtsDeclaration(class2);
|
||||
const class2DtsDeclaration = host.getDtsDeclarationOfClass(class2);
|
||||
expect(class2DtsDeclaration !.getSourceFile().fileName).toEqual('/typings/class2.d.ts');
|
||||
|
||||
const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2);
|
||||
const internalClass2DtsDeclaration = host.getDtsDeclarationOfClass(internalClass2);
|
||||
expect(internalClass2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual('/typings/class2.d.ts');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getModuleWithProvidersFunctions', () => {
|
||||
it('should find every exported function that returns an object that looks like a ModuleWithProviders object',
|
||||
() => {
|
||||
const srcProgram = makeTestProgram(...MODULE_WITH_PROVIDERS_PROGRAM);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker());
|
||||
const file = srcProgram.getSourceFile('/src/functions.js') !;
|
||||
const fns = host.getModuleWithProvidersFunctions(file);
|
||||
expect(fns.map(info => [info.declaration.name !.getText(), info.ngModule.text])).toEqual([
|
||||
['ngModuleIdentifier', 'InternalModule'],
|
||||
['ngModuleWithEmptyProviders', 'InternalModule'],
|
||||
['ngModuleWithProviders', 'InternalModule'],
|
||||
['externalNgModule', 'ExternalModule'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should find every static method on exported classes that return an object that looks like a ModuleWithProviders object',
|
||||
() => {
|
||||
const srcProgram = makeTestProgram(...MODULE_WITH_PROVIDERS_PROGRAM);
|
||||
const host = new Esm2015ReflectionHost(false, srcProgram.getTypeChecker());
|
||||
const file = srcProgram.getSourceFile('/src/methods.js') !;
|
||||
const fn = host.getModuleWithProvidersFunctions(file);
|
||||
expect(fn.map(fn => [fn.declaration.name !.getText(), fn.ngModule.text])).toEqual([
|
||||
['ngModuleIdentifier', 'InternalModule'],
|
||||
['ngModuleWithEmptyProviders', 'InternalModule'],
|
||||
['ngModuleWithProviders', 'InternalModule'],
|
||||
['externalNgModule', 'ExternalModule'],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -11,7 +11,6 @@ import * as ts from 'typescript';
|
||||
import {fromObject, generateMapFileComment} from 'convert-source-map';
|
||||
import {CompiledClass, DecorationAnalyzer} from '../../src/analysis/decoration_analyzer';
|
||||
import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry';
|
||||
import {ModuleWithProvidersAnalyzer} from '../../src/analysis/module_with_providers_analyzer';
|
||||
import {PrivateDeclarationsAnalyzer} from '../../src/analysis/private_declarations_analyzer';
|
||||
import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer';
|
||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||
@ -48,9 +47,9 @@ class TestRenderer extends Renderer {
|
||||
|
||||
function createTestRenderer(
|
||||
packageName: string, files: {name: string, contents: string}[],
|
||||
dtsFiles?: {name: string, contents: string}[]) {
|
||||
dtsFile?: {name: string, contents: string}) {
|
||||
const isCore = packageName === '@angular/core';
|
||||
const bundle = makeTestEntryPointBundle('esm2015', files, dtsFiles);
|
||||
const bundle = makeTestEntryPointBundle('esm2015', files, dtsFile && [dtsFile]);
|
||||
const typeChecker = bundle.src.program.getTypeChecker();
|
||||
const host = new Esm2015ReflectionHost(isCore, typeChecker, bundle.dts);
|
||||
const referencesRegistry = new NgccReferencesRegistry(host);
|
||||
@ -58,8 +57,6 @@ function createTestRenderer(
|
||||
new DecorationAnalyzer(typeChecker, host, referencesRegistry, bundle.rootDirs, isCore)
|
||||
.analyzeProgram(bundle.src.program);
|
||||
const switchMarkerAnalyses = new SwitchMarkerAnalyzer(host).analyzeProgram(bundle.src.program);
|
||||
const moduleWithProvidersAnalyses =
|
||||
new ModuleWithProvidersAnalyzer(host, referencesRegistry).analyzeProgram(bundle.src.program);
|
||||
const privateDeclarationsAnalyses =
|
||||
new PrivateDeclarationsAnalyzer(host, referencesRegistry).analyzeProgram(bundle.src.program);
|
||||
const renderer = new TestRenderer(host, isCore, bundle);
|
||||
@ -67,8 +64,7 @@ function createTestRenderer(
|
||||
spyOn(renderer, 'addDefinitions').and.callThrough();
|
||||
spyOn(renderer, 'removeDecorators').and.callThrough();
|
||||
|
||||
return {renderer, decorationAnalyses, switchMarkerAnalyses, moduleWithProvidersAnalyses,
|
||||
privateDeclarationsAnalyses};
|
||||
return {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses};
|
||||
}
|
||||
|
||||
|
||||
@ -125,11 +121,10 @@ describe('Renderer', () => {
|
||||
describe('renderProgram()', () => {
|
||||
it('should render the modified contents; and a new map file, if the original provided no map file.',
|
||||
() => {
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} = createTestRenderer('test-package', [INPUT_PROGRAM]);
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM]);
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
expect(result[0].path).toEqual('/dist/file.js');
|
||||
expect(result[0].contents)
|
||||
.toEqual(RENDERED_CONTENTS + '\n' + generateMapFileComment('/dist/file.js.map'));
|
||||
@ -139,11 +134,9 @@ describe('Renderer', () => {
|
||||
|
||||
|
||||
it('should render as JavaScript', () => {
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} = createTestRenderer('test-package', [COMPONENT_PROGRAM]);
|
||||
renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('test-package', [COMPONENT_PROGRAM]);
|
||||
renderer.renderProgram(decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
const addDefinitionsSpy = renderer.addDefinitions as jasmine.Spy;
|
||||
expect(addDefinitionsSpy.calls.first().args[2])
|
||||
.toEqual(`/*@__PURE__*/ ɵngcc0.ɵsetClassMetadata(A, [{
|
||||
@ -161,12 +154,10 @@ A.ngComponentDef = ɵngcc0.ɵdefineComponent({ type: A, selectors: [["a"]], fact
|
||||
describe('calling abstract methods', () => {
|
||||
it('should call addImports with the source code and info about the core Angular library.',
|
||||
() => {
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM]);
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
const addImportsSpy = renderer.addImports as jasmine.Spy;
|
||||
expect(addImportsSpy.calls.first().args[0].toString()).toEqual(RENDERED_CONTENTS);
|
||||
expect(addImportsSpy.calls.first().args[1]).toEqual([
|
||||
@ -176,12 +167,10 @@ A.ngComponentDef = ɵngcc0.ɵdefineComponent({ type: A, selectors: [["a"]], fact
|
||||
|
||||
it('should call addDefinitions with the source code, the analyzed class and the rendered definitions.',
|
||||
() => {
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM]);
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
const addDefinitionsSpy = renderer.addDefinitions as jasmine.Spy;
|
||||
expect(addDefinitionsSpy.calls.first().args[0].toString()).toEqual(RENDERED_CONTENTS);
|
||||
expect(addDefinitionsSpy.calls.first().args[1]).toEqual(jasmine.objectContaining({
|
||||
@ -198,12 +187,10 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""
|
||||
|
||||
it('should call removeDecorators with the source code, a map of class decorators that have been analyzed',
|
||||
() => {
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM]);
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
const removeDecoratorsSpy = renderer.removeDecorators as jasmine.Spy;
|
||||
expect(removeDecoratorsSpy.calls.first().args[0].toString()).toEqual(RENDERED_CONTENTS);
|
||||
|
||||
@ -225,16 +212,14 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""
|
||||
describe('source map merging', () => {
|
||||
it('should merge any inline source map from the original file and write the output as an inline source map',
|
||||
() => {
|
||||
const {decorationAnalyses, renderer, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
const {decorationAnalyses, renderer, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer(
|
||||
'test-package', [{
|
||||
...INPUT_PROGRAM,
|
||||
contents: INPUT_PROGRAM.contents + '\n' + INPUT_PROGRAM_MAP.toComment()
|
||||
}]);
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
expect(result[0].path).toEqual('/dist/file.js');
|
||||
expect(result[0].contents)
|
||||
.toEqual(RENDERED_CONTENTS + '\n' + MERGED_OUTPUT_PROGRAM_MAP.toComment());
|
||||
@ -245,16 +230,14 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""
|
||||
() => {
|
||||
// Mock out reading the map file from disk
|
||||
spyOn(fs, 'readFileSync').and.returnValue(INPUT_PROGRAM_MAP.toJSON());
|
||||
const {decorationAnalyses, renderer, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
const {decorationAnalyses, renderer, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer(
|
||||
'test-package', [{
|
||||
...INPUT_PROGRAM,
|
||||
contents: INPUT_PROGRAM.contents + '\n//# sourceMappingURL=file.js.map'
|
||||
}]);
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
expect(result[0].path).toEqual('/dist/file.js');
|
||||
expect(result[0].contents)
|
||||
.toEqual(RENDERED_CONTENTS + '\n' + generateMapFileComment('/dist/file.js.map'));
|
||||
@ -276,12 +259,10 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""
|
||||
contents: `export const NgModule = () => null;`
|
||||
};
|
||||
// The package name of `@angular/core` indicates that we are compiling the core library.
|
||||
const {decorationAnalyses, renderer, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
const {decorationAnalyses, renderer, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('@angular/core', [CORE_FILE, R3_SYMBOLS_FILE]);
|
||||
renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
const addDefinitionsSpy = renderer.addDefinitions as jasmine.Spy;
|
||||
expect(addDefinitionsSpy.calls.first().args[2])
|
||||
.toContain(`/*@__PURE__*/ ɵngcc0.setClassMetadata(`);
|
||||
@ -296,11 +277,10 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""
|
||||
export class MyModule {}\nMyModule.decorators = [\n { type: NgModule, args: [] }\n];\n`
|
||||
};
|
||||
|
||||
const {decorationAnalyses, renderer, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} = createTestRenderer('@angular/core', [CORE_FILE]);
|
||||
const {decorationAnalyses, renderer, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('@angular/core', [CORE_FILE]);
|
||||
renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
const addDefinitionsSpy = renderer.addDefinitions as jasmine.Spy;
|
||||
expect(addDefinitionsSpy.calls.first().args[2])
|
||||
.toContain(`/*@__PURE__*/ setClassMetadata(`);
|
||||
@ -311,12 +291,10 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""
|
||||
|
||||
describe('rendering typings', () => {
|
||||
it('should render extract types into typings files', () => {
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM], [INPUT_DTS_PROGRAM]);
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM], INPUT_DTS_PROGRAM);
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
|
||||
const typingsFile = result.find(f => f.path === '/typings/file.d.ts') !;
|
||||
expect(typingsFile.contents)
|
||||
@ -325,195 +303,30 @@ A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""
|
||||
});
|
||||
|
||||
it('should render imports into typings files', () => {
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM], [INPUT_DTS_PROGRAM]);
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM], INPUT_DTS_PROGRAM);
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
|
||||
const typingsFile = result.find(f => f.path === '/typings/file.d.ts') !;
|
||||
expect(typingsFile.contents).toContain(`// ADD IMPORTS\nexport declare class A`);
|
||||
});
|
||||
|
||||
it('should render exports into typings files', () => {
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM], [INPUT_DTS_PROGRAM]);
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} =
|
||||
createTestRenderer('test-package', [INPUT_PROGRAM], INPUT_DTS_PROGRAM);
|
||||
|
||||
// Add a mock export to trigger export rendering
|
||||
privateDeclarationsAnalyses.push(
|
||||
{identifier: 'ComponentB', from: '/src/file.js', dtsFrom: '/typings/b.d.ts'});
|
||||
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
|
||||
|
||||
const typingsFile = result.find(f => f.path === '/typings/file.d.ts') !;
|
||||
expect(typingsFile.contents)
|
||||
.toContain(`// ADD EXPORTS\n\n// ADD IMPORTS\nexport declare class A`);
|
||||
});
|
||||
|
||||
it('should fixup functions/methods that return ModuleWithProviders structures', () => {
|
||||
const MODULE_WITH_PROVIDERS_PROGRAM = [
|
||||
{
|
||||
name: '/src/index.js',
|
||||
contents: `
|
||||
import {ExternalModule} from './module';
|
||||
import {LibraryModule} from 'some-library';
|
||||
export class SomeClass {}
|
||||
export class SomeModule {
|
||||
static withProviders1() {
|
||||
return {ngModule: SomeModule};
|
||||
}
|
||||
static withProviders2() {
|
||||
return {ngModule: SomeModule};
|
||||
}
|
||||
static withProviders3() {
|
||||
return {ngModule: SomeClass};
|
||||
}
|
||||
static withProviders4() {
|
||||
return {ngModule: ExternalModule};
|
||||
}
|
||||
static withProviders5() {
|
||||
return {ngModule: ExternalModule};
|
||||
}
|
||||
static withProviders6() {
|
||||
return {ngModule: LibraryModule};
|
||||
}
|
||||
static withProviders7() {
|
||||
return {ngModule: SomeModule, providers: []};
|
||||
};
|
||||
static withProviders8() {
|
||||
return {ngModule: SomeModule};
|
||||
}
|
||||
}
|
||||
export function withProviders1() {
|
||||
return {ngModule: SomeModule};
|
||||
}
|
||||
export function withProviders2() {
|
||||
return {ngModule: SomeModule};
|
||||
}
|
||||
export function withProviders3() {
|
||||
return {ngModule: SomeClass};
|
||||
}
|
||||
export function withProviders4() {
|
||||
return {ngModule: ExternalModule};
|
||||
}
|
||||
export function withProviders5() {
|
||||
return {ngModule: ExternalModule};
|
||||
}
|
||||
export function withProviders6() {
|
||||
return {ngModule: LibraryModule};
|
||||
}
|
||||
export function withProviders7() {
|
||||
return {ngModule: SomeModule, providers: []};
|
||||
};
|
||||
export function withProviders8() {
|
||||
return {ngModule: SomeModule};
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: '/src/module.js',
|
||||
contents: `
|
||||
export class ExternalModule {
|
||||
static withProviders1() {
|
||||
return {ngModule: ExternalModule};
|
||||
}
|
||||
static withProviders2() {
|
||||
return {ngModule: ExternalModule};
|
||||
}
|
||||
}`
|
||||
},
|
||||
{
|
||||
name: '/node_modules/some-library/index.d.ts',
|
||||
contents: 'export declare class LibraryModule {}'
|
||||
},
|
||||
];
|
||||
const MODULE_WITH_PROVIDERS_DTS_PROGRAM = [
|
||||
{
|
||||
name: '/typings/index.d.ts',
|
||||
contents: `
|
||||
import {ModuleWithProviders} from '@angular/core';
|
||||
export declare class SomeClass {}
|
||||
export interface MyModuleWithProviders extends ModuleWithProviders {}
|
||||
export declare class SomeModule {
|
||||
static withProviders1(): ModuleWithProviders;
|
||||
static withProviders2(): ModuleWithProviders<any>;
|
||||
static withProviders3(): ModuleWithProviders<SomeClass>;
|
||||
static withProviders4(): ModuleWithProviders;
|
||||
static withProviders5();
|
||||
static withProviders6(): ModuleWithProviders;
|
||||
static withProviders7(): {ngModule: SomeModule, providers: any[]};
|
||||
static withProviders8(): MyModuleWithProviders;
|
||||
}
|
||||
export declare function withProviders1(): ModuleWithProviders;
|
||||
export declare function withProviders2(): ModuleWithProviders<any>;
|
||||
export declare function withProviders3(): ModuleWithProviders<SomeClass>;
|
||||
export declare function withProviders4(): ModuleWithProviders;
|
||||
export declare function withProviders5();
|
||||
export declare function withProviders6(): ModuleWithProviders;
|
||||
export declare function withProviders7(): {ngModule: SomeModule, providers: any[]};
|
||||
export declare function withProviders8(): MyModuleWithProviders;`
|
||||
},
|
||||
{
|
||||
name: '/typings/module.d.ts',
|
||||
contents: `
|
||||
export interface ModuleWithProviders {}
|
||||
export declare class ExternalModule {
|
||||
static withProviders1(): ModuleWithProviders;
|
||||
static withProviders2(): ModuleWithProviders;
|
||||
}`
|
||||
},
|
||||
{
|
||||
name: '/node_modules/some-library/index.d.ts',
|
||||
contents: 'export declare class LibraryModule {}'
|
||||
},
|
||||
];
|
||||
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses} =
|
||||
createTestRenderer(
|
||||
'test-package', MODULE_WITH_PROVIDERS_PROGRAM, MODULE_WITH_PROVIDERS_DTS_PROGRAM);
|
||||
|
||||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
||||
moduleWithProvidersAnalyses);
|
||||
|
||||
const typingsFile = result.find(f => f.path === '/typings/index.d.ts') !;
|
||||
|
||||
expect(typingsFile.contents).toContain(`
|
||||
static withProviders1(): ModuleWithProviders<SomeModule>;
|
||||
static withProviders2(): ModuleWithProviders<SomeModule>;
|
||||
static withProviders3(): ModuleWithProviders<SomeClass>;
|
||||
static withProviders4(): ModuleWithProviders<ɵngcc0.ExternalModule>;
|
||||
static withProviders5(): ɵngcc1.ModuleWithProviders<ɵngcc0.ExternalModule>;
|
||||
static withProviders6(): ModuleWithProviders<ɵngcc2.LibraryModule>;
|
||||
static withProviders7(): ({ngModule: SomeModule, providers: any[]})&{ngModule:SomeModule};
|
||||
static withProviders8(): (MyModuleWithProviders)&{ngModule:SomeModule};`);
|
||||
expect(typingsFile.contents).toContain(`
|
||||
export declare function withProviders1(): ModuleWithProviders<SomeModule>;
|
||||
export declare function withProviders2(): ModuleWithProviders<SomeModule>;
|
||||
export declare function withProviders3(): ModuleWithProviders<SomeClass>;
|
||||
export declare function withProviders4(): ModuleWithProviders<ɵngcc0.ExternalModule>;
|
||||
export declare function withProviders5(): ɵngcc1.ModuleWithProviders<ɵngcc0.ExternalModule>;
|
||||
export declare function withProviders6(): ModuleWithProviders<ɵngcc2.LibraryModule>;
|
||||
export declare function withProviders7(): ({ngModule: SomeModule, providers: any[]})&{ngModule:SomeModule};
|
||||
export declare function withProviders8(): (MyModuleWithProviders)&{ngModule:SomeModule};`);
|
||||
|
||||
expect(renderer.addImports).toHaveBeenCalledWith(jasmine.any(MagicString), [
|
||||
{name: './module', as: 'ɵngcc0'},
|
||||
{name: '@angular/core', as: 'ɵngcc1'},
|
||||
{name: 'some-library', as: 'ɵngcc2'},
|
||||
]);
|
||||
|
||||
|
||||
// The following expectation checks that we do not mistake `ModuleWithProviders` types
|
||||
// that are not imported from `@angular/core`.
|
||||
const typingsFile2 = result.find(f => f.path === '/typings/module.d.ts') !;
|
||||
expect(typingsFile2.contents).toContain(`
|
||||
static withProviders1(): (ModuleWithProviders)&{ngModule:ExternalModule};
|
||||
static withProviders2(): (ModuleWithProviders)&{ngModule:ExternalModule};`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -434,7 +434,7 @@ function extractHostBindings(
|
||||
});
|
||||
}
|
||||
|
||||
const {attributes, listeners, properties} = parseHostBindings(hostMetadata);
|
||||
const {attributes, listeners, properties, animations} = parseHostBindings(hostMetadata);
|
||||
|
||||
filterToMembersWithDecorator(members, 'HostBinding', coreModule)
|
||||
.forEach(({member, decorators}) => {
|
||||
|
@ -109,7 +109,7 @@ export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalys
|
||||
const valueContext = node.getSourceFile();
|
||||
|
||||
let typeContext = valueContext;
|
||||
const typeNode = this.reflector.getDtsDeclaration(node);
|
||||
const typeNode = this.reflector.getDtsDeclarationOfClass(node);
|
||||
if (typeNode !== null) {
|
||||
typeContext = typeNode.getSourceFile();
|
||||
}
|
||||
@ -183,8 +183,8 @@ export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalys
|
||||
return toR3Reference(valueRef, valueRef, valueContext, valueContext);
|
||||
} else {
|
||||
let typeRef = valueRef;
|
||||
let typeNode = this.reflector.getDtsDeclaration(typeRef.node);
|
||||
if (typeNode !== null && ts.isClassDeclaration(typeNode)) {
|
||||
let typeNode = this.reflector.getDtsDeclarationOfClass(typeRef.node);
|
||||
if (typeNode !== null) {
|
||||
typeRef = new ResolvedReference(typeNode, typeNode.name !);
|
||||
}
|
||||
return toR3Reference(valueRef, typeRef, valueContext, typeContext);
|
||||
@ -197,20 +197,9 @@ export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalys
|
||||
*/
|
||||
private _extractModuleFromModuleWithProvidersFn(node: ts.FunctionDeclaration|
|
||||
ts.MethodDeclaration): ts.Expression|null {
|
||||
const type = node.type || null;
|
||||
return type &&
|
||||
(this._reflectModuleFromTypeParam(type) || this._reflectModuleFromLiteralType(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an `NgModule` identifier (T) from the specified `type`, if it is of the form:
|
||||
* `ModuleWithProviders<T>`
|
||||
* @param type The type to reflect on.
|
||||
* @returns the identifier of the NgModule type if found, or null otherwise.
|
||||
*/
|
||||
private _reflectModuleFromTypeParam(type: ts.TypeNode): ts.Expression|null {
|
||||
const type = node.type;
|
||||
// Examine the type of the function to see if it's a ModuleWithProviders reference.
|
||||
if (!ts.isTypeReferenceNode(type) || !ts.isIdentifier(type.typeName)) {
|
||||
if (type === undefined || !ts.isTypeReferenceNode(type) || !ts.isIdentifier(type.typeName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -237,32 +226,6 @@ export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalys
|
||||
return typeNodeToValueExpr(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an `NgModule` identifier (T) from the specified `type`, if it is of the form:
|
||||
* `A|B|{ngModule: T}|C`.
|
||||
* @param type The type to reflect on.
|
||||
* @returns the identifier of the NgModule type if found, or null otherwise.
|
||||
*/
|
||||
private _reflectModuleFromLiteralType(type: ts.TypeNode): ts.Expression|null {
|
||||
if (!ts.isIntersectionTypeNode(type)) {
|
||||
return null;
|
||||
}
|
||||
for (const t of type.types) {
|
||||
if (ts.isTypeLiteralNode(t)) {
|
||||
for (const m of t.members) {
|
||||
const ngModuleType = ts.isPropertySignature(m) && ts.isIdentifier(m.name) &&
|
||||
m.name.text === 'ngModule' && m.type ||
|
||||
null;
|
||||
const ngModuleExpression = ngModuleType && typeNodeToValueExpr(ngModuleType);
|
||||
if (ngModuleExpression) {
|
||||
return ngModuleExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a list of `Reference`s from a resolved metadata value.
|
||||
*/
|
||||
|
@ -448,7 +448,7 @@ export interface ReflectionHost {
|
||||
getVariableValue(declaration: ts.VariableDeclaration): ts.Expression|null;
|
||||
|
||||
/**
|
||||
* Take an exported declaration (maybe a class down-leveled to a variable) and look up the
|
||||
* Take an exported declaration of a class (maybe downleveled to a variable) and look up the
|
||||
* declaration of its type in a separate .d.ts tree.
|
||||
*
|
||||
* This function is allowed to return `null` if the current compilation unit does not have a
|
||||
@ -456,8 +456,8 @@ export interface ReflectionHost {
|
||||
* are produced only during the emit of such a compilation. When compiling .js code, however,
|
||||
* there is frequently a parallel .d.ts tree which this method exposes.
|
||||
*
|
||||
* Note that the `ts.Declaration` returned from this function may not be from the same
|
||||
* Note that the `ts.ClassDeclaration` returned from this function may not be from the same
|
||||
* `ts.Program` as the input declaration.
|
||||
*/
|
||||
getDtsDeclaration(declaration: ts.Declaration): ts.Declaration|null;
|
||||
getDtsDeclarationOfClass(declaration: ts.Declaration): ts.ClassDeclaration|null;
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||
return declaration.initializer || null;
|
||||
}
|
||||
|
||||
getDtsDeclaration(_: ts.Declaration): ts.Declaration|null { return null; }
|
||||
getDtsDeclarationOfClass(_: ts.Declaration): ts.ClassDeclaration|null { return null; }
|
||||
|
||||
/**
|
||||
* Resolve a `ts.Symbol` to its declaration, keeping track of the `viaModule` along the way.
|
||||
|
@ -208,21 +208,14 @@ export class NgtscProgram implements api.Program {
|
||||
this.host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles);
|
||||
};
|
||||
|
||||
const customTransforms = opts && opts.customTransformers;
|
||||
const beforeTransforms =
|
||||
const transforms =
|
||||
[ivyTransformFactory(this.compilation !, this.reflector, this.coreImportsFrom)];
|
||||
|
||||
if (this.factoryToSourceInfo !== null) {
|
||||
beforeTransforms.push(
|
||||
generatedFactoryTransform(this.factoryToSourceInfo, this.coreImportsFrom));
|
||||
transforms.push(generatedFactoryTransform(this.factoryToSourceInfo, this.coreImportsFrom));
|
||||
}
|
||||
if (this.isCore) {
|
||||
beforeTransforms.push(ivySwitchTransform);
|
||||
transforms.push(ivySwitchTransform);
|
||||
}
|
||||
if (customTransforms && customTransforms.beforeTs) {
|
||||
beforeTransforms.push(...customTransforms.beforeTs);
|
||||
}
|
||||
|
||||
// Run the emit, including a custom transformer that will downlevel the Ivy decorators in code.
|
||||
const emitResult = emitCallback({
|
||||
program: this.tsProgram,
|
||||
@ -230,8 +223,7 @@ export class NgtscProgram implements api.Program {
|
||||
options: this.options,
|
||||
emitOnlyDtsFiles: false, writeFile,
|
||||
customTransformers: {
|
||||
before: beforeTransforms,
|
||||
after: customTransforms && customTransforms.afterTs,
|
||||
before: transforms,
|
||||
},
|
||||
});
|
||||
return emitResult;
|
||||
|
@ -19,7 +19,6 @@ import {DTS, GENERATED_FILES, isInRootDir, relativeToRootDirs} from './util';
|
||||
|
||||
const NODE_MODULES_PACKAGE_NAME = /node_modules\/((\w|-|\.)+|(@(\w|-|\.)+\/(\w|-|\.)+))/;
|
||||
const EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
|
||||
const CSS_PREPROCESSOR_EXT = /(\.scss|\.less|\.styl)$/;
|
||||
|
||||
export function createCompilerHost(
|
||||
{options, tsHost = ts.createCompilerHost(options, true)}:
|
||||
@ -247,7 +246,7 @@ export class TsCompilerAotCompilerTypeCheckHostAdapter implements ts.CompilerHos
|
||||
if (packageTypings === originalImportedFile) {
|
||||
moduleName = importedFilePackageName;
|
||||
}
|
||||
} catch {
|
||||
} catch (e) {
|
||||
// the above require() will throw if there is no package.json file
|
||||
// and this is safe to ignore and correct to keep the longer
|
||||
// moduleName in this case
|
||||
@ -271,15 +270,8 @@ export class TsCompilerAotCompilerTypeCheckHostAdapter implements ts.CompilerHos
|
||||
} else if (firstChar !== '.') {
|
||||
resourceName = `./${resourceName}`;
|
||||
}
|
||||
let filePathWithNgResource =
|
||||
const filePathWithNgResource =
|
||||
this.moduleNameToFileName(addNgResourceSuffix(resourceName), containingFile);
|
||||
// If the user specified styleUrl pointing to *.scss, but the Sass compiler was run before
|
||||
// Angular, then the resource may have been generated as *.css. Simply try the resolution again.
|
||||
if (!filePathWithNgResource && CSS_PREPROCESSOR_EXT.test(resourceName)) {
|
||||
const fallbackResourceName = resourceName.replace(CSS_PREPROCESSOR_EXT, '.css');
|
||||
filePathWithNgResource =
|
||||
this.moduleNameToFileName(addNgResourceSuffix(fallbackResourceName), containingFile);
|
||||
}
|
||||
const result = filePathWithNgResource ? stripNgResourceSuffix(filePathWithNgResource) : null;
|
||||
// Used under Bazel to report more specific error with remediation advice
|
||||
if (!result && (this.context as any).reportMissingResource) {
|
||||
@ -590,7 +582,7 @@ export class TsCompilerAotCompilerTypeCheckHostAdapter implements ts.CompilerHos
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
} catch (e) {
|
||||
// If we encounter any errors assume we this isn't a bundle index.
|
||||
result = false;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AttributeMarker} from '@angular/compiler/src/core';
|
||||
import {AttributeMarker, InitialStylingFlags} from '@angular/compiler/src/core';
|
||||
import {setup} from '@angular/compiler/test/aot/test_util';
|
||||
import {compile, expectEmit} from './mock_compile';
|
||||
|
||||
@ -48,15 +48,17 @@ describe('compiler compliance', () => {
|
||||
|
||||
// The template should look like this (where IDENT is a wild card for an identifier):
|
||||
const template = `
|
||||
const $c1$ = ["title", "Hello", ${AttributeMarker.Classes}, "my-app"];
|
||||
const $c2$ = ["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, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $c1$);
|
||||
$r3$.ɵelementStyling($c2$);
|
||||
$r3$.ɵnamespaceSVG();
|
||||
$r3$.ɵelementStart(1, "svg");
|
||||
$r3$.ɵelement(2, "circle", $c2$);
|
||||
$r3$.ɵelement(2, "circle", $c3$);
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵnamespaceHTML();
|
||||
$r3$.ɵelementStart(3, "p");
|
||||
@ -98,11 +100,13 @@ describe('compiler compliance', () => {
|
||||
|
||||
// The template should look like this (where IDENT is a wild card for an identifier):
|
||||
const template = `
|
||||
const $c1$ = ["title", "Hello", ${AttributeMarker.Classes}, "my-app"];
|
||||
const $c1$ = ["title", "Hello"];
|
||||
const $c2$ = ["my-app", ${InitialStylingFlags.VALUES_MODE}, "my-app", true];
|
||||
…
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $c1$);
|
||||
$r3$.ɵelementStyling($c2$);
|
||||
$r3$.ɵnamespaceMathML();
|
||||
$r3$.ɵelementStart(1, "math");
|
||||
$r3$.ɵelement(2, "infinity");
|
||||
@ -146,11 +150,13 @@ describe('compiler compliance', () => {
|
||||
|
||||
// The template should look like this (where IDENT is a wild card for an identifier):
|
||||
const template = `
|
||||
const $c1$ = ["title", "Hello", ${AttributeMarker.Classes}, "my-app"];
|
||||
const $c1$ = ["title", "Hello"];
|
||||
const $c2$ = ["my-app", ${InitialStylingFlags.VALUES_MODE}, "my-app", true];
|
||||
…
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $c1$);
|
||||
$r3$.ɵelementStyling($c2$);
|
||||
$r3$.ɵtext(1, "Hello ");
|
||||
$r3$.ɵelementStart(2, "b");
|
||||
$r3$.ɵtext(3, "World");
|
||||
@ -434,14 +440,14 @@ describe('compiler compliance', () => {
|
||||
$r3$.ɵallocHostVars(14);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵcomponentHostSyntheticProperty(elIndex, "@expansionHeight",
|
||||
$r3$.ɵelementProperty(elIndex, "expansionHeight",
|
||||
$r3$.ɵbind(
|
||||
$r3$.ɵpureFunction2(5, $_c1$, ctx.getExpandedState(),
|
||||
$r3$.ɵpureFunction2(2, $_c0$, ctx.collapsedHeight, ctx.expandedHeight)
|
||||
)
|
||||
), null, true
|
||||
);
|
||||
$r3$.ɵcomponentHostSyntheticProperty(elIndex, "@expansionWidth",
|
||||
$r3$.ɵelementProperty(elIndex, "expansionWidth",
|
||||
$r3$.ɵbind(
|
||||
$r3$.ɵpureFunction2(11, $_c1$, ctx.getExpandedState(),
|
||||
$r3$.ɵpureFunction2(8, $_c2$, ctx.collapsedWidth, ctx.expandedWidth)
|
||||
@ -480,8 +486,8 @@ describe('compiler compliance', () => {
|
||||
const factory =
|
||||
'factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }';
|
||||
const template = `
|
||||
const $e0_classBindings$ = ["error"];
|
||||
const $e0_styleBindings$ = ["background-color"];
|
||||
const _c0 = ["error"];
|
||||
const _c1 = ["background-color"];
|
||||
…
|
||||
MyComponent.ngComponentDef = i0.ɵdefineComponent({type:MyComponent,selectors:[["my-component"]],
|
||||
factory: function MyComponent_Factory(t){
|
||||
@ -492,7 +498,7 @@ describe('compiler compliance', () => {
|
||||
template: function MyComponent_Template(rf,ctx){
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵelementStyling($e0_classBindings$, $e0_styleBindings$);
|
||||
$r3$.ɵelementStyling(_c0, _c1);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -767,7 +773,7 @@ describe('compiler compliance', () => {
|
||||
const MyComponentDefinition = `
|
||||
const $c1$ = ["foo", ""];
|
||||
const $c2$ = ["if", ""];
|
||||
function MyComponent_li_2_Template(rf, ctx) {
|
||||
function MyComponent_li_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "li");
|
||||
$r3$.ɵtext(1);
|
||||
@ -789,7 +795,7 @@ describe('compiler compliance', () => {
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "ul", null, $c1$);
|
||||
$r3$.ɵtemplate(2, MyComponent_li_2_Template, 2, 2, "li", $c2$);
|
||||
$r3$.ɵtemplate(2, MyComponent_li_Template_2, 2, 2, "li", $c2$);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
},
|
||||
@ -1086,224 +1092,156 @@ describe('compiler compliance', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('content projection', () => {
|
||||
it('should support content projection in root template', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, Directive, NgModule, TemplateRef} from '@angular/core';
|
||||
|
||||
it('should support content projection in root template', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, Directive, NgModule, TemplateRef} from '@angular/core';
|
||||
@Component({selector: 'simple', template: '<div><ng-content></ng-content></div>'})
|
||||
export class SimpleComponent {}
|
||||
|
||||
@Component({selector: 'simple', template: '<div><ng-content></ng-content></div>'})
|
||||
export class SimpleComponent {}
|
||||
|
||||
@Component({
|
||||
selector: 'complex',
|
||||
template: \`
|
||||
<div id="first"><ng-content select="span[title=toFirst]"></ng-content></div>
|
||||
<div id="second"><ng-content SELECT="span[title=toSecond]"></ng-content></div>\`
|
||||
})
|
||||
export class ComplexComponent { }
|
||||
|
||||
@NgModule({declarations: [SimpleComponent, ComplexComponent]})
|
||||
export class MyModule {}
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: '<simple>content</simple> <complex></complex>'
|
||||
@Component({
|
||||
selector: 'complex',
|
||||
template: \`
|
||||
<div id="first"><ng-content select="span[title=toFirst]"></ng-content></div>
|
||||
<div id="second"><ng-content SELECT="span[title=toSecond]"></ng-content></div>\`
|
||||
})
|
||||
export class MyApp {}
|
||||
`
|
||||
}
|
||||
};
|
||||
export class ComplexComponent { }
|
||||
|
||||
const SimpleComponentDefinition = `
|
||||
SimpleComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: SimpleComponent,
|
||||
selectors: [["simple"]],
|
||||
factory: function SimpleComponent_Factory(t) { return new (t || SimpleComponent)(); },
|
||||
consts: 2,
|
||||
vars: 0,
|
||||
template: function SimpleComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵprojectionDef();
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵprojection(1);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
},
|
||||
encapsulation: 2
|
||||
});`;
|
||||
@NgModule({declarations: [SimpleComponent, ComplexComponent]})
|
||||
export class MyModule {}
|
||||
|
||||
const ComplexComponentDefinition = `
|
||||
const $c3$ = ["id","first"];
|
||||
const $c4$ = ["id","second"];
|
||||
const $c1$ = [[["span", "title", "tofirst"]], [["span", "title", "tosecond"]]];
|
||||
const $c2$ = ["span[title=toFirst]", "span[title=toSecond]"];
|
||||
…
|
||||
ComplexComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ComplexComponent,
|
||||
selectors: [["complex"]],
|
||||
factory: function ComplexComponent_Factory(t) { return new (t || ComplexComponent)(); },
|
||||
consts: 4,
|
||||
vars: 0,
|
||||
template: function ComplexComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵprojectionDef($c1$, $c2$);
|
||||
$r3$.ɵelementStart(0, "div", $c3$);
|
||||
$r3$.ɵprojection(1, 1);
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵelementStart(2, "div", $c4$);
|
||||
$r3$.ɵprojection(3, 2);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
},
|
||||
encapsulation: 2
|
||||
});
|
||||
`;
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: '<simple>content</simple> <complex></complex>'
|
||||
})
|
||||
export class MyApp {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
const source = result.source;
|
||||
const SimpleComponentDefinition = `
|
||||
SimpleComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: SimpleComponent,
|
||||
selectors: [["simple"]],
|
||||
factory: function SimpleComponent_Factory(t) { return new (t || SimpleComponent)(); },
|
||||
consts: 2,
|
||||
vars: 0,
|
||||
template: function SimpleComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵprojectionDef();
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵprojection(1);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
},
|
||||
encapsulation: 2
|
||||
});`;
|
||||
|
||||
expectEmit(
|
||||
result.source, SimpleComponentDefinition, 'Incorrect SimpleComponent definition');
|
||||
expectEmit(
|
||||
result.source, ComplexComponentDefinition, 'Incorrect ComplexComponent definition');
|
||||
});
|
||||
|
||||
it('should support content projection in nested templates', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
template: \`
|
||||
<div id="second" *ngIf="visible">
|
||||
<ng-content SELECT="span[title=toFirst]"></ng-content>
|
||||
</div>
|
||||
<div id="third" *ngIf="visible">
|
||||
No ng-content, no instructions generated.
|
||||
</div>
|
||||
<ng-template>
|
||||
'*' selector: <ng-content></ng-content>
|
||||
</ng-template>
|
||||
\`,
|
||||
})
|
||||
class Cmp {}
|
||||
|
||||
@NgModule({ declarations: [Cmp] })
|
||||
class Module {}
|
||||
`
|
||||
}
|
||||
};
|
||||
const output = `
|
||||
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
const $_c1$ = ["id", "second"];
|
||||
function Cmp_div_0_Template(rf, ctx) { if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $_c1$);
|
||||
const ComplexComponentDefinition = `
|
||||
const $c3$ = ["id","first"];
|
||||
const $c4$ = ["id","second"];
|
||||
const $c1$ = [[["span", "title", "tofirst"]], [["span", "title", "tosecond"]]];
|
||||
const $c2$ = ["span[title=toFirst]", "span[title=toSecond]"];
|
||||
…
|
||||
ComplexComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ComplexComponent,
|
||||
selectors: [["complex"]],
|
||||
factory: function ComplexComponent_Factory(t) { return new (t || ComplexComponent)(); },
|
||||
consts: 4,
|
||||
vars: 0,
|
||||
template: function ComplexComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵprojectionDef($c1$, $c2$);
|
||||
$r3$.ɵelementStart(0, "div", $c3$);
|
||||
$r3$.ɵprojection(1, 1);
|
||||
$r3$.ɵelementEnd();
|
||||
} }
|
||||
const $_c4$ = ["id", "third"];
|
||||
function Cmp_div_1_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $_c4$);
|
||||
$r3$.ɵtext(1, " No ng-content, no instructions generated. ");
|
||||
$r3$.ɵelementStart(2, "div", $c4$);
|
||||
$r3$.ɵprojection(3, 2);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
}
|
||||
function Cmp_ng_template_2_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtext(0, " '*' selector: ");
|
||||
$r3$.ɵprojection(1);
|
||||
}
|
||||
}
|
||||
const $_c2$ = [[["span", "title", "tofirst"]]];
|
||||
const $_c3$ = ["span[title=toFirst]"];
|
||||
…
|
||||
template: function Cmp_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵprojectionDef($_c2$, $_c3$);
|
||||
$r3$.ɵtemplate(0, Cmp_div_0_Template, 2, 0, "div", $_c0$);
|
||||
$r3$.ɵtemplate(1, Cmp_div_1_Template, 2, 0, "div", $_c0$);
|
||||
$r3$.ɵtemplate(2, Cmp_ng_template_2_Template, 2, 0, "ng-template");
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(0, "ngIf", $r3$.ɵbind(ctx.visible));
|
||||
$r3$.ɵelementProperty(1, "ngIf", $r3$.ɵbind(ctx.visible));
|
||||
}
|
||||
}
|
||||
`;
|
||||
},
|
||||
encapsulation: 2
|
||||
});
|
||||
`;
|
||||
|
||||
const {source} = compile(files, angularFiles);
|
||||
expectEmit(source, output, 'Invalid content projection instructions generated');
|
||||
});
|
||||
const result = compile(files, angularFiles);
|
||||
const source = result.source;
|
||||
|
||||
it('should support content projection in both the root and nested templates', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
expectEmit(result.source, SimpleComponentDefinition, 'Incorrect SimpleComponent definition');
|
||||
expectEmit(
|
||||
result.source, ComplexComponentDefinition, 'Incorrect ComplexComponent definition');
|
||||
});
|
||||
|
||||
@Component({
|
||||
template: \`
|
||||
<ng-content select="[id=toMainBefore]"></ng-content>
|
||||
<ng-template>
|
||||
<ng-content select="[id=toTemplate]"></ng-content>
|
||||
<ng-template>
|
||||
<ng-content select="[id=toNestedTemplate]"></ng-content>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
<ng-template>
|
||||
'*' selector in a template: <ng-content></ng-content>
|
||||
</ng-template>
|
||||
<ng-content select="[id=toMainAfter]"></ng-content>
|
||||
\`,
|
||||
})
|
||||
class Cmp {}
|
||||
it('should support content projection in nested templates', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@NgModule({ declarations: [Cmp] })
|
||||
class Module {}
|
||||
`
|
||||
}
|
||||
};
|
||||
@Component({
|
||||
template: \`
|
||||
<div id="second" *ngIf="visible">
|
||||
<ng-content SELECT="span[title=toFirst]"></ng-content>
|
||||
</div>
|
||||
<div id="third" *ngIf="visible">
|
||||
No ng-content, no instructions generated.
|
||||
</div>
|
||||
<ng-template>
|
||||
'*' selector: <ng-content></ng-content>
|
||||
</ng-template>
|
||||
\`,
|
||||
})
|
||||
class Cmp {}
|
||||
|
||||
const output = `
|
||||
function Cmp_ng_template_1_ng_template_1_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵprojection(0, 4);
|
||||
}
|
||||
@NgModule({ declarations: [Cmp] })
|
||||
class Module {}
|
||||
`
|
||||
}
|
||||
};
|
||||
const output = `
|
||||
const $_c0$ = [1, "ngIf"];
|
||||
const $_c1$ = ["id", "second"];
|
||||
const $_c2$ = [[["span", "title", "tofirst"]]];
|
||||
const $_c3$ = ["span[title=toFirst]"];
|
||||
function Cmp_div_Template_0(rf, ctx) { if (rf & 1) {
|
||||
$r3$.ɵprojectionDef($_c2$, $_c3$);
|
||||
$r3$.ɵelementStart(0, "div", $_c1$);
|
||||
$r3$.ɵprojection(1, 1);
|
||||
$r3$.ɵelementEnd();
|
||||
} }
|
||||
const $_c4$ = ["id", "third"];
|
||||
function Cmp_div_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $_c4$);
|
||||
$r3$.ɵtext(1, " No ng-content, no instructions generated. ");
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
function Cmp_ng_template_1_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵprojection(0, 3);
|
||||
$r3$.ɵtemplate(1, Cmp_ng_template_1_ng_template_1_Template, 1, 0, "ng-template");
|
||||
}
|
||||
}
|
||||
function Cmp_ng_template_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵprojectionDef();
|
||||
$r3$.ɵtext(0, " '*' selector: ");
|
||||
$r3$.ɵprojection(1);
|
||||
}
|
||||
function Cmp_ng_template_2_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtext(0, " '*' selector in a template: ");
|
||||
$r3$.ɵprojection(1);
|
||||
}
|
||||
}
|
||||
…
|
||||
template: function Cmp_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, Cmp_div_Template_0, 2, 0, "div", $_c0$);
|
||||
$r3$.ɵtemplate(1, Cmp_div_Template_1, 2, 0, "div", $_c0$);
|
||||
$r3$.ɵtemplate(2, Cmp_ng_template_Template_2, 2, 0, "ng-template");
|
||||
}
|
||||
const $_c0$ = [[["", "id", "tomainbefore"]], [["", "id", "tomainafter"]], [["", "id", "totemplate"]], [["", "id", "tonestedtemplate"]]];
|
||||
const $_c1$ = ["[id=toMainBefore]", "[id=toMainAfter]", "[id=toTemplate]", "[id=toNestedTemplate]"];
|
||||
…
|
||||
template: function Cmp_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵprojectionDef($_c2$, $_c3$);
|
||||
$r3$.ɵprojection(0, 1);
|
||||
$r3$.ɵtemplate(1, Cmp_ng_template_1_Template, 2, 0, "ng-template");
|
||||
$r3$.ɵtemplate(2, Cmp_ng_template_2_Template, 2, 0, "ng-template");
|
||||
$r3$.ɵprojection(3, 2);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(0, "ngIf", $r3$.ɵbind(ctx.visible));
|
||||
$r3$.ɵelementProperty(1, "ngIf", $r3$.ɵbind(ctx.visible));
|
||||
}
|
||||
`;
|
||||
}
|
||||
`;
|
||||
|
||||
const {source} = compile(files, angularFiles);
|
||||
expectEmit(source, output, 'Invalid content projection instructions generated');
|
||||
});
|
||||
const {source} = compile(files, angularFiles);
|
||||
expectEmit(source, output, 'Invalid content projection instructions generated');
|
||||
});
|
||||
|
||||
describe('queries', () => {
|
||||
@ -1911,7 +1849,7 @@ describe('compiler compliance', () => {
|
||||
const $c2$ = ["if", ""];
|
||||
const $c3$ = ["baz", ""];
|
||||
const $c4$ = ["bar", ""];
|
||||
function MyComponent_div_3_span_2_Template(rf, ctx) {
|
||||
function MyComponent_div_span_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "span");
|
||||
$r3$.ɵtext(1);
|
||||
@ -1926,11 +1864,11 @@ describe('compiler compliance', () => {
|
||||
$r3$.ɵtextBinding(1, $r3$.ɵinterpolation3("", $foo$, "-", $bar$, "-", $baz$, ""));
|
||||
}
|
||||
}
|
||||
function MyComponent_div_3_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_3(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵtext(1);
|
||||
$r3$.ɵtemplate(2, MyComponent_div_3_span_2_Template, 2, 3, "span", $c2$);
|
||||
$r3$.ɵtemplate(2, MyComponent_div_span_Template_2, 2, 3, "span", $c2$);
|
||||
$r3$.ɵelement(3, "span", null, $c4$);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
@ -1952,7 +1890,7 @@ describe('compiler compliance', () => {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, "div", null, $c1$);
|
||||
$r3$.ɵtext(2);
|
||||
$r3$.ɵtemplate(3, MyComponent_div_3_Template, 5, 2, "div", $c2$);
|
||||
$r3$.ɵtemplate(3, MyComponent_div_Template_3, 5, 2, "div", $c2$);
|
||||
$r3$.ɵelement(4, "div", null, $c3$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -2000,7 +1938,7 @@ describe('compiler compliance', () => {
|
||||
const $c1$ = ["foo", ""];
|
||||
const $c2$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
|
||||
function MyComponent_div_0_span_3_Template(rf, ctx) {
|
||||
function MyComponent_div_span_Template_3(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "span");
|
||||
$i0$.ɵtext(1);
|
||||
@ -2013,11 +1951,11 @@ describe('compiler compliance', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function MyComponent_div_0_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "div");
|
||||
$i0$.ɵelement(1, "div", null, $c1$);
|
||||
$i0$.ɵtemplate(3, MyComponent_div_0_span_3_Template, 2, 2, "span", $c2$);
|
||||
$i0$.ɵtemplate(3, MyComponent_div_span_Template_3, 2, 2, "span", $c2$);
|
||||
$i0$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -2029,7 +1967,7 @@ describe('compiler compliance', () => {
|
||||
// ...
|
||||
template:function MyComponent_Template(rf, ctx){
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtemplate(0, MyComponent_div_0_Template, 4, 1, "div", $c0$);
|
||||
$i0$.ɵtemplate(0, MyComponent_div_Template_0, 4, 1, "div", $c0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items));
|
||||
@ -2224,7 +2162,7 @@ describe('compiler compliance', () => {
|
||||
|
||||
const MyComponentDefinition = `
|
||||
const $t1_attrs$ = ["for", "", ${AttributeMarker.SelectOnly}, "forOf"];
|
||||
function MyComponent__svg_g_1_Template(rf, ctx) {
|
||||
function MyComponent__svg_g_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵnamespaceSVG();
|
||||
$r3$.ɵelementStart(0,"g");
|
||||
@ -2243,7 +2181,7 @@ describe('compiler compliance', () => {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵnamespaceSVG();
|
||||
$r3$.ɵelementStart(0,"svg");
|
||||
$r3$.ɵtemplate(1, MyComponent__svg_g_1_Template, 2, 0, ":svg:g", $t1_attrs$);
|
||||
$r3$.ɵtemplate(1, MyComponent__svg_g_Template_1, 2, 0, ":svg:g", $t1_attrs$);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) { $r3$.ɵelementProperty(1,"forOf",$r3$.ɵbind(ctx.items)); }
|
||||
@ -2300,7 +2238,7 @@ describe('compiler compliance', () => {
|
||||
|
||||
const MyComponentDefinition = `
|
||||
const $t1_attrs$ = ["for", "", ${AttributeMarker.SelectOnly}, "forOf"];
|
||||
function MyComponent_li_1_Template(rf, ctx) {
|
||||
function MyComponent_li_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "li");
|
||||
$r3$.ɵtext(1);
|
||||
@ -2321,7 +2259,7 @@ describe('compiler compliance', () => {
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "ul");
|
||||
$r3$.ɵtemplate(1, MyComponent_li_1_Template, 2, 1, "li", $t1_attrs$);
|
||||
$r3$.ɵtemplate(1, MyComponent_li_Template_1, 2, 1, "li", $t1_attrs$);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -2380,7 +2318,7 @@ describe('compiler compliance', () => {
|
||||
|
||||
const MyComponentDefinition = `
|
||||
const $t4_attrs$ = ["for", "", ${AttributeMarker.SelectOnly}, "forOf"];
|
||||
function MyComponent_li_1_li_4_Template(rf, ctx) {
|
||||
function MyComponent_li_li_Template_4(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "li");
|
||||
$r3$.ɵtext(1);
|
||||
@ -2393,14 +2331,14 @@ describe('compiler compliance', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function MyComponent_li_1_Template(rf, ctx) {
|
||||
function MyComponent_li_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "li");
|
||||
$r3$.ɵelementStart(1, "div");
|
||||
$r3$.ɵtext(2);
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵelementStart(3, "ul");
|
||||
$r3$.ɵtemplate(4, MyComponent_li_1_li_4_Template, 2, 2, "li", $t4_attrs$);
|
||||
$r3$.ɵtemplate(4, MyComponent_li_li_Template_4, 2, 2, "li", $t4_attrs$);
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
@ -2421,7 +2359,7 @@ describe('compiler compliance', () => {
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "ul");
|
||||
$r3$.ɵtemplate(1, MyComponent_li_1_Template, 5, 2, "li", $c1$);
|
||||
$r3$.ɵtemplate(1, MyComponent_li_Template_1, 5, 2, "li", $c1$);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
|
@ -24,13 +24,13 @@ describe('compiler compliance: directives', () => {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, Directive, NgModule} from '@angular/core';
|
||||
|
||||
|
||||
@Directive({selector: '[i18n]'})
|
||||
export class I18nDirective {}
|
||||
|
||||
|
||||
@Component({selector: 'my-component', template: '<div i18n></div>'})
|
||||
export class MyComponent {}
|
||||
|
||||
|
||||
@NgModule({declarations: [I18nDirective, MyComponent]})
|
||||
export class MyModule{}`
|
||||
}
|
||||
@ -39,11 +39,11 @@ describe('compiler compliance: directives', () => {
|
||||
// MyComponent definition should be:
|
||||
const MyComponentDefinition = `
|
||||
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
consts: 1,
|
||||
vars: 0,
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
consts: 1,
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, "div");
|
||||
@ -64,7 +64,7 @@ describe('compiler compliance: directives', () => {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, Directive, NgModule} from '@angular/core';
|
||||
|
||||
|
||||
@Directive({selector: '[i18n]'})
|
||||
export class I18nDirective {}
|
||||
|
||||
@ -73,10 +73,10 @@ describe('compiler compliance: directives', () => {
|
||||
|
||||
@Directive({selector: '[foo]'})
|
||||
export class FooDirective {}
|
||||
|
||||
|
||||
@Component({selector: 'my-component', template: '<div i18n-foo></div>'})
|
||||
export class MyComponent {}
|
||||
|
||||
|
||||
@NgModule({declarations: [I18nDirective, I18nFooDirective, FooDirective, MyComponent]})
|
||||
export class MyModule{}`
|
||||
}
|
||||
@ -85,11 +85,11 @@ describe('compiler compliance: directives', () => {
|
||||
// MyComponent definition should be:
|
||||
const MyComponentDefinition = `
|
||||
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
consts: 1,
|
||||
vars: 0,
|
||||
type: MyComponent,
|
||||
selectors: [["my-component"]],
|
||||
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
|
||||
consts: 1,
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, "div");
|
||||
@ -111,15 +111,15 @@ describe('compiler compliance: directives', () => {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, Directive, Input, NgModule} from '@angular/core';
|
||||
|
||||
|
||||
@Directive({selector: '[someDirective]'})
|
||||
export class SomeDirective {
|
||||
@Input() someDirective;
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'my-component', template: '<div [someDirective]="true"></div>'})
|
||||
export class MyComponent {}
|
||||
|
||||
|
||||
@NgModule({declarations: [SomeDirective, MyComponent]})
|
||||
export class MyModule{}
|
||||
`
|
||||
@ -129,7 +129,7 @@ describe('compiler compliance: directives', () => {
|
||||
|
||||
// MyComponent definition should be:
|
||||
const MyComponentDefinition = `
|
||||
…
|
||||
…
|
||||
const _c0 = [${AttributeMarker.SelectOnly}, "someDirective"];
|
||||
…
|
||||
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
@ -184,7 +184,7 @@ describe('compiler compliance: directives', () => {
|
||||
const MyComponentDefinition = `
|
||||
…
|
||||
const $_c0$ = ["directiveA", ""];
|
||||
function MyComponent_ng_template_0_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtext(0, "Some content");
|
||||
}
|
||||
@ -194,7 +194,7 @@ describe('compiler compliance: directives', () => {
|
||||
…
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", $_c0$);
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 0, "ng-template", $_c0$);
|
||||
}
|
||||
},
|
||||
…
|
||||
@ -236,9 +236,9 @@ describe('compiler compliance: directives', () => {
|
||||
|
||||
const MyComponentDefinition = `
|
||||
…
|
||||
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
const $_c0$ = [1, "ngIf"];
|
||||
const $_c1$ = ["directiveA", ""];
|
||||
function MyComponent_ng_container_0_Template(rf, ctx) {
|
||||
function MyComponent_ng_container_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementContainerStart(0, $_c1$);
|
||||
$r3$.ɵtext(1, "Some content");
|
||||
@ -250,7 +250,7 @@ describe('compiler compliance: directives', () => {
|
||||
…
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_container_0_Template, 2, 0, "ng-container", $_c0$);
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_container_Template_0, 2, 0, "ng-container", $_c0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(0, "ngIf", $r3$.ɵbind(ctx.showing));
|
||||
@ -272,15 +272,15 @@ describe('compiler compliance: directives', () => {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, Directive, Input, NgModule} from '@angular/core';
|
||||
|
||||
|
||||
@Directive({selector: '[someDirective]'})
|
||||
export class SomeDirective {
|
||||
@Input() someDirective;
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'my-component', template: '<ng-template [someDirective]="true"></ng-template>'})
|
||||
export class MyComponent {}
|
||||
|
||||
|
||||
@NgModule({declarations: [SomeDirective, MyComponent]})
|
||||
export class MyModule{}
|
||||
`
|
||||
@ -290,14 +290,14 @@ describe('compiler compliance: directives', () => {
|
||||
|
||||
// MyComponent definition should be:
|
||||
const MyComponentDefinition = `
|
||||
…
|
||||
…
|
||||
const $c0_a0$ = [${AttributeMarker.SelectOnly}, "someDirective"];
|
||||
…
|
||||
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
…
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 0, 0, "ng-template", $c0_a0$);
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 0, 0, "ng-template", $c0_a0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(0, "someDirective", $r3$.ɵbind(true));
|
||||
@ -321,15 +321,15 @@ describe('compiler compliance: directives', () => {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, Directive, Input, NgModule} from '@angular/core';
|
||||
|
||||
|
||||
@Directive({selector: '[someDirective]'})
|
||||
export class SomeDirective {
|
||||
@Input() someDirective;
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'my-component', template: '<div *someDirective></div>'})
|
||||
export class MyComponent {}
|
||||
|
||||
|
||||
@NgModule({declarations: [SomeDirective, MyComponent]})
|
||||
export class MyModule{}
|
||||
`
|
||||
@ -338,14 +338,14 @@ describe('compiler compliance: directives', () => {
|
||||
|
||||
// MyComponent definition should be:
|
||||
const MyComponentDefinition = `
|
||||
…
|
||||
…
|
||||
const $c0_a0$ = ["someDirective", ""];
|
||||
…
|
||||
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
…
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_div_0_Template, 1, 0, "div", $c0_a0$);
|
||||
$r3$.ɵtemplate(0, MyComponent_div_Template_0, 1, 0, "div", $c0_a0$);
|
||||
}
|
||||
},
|
||||
…
|
||||
@ -367,17 +367,17 @@ describe('compiler compliance: directives', () => {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, Directive, Output, EventEmitter, NgModule} from '@angular/core';
|
||||
|
||||
|
||||
@Directive({selector: '[someDirective]'})
|
||||
export class SomeDirective {
|
||||
@Output() someDirective = new EventEmitter();
|
||||
}
|
||||
|
||||
|
||||
@Component({selector: 'my-component', template: '<div (someDirective)="noop()"></div>'})
|
||||
export class MyComponent {
|
||||
noop() {}
|
||||
}
|
||||
|
||||
|
||||
@NgModule({declarations: [SomeDirective, MyComponent]})
|
||||
export class MyModule{}
|
||||
`
|
||||
@ -387,7 +387,7 @@ describe('compiler compliance: directives', () => {
|
||||
|
||||
// MyComponent definition should be:
|
||||
const MyComponentDefinition = `
|
||||
…
|
||||
…
|
||||
const $c0_a0$ = [${AttributeMarker.SelectOnly}, "someDirective"];
|
||||
…
|
||||
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
@ -395,7 +395,7 @@ describe('compiler compliance: directives', () => {
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $c0_a0$);
|
||||
$r3$.ɵlistener("someDirective", function MyComponent_Template_div_someDirective_0_listener($event) { return ctx.noop(); });
|
||||
$r3$.ɵlistener("someDirective", function MyComponent_Template_div_someDirective_listener($event) { return ctx.noop(); });
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
},
|
||||
|
@ -6,7 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AttributeMarker} from '@angular/compiler/src/core';
|
||||
import {setup} from '@angular/compiler/test/aot/test_util';
|
||||
|
||||
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../../compiler/src/compiler';
|
||||
@ -394,7 +393,7 @@ describe('i18n support in the view compiler', () => {
|
||||
`;
|
||||
|
||||
const output = String.raw `
|
||||
const $_c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"];
|
||||
const $_c0$ = ["ngFor", "", 1, "ngForOf"];
|
||||
/**
|
||||
* @desc d
|
||||
* @meaning m
|
||||
@ -403,7 +402,7 @@ describe('i18n support in the view compiler', () => {
|
||||
"interpolation": "\uFFFD0\uFFFD"
|
||||
});
|
||||
const $_c1$ = ["title", $MSG_EXTERNAL_8538466649243975456$$APP_SPEC_TS__1$];
|
||||
function MyComponent_div_0_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵelementStart(1, "div");
|
||||
@ -423,7 +422,7 @@ describe('i18n support in the view compiler', () => {
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_div_0_Template, 4, 3, "div", $_c0$);
|
||||
$r3$.ɵtemplate(0, MyComponent_div_Template_0, 4, 3, "div", $_c0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(0, "ngForOf", $r3$.ɵbind(ctx.items));
|
||||
@ -523,7 +522,7 @@ describe('i18n support in the view compiler', () => {
|
||||
`;
|
||||
|
||||
const output = String.raw `
|
||||
const $_c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"];
|
||||
const $_c0$ = ["ngFor", "", 1, "ngForOf"];
|
||||
/**
|
||||
* @desc d
|
||||
* @meaning m
|
||||
@ -532,7 +531,7 @@ describe('i18n support in the view compiler', () => {
|
||||
"interpolation": "\uFFFD0\uFFFD"
|
||||
});
|
||||
const $_c1$ = ["title", $MSG_EXTERNAL_8538466649243975456$$APP_SPEC_TS__1$];
|
||||
function MyComponent_div_0_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵelementStart(1, "div");
|
||||
@ -552,7 +551,7 @@ describe('i18n support in the view compiler', () => {
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_div_0_Template, 4, 3, "div", $_c0$);
|
||||
$r3$.ɵtemplate(0, MyComponent_div_Template_0, 4, 3, "div", $_c0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(0, "ngForOf", $r3$.ɵbind(ctx.items));
|
||||
@ -923,7 +922,7 @@ describe('i18n support in the view compiler', () => {
|
||||
`;
|
||||
|
||||
const output = String.raw `
|
||||
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
const $_c0$ = [1, "ngIf"];
|
||||
const $MSG_EXTERNAL_7679414751795588050$$APP_SPEC_TS__1$ = goog.getMsg(" Some other content {$interpolation} {$startTagDiv} More nested levels with bindings {$interpolation_1} {$closeTagDiv}", {
|
||||
"interpolation": "\uFFFD0\uFFFD",
|
||||
"startTagDiv": "\uFFFD#3\uFFFD",
|
||||
@ -931,7 +930,7 @@ describe('i18n support in the view compiler', () => {
|
||||
"closeTagDiv": "\uFFFD/#3\uFFFD"
|
||||
});
|
||||
…
|
||||
function MyComponent_div_2_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵelementStart(1, "div");
|
||||
@ -956,7 +955,7 @@ describe('i18n support in the view compiler', () => {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵtext(1, " Some content ");
|
||||
$r3$.ɵtemplate(2, MyComponent_div_2_Template, 5, 4, "div", $_c0$);
|
||||
$r3$.ɵtemplate(2, MyComponent_div_Template_2, 5, 4, "div", $_c0$);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -977,8 +976,8 @@ describe('i18n support in the view compiler', () => {
|
||||
|
||||
const output = String.raw `
|
||||
const $_c0$ = ["src", "logo.png"];
|
||||
const $_c1$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
function MyComponent_img_1_Template(rf, ctx) {
|
||||
const $_c1$ = [1, "ngIf"];
|
||||
function MyComponent_img_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, "img", $_c0$);
|
||||
}
|
||||
@ -987,7 +986,7 @@ describe('i18n support in the view compiler', () => {
|
||||
"interpolation": "\uFFFD0\uFFFD"
|
||||
});
|
||||
const $_c2$ = ["title", $MSG_EXTERNAL_2367729185105559721$];
|
||||
function MyComponent_img_2_Template(rf, ctx) {
|
||||
function MyComponent_img_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "img", $_c0$);
|
||||
$r3$.ɵi18nAttributes(1, $_c2$);
|
||||
@ -1005,8 +1004,8 @@ describe('i18n support in the view compiler', () => {
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, "img", $_c0$);
|
||||
$r3$.ɵtemplate(1, MyComponent_img_1_Template, 1, 0, "img", $_c1$);
|
||||
$r3$.ɵtemplate(2, MyComponent_img_2_Template, 2, 1, "img", $_c1$);
|
||||
$r3$.ɵtemplate(1, MyComponent_img_Template_1, 1, 0, "img", $_c1$);
|
||||
$r3$.ɵtemplate(2, MyComponent_img_Template_2, 2, 1, "img", $_c1$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(1, "ngIf", $r3$.ɵbind(ctx.visible));
|
||||
@ -1044,8 +1043,8 @@ describe('i18n support in the view compiler', () => {
|
||||
`;
|
||||
|
||||
const output = String.raw `
|
||||
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
function MyComponent_div_2_div_4_Template(rf, ctx) {
|
||||
const $_c0$ = [1, "ngIf"];
|
||||
function MyComponent_div_div_Template_4(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18nStart(0, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$, 2);
|
||||
$r3$.ɵelementStart(1, "div");
|
||||
@ -1060,13 +1059,13 @@ describe('i18n support in the view compiler', () => {
|
||||
$r3$.ɵi18nApply(0);
|
||||
}
|
||||
}
|
||||
function MyComponent_div_2_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18nStart(0, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$, 1);
|
||||
$r3$.ɵelementStart(1, "div");
|
||||
$r3$.ɵelementStart(2, "div");
|
||||
$r3$.ɵpipe(3, "uppercase");
|
||||
$r3$.ɵtemplate(4, MyComponent_div_2_div_4_Template, 3, 2, "div", $_c1$);
|
||||
$r3$.ɵtemplate(4, MyComponent_div_div_Template_4, 3, 2, "div", $_c1$);
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵi18nEnd();
|
||||
@ -1093,7 +1092,7 @@ describe('i18n support in the view compiler', () => {
|
||||
"interpolation_5": "\uFFFD1:3\uFFFD"
|
||||
});
|
||||
const $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$);
|
||||
function MyComponent_div_3_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_3(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18nStart(0, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$, 3);
|
||||
$r3$.ɵelementStart(1, "div");
|
||||
@ -1116,8 +1115,8 @@ describe('i18n support in the view compiler', () => {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵi18nStart(1, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵtemplate(2, MyComponent_div_2_Template, 5, 5, "div", $_c1$);
|
||||
$r3$.ɵtemplate(3, MyComponent_div_3_Template, 4, 4, "div", $_c1$);
|
||||
$r3$.ɵtemplate(2, MyComponent_div_Template_2, 5, 5, "div", $_c1$);
|
||||
$r3$.ɵtemplate(3, MyComponent_div_Template_3, 4, 4, "div", $_c1$);
|
||||
$r3$.ɵi18nEnd();
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
@ -1137,14 +1136,14 @@ describe('i18n support in the view compiler', () => {
|
||||
`;
|
||||
|
||||
const output = String.raw `
|
||||
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
const $_c0$ = [1, "ngIf"];
|
||||
const $MSG_EXTERNAL_119975189388320493$$APP_SPEC_TS__1$ = goog.getMsg("Some other content {$startTagSpan}{$interpolation}{$closeTagSpan}", {
|
||||
"startTagSpan": "\uFFFD#2\uFFFD",
|
||||
"interpolation": "\uFFFD0\uFFFD",
|
||||
"closeTagSpan": "\uFFFD/#2\uFFFD"
|
||||
});
|
||||
…
|
||||
function MyComponent_div_0_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵi18nStart(1, $MSG_EXTERNAL_119975189388320493$$APP_SPEC_TS__1$);
|
||||
@ -1163,7 +1162,7 @@ describe('i18n support in the view compiler', () => {
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_div_0_Template, 3, 1, "div", $_c0$);
|
||||
$r3$.ɵtemplate(0, MyComponent_div_Template_0, 3, 1, "div", $_c0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(0, "ngIf", $r3$.ɵbind(ctx.visible));
|
||||
@ -1234,7 +1233,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const output = String.raw `
|
||||
const $MSG_EXTERNAL_2413150872298537152$$APP_SPEC_TS_0$ = goog.getMsg("My i18n block #2");
|
||||
const $MSG_EXTERNAL_4890179241114413722$$APP_SPEC_TS__1$ = goog.getMsg("My i18n block #1");
|
||||
function MyComponent_ng_template_0_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18n(0, $MSG_EXTERNAL_4890179241114413722$$APP_SPEC_TS__1$);
|
||||
}
|
||||
@ -1242,7 +1241,7 @@ describe('i18n support in the view compiler', () => {
|
||||
…
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template");
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 0, "ng-template");
|
||||
$r3$.ɵelementContainerStart(1);
|
||||
$r3$.ɵi18n(2, $MSG_EXTERNAL_2413150872298537152$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵelementContainerEnd();
|
||||
@ -1260,21 +1259,23 @@ describe('i18n support in the view compiler', () => {
|
||||
`;
|
||||
|
||||
const output = String.raw `
|
||||
const $_c0$ = [${AttributeMarker.Classes}, "myClass"];
|
||||
const $_c0$ = ["myClass", 1, "myClass", true];
|
||||
const $MSG_EXTERNAL_5295701706185791735$$APP_SPEC_TS_0$ = goog.getMsg("Text #1");
|
||||
const $_c1$ = [${AttributeMarker.Styles}, "padding", "10px"];
|
||||
const $_c1$ = ["padding", 1, "padding", "10px"];
|
||||
const $MSG_EXTERNAL_4722270221386399294$$APP_SPEC_TS_2$ = goog.getMsg("Text #2");
|
||||
…
|
||||
consts: 4,
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "span", $_c0$);
|
||||
$r3$.ɵelementStart(0, "span");
|
||||
$r3$.ɵi18nStart(1, $MSG_EXTERNAL_5295701706185791735$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵelementStyling($_c0$);
|
||||
$r3$.ɵi18nEnd();
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵelementStart(2, "span", $_c1$);
|
||||
$r3$.ɵelementStart(2, "span");
|
||||
$r3$.ɵi18nStart(3, $MSG_EXTERNAL_4722270221386399294$$APP_SPEC_TS_2$);
|
||||
$r3$.ɵelementStyling(null, $_c1$);
|
||||
$r3$.ɵi18nEnd();
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
@ -1324,7 +1325,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const $MSG_EXTERNAL_355394464191978948$$APP_SPEC_TS__0$ = goog.getMsg("Some content: {$interpolation}", {
|
||||
"interpolation": "\uFFFD0\uFFFD"
|
||||
});
|
||||
function MyComponent_ng_template_0_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18n(0, $MSG_EXTERNAL_355394464191978948$$APP_SPEC_TS__0$);
|
||||
$r3$.ɵpipe(1, "uppercase");
|
||||
@ -1339,7 +1340,7 @@ describe('i18n support in the view compiler', () => {
|
||||
vars: 0,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 2, 3, "ng-template");
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 2, 3, "ng-template");
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1364,7 +1365,7 @@ describe('i18n support in the view compiler', () => {
|
||||
"closeTagNgContainer": "\uFFFD/#3\uFFFD",
|
||||
"interpolation": "\uFFFD0:1\uFFFD"
|
||||
});
|
||||
function MyComponent_ng_template_2_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18n(0, $MSG_EXTERNAL_702706566400598764$$APP_SPEC_TS_0$, 1);
|
||||
$r3$.ɵpipe(1, "uppercase");
|
||||
@ -1382,7 +1383,7 @@ describe('i18n support in the view compiler', () => {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵi18nStart(1, $MSG_EXTERNAL_702706566400598764$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵtemplate(2, MyComponent_ng_template_2_Template, 2, 3, "ng-template");
|
||||
$r3$.ɵtemplate(2, MyComponent_ng_template_Template_2, 2, 3, "ng-template");
|
||||
$r3$.ɵelementContainerStart(3);
|
||||
$r3$.ɵpipe(4, "uppercase");
|
||||
$r3$.ɵelementContainerEnd();
|
||||
@ -1414,7 +1415,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS__1$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7842238767399919809$$APP_SPEC_TS__1$, {
|
||||
"VAR_SELECT": "\uFFFD0\uFFFD"
|
||||
});
|
||||
function MyComponent_ng_template_0_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18n(0, $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS__1$);
|
||||
}
|
||||
@ -1429,7 +1430,7 @@ describe('i18n support in the view compiler', () => {
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 1, "ng-template");
|
||||
$r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 1, "ng-template");
|
||||
$r3$.ɵelementContainerStart(1);
|
||||
$r3$.ɵi18n(2, $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵelementContainerEnd();
|
||||
@ -1460,7 +1461,7 @@ describe('i18n support in the view compiler', () => {
|
||||
`;
|
||||
|
||||
const output = String.raw `
|
||||
function MyComponent_ng_template_2_ng_template_2_ng_template_1_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_ng_template_ng_template_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18n(0, $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$, 3);
|
||||
}
|
||||
@ -1470,10 +1471,10 @@ describe('i18n support in the view compiler', () => {
|
||||
$r3$.ɵi18nApply(0);
|
||||
}
|
||||
}
|
||||
function MyComponent_ng_template_2_ng_template_2_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_ng_template_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18nStart(0, $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$, 2);
|
||||
$r3$.ɵtemplate(1, MyComponent_ng_template_2_ng_template_2_ng_template_1_Template, 1, 1, "ng-template");
|
||||
$r3$.ɵtemplate(1, MyComponent_ng_template_ng_template_ng_template_Template_1, 1, 1, "ng-template");
|
||||
$r3$.ɵi18nEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -1490,11 +1491,11 @@ describe('i18n support in the view compiler', () => {
|
||||
"interpolation_2": "\uFFFD0:3\uFFFD"
|
||||
});
|
||||
const $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$);
|
||||
function MyComponent_ng_template_2_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18nStart(0, $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$, 1);
|
||||
$r3$.ɵpipe(1, "uppercase");
|
||||
$r3$.ɵtemplate(2, MyComponent_ng_template_2_ng_template_2_Template, 2, 1, "ng-template");
|
||||
$r3$.ɵtemplate(2, MyComponent_ng_template_ng_template_Template_2, 2, 1, "ng-template");
|
||||
$r3$.ɵi18nEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -1510,7 +1511,7 @@ describe('i18n support in the view compiler', () => {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵi18nStart(1, $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵtemplate(2, MyComponent_ng_template_2_Template, 3, 3, "ng-template");
|
||||
$r3$.ɵtemplate(2, MyComponent_ng_template_Template_2, 3, 3, "ng-template");
|
||||
$r3$.ɵi18nEnd();
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
@ -1535,7 +1536,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__1$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_8806993169187953163$$APP_SPEC_TS__1$, {
|
||||
"VAR_SELECT": "\uFFFD0\uFFFD"
|
||||
});
|
||||
function MyComponent_ng_template_2_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18n(0, $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__1$);
|
||||
}
|
||||
@ -1553,7 +1554,7 @@ describe('i18n support in the view compiler', () => {
|
||||
$r3$.ɵelementContainerStart(0);
|
||||
$r3$.ɵi18n(1, $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵelementContainerEnd();
|
||||
$r3$.ɵtemplate(2, MyComponent_ng_template_2_Template, 1, 1, "ng-template");
|
||||
$r3$.ɵtemplate(2, MyComponent_ng_template_Template_2, 1, 1, "ng-template");
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵi18nExp($r3$.ɵbind(ctx.gender));
|
||||
@ -1583,7 +1584,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const $MSG_EXTERNAL_461986953980355147$$APP_SPEC_TS__2$ = goog.getMsg("{$tagImg} is my logo #2 ", {
|
||||
"tagImg": "\uFFFD#1\uFFFD\uFFFD/#1\uFFFD"
|
||||
});
|
||||
function MyComponent_ng_template_3_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_3(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18nStart(0, $MSG_EXTERNAL_461986953980355147$$APP_SPEC_TS__2$);
|
||||
$r3$.ɵelement(1, "img", $_c0$);
|
||||
@ -1598,7 +1599,7 @@ describe('i18n support in the view compiler', () => {
|
||||
$r3$.ɵelement(2, "img", $_c0$);
|
||||
$r3$.ɵi18nEnd();
|
||||
$r3$.ɵelementContainerEnd();
|
||||
$r3$.ɵtemplate(3, MyComponent_ng_template_3_Template, 2, 0, "ng-template");
|
||||
$r3$.ɵtemplate(3, MyComponent_ng_template_Template_3, 2, 0, "ng-template");
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1700,13 +1701,13 @@ describe('i18n support in the view compiler', () => {
|
||||
const $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$, {
|
||||
"VAR_SELECT": "\uFFFD0\uFFFD"
|
||||
});
|
||||
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
const $_c0$ = [1, "ngIf"];
|
||||
const $_c1$ = ["title", "icu only"];
|
||||
const $MSG_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$ = goog.getMsg("{VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}}");
|
||||
const $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$, {
|
||||
"VAR_SELECT": "\uFFFD0\uFFFD"
|
||||
});
|
||||
function MyComponent_div_2_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $_c1$);
|
||||
$r3$.ɵi18n(1, $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$);
|
||||
@ -1725,7 +1726,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const $I18N_EXTERNAL_1922743304863699161$$APP_SPEC_TS__5$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_1922743304863699161$$APP_SPEC_TS__5$, {
|
||||
"VAR_SELECT": "\uFFFD0\uFFFD"
|
||||
});
|
||||
function MyComponent_div_3_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_3(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $_c2$);
|
||||
$r3$.ɵtext(1, " You have ");
|
||||
@ -1748,8 +1749,8 @@ describe('i18n support in the view compiler', () => {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵi18n(1, $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵtemplate(2, MyComponent_div_2_Template, 2, 1, "div", $_c0$);
|
||||
$r3$.ɵtemplate(3, MyComponent_div_3_Template, 4, 2, "div", $_c0$);
|
||||
$r3$.ɵtemplate(2, MyComponent_div_Template_2, 2, 1, "div", $_c0$);
|
||||
$r3$.ɵtemplate(3, MyComponent_div_Template_3, 4, 2, "div", $_c0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵi18nExp($r3$.ɵbind(ctx.gender));
|
||||
@ -1941,7 +1942,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const $I18N_APP_SPEC_TS_2$ = $r3$.ɵi18nPostprocess($MSG_APP_SPEC_TS_2$, {
|
||||
"VAR_SELECT": "\uFFFD1\uFFFD"
|
||||
});
|
||||
const $_c3$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
const $_c3$ = [1, "ngIf"];
|
||||
const $MSG_APP_SPEC_TS__4$ = goog.getMsg("{VAR_SELECT, select, male {male} female {female} other {other}}");
|
||||
const $I18N_APP_SPEC_TS__4$ = $r3$.ɵi18nPostprocess($MSG_APP_SPEC_TS__4$, {
|
||||
"VAR_SELECT": "\uFFFD0:1\uFFFD"
|
||||
@ -1955,7 +1956,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const $I18N_APP_SPEC_TS_0$ = $r3$.ɵi18nPostprocess($MSG_APP_SPEC_TS_0$, {
|
||||
"ICU": [$I18N_APP_SPEC_TS_1$, $I18N_APP_SPEC_TS_2$, $I18N_APP_SPEC_TS__4$]
|
||||
});
|
||||
function MyComponent_div_3_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_3(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18nStart(0, $I18N_APP_SPEC_TS_0$, 1);
|
||||
$r3$.ɵelement(1, "div");
|
||||
@ -1975,7 +1976,7 @@ describe('i18n support in the view compiler', () => {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵi18nStart(1, $I18N_APP_SPEC_TS_0$);
|
||||
$r3$.ɵelement(2, "div");
|
||||
$r3$.ɵtemplate(3, MyComponent_div_3_Template, 2, 1, "div", $_c3$);
|
||||
$r3$.ɵtemplate(3, MyComponent_div_Template_3, 2, 1, "div", $_c3$);
|
||||
$r3$.ɵi18nEnd();
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
@ -2049,7 +2050,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_1$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7842238767399919809$$APP_SPEC_TS_1$, {
|
||||
"VAR_SELECT": "\uFFFD0\uFFFD"
|
||||
});
|
||||
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
const $_c0$ = [1, "ngIf"];
|
||||
const $MSG_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$ = goog.getMsg("{VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other}}");
|
||||
const $I18N_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$, {
|
||||
"VAR_SELECT": "\uFFFD0:1\uFFFD"
|
||||
@ -2060,7 +2061,7 @@ describe('i18n support in the view compiler', () => {
|
||||
"icu": $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_1$,
|
||||
"icu_1": $I18N_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$
|
||||
});
|
||||
function MyComponent_span_2_Template(rf, ctx) {
|
||||
function MyComponent_span_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18nStart(0, $MSG_EXTERNAL_1194472282609532229$$APP_SPEC_TS_0$, 1);
|
||||
$r3$.ɵelement(1, "span");
|
||||
@ -2079,7 +2080,7 @@ describe('i18n support in the view compiler', () => {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵi18nStart(1, $MSG_EXTERNAL_1194472282609532229$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵtemplate(2, MyComponent_span_2_Template, 2, 1, "span", $_c2$);
|
||||
$r3$.ɵtemplate(2, MyComponent_span_Template_2, 2, 1, "span", $_c2$);
|
||||
$r3$.ɵi18nEnd();
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
@ -2112,7 +2113,7 @@ describe('i18n support in the view compiler', () => {
|
||||
const $I18N_EXTERNAL_7825031864601787094$$APP_SPEC_TS_1$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7825031864601787094$$APP_SPEC_TS_1$, {
|
||||
"VAR_SELECT": "\uFFFD0\uFFFD"
|
||||
});
|
||||
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
const $_c0$ = [1, "ngIf"];
|
||||
const $MSG_EXTERNAL_2310343208266678305$$APP_SPEC_TS__3$ = goog.getMsg("{VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other: {$interpolation}}}", {
|
||||
"interpolation": "\uFFFD1:1\uFFFD"
|
||||
});
|
||||
@ -2125,7 +2126,7 @@ describe('i18n support in the view compiler', () => {
|
||||
"icu": $I18N_EXTERNAL_7825031864601787094$$APP_SPEC_TS_1$,
|
||||
"icu_1": $I18N_EXTERNAL_2310343208266678305$$APP_SPEC_TS__3$
|
||||
});
|
||||
function MyComponent_span_2_Template(rf, ctx) {
|
||||
function MyComponent_span_Template_2(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵi18nStart(0, $MSG_EXTERNAL_7186042105600518133$$APP_SPEC_TS_0$, 1);
|
||||
$r3$.ɵelement(1, "span");
|
||||
@ -2145,7 +2146,7 @@ describe('i18n support in the view compiler', () => {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵi18nStart(1, $MSG_EXTERNAL_7186042105600518133$$APP_SPEC_TS_0$);
|
||||
$r3$.ɵtemplate(2, MyComponent_span_2_Template, 2, 2, "span", $_c2$);
|
||||
$r3$.ɵtemplate(2, MyComponent_span_Template_2, 2, 2, "span", $_c2$);
|
||||
$r3$.ɵi18nEnd();
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ describe('compiler compliance: listen()', () => {
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $e0_attrs$);
|
||||
$r3$.ɵlistener("click", function MyComponent_Template_div_click_0_listener($event) {
|
||||
$r3$.ɵlistener("click", function MyComponent_Template_div_click_listener($event) {
|
||||
ctx.onClick($event);
|
||||
return (1 == 2);
|
||||
});
|
||||
@ -92,7 +92,7 @@ describe('compiler compliance: listen()', () => {
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "my-app", $e0_attrs$);
|
||||
$r3$.ɵlistener("click", function MyComponent_Template_my_app_click_0_listener($event) {
|
||||
$r3$.ɵlistener("click", function MyComponent_Template_my_app_click_listener($event) {
|
||||
return ctx.onClick($event);
|
||||
});
|
||||
$r3$.ɵelementEnd();
|
||||
@ -136,19 +136,19 @@ describe('compiler compliance: listen()', () => {
|
||||
const $t0_attrs$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
const $e_attrs$ = [${AttributeMarker.SelectOnly}, "click"];
|
||||
|
||||
function MyComponent_div_0_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
const $s$ = $r3$.ɵgetCurrentView();
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵelementStart(1, "div", $e_attrs$);
|
||||
$r3$.ɵlistener("click", function MyComponent_div_0_Template_div_click_1_listener($event) {
|
||||
$r3$.ɵlistener("click", function MyComponent_div_Template_0_div_click_listener($event) {
|
||||
$r3$.ɵrestoreView($s$);
|
||||
const $comp$ = $r3$.ɵnextContext();
|
||||
return $comp$.onClick($comp$.foo);
|
||||
});
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵelementStart(2, "button", $e_attrs$);
|
||||
$r3$.ɵlistener("click", function MyComponent_div_0_Template_button_click_2_listener($event) {
|
||||
$r3$.ɵlistener("click", function MyComponent_div_Template_0_button_click_listener($event) {
|
||||
$r3$.ɵrestoreView($s$);
|
||||
const $comp2$ = $r3$.ɵnextContext();
|
||||
return $comp2$.onClick2($comp2$.bar);
|
||||
@ -160,7 +160,7 @@ describe('compiler compliance: listen()', () => {
|
||||
// ...
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵtemplate(0, MyComponent_div_0_Template, 3, 0, "div", $c0$);
|
||||
$r3$.ɵtemplate(0, MyComponent_div_Template_0, 3, 0, "div", $c0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$i0$.ɵelementProperty(0, "ngIf", $i0$.ɵbind(ctx.showing));
|
||||
@ -208,7 +208,7 @@ describe('compiler compliance: listen()', () => {
|
||||
if (rf & 1) {
|
||||
const $s$ = $r3$.ɵgetCurrentView();
|
||||
$r3$.ɵelementStart(0, "button", $e0_attrs$);
|
||||
$r3$.ɵlistener("click", function MyComponent_Template_button_click_0_listener($event) {
|
||||
$r3$.ɵlistener("click", function MyComponent_Template_button_click_listener($event) {
|
||||
$r3$.ɵrestoreView($s$);
|
||||
const $user$ = $r3$.ɵreference(3);
|
||||
return ctx.onClick($user$.value);
|
||||
|
@ -120,70 +120,4 @@ describe('r3_view_compiler', () => {
|
||||
expectEmit(result.source, bV_call, 'Incorrect bV call');
|
||||
});
|
||||
});
|
||||
|
||||
describe('animations', () => {
|
||||
it('should keep @attr but suppress [@attr]', () => {
|
||||
const files: MockDirectory = {
|
||||
app: {
|
||||
'example.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: '<div @attrOnly [@myAnimation]="exp"></div>'
|
||||
})
|
||||
export class MyApp {
|
||||
}
|
||||
|
||||
@NgModule({declarations: [MyApp]})
|
||||
export class MyModule {}`
|
||||
}
|
||||
};
|
||||
|
||||
const template = `
|
||||
const _c0 = ["@attrOnly", ""];
|
||||
// ...
|
||||
template: function MyApp_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelement(0, "div", _c0);
|
||||
// ...
|
||||
}
|
||||
// ...
|
||||
}`;
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect initialization attributes');
|
||||
});
|
||||
|
||||
it('should dedup multiple [@event] listeners', () => {
|
||||
const files: MockDirectory = {
|
||||
app: {
|
||||
'example.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: '<div (@mySelector.start)="false" (@mySelector.done)="false" [@mySelector]="0"></div>'
|
||||
})
|
||||
export class MyApp {
|
||||
}
|
||||
|
||||
@NgModule({declarations: [MyApp]})
|
||||
export class MyModule {}`
|
||||
}
|
||||
};
|
||||
|
||||
const template = `
|
||||
const _c0 = [3, "@mySelector"];
|
||||
// ...
|
||||
template: function MyApp_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "div", _c0);
|
||||
// ...
|
||||
}
|
||||
// ...
|
||||
}`;
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect initialization attributes');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AttributeMarker, ViewEncapsulation} from '@angular/compiler/src/core';
|
||||
import {AttributeMarker, InitialStylingFlags, ViewEncapsulation} from '@angular/compiler/src/core';
|
||||
import {setup} from '@angular/compiler/test/aot/test_util';
|
||||
import {compile, expectEmit} from './mock_compile';
|
||||
|
||||
@ -214,6 +214,7 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $e0_attrs$ = ["@foo", ""];
|
||||
const $e1_attrs$ = ["@bar", ""];
|
||||
const $e2_attrs$ = ["@baz", ""];
|
||||
…
|
||||
@ -223,7 +224,7 @@ describe('compiler compliance: styling', () => {
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, $ctx$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, "div");
|
||||
$r3$.ɵelement(0, "div", $e0_attrs$);
|
||||
$r3$.ɵelement(1, "div", $e1_attrs$);
|
||||
$r3$.ɵelement(2, "div", $e2_attrs$);
|
||||
}
|
||||
@ -281,8 +282,8 @@ describe('compiler compliance: styling', () => {
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", _c0);
|
||||
$r3$.ɵlistener("@myAnimation.start", function MyComponent_Template_div_animation_myAnimation_start_0_listener($event) { return ctx.onStart($event); });
|
||||
$r3$.ɵlistener("@myAnimation.done", function MyComponent_Template_div_animation_myAnimation_done_0_listener($event) { return ctx.onDone($event); });
|
||||
$r3$.ɵlistener("@myAnimation.start", function MyComponent_Template_div__myAnimation_start_listener($event) { return ctx.onStart($event); });
|
||||
$r3$.ɵlistener("@myAnimation.done", function MyComponent_Template_div__myAnimation_done_listener($event) { return ctx.onDone($event); });
|
||||
$r3$.ɵelementEnd();
|
||||
} if (rf & 2) {
|
||||
$r3$.ɵelementProperty(0, "@myAnimation", $r3$.ɵbind(ctx.exp));
|
||||
@ -296,64 +297,6 @@ describe('compiler compliance: styling', () => {
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
|
||||
it('should generate animation host binding and listener code for directives', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Directive, Component, NgModule} from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[my-anim-dir]',
|
||||
animations: [
|
||||
{name: 'myAnim'}
|
||||
],
|
||||
host: {
|
||||
'[@myAnim]': 'myAnimState',
|
||||
'(@myAnim.start)': 'onStart()',
|
||||
'(@myAnim.done)': 'onDone()'
|
||||
}
|
||||
})
|
||||
class MyAnimDir {
|
||||
onStart() {}
|
||||
onDone() {}
|
||||
myAnimState = '123';
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'my-cmp',
|
||||
template: \`
|
||||
<div my-anim-dir></div>
|
||||
\`
|
||||
})
|
||||
class MyComponent {
|
||||
}
|
||||
|
||||
@NgModule({declarations: [MyComponent, MyAnimDir]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const template = `
|
||||
MyAnimDir.ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
…
|
||||
hostBindings: function MyAnimDir_HostBindings(rf, ctx, elIndex) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵallocHostVars(1);
|
||||
$r3$.ɵlistener("@myAnim.start", function MyAnimDir_animation_myAnim_start_HostBindingHandler($event) { return ctx.onStart(); });
|
||||
$r3$.ɵlistener("@myAnim.done", function MyAnimDir_animation_myAnim_done_HostBindingHandler($event) { return ctx.onDone(); });
|
||||
} if (rf & 2) {
|
||||
$r3$.ɵcomponentHostSyntheticProperty(elIndex, "@myAnim", $r3$.ɵbind(ctx.myAnimState), null, true);
|
||||
}
|
||||
}
|
||||
…
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
});
|
||||
|
||||
describe('[style] and [style.prop]', () => {
|
||||
@ -423,8 +366,8 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $_c0$ = [${AttributeMarker.Styles}, "opacity", "1", ${AttributeMarker.SelectOnly}, "style"];
|
||||
const $_c1$ = ["width", "height"];
|
||||
const $e0_attrs$ = [${AttributeMarker.SelectOnly}, "style"];
|
||||
const $e0_styling$ = ["opacity","width","height",${InitialStylingFlags.VALUES_MODE},"opacity","1"];
|
||||
…
|
||||
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
@ -436,14 +379,14 @@ describe('compiler compliance: styling', () => {
|
||||
vars: 1,
|
||||
template: function MyComponent_Template(rf, $ctx$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $_c0$);
|
||||
$r3$.ɵelementStyling(null, $_c1$, $r3$.ɵdefaultStyleSanitizer);
|
||||
$r3$.ɵelementStart(0, "div", $e0_attrs$);
|
||||
$r3$.ɵelementStyling(null, $e0_styling$, $r3$.ɵdefaultStyleSanitizer);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementStylingMap(0, null, $ctx$.myStyleExp);
|
||||
$r3$.ɵelementStyleProp(0, 0, $ctx$.myWidth);
|
||||
$r3$.ɵelementStyleProp(0, 1, $ctx$.myHeight);
|
||||
$r3$.ɵelementStyleProp(0, 1, $ctx$.myWidth);
|
||||
$r3$.ɵelementStyleProp(0, 2, $ctx$.myHeight);
|
||||
$r3$.ɵelementStylingApply(0);
|
||||
$r3$.ɵelementAttribute(0, "style", $r3$.ɵbind("border-width: 10px"), $r3$.ɵsanitizeStyle);
|
||||
}
|
||||
@ -478,7 +421,7 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $_c0$ = ["background-image"];
|
||||
const _c0 = ["background-image"];
|
||||
export class MyComponent {
|
||||
constructor() {
|
||||
this.myImage = 'url(foo.jpg)';
|
||||
@ -513,6 +456,7 @@ describe('compiler compliance: styling', () => {
|
||||
});
|
||||
|
||||
it('should support [style.foo.suffix] style bindings with a suffix', () => {
|
||||
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
@ -532,7 +476,7 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $e0_styles$ = ["font-size"];
|
||||
const $e0_styles$= ["font-size"];
|
||||
…
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
@ -620,8 +564,8 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $e0_attrs$ = [${AttributeMarker.Classes}, "grape", ${AttributeMarker.SelectOnly}, "class"];
|
||||
const $e0_bindings$ = ["apple", "orange"];
|
||||
const $e0_attrs$ = [${AttributeMarker.SelectOnly}, "class"];
|
||||
const $e0_cd$ = ["grape","apple","orange",${InitialStylingFlags.VALUES_MODE},"grape",true];
|
||||
…
|
||||
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
@ -634,13 +578,13 @@ describe('compiler compliance: styling', () => {
|
||||
template: function MyComponent_Template(rf, $ctx$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $e0_attrs$);
|
||||
$r3$.ɵelementStyling($e0_bindings$);
|
||||
$r3$.ɵelementStyling($e0_cd$);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementStylingMap(0, $ctx$.myClassExp);
|
||||
$r3$.ɵelementClassProp(0, 0, $ctx$.yesToApple);
|
||||
$r3$.ɵelementClassProp(0, 1, $ctx$.yesToOrange);
|
||||
$r3$.ɵelementClassProp(0, 1, $ctx$.yesToApple);
|
||||
$r3$.ɵelementClassProp(0, 2, $ctx$.yesToOrange);
|
||||
$r3$.ɵelementStylingApply(0);
|
||||
$r3$.ɵelementAttribute(0, "class", $r3$.ɵbind("banana"));
|
||||
}
|
||||
@ -662,7 +606,7 @@ describe('compiler compliance: styling', () => {
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: \`<div class=" foo "
|
||||
template: \`<div class="foo"
|
||||
style="width:100px"
|
||||
[attr.class]="'round'"
|
||||
[attr.style]="'height:100px'"></div>\`
|
||||
@ -676,7 +620,9 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $e0_attrs$ = [${AttributeMarker.Classes}, "foo", ${AttributeMarker.Styles}, "width", "100px", ${AttributeMarker.SelectOnly}, "class", "style"];
|
||||
const $e0_attrs$ = [${AttributeMarker.SelectOnly}, "class", "style"];
|
||||
const $e0_cd$ = ["foo",${InitialStylingFlags.VALUES_MODE},"foo",true];
|
||||
const $e0_sd$ = ["width",${InitialStylingFlags.VALUES_MODE},"width","100px"];
|
||||
…
|
||||
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
@ -689,6 +635,7 @@ describe('compiler compliance: styling', () => {
|
||||
template: function MyComponent_Template(rf, $ctx$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div", $e0_attrs$);
|
||||
$r3$.ɵelementStyling($e0_cd$, $e0_sd$);
|
||||
$r3$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -818,13 +765,10 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $e0_classBindings$ = ["foo"];
|
||||
const $e0_styleBindings$ = ["bar", "baz"];
|
||||
…
|
||||
template: function MyComponent_Template(rf, $ctx$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, "div");
|
||||
$r3$.ɵelementStyling($e0_classBindings$, $e0_styleBindings$, $r3$.ɵdefaultStyleSanitizer);
|
||||
$r3$.ɵelementStyling($e0_styling$, $e1_styling$, $r3$.ɵdefaultStyleSanitizer);
|
||||
$r3$.ɵpipe(1, "pipe");
|
||||
$r3$.ɵpipe(2, "pipe");
|
||||
$r3$.ɵpipe(3, "pipe");
|
||||
@ -884,18 +828,16 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $e0_attrs$ = [${AttributeMarker.Classes}, "foo", "baz", ${AttributeMarker.Styles}, "width", "200px", "height", "500px"];
|
||||
const $e0_classBindings$ = ["foo"];
|
||||
const $e0_styleBindings$ = ["color"];
|
||||
const _c0 = ["foo", "baz", ${InitialStylingFlags.VALUES_MODE}, "foo", true, "baz", true];
|
||||
const _c1 = ["width", "height", "color", ${InitialStylingFlags.VALUES_MODE}, "width", "200px", "height", "500px"];
|
||||
…
|
||||
hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementHostAttrs(ctx, $e0_attrs$);
|
||||
$r3$.ɵelementStyling($e0_classBindings$, $e0_styleBindings$, $r3$.ɵdefaultStyleSanitizer, ctx);
|
||||
$r3$.ɵelementStyling(_c0, _c1, $r3$.ɵdefaultStyleSanitizer, ctx);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementStylingMap(elIndex, ctx.myClass, ctx.myStyle, ctx);
|
||||
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myColorProp, null, ctx);
|
||||
$r3$.ɵelementStyleProp(elIndex, 2, ctx.myColorProp, null, ctx);
|
||||
$r3$.ɵelementClassProp(elIndex, 0, ctx.myFooClass, ctx);
|
||||
$r3$.ɵelementStylingApply(elIndex, ctx);
|
||||
}
|
||||
@ -1017,10 +959,10 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $widthDir_classes$ = ["foo"];
|
||||
const $widthDir_styles$ = ["width"];
|
||||
const $heightDir_classes$ = ["bar"];
|
||||
const $heightDir_styles$ = ["height"];
|
||||
const _c0 = ["foo"];
|
||||
const _c1 = ["width"];
|
||||
const _c2 = ["bar"];
|
||||
const _c3 = ["height"];
|
||||
…
|
||||
function ClassDirective_HostBindings(rf, ctx, elIndex) {
|
||||
if (rf & 1) {
|
||||
@ -1034,7 +976,7 @@ describe('compiler compliance: styling', () => {
|
||||
…
|
||||
function WidthDirective_HostBindings(rf, ctx, elIndex) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStyling($widthDir_classes$, $widthDir_styles$, null, ctx);
|
||||
$r3$.ɵelementStyling(_c0, _c1, null, ctx);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myWidth, null, ctx);
|
||||
@ -1045,7 +987,7 @@ describe('compiler compliance: styling', () => {
|
||||
…
|
||||
function HeightDirective_HostBindings(rf, ctx, elIndex) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStyling($heightDir_classes$, $heightDir_styles$, null, ctx);
|
||||
$r3$.ɵelementStyling(_c2, _c3, null, ctx);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myHeight, null, ctx);
|
||||
@ -1072,8 +1014,7 @@ describe('compiler compliance: styling', () => {
|
||||
template: '',
|
||||
host: {
|
||||
'style': 'width:200px; height:500px',
|
||||
'class': 'foo baz',
|
||||
'title': 'foo title'
|
||||
'class': 'foo baz'
|
||||
}
|
||||
})
|
||||
export class MyComponent {
|
||||
@ -1088,9 +1029,6 @@ describe('compiler compliance: styling', () => {
|
||||
|
||||
@HostBinding('title')
|
||||
title = 'some title';
|
||||
|
||||
@Input('name')
|
||||
name = '';
|
||||
}
|
||||
|
||||
@NgModule({declarations: [MyComponent]})
|
||||
@ -1100,13 +1038,13 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const $_c0$ = [${AttributeMarker.Classes}, "foo", "baz", ${AttributeMarker.Styles}, "width", "200px", "height", "500px"];
|
||||
const $_c0$ = ["foo", "baz", ${InitialStylingFlags.VALUES_MODE}, "foo", true, "baz", true];
|
||||
const $_c1$ = ["width", "height", ${InitialStylingFlags.VALUES_MODE}, "width", "200px", "height", "500px"];
|
||||
…
|
||||
hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵallocHostVars(2);
|
||||
$r3$.ɵelementHostAttrs(ctx, $_c0$);
|
||||
$r3$.ɵelementStyling(null, null, $r3$.ɵdefaultStyleSanitizer, ctx);
|
||||
$r3$.ɵelementStyling($_c0$, $_c1$, $r3$.ɵdefaultStyleSanitizer, ctx);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind(ctx.id), null, true);
|
||||
|
@ -52,12 +52,12 @@ describe('compiler compliance: template', () => {
|
||||
const template = `
|
||||
const $c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"];
|
||||
const $e0_attrs$ = [${AttributeMarker.SelectOnly}, "title", "click"];
|
||||
function MyComponent_ul_0_li_1_div_1_Template(rf, ctx) {
|
||||
function MyComponent_ul_li_div_Template_1(rf, ctx) {
|
||||
|
||||
if (rf & 1) {
|
||||
const $s$ = $i0$.ɵgetCurrentView();
|
||||
$i0$.ɵelementStart(0, "div", $e0_attrs$);
|
||||
$i0$.ɵlistener("click", function MyComponent_ul_0_li_1_div_1_Template_div_click_0_listener($event){
|
||||
$i0$.ɵlistener("click", function MyComponent_ul_li_div_Template_1_div_click_listener($event){
|
||||
$i0$.ɵrestoreView($s$);
|
||||
const $inner$ = ctx.$implicit;
|
||||
const $middle$ = $i0$.ɵnextContext().$implicit;
|
||||
@ -79,10 +79,10 @@ describe('compiler compliance: template', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function MyComponent_ul_0_li_1_Template(rf, ctx) {
|
||||
function MyComponent_ul_li_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "li");
|
||||
$i0$.ɵtemplate(1, MyComponent_ul_0_li_1_div_1_Template, 2, 2, "div", _c0);
|
||||
$i0$.ɵtemplate(1, MyComponent_ul_li_div_Template_1, 2, 2, "div", _c0);
|
||||
$i0$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -91,10 +91,10 @@ describe('compiler compliance: template', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function MyComponent_ul_0_Template(rf, ctx) {
|
||||
function MyComponent_ul_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "ul");
|
||||
$i0$.ɵtemplate(1, MyComponent_ul_0_li_1_Template, 2, 1, "li", _c0);
|
||||
$i0$.ɵtemplate(1, MyComponent_ul_li_Template_1, 2, 1, "li", _c0);
|
||||
$i0$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -105,7 +105,7 @@ describe('compiler compliance: template', () => {
|
||||
// ...
|
||||
template:function MyComponent_Template(rf, ctx){
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtemplate(0, MyComponent_ul_0_Template, 2, 1, "ul", _c0);
|
||||
$i0$.ɵtemplate(0, MyComponent_ul_Template_0, 2, 1, "ul", _c0);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items));
|
||||
@ -141,7 +141,7 @@ describe('compiler compliance: template', () => {
|
||||
const template = `
|
||||
const $c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"];
|
||||
|
||||
function MyComponent_span_0_Template(rf, ctx) {
|
||||
function MyComponent_span_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "span");
|
||||
$i0$.ɵtext(1);
|
||||
@ -156,7 +156,7 @@ describe('compiler compliance: template', () => {
|
||||
// ...
|
||||
template:function MyComponent_Template(rf, ctx){
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtemplate(0, MyComponent_span_0_Template, 2, 2, "span", _c0);
|
||||
$i0$.ɵtemplate(0, MyComponent_span_Template_0, 2, 2, "span", _c0);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items));
|
||||
@ -195,7 +195,7 @@ describe('compiler compliance: template', () => {
|
||||
const $c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"];
|
||||
const $c1$ = [${AttributeMarker.SelectOnly}, "ngIf"];
|
||||
|
||||
function MyComponent_div_0_span_1_Template(rf, ctx) {
|
||||
function MyComponent_div_span_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "span");
|
||||
$i0$.ɵtext(1);
|
||||
@ -209,10 +209,10 @@ describe('compiler compliance: template', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function MyComponent_div_0_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "div");
|
||||
$i0$.ɵtemplate(1, MyComponent_div_0_span_1_Template, 2, 2, "span", $c1$);
|
||||
$i0$.ɵtemplate(1, MyComponent_div_span_Template_1, 2, 2, "span", $c1$);
|
||||
$i0$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -224,7 +224,7 @@ describe('compiler compliance: template', () => {
|
||||
// ...
|
||||
template:function MyComponent_Template(rf, ctx){
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtemplate(0, MyComponent_div_0_Template, 2, 1, "div", $c0$);
|
||||
$i0$.ɵtemplate(0, MyComponent_div_Template_0, 2, 1, "div", $c0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items));
|
||||
@ -264,7 +264,7 @@ describe('compiler compliance: template', () => {
|
||||
// The template should look like this (where IDENT is a wild card for an identifier):
|
||||
const template = `
|
||||
const $c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"];
|
||||
function MyComponent_div_0_div_1_div_1_Template(rf, ctx) {
|
||||
function MyComponent_div_div_div_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "div");
|
||||
$i0$.ɵtext(1);
|
||||
@ -277,10 +277,10 @@ describe('compiler compliance: template', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function MyComponent_div_0_div_1_Template(rf, ctx) {
|
||||
function MyComponent_div_div_Template_1(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "div");
|
||||
$i0$.ɵtemplate(1, MyComponent_div_0_div_1_div_1_Template, 2, 2, "div", _c0);
|
||||
$i0$.ɵtemplate(1, MyComponent_div_div_div_Template_1, 2, 2, "div", _c0);
|
||||
$i0$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -289,10 +289,10 @@ describe('compiler compliance: template', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function MyComponent_div_0_Template(rf, ctx) {
|
||||
function MyComponent_div_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵelementStart(0, "div");
|
||||
$i0$.ɵtemplate(1, MyComponent_div_0_div_1_Template, 2, 1, "div", _c0);
|
||||
$i0$.ɵtemplate(1, MyComponent_div_div_Template_1, 2, 1, "div", _c0);
|
||||
$i0$.ɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
@ -303,7 +303,7 @@ describe('compiler compliance: template', () => {
|
||||
// ...
|
||||
template:function MyComponent_Template(rf, ctx){
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtemplate(0, MyComponent_div_0_Template, 2, 1, "div", _c0);
|
||||
$i0$.ɵtemplate(0, MyComponent_div_Template_0, 2, 1, "div", _c0);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items));
|
||||
@ -339,7 +339,7 @@ describe('compiler compliance: template', () => {
|
||||
const template = `
|
||||
const $c0$ = ["attr", "l", ${AttributeMarker.SelectOnly}, "boundAttr"];
|
||||
|
||||
function MyComponent_ng_template_0_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtext(0, " some-content ");
|
||||
}
|
||||
@ -349,7 +349,7 @@ describe('compiler compliance: template', () => {
|
||||
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", $c0$);
|
||||
$i0$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 0, "ng-template", $c0$);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$i0$.ɵelementProperty(0, "boundAttr", $i0$.ɵbind(ctx.b));
|
||||
@ -370,7 +370,7 @@ describe('compiler compliance: template', () => {
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: '<ng-template #foo>some-content</ng-template>',
|
||||
template: '<ng-template #foo>some-content</ng-template>';
|
||||
})
|
||||
export class MyComponent {}
|
||||
|
||||
@ -383,7 +383,7 @@ describe('compiler compliance: template', () => {
|
||||
const template = `
|
||||
const $t0_refs$ = ["foo", ""];
|
||||
|
||||
function MyComponent_ng_template_0_Template(rf, ctx) {
|
||||
function MyComponent_ng_template_Template_0(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtext(0, "some-content");
|
||||
}
|
||||
@ -393,7 +393,7 @@ describe('compiler compliance: template', () => {
|
||||
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", null, $t0_refs$, $i0$.ɵtemplateRefExtractor);
|
||||
$i0$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 0, "ng-template", null, $t0_refs$, $i0$.ɵtemplateRefExtractor);
|
||||
}
|
||||
}`;
|
||||
|
||||
@ -411,7 +411,7 @@ describe('compiler compliance: template', () => {
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: '<ng-template (outDirective)="$event.doSth()"></ng-template>',
|
||||
template: '<ng-template (outDirective)="$event.doSth()"></ng-template>';
|
||||
})
|
||||
export class MyComponent {}
|
||||
|
||||
@ -424,14 +424,14 @@ describe('compiler compliance: template', () => {
|
||||
const template = `
|
||||
const $t0_attrs$ = [${AttributeMarker.SelectOnly}, "outDirective"];
|
||||
|
||||
function MyComponent_ng_template_0_Template(rf, ctx) { }
|
||||
function MyComponent_ng_template_Template_0(rf, ctx) { }
|
||||
|
||||
// ...
|
||||
|
||||
template: function MyComponent_Template(rf, ctx) {
|
||||
if (rf & 1) {
|
||||
$i0$.ɵtemplate(0, MyComponent_ng_template_0_Template, 0, 0, "ng-template", $t0_attrs$);
|
||||
$i0$.ɵlistener("outDirective", function MyComponent_Template_ng_template_outDirective_0_listener($event) { return $event.doSth(); });
|
||||
$i0$.ɵtemplate(0, MyComponent_ng_template_Template_0, 0, 0, "ng-template", $t0_attrs$);
|
||||
$i0$.ɵlistener("outDirective", function MyComponent_Template_ng_template_outDirective_listener($event) { return $event.doSth(); });
|
||||
}
|
||||
}`;
|
||||
|
||||
@ -440,122 +440,4 @@ describe('compiler compliance: template', () => {
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
|
||||
});
|
||||
|
||||
it('should create unique template function names even for similar nested template structures',
|
||||
() => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec1.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'a-component',
|
||||
template: \`
|
||||
<div *ngFor="let item of items">
|
||||
<p *ngIf="item < 10">less than 10</p>
|
||||
<p *ngIf="item < 10">less than 10</p>
|
||||
</div>
|
||||
<div *ngFor="let item of items">
|
||||
<p *ngIf="item > 10">more than 10</p>
|
||||
</div>
|
||||
\`,
|
||||
})
|
||||
export class AComponent {
|
||||
items = [4, 2];
|
||||
}
|
||||
|
||||
@NgModule({declarations: [AComponent]})
|
||||
export class AModule {}
|
||||
`,
|
||||
'spec2.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'b-component',
|
||||
template: \`
|
||||
<div *ngFor="let item of items">
|
||||
<ng-container *ngFor="let subitem of item.subitems">
|
||||
<p *ngIf="subitem < 10">less than 10</p>
|
||||
<p *ngIf="subitem < 10">less than 10</p>
|
||||
</ng-container>
|
||||
<ng-container *ngFor="let subitem of item.subitems">
|
||||
<p *ngIf="subitem < 10">less than 10</p>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div *ngFor="let item of items">
|
||||
<ng-container *ngFor="let subitem of item.subitems">
|
||||
<p *ngIf="subitem > 10">more than 10</p>
|
||||
</ng-container>
|
||||
</div>
|
||||
\`,
|
||||
})
|
||||
export class BComponent {
|
||||
items = [
|
||||
{subitems: [1, 3]},
|
||||
{subitems: [3, 7]},
|
||||
];
|
||||
}
|
||||
|
||||
@NgModule({declarations: [BComponent]})
|
||||
export class BModule {}
|
||||
`,
|
||||
},
|
||||
};
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
|
||||
const allTemplateFunctionsNames = (result.source.match(/function ([^\s(]+)/g) || [])
|
||||
.map(x => x.slice(9))
|
||||
.filter(x => x.includes('Template'))
|
||||
.sort();
|
||||
const uniqueTemplateFunctionNames = Array.from(new Set(allTemplateFunctionsNames));
|
||||
|
||||
// Expected template function:
|
||||
// - 5 for AComponent's template.
|
||||
// - 9 for BComponent's template.
|
||||
// - 2 for the two components.
|
||||
expect(allTemplateFunctionsNames.length).toBe(5 + 9 + 2);
|
||||
expect(allTemplateFunctionsNames).toEqual(uniqueTemplateFunctionNames);
|
||||
});
|
||||
|
||||
it('should create unique listener function names even for similar nested template structures',
|
||||
() => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: \`
|
||||
<div *ngFor="let item of items">
|
||||
<p (click)="$event">{{ item }}</p>
|
||||
<p (click)="$event">{{ item }}</p>
|
||||
</div>
|
||||
<div *ngFor="let item of items">
|
||||
<p (click)="$event">{{ item }}</p>
|
||||
</div>
|
||||
\`,
|
||||
})
|
||||
export class MyComponent {
|
||||
items = [4, 2];
|
||||
}
|
||||
|
||||
@NgModule({declarations: [MyComponent]})
|
||||
export class MyModule {}
|
||||
`,
|
||||
},
|
||||
};
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
|
||||
const allListenerFunctionsNames = (result.source.match(/function ([^\s(]+)/g) || [])
|
||||
.map(x => x.slice(9))
|
||||
.filter(x => x.includes('listener'))
|
||||
.sort();
|
||||
const uniqueListenerFunctionNames = Array.from(new Set(allListenerFunctionsNames));
|
||||
|
||||
expect(allListenerFunctionsNames.length).toBe(3);
|
||||
expect(allListenerFunctionsNames).toEqual(uniqueListenerFunctionNames);
|
||||
});
|
||||
});
|
||||
|
@ -6,7 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {CustomTransformers} from '@angular/compiler-cli';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
@ -112,9 +111,9 @@ export class NgtscTestEnvironment {
|
||||
/**
|
||||
* Run the compiler to completion, and assert that no errors occurred.
|
||||
*/
|
||||
driveMain(customTransformers?: CustomTransformers): void {
|
||||
driveMain(): void {
|
||||
const errorSpy = jasmine.createSpy('consoleError').and.callFake(console.error);
|
||||
const exitCode = main(['-p', this.basePath], errorSpy, undefined, customTransformers);
|
||||
const exitCode = main(['-p', this.basePath], errorSpy);
|
||||
expect(errorSpy).not.toHaveBeenCalled();
|
||||
expect(exitCode).toBe(0);
|
||||
}
|
||||
|
@ -441,39 +441,6 @@ describe('ngtsc behavioral tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should unwrap a ModuleWithProviders-like function if a matching literal type is provided for it',
|
||||
() => {
|
||||
env.tsconfig();
|
||||
env.write(`test.ts`, `
|
||||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule} from 'router';
|
||||
|
||||
@NgModule({imports: [RouterModule.forRoot()]})
|
||||
export class TestModule {}
|
||||
`);
|
||||
|
||||
env.write('node_modules/router/index.d.ts', `
|
||||
import {ModuleWithProviders} from '@angular/core';
|
||||
|
||||
export interface MyType extends ModuleWithProviders {}
|
||||
|
||||
declare class RouterModule {
|
||||
static forRoot(): (MyType)&{ngModule:RouterModule};
|
||||
}
|
||||
`);
|
||||
|
||||
env.driveMain();
|
||||
|
||||
const jsContents = env.getContents('test.js');
|
||||
expect(jsContents).toContain('imports: [[RouterModule.forRoot()]]');
|
||||
|
||||
const dtsContents = env.getContents('test.d.ts');
|
||||
expect(dtsContents).toContain(`import * as i1 from 'router';`);
|
||||
expect(dtsContents)
|
||||
.toContain(
|
||||
'i0.ɵNgModuleDefWithMeta<TestModule, never, [typeof i1.RouterModule], never>');
|
||||
});
|
||||
|
||||
it('should inject special types according to the metadata', () => {
|
||||
env.tsconfig();
|
||||
env.write(`test.ts`, `
|
||||
@ -1227,32 +1194,4 @@ describe('ngtsc behavioral tests', () => {
|
||||
expect(dtsContents).toContain('/// <amd-module name="@mymodule" />');
|
||||
});
|
||||
});
|
||||
|
||||
it('should execute custom transformers', () => {
|
||||
let beforeCount = 0;
|
||||
let afterCount = 0;
|
||||
|
||||
env.tsconfig();
|
||||
env.write('test.ts', `
|
||||
import {NgModule} from '@angular/core';
|
||||
|
||||
@NgModule({})
|
||||
class Module {}
|
||||
`);
|
||||
|
||||
env.driveMain({
|
||||
beforeTs: [() => sourceFile => {
|
||||
beforeCount++;
|
||||
return sourceFile;
|
||||
}],
|
||||
afterTs: [() => sourceFile => {
|
||||
afterCount++;
|
||||
return sourceFile;
|
||||
}],
|
||||
});
|
||||
|
||||
expect(beforeCount).toBe(1);
|
||||
expect(afterCount).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -196,21 +196,7 @@ describe('NgCompilerHost', () => {
|
||||
const host = createHost({ngHost});
|
||||
expect(host.resourceNameToFileName('a', 'b')).toBe('someResult');
|
||||
});
|
||||
it('should resolve Sass imports to generated .css files', () => {
|
||||
const host = createHost({files: {'tmp': {'src': {'a': {'style.css': 'h1: bold'}}}}});
|
||||
expect(host.resourceNameToFileName('./a/style.scss', '/tmp/src/index.ts'))
|
||||
.toBe('/tmp/src/a/style.css');
|
||||
});
|
||||
it('should resolve Less imports to generated .css files', () => {
|
||||
const host = createHost({files: {'tmp': {'src': {'a': {'style.css': 'h1: bold'}}}}});
|
||||
expect(host.resourceNameToFileName('./a/style.less', '/tmp/src/index.ts'))
|
||||
.toBe('/tmp/src/a/style.css');
|
||||
});
|
||||
it('should resolve Stylus imports to generated .css files', () => {
|
||||
const host = createHost({files: {'tmp': {'src': {'a': {'style.css': 'h1: bold'}}}}});
|
||||
expect(host.resourceNameToFileName('./a/style.styl', '/tmp/src/index.ts'))
|
||||
.toBe('/tmp/src/a/style.css');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getSourceFile', () => {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user