Compare commits

..

125 Commits

Author SHA1 Message Date
579bed1a7a docs: add changelog for 5.2.3 2018-01-31 12:47:02 -08:00
b59fb23f4a release: cut the 5.2.3 release 2018-01-31 12:45:17 -08:00
2aa460b30e docs: add http guide sample and adjust text (#21326)
PR Close #21326
2018-01-31 10:24:43 -08:00
e0022ae9cd docs: Fix platform-detection example for Universal (#21796)
PR Close #21796
2018-01-31 10:21:04 -08:00
f2e923edd8 build(aio): upgrade to dgeni-packages 0.24.0 (#21802)
This has two benefits:

* it prepares the way for the API docs update, which need parameter docs
* it doesn't incorrectly report dangling links for non-latin anchors

Closes #21306

PR Close #21802
2018-01-31 10:20:37 -08:00
c2f5ed545c fix(common): generate closure-locale data file with exported plural functions (#21873)
Fixes #21870
PR Close #21873
2018-01-30 11:42:31 -08:00
5d75df8fb1 ci: unblock master by ignoring date pipe tests while we fix it (#21906)
PR Close #21906
2018-01-30 11:33:46 -08:00
ed2b71799c fix(common): allow HttpInterceptors to inject HttpClient (#19809)
Previously, an interceptor attempting to inject HttpClient directly
would receive a circular dependency error, as HttpClient was
constructed via a factory which injected the interceptor instances.
Users want to inject HttpClient into interceptors to make supporting
requests (ex: to retrieve an authentication token). Currently this is
only possible by injecting the Injector and using it to resolve
HttpClient at request time.

Either HttpClient or the user has to deal specially with the circular
dependency. This change moves that responsibility into HttpClient
itself. By utilizing a new class HttpInterceptingHandler which lazily
loads the set of interceptors at request time, it's possible to inject
HttpClient directly into interceptors as construction of HttpClient no
longer requires the interceptor chain to be constructed.

Fixes #18224.

PR Close #19809
2018-01-29 16:12:32 -08:00
fad99cca0e fix(forms): inserting and removing controls should work in re-bound form arrays (#21822)
Closes #21501

PR Close #21822
2018-01-29 16:11:41 -08:00
3f5ead3845 fix(aio): missing plural s in preserveWhiteSpaces example (#21854)
PR Close #21854
2018-01-29 11:35:13 -08:00
a89e709515 docs: change ”it's" to "its" as needed in several docs. (#21867)
Most of them are in content but one is in common and needs special approval.

PR Close #21867
2018-01-29 11:34:47 -08:00
6a7689d4ea build: update to latest bazel rules (#21821)
PR Close #21821
2018-01-27 10:55:45 -08:00
696ba01a4e fix(aio): don't set noindex metatag in the static index.html (#21816)
This seems to be causing crawling issues for google.

Ref #21665

PR Close #21816
2018-01-26 16:08:31 -08:00
81d64d6bec fix(core): fix retrieving the binding name when an expression changes (#21814)
fixes #21735
fixes #21788

PR Close #21814
2018-01-26 15:34:48 -08:00
7410941a7c build: merge-pr now checks that PR status is green before proceeding (#21810)
Optionally one can use `--force` to override and merge no non-green PR.

PR Close #21810
2018-01-26 14:50:41 -08:00
d159ad8b88 build(aio): prevent Windows error on serve-and-sync (#21806)
Running `yarn start` (which watches the `src/` directory) and
`yarn docs-watch` (which cleans up files in `src/generated/api/`) often
results in `ENOTEMPTY` errors.

This commit solves it by ensuring that `yarn docs` has been completed
before running `yarn start`.

PR Close #21806
2018-01-26 14:50:15 -08:00
250c8da768 fix(language-service): ensure correct paths are passed to TypeScript (#21812)
The 2.6 version of TypeScript's `resolveModuleName`  started to
require paths passed to be separated by '/' instead of being
able to handle '\'.

`ngc` and `ng` already do this transformation.

Fixes: #21811

PR Close #21812
2018-01-26 14:49:23 -08:00
778e6e759f fix(language-service): spell diagnostics correctly (#21812)
PR Close #21812
2018-01-26 14:49:23 -08:00
35a0721217 fix(router): remove @internal tag on ParamInheritanceType (#21773)
This is a more defensive approach to ensure that references to
ParamInheritanceType from the published declarations do not cause
compilation errors when compiling Angular from the published packages.

Fixes #21456

PR Close #21773
2018-01-26 10:28:34 -08:00
ba045e88d7 docs: add notes on email used for CLA (#21754)
Closes #20034

PR Close #21754
2018-01-26 10:28:18 -08:00
67806a7b25 fix(aio): close SideNav on non-sidenav doc on wide screen (#21538)
Partly addresses #21520.

PR Close #21538
2018-01-26 10:25:16 -08:00
9778a23be8 fix(aio): fix SideNav height on narrow screens (#21538)
Since we specify `bottom: 0`, specifying the height is unnecessary and
leads to wrong height (unless updated) on narrow screens where the
topbar height is decreased.

Partly addresses #21520.

PR Close #21538
2018-01-26 10:25:15 -08:00
87e06d765e ci: Add back the CLI integration test with pinning (#21555)
The CLI app is now checked in, rather than generated dynamically with
`ng new`. This loses some assertion power, but gains hermeticity.
It also checks in lock files for all integration tests, avoiding
floating version numbers.

We'll need another place to integration test between changes in
the various repositories - but the angular/angular PR-blocking status
is not the right place to do this.

PR Close #21555
2018-01-25 22:18:56 -08:00
56f3e18c1c fix(forms): allow FormBuilder to create controls with any formState type (#20917)
Align formState type in FormBuilder#control with FormControl#constructor

Fixes #20368

PR Close #20917
2018-01-25 22:17:43 -08:00
637515e71b build: autosquashes SHAs as part of merge-pr script (#21791)
To support `git checkin --fixup` and `git checkin —squash`
we need to make sure that `merge-pr` squashes the sepecial
commits before they are merged.

For more details see:
https://robots.thoughtbot.com/autosquashing-git-commits

PR Close #21791
2018-01-25 22:12:11 -08:00
27ecd077d4 docs(aio): fix missing stylesheet in component-styles example (#21772)
The code in the example was referring to `hero-app.component.css` but this did
not exist.

PR Close #21772
2018-01-25 13:38:14 -08:00
4db1be0292 docs(aio): fix paths to imported CSS stylesheets (#21772)
The AOT compiler needs relative paths so that it can find
the imported stylesheets.

PR Close #21772
2018-01-25 13:38:14 -08:00
a0dbef9ea4 build(aio): upgrade CLI version to cope with new Angular 6.0.0-beta.1 release (#21772)
Before version 1.6 of Angular CLI there was a check that prevented use of Angular
compiler CLI with major version 6.

PR Close #21772
2018-01-25 13:38:13 -08:00
3aaf43f73c docs: add changelog for 5.2.2 2018-01-24 21:26:17 -08:00
d952ae24dd release: cut the 5.2.2 release 2018-01-24 21:23:04 -08:00
da9e57b3d5 build: Update to latest rules_typescript. (#21675)
Fixes #21481

PR Close #21675
2018-01-24 20:47:41 -08:00
44d4f82dae docs(aio): added a link to Angular-RU (#21687)
Angular-RU Community on GitHub is a single point for all resources, chats, podcasts and meetups for Angular in Russia

PR Close #21687
2018-01-24 20:47:40 -08:00
bde2b4425c ci: use sudo: false on Travis (#21641)
Related to #21422.

PR Close #21641
2018-01-24 20:47:40 -08:00
2a3de802a0 fix(aio): fix code highlight in API docs templates (#21630)
Fixes #21108

PR Close #21630
2018-01-24 20:47:40 -08:00
71f9eaa743 fix(common): extract plural function from i18n locale data files for TS 2.6 (#21626)
Fixes #21608

PR Close #21626
2018-01-24 20:47:40 -08:00
a62c186d15 fix(common): don't remove special characters when extracting CLDR data (#21626)
PR Close #21626
2018-01-24 20:47:40 -08:00
c8bf281174 build(aio): generate sitemap from the generated pages (#21689)
Closes #21684

PR Close #21689
2018-01-24 20:47:40 -08:00
de6c6445af fix(compiler): Don't strip /*# sourceURL ... */ (#16088)
Currently, `shimCssText` only keep `/*# sourceMappingUrl ... */` comments and strip `/*# sourceURL ... */` comments. So, Chrome can't find the source maps for component style(that's created in new `style` tags)

PR Close #16088
2018-01-24 12:35:31 -08:00
54238822e6 build: merge PR to all branches per target: label (#21739)
PR Close #21739
2018-01-24 12:35:13 -08:00
8b3fbb5bf4 fix(router): don't use ParamsInheritanceStrategy in declarations (#21574)
ParamsInheritanceStrategy is internal, so any references to it from the
published .d.ts files will fail.

Fixes #21456.

PR Close #21574
2018-01-23 21:34:37 -08:00
2f61d3c320 fix(aio): remove remaining plnkr references (#20165)
PR Close #20165
2018-01-23 21:33:55 -08:00
5894f6ee1c build(aio): check for obsolete plnkr.json and missing main files (#20165)
Also, remove `plnkr.json` for `service-worker-getting-started` guide,
since it is not used and ServiceWorker cannot work correctly in
plnkr/stackblitz anyway (e.g. no build step to re-compute hashes).
A zipper might be useful and can be added in a subsequent PR, but it is
currently broken (e.g. no dependency on `@angular/service-worker`).

PR Close #20165
2018-01-23 21:33:55 -08:00
6d9fcd62de build(aio): upgrade sample package.json files to jasmine@~2.8.0 (#20165)
- Update tooling to support revised testing guide (PR #20697).
- Require jasmine upgrade for examples that use marble testing.
- Copy `cli/package.json` to `testing/` and add `jasmine-marbles`.
- Resolve merge conflicts created by `NgModules` guides.

PR Close #20165
2018-01-23 21:33:55 -08:00
0cbccc06dd build(aio): migrate plunker to stackblitz (#20165)
PR Close #20165
2018-01-23 21:33:52 -08:00
ed670a36fb docs: update ICU select messages to use male/female (#21713)
fixes #21694

PR Close #21713
2018-01-23 16:32:24 -08:00
8e44577df3 fix(compiler): fix ICU select messages to use male/female/other (#21713)
related to #21694

PR Close #21713
2018-01-23 16:32:24 -08:00
6921c20ea1 test(forms): Better description and coverage for #19256 (#21652)
fixes #21575

PR Close #21652
2018-01-23 16:31:45 -08:00
52970c09e1 fix(compiler-cli): do not fold errors past calls in the collector (#21708)
Folding errors passed calls prevented the static reflector from
begin able to ignore errors in annotations it doesn't know as
the call to the unknown annotation was elided from the metadata.

Fixes: #21273

PR Close #21708
2018-01-23 13:33:26 -08:00
eecdf3414e docs: fix #19989, add zone flags(blacklist/module) in guide (#21701)
PR Close #21701
2018-01-23 13:33:11 -08:00
21f766968d refactor(bazel): pass around tsconfig as a file, not a path (#21614)
this unlocks the ability to replay ts compilations with different settings

PR Close #21614
2018-01-23 10:06:05 -08:00
4b68fdce6f build: Update to latest rules_typescript. (#21675)
Fixes #21481

PR Close #21675
2018-01-22 15:34:48 -08:00
c12ea3a1f0 fix(common): A null value should remove the style on IE (#21679)
fixes #21064

PR Close #21679
2018-01-22 12:57:23 -08:00
d7dbdc5c36 docs: fix stray div and reformat paragraph (#21676)
PR Close #21676
2018-01-19 20:42:04 -08:00
0112a903f9 ci: add github bot config to triage issues (#21672)
Fixes #21635
PR Close #21672
2018-01-19 20:41:15 -08:00
66bbc84127 ci(aio): do not limit size of gzip7 and gzip 9 (#21601)
PR Close #21601
2018-01-19 20:41:01 -08:00
554129d6fe feat(aio): update metatags to control search engine crawling (#21665)
The `<meta name="robots" content="noindex">` tag is used
to indicate to search engine crawlers that they should not index
the current page. This is set dynamically by the the document
viewer component to ensure that 404 and other erroring pages
are not added to the search index.

This relies upon the idea that the crawling bot will run the JS
and wait to see if this meta tag has been added or not.

Since we believe that the `googebot` will do this, we also
pre-emptively add a hard-coded noindex tag specifically for
this bot, so that if anything else fails in bootstrapping the app,
the failed page will not be added to the index.

Closes #21317

PR Close #21665
2018-01-19 20:31:45 -08:00
e32a0cabfe fix(aio): add a required comma in firebase.json (#21618)
PR Close #21618
2018-01-19 20:31:30 -08:00
c828e5627b build: Remove angular_src nested workspace (#21096)
PR Close #21096
2018-01-19 13:10:09 -08:00
1626e74c59 docs: clarify the use of classes and interfaces in style guide (#20919)
PR Close #20919
2018-01-19 13:09:58 -08:00
a15a2b46d1 ci: add "PR action: cleanup" to the bot's forbiddenLabels list (#21562)
PR Close #21562
2018-01-19 13:09:41 -08:00
379ed75593 docs: improve/simplify example for providers guide (#21589)
PR Close #21589
2018-01-19 13:09:31 -08:00
0f619896b3 docs: fix/improve example for singleton-services guide (#21589)
PR Close #21589
2018-01-19 13:09:31 -08:00
7060655806 docs: several minor NgModule guide fixes/improvements (#21589)
PR Close #21589
2018-01-19 13:09:31 -08:00
b5fc3eb9de docs: minor fixes (anchor tags, redundant whitespace, consistent code-snippets lang) (#21589)
PR Close #21589
2018-01-19 13:09:31 -08:00
451bdb9a75 docs: change titles to sentence case (#21620)
PR Close #21620
2018-01-19 13:09:25 -08:00
983ccc02ad build(aio): fix zips testing commands (#21629)
PR Close #21629
2018-01-19 13:09:17 -08:00
00f99b3c4c ci: update github bot messages (#21634)
Fixes #21633
PR Close #21634
2018-01-19 13:09:11 -08:00
ba4ea82f68 fix(compiler-cli): do not lower expressions in non-modules (#21649)
Fixes: #21651

PR Close #21649
2018-01-19 13:09:04 -08:00
982eb7bba8 fix(common): fallback to last defined value for named date and time formats (#21299)
closes #21282

PR Close #21299
2018-01-19 13:08:57 -08:00
3606c55410 docs: edit entry component FAQ (#21487)
PR Close #21487
2018-01-19 13:08:50 -08:00
2c65027391 docs: add server side redirect and fix NgModule FAQ links (#21487)
PR Close #21487
2018-01-19 13:08:50 -08:00
4ee92f14a6 docs: fix lazy loading example dir name (#21475)
PR Close #21475
2018-01-19 13:08:30 -08:00
c9b65914d3 build: add mhevery to bazel approvers (#21314)
PR Close #21314
2018-01-19 13:08:19 -08:00
02352bcd9e fix(compiler): add support for marker tags in xliff serializers (#21250)
The Xliff serializer now supports the tags `seg-source` and `mrk`, while the Xliff2 serializer now supports `mrk`.
Fixes #21078
PR Close #21250
2018-01-19 13:08:10 -08:00
0d55600fd8 Revert "fix(core): fix chained http call (#20924)"
This reverts commit 54e75766ad.
2018-01-19 13:06:33 -08:00
af4eb00c91 docs: add changelog for 5.2.1 2018-01-17 09:39:46 -08:00
d3e7ebb3b4 release: cut the 5.2.1 release 2018-01-17 09:37:50 -08:00
420f5c4275 build(bazel): remove spurious file (#21455)
PR Close #21455
2018-01-17 08:24:34 -08:00
b773a4ab98 docs(aio): change df-question to app-question (#21438)
closes: #21404
PR Close #21438
2018-01-17 07:20:52 -08:00
55f15c54d9 docs(aio): add description and docs links for code samples (#21561)
PR Close #21561
2018-01-17 07:19:37 -08:00
4556532c26 feat(core): add binding name to content changed error (#20352)
Adding the binding name to the error message recieved by the user gives
extra context on what exactly changed. The tests are also updated to
reflect the new error message.

PR Close #20352
2018-01-17 07:17:00 -08:00
54e75766ad fix(core): fix chained http call (#20924)
Fixes an issue where chained http calls would prematurely call
testability whenStable callbacks after the first http call.

Fixes #20921

PR Close #20924
2018-01-17 07:14:55 -08:00
d3333f04ba refactor(core): refactor WrappedValue (#20997)
- Improve `WrappedValue` by adding `unwrap` symetrical to `wrap`.
- remove dead code - `ValueUnwrapper`

The property `wrapped` is an implementation details and should never be accessed
directly - use `unwrap(wrappedValue)`. Will change to protected in Angular 7.

PR Close #20997
2018-01-16 07:13:24 -08:00
75f8522b8d feat(forms): handle string with and without line boundary on pattern validator (#19256)
PR Close #19256
2018-01-16 07:12:14 -08:00
a771ee5d90 build(aio): move file cleaning to later in the doc gen (#21540)
Previously the generated files were cleaned out before
doc-gen began (via a yarn pre-script). This can cause a
race condition in the CLI server, which prevents the new
generated files from being picked up.

Now we delay the cleaning until the last minute to ensure
that they ar still picked up by the webpack server.

PR Close #21540
2018-01-16 07:11:01 -08:00
a4cbe3542a ci: disable integration/cli-hello-world test (#21492)
it is non-hermetic and breaks often due to unpinned dependencies.

PR Close #21492
2018-01-12 14:57:45 -08:00
cc9419d1ca fix(language-service): Clear caches when program changes (#21337)
This commit fixes a bug whereby the caches are not cleared when the
program changes. This subsequently produces the incorrect error of
'Component ... is not included in a module ...'.

PR Close #19405

PR Close #21337
2018-01-12 14:43:34 -08:00
d5393c7f91 docs(compiler): document the $any type cast function (#20968)
Closes #20966

PR Close #20968
2018-01-12 14:38:42 -08:00
71dd92bbb8 style(aio): enforce strict TypeScript checks (#21342)
Closes #20646

PR Close #21342
2018-01-12 14:37:02 -08:00
977978edb5 test(common): make date pipe tests work in more timezones (#21379)
Fixes #21112
PR Close #21379
2018-01-12 13:50:06 -08:00
eb70966065 fix(aio): correctly handle redirects (#21416)
- Fixes handling of some redirects by the ServiceWorker.
- Fixes redirect for old `NgFor` to new `NgForOf` URL.

Fixes #21318

PR Close #21416
2018-01-12 13:49:10 -08:00
cf4bea587d ci(aio): run e2e tests in production mode (#21470)
This will enable catching errors introduced by build optimizations that
do not appear in `development` mode.

Fixes #21446

PR Close #21470
2018-01-12 13:46:00 -08:00
8e9cd57951 fix(common): set correct timezone for ISO8601 dates in Safari (#21506)
Fixes #21491
PR Close #21506
2018-01-12 13:21:11 -08:00
f23896f519 docs: fix release schedule date (#21474)
PR Close #21474
2018-01-12 12:10:26 -08:00
0e59d18fc2 ci: add angular robot config file (#21489)
PR Close #21489
2018-01-12 10:12:28 -08:00
54c8a321a9 ci: update pullapprove rules now that we allow selfapprovals (#21494)
PR Close #21494
2018-01-12 10:11:37 -08:00
9005a6f3cd feat(aio): implement survey notification link (#21371)
Closes #21094

PR Close #21371
2018-01-12 10:06:08 -08:00
3c6a5063f7 fix(benchpress): should still support selenium_webdriver < 3.6.0 (#21477)
PR Close #21477
2018-01-11 10:54:11 -08:00
b49d54e606 docs(forms): clarify note in reactive forms doc (#21134)
PR Close #21134
2018-01-11 07:04:15 -08:00
55fd82e587 docs: fix release schedule date (#21469)
PR Close #21469
2018-01-11 06:45:49 -08:00
7f3d0bbf97 build: update polyfill size (#21461)
PR Close #21461
2018-01-10 17:07:32 -08:00
3db02d244a docs: fix lazy-loading example (#20306)
PR Close #20306
2018-01-10 16:26:28 -08:00
50b605686e docs: fix yarn.lock (#20306)
PR Close #20306
2018-01-10 16:26:28 -08:00
64d4aafbc7 docs(aio): add NgModule docs (#20306)
PR Close #20306
2018-01-10 16:26:28 -08:00
a931a419fa fix(compiler): make .ngsummary.json files idempotent (#21448)
Fixes: #21432

PR Close #21448
2018-01-10 16:21:32 -08:00
6a97b5b722 docs(ivy): add Ivy as a recognized label (#21428)
PR Close #21428
2018-01-10 15:32:59 -08:00
aad1126446 docs: update the release schedule with v6 info (#21435)
Fixes #20649

PR Close #21435
2018-01-10 15:20:27 -08:00
7b463df52b fix(aio): preserve static Observable methods (#21351)
PR Close #21351
2018-01-10 14:30:42 -08:00
a2432c9f10 build(aio): turn on namedChunks option to make debugging, profiling and tracking easier (#21351)
PR Close #21351
2018-01-10 14:30:42 -08:00
e500484ccc build(aio): upgrade to angular@5.2.0 (#21351)
-rw-r--r--  1 iminar  eng   72498 Jan  9 22:20 dist/0.0d2802b63e9f4f4615cd.chunk.js
-rw-r--r--  1 iminar  eng   14872 Jan  9 22:20 dist/4.c719ac5645940382cdce.chunk.js
-rw-r--r--  1 iminar  eng    1558 Jan  9 22:20 dist/inline.cb4b7a639193fc489d3b.bundle.js
-rw-r--r--  1 iminar  eng  454654 Jan  9 22:20 dist/main.b65f32ffc92e075e64e0.bundle.js
-rw-r--r--  1 iminar  eng   40264 Jan  9 22:20 dist/polyfills.87edf5d695f14a29bf91.bundle.js
-rw-r--r--  1 iminar  eng   54001 Jan  9 22:20 dist/worker-basic.min.js

PR Close #21351
2018-01-10 14:30:42 -08:00
a0dcb0b828 ci(aio): track sizes of all js files (#21351)
PR Close #21351
2018-01-10 14:30:42 -08:00
c4b71920d1 build(aio): upgrade to angular@5.2.0-rc.0 (#21351)
Because of c2b3792 one of the test assertions had to be adjusted (more info: https://github.com/angular/angular/pull/21351#issuecomment-356083940).

PR Close #21351
2018-01-10 14:30:42 -08:00
650f5fb5c7 build(bazel): fix merge conflict between c4f02e2 and ef956a2 (#21453)
PR Close #21453
2018-01-10 12:57:38 -08:00
c32e83334b fix(compiler): cache external reference resolution (#21359)
Cache reference resolution for external references as finding
the declaration of a symbol is expensive and does not change
for a program once created.

This resolves a signficant performance regression in the langauge
service.

PR Close #21359
2018-01-10 12:34:07 -08:00
7bdd9aecbd build: upgrade yarn to 1.3.2 (#21406)
Fixes #20566
PR Close #21406
2018-01-10 12:32:47 -08:00
5ede67c345 build: move repeated tsconfig attributes to a macro (#20964)
This helps ensure we use the same tsconfig.json file for all compilations.
Next steps are to make it the same tsconfig.json file used by the editor

PR Close #20964
2018-01-10 12:30:44 -08:00
31b671ab54 fix(aio): support multibyte character in heading (#21414)
PR Close #21414
2018-01-10 12:25:45 -08:00
3804d20b6d docs(bazel): document an installation issue (#21401)
observed by Igor on a Mac

PR Close #21401
2018-01-10 12:24:03 -08:00
0a5a87887e build(aio): upgrade to uglify-es@3.3.5 (#21350)
This should fix the size regression spotted via the previous commit.

-rw-r--r--  1 iminar  eng   72498 Jan  8 00:03 dist/0.86a7a08f7866e6cdc36f.chunk.js
-rw-r--r--  1 iminar  eng   14872 Jan  8 00:03 dist/4.c719ac5645940382cdce.chunk.js
-rw-r--r--  1 iminar  eng    1558 Jan  8 00:03 dist/inline.7722895d8c844f710bcd.bundle.js
-rw-r--r--  1 iminar  eng  453905 Jan  8 00:03 dist/main.faff0e2da95443f759f5.bundle.js
-rw-r--r--  1 iminar  eng   40264 Jan  8 00:03 dist/polyfills.87edf5d695f14a29bf91.bundle.js
-rw-r--r--  1 iminar  eng   54001 Jan  8 00:03 dist/worker-basic.min.js

PR Close #21350
2018-01-10 12:22:12 -08:00
c46afce0f5 build(aio): upgrade to @angular/cli@1.6.3 (#21350)
This change introduces a size regression of 9kb for main.js :-(

I filed an issue for this: https://github.com/angular/angular-cli/issues/9108

-rw-r--r--  1 iminar  eng   72546 Jan  5 19:27 dist.cli-1.6.3/0.86a7a08f7866e6cdc36f.chunk.js
-rw-r--r--  1 iminar  eng   14893 Jan  5 19:27 dist.cli-1.6.3/4.c719ac5645940382cdce.chunk.js
-rw-r--r--  1 iminar  eng    1558 Jan  5 19:27 dist.cli-1.6.3/inline.7722895d8c844f710bcd.bundle.js
-rw-r--r--  1 iminar  eng  466484 Jan  5 19:27 dist.cli-1.6.3/main.faff0e2da95443f759f5.bundle.js
-rw-r--r--  1 iminar  eng   40363 Jan  5 19:27 dist.cli-1.6.3/polyfills.87edf5d695f14a29bf91.bundle.js
-rw-r--r--  1 iminar  eng   54001 Jan  5 19:27 dist.cli-1.6.3/worker-basic.min.js

PR Close #21350
2018-01-10 12:22:12 -08:00
76c781fd37 docs(router): remove extra brackets (#21294)
PR Close #21294
2018-01-10 12:20:48 -08:00
51eb3d418e fix(service-worker): properly handle invalid hashes in all scenarios (#21288)
When the SW fetches URLs listed in a manifest with hashes, it checks
the content hash against the manifest to make sure it has the correct
version of the URL. In the event of a mismatch, the SW is supposed to
consider the manifest invalid, and avoid using it. There are 3 cases
to consider by which this can happen.

Case 1: during the initial SW installation, a manifest is activated
without waiting for every URL to be fully loaded. In the background,
every prefetch URL listed by the manifest is requested and cached.
One such prefetch request could fail the hash test, and cause the
manifest to be treated as invalid. In such a case, the SW should
enter a state of EXISTING_CLIENTS_ONLY, as the latest manifest is
invalid.

This case works today.

Case 2: during the initial SW installation, as in Case 1, a manifest
is activated without waiting for each URL to fully load. However,
it's possible that the application could request a URL with a bad
hash before background initialization tries to load that URL. This
happens if, for example, the application has a broken index.html.

In this case, the SW should enter a state of EXISTING_CLIENTS_ONLY,
and serve the request from the network instead.

What happens today is that the internal error escapes the SW and
is returned as a rejected Promise to respondWith(), causing a
browser-level error that the site cannot be loaded, breaking the
site.

This change allows the SW to detect the error and enter the correct
state, falling back on the network if needed.

Case 3: during checkForUpdate(), the SW will try to fully cache the
new update before making it the latest version. Failure here is
complicated - if the page fails to load due to transient network
conditions (timeouts, 500s, etc), then it makes sense to continue
serving the existing cached version, and attempt to activate the
update on the next cycle.

If the page fails due to non-transient conditions though (400 error,
hash mismatch, etc), then the SW should consider the updated
manifest invalid, and enter a state of EXISTING_CLIENTS_ONLY.

Currently, all errors are treated as transient.

This change causes the SW to treat all errors during updates as
non-transient, which can cause the SW to unnecessarily enter a
safe mode. A future change can allow the SW to remain in normal mode
if the error is provably transient.

PR Close #21288
2018-01-10 12:18:55 -08:00
48c18985cc fix(animations): fix increment/decrement aliases example (#18323)
PR Close #18323
2018-01-10 12:07:24 -08:00
167cbed266 build: add bazel rulse for benchmarks (#21436)
PR Close #21436
2018-01-10 12:01:17 -08:00
70e8802540 docs(core): provide note for unit test changes with the ng-star-inserted className (#21450)
PR Close #21450
2018-01-10 11:14:28 -08:00
161 changed files with 2589 additions and 14279 deletions

View File

@ -206,12 +206,6 @@ groups:
conditions:
files:
- "packages/forms/*"
- "aio/content/guide/forms.md"
- "aio/content/guide/form-validation.md"
- "aio/content/guide/reactive-forms.md"
- "aio/content/examples/forms/*"
- "aio/content/examples/form-validation/*"
- "aio/content/examples/reactive-forms/*"
users:
- kara #primary
- tinayuangao #secondary

View File

@ -1,14 +1,3 @@
<a name="6.0.0-beta.2"></a>
# [6.0.0-beta.2](https://github.com/angular/angular/compare/6.0.0-beta.1...6.0.0-beta.2) (2018-01-31)
### Features
* **router:** add navigationSource and restoredState to NavigationStart event ([#21728](https://github.com/angular/angular/issues/21728)) ([c40ae7f](https://github.com/angular/angular/commit/c40ae7f))
* **service-worker:** add helper script which will uninstall SW ([#21863](https://github.com/angular/angular/issues/21863)) ([b10540a](https://github.com/angular/angular/commit/b10540a))
<a name="5.2.3"></a>
## [5.2.3](https://github.com/angular/angular/compare/5.2.2...5.2.3) (2018-01-31)
@ -26,32 +15,6 @@
<a name="6.0.0-beta.1"></a>
# [6.0.0-beta.1](https://github.com/angular/angular/compare/6.0.0-beta.0...6.0.0-beta.1) (2018-01-25)
### Bug Fixes
* **common:** A null value should remove the style on IE ([#21679](https://github.com/angular/angular/issues/21679)) ([7d49443](https://github.com/angular/angular/commit/7d49443)), closes [#21064](https://github.com/angular/angular/issues/21064)
* avoid triggering a cli bug ([#21611](https://github.com/angular/angular/issues/21611)) ([0eabd07](https://github.com/angular/angular/commit/0eabd07))
* **common:** don't remove special characters when extracting CLDR data ([#21626](https://github.com/angular/angular/issues/21626)) ([135a282](https://github.com/angular/angular/commit/135a282))
* **common:** extract plural function from i18n locale data files for TS 2.6 ([#21626](https://github.com/angular/angular/issues/21626)) ([97b18b2](https://github.com/angular/angular/commit/97b18b2)), closes [#21608](https://github.com/angular/angular/issues/21608)
* **common:** fallback to last defined value for named date and time formats ([#21299](https://github.com/angular/angular/issues/21299)) ([879756d](https://github.com/angular/angular/commit/879756d)), closes [#21282](https://github.com/angular/angular/issues/21282)
* **compiler:** add support for marker tags in xliff serializers ([#21250](https://github.com/angular/angular/issues/21250)) ([f74130c](https://github.com/angular/angular/commit/f74130c)), closes [#21078](https://github.com/angular/angular/issues/21078)
* **compiler:** Don't strip `/*# sourceURL ... */` ([#16088](https://github.com/angular/angular/issues/16088)) ([5f681f9](https://github.com/angular/angular/commit/5f681f9))
* **compiler:** fix ICU select messages to use male/female/other ([#21713](https://github.com/angular/angular/issues/21713)) ([cb5090c](https://github.com/angular/angular/commit/cb5090c))
* **compiler-cli:** do not fold errors past calls in the collector ([#21708](https://github.com/angular/angular/issues/21708)) ([dd86790](https://github.com/angular/angular/commit/dd86790))
* **compiler-cli:** do not lower expressions in non-modules ([#21649](https://github.com/angular/angular/issues/21649)) ([7f93aad](https://github.com/angular/angular/commit/7f93aad))
* **router:** don't use ParamsInheritanceStrategy in declarations ([#21574](https://github.com/angular/angular/issues/21574)) ([925e654](https://github.com/angular/angular/commit/925e654)), closes [#21456](https://github.com/angular/angular/issues/21456)
### Features
* **compiler:** implement "enableIvy" compiler option ([#21427](https://github.com/angular/angular/issues/21427)) ([64d16de](https://github.com/angular/angular/commit/64d16de))
* **core:** optional generic type for ElementRef ([#20765](https://github.com/angular/angular/issues/20765)) ([d3d9aac](https://github.com/angular/angular/commit/d3d9aac)), closes [#13139](https://github.com/angular/angular/issues/13139)
<a name="5.2.2"></a>
## [5.2.2](https://github.com/angular/angular/compare/5.2.1...5.2.2) (2018-01-25)
@ -71,36 +34,6 @@
<a name="6.0.0-beta.0"></a>
# [6.0.0-beta.0](https://github.com/angular/angular/compare/5.2.0...6.0.0-beta.0) (2018-01-17)
### Bug Fixes
* **animations:** fix increment/decrement aliases example ([#18323](https://github.com/angular/angular/issues/18323)) ([d2aa8ac](https://github.com/angular/angular/commit/d2aa8ac))
* **benchpress:** should still support selenium_webdriver < 3.6.0 ([#21477](https://github.com/angular/angular/issues/21477)) ([9b84a32](https://github.com/angular/angular/commit/9b84a32))
* **common:** set correct timezone for ISO8601 dates in Safari ([#21506](https://github.com/angular/angular/issues/21506)) ([05208b8](https://github.com/angular/angular/commit/05208b8)), closes [#21491](https://github.com/angular/angular/issues/21491)
* **compiler:** cache external reference resolution ([#21359](https://github.com/angular/angular/issues/21359)) ([e3e2fc0](https://github.com/angular/angular/commit/e3e2fc0))
* **compiler:** make `.ngsummary.json` files idempotent ([#21448](https://github.com/angular/angular/issues/21448)) ([e64b1e9](https://github.com/angular/angular/commit/e64b1e9))
* **core:** fix chained http call ([#20924](https://github.com/angular/angular/issues/20924)) ([7e3f9a4](https://github.com/angular/angular/commit/7e3f9a4)), closes [#20921](https://github.com/angular/angular/issues/20921)
* **ivy:** Add workaround for AJD in google3 ([#21488](https://github.com/angular/angular/issues/21488)) ([6af3672](https://github.com/angular/angular/commit/6af3672))
* **language-service:** Clear caches when program changes ([#21337](https://github.com/angular/angular/issues/21337)) ([43e1520](https://github.com/angular/angular/commit/43e1520)), closes [#19405](https://github.com/angular/angular/issues/19405)
* **service-worker:** properly handle invalid hashes in all scenarios ([#21288](https://github.com/angular/angular/issues/21288)) ([3951098](https://github.com/angular/angular/commit/3951098))
### Features
* **bazel:** allow ng_module rules to control whether type checking is enabled ([#21460](https://github.com/angular/angular/issues/21460)) ([cffa0fe](https://github.com/angular/angular/commit/cffa0fe))
* **core:** add binding name to content changed error ([#20352](https://github.com/angular/angular/issues/20352)) ([d3bf54b](https://github.com/angular/angular/commit/d3bf54b))
* **forms:** handle string with and without line boundary on pattern validator ([#19256](https://github.com/angular/angular/issues/19256)) ([54bf179](https://github.com/angular/angular/commit/54bf179))
### Performance Improvements
* **ivy:** add missing dom element in render3_function tree benchmark ([#21476](https://github.com/angular/angular/issues/21476)) ([9b5a485](https://github.com/angular/angular/commit/9b5a485))
<a name="5.2.1"></a>
## [5.2.1](https://github.com/angular/angular/compare/5.2.0...5.2.1) (2018-01-17)

View File

@ -245,16 +245,6 @@ Tells the compiler to generate all the possible generated files even if they are
how `bazel` rules track file dependencies. It is not recommended to use this option outside of the `bazel`
rules.
### *enableIvy*
Tells the compiler to generate definitions using the Render3 style code generation. This option defaults to `false`.
Not all features are supported with this option enabled. It is only supported
for experimentation and testing of Render3 style code generation.
*Note*: Is it not recommended to use this option as it is not yet feature complete with the Render2 code generation.
## Angular Metadata and AOT
The Angular **AOT compiler** extracts and interprets **metadata** about the parts of the application that Angular is supposed to manage.

View File

@ -290,42 +290,20 @@ out of date. Right click the Cache Storage title and refresh the caches.
Stopping and starting the service worker in the Service Worker
pane triggers a check for updates.
## Service Worker Safety
## Fail-safe
Like any complex system, bugs or broken configurations can cause
the Angular service worker to act in unforeseen ways. While its
design attempts to minimize the impact of such problems, the
Angular service worker contains several failsafe mechanisms in case
Angular service worker contains a failsafe mechanism in case
an administrator ever needs to deactivate the service worker quickly.
## Fail-safe
To deactivate the service worker, remove or rename the
`ngsw-config.json` file. When the service worker's request
for `ngsw.json` returns a `404`, then the service worker
removes all of its caches and de-registers itself,
essentially self-destructing.
### Safety Worker
Also included in the `@angular/service-worker` NPM package is a small
script `safety-worker.js`, which when loaded will unregister itself
from the browser. This script can be used as a last resort to get rid
of unwanted service workers already installed on client pages.
It's important to note that you cannot register this worker directly,
as old clients with cached state may not see a new `index.html` which
installs the different worker script. Instead, you must serve the
contents of `safety-worker.js` at the URL of the Service Worker script
you are trying to unregister, and must continue to do so until you are
certain all users have successfully unregistered the old worker. For
most sites, this means that you should serve the safety worker at the
old Service Worker URL forever.
This script can be used both to deactivate `@angular/service-worker`
as well as any other Service Workers which might have been served in
the past on your site.
## More on Angular service workers
You may also be interested in the following:

View File

@ -19,7 +19,7 @@
"routing": {
"index": "/index.html",
"routes": {
"^(?!/docs/ts/latest|/guide/(?:cli-quickstart|metadata|ngmodule|service-worker-(?:getstart|comm|configref))/?$|/styleguide).*/(?!e?plnkr)[^/.]*$": {
"^(?!/docs/.|(?:/guide/(?:cli-quickstart|metadata|ngmodule|service-worker-(?:getstart|comm|configref)|learning-angular)|/news/?)$|/testing|/api/(?:common/NgModel|platform-browser/AnimationDriver|testing|api)).*/(?!e?stackblitz|(?:NgFor|MaxLengthValidator)-|Control(?:Group)?|AnimationStateDeclarationMetadata|CORE_DIRECTIVES|PLATFORM_PIPES|DirectiveMetadata|HTTP_PROVIDERS)[^/.]*$": {
"match": "regex"
}
}

View File

@ -58,7 +58,7 @@ new as of May 2017 and not very stable yet.
- Test all packages: `bazel test packages/...`
You can use [ibazel] to get a "watch mode" that continuously
keeps the outputs up-to-date as you save sources.
keeps the outputs up-to-date as you save sources.
### Debugging a Node Test
@ -68,44 +68,6 @@ keeps the outputs up-to-date as you save sources.
The process should automatically connect to the debugger.
### Debugging a Node Test in VSCode
First time setup:
- Go to Debug > Add configuration (in the menu bar) to open `launch.json`
- Add the following to the `configurations` array:
```
{
"name": "Attach (inspect)",
"type": "node",
"request": "attach",
"port": 9229,
"address": "localhost",
"restart": false,
"sourceMaps": true,
"localRoot": "${workspaceRoot}",
"remoteRoot": null
},
{
"name": "Attach (no-sm,inspect)",
"type": "node",
"request": "attach",
"port": 9229,
"address": "localhost",
"restart": false,
"sourceMaps": false,
"localRoot": "${workspaceRoot}",
"remoteRoot": null
},
```
The easiest way to debug a test for now is to add a `debugger` statement in the code
and launch the bazel corresponding test (`bazel test <target> --config=debug`).
Bazel will wait on a connection. Go to the debug view (by clicking on the sidebar or
Apple+Shift+D on Mac) and click on the green play icon next to the configuration name
(ie `Attach (inspect)`).
### Debugging a Karma Test
- Run test: `bazel run packages/core/test:test_web`

View File

@ -20,15 +20,6 @@ $ ng new cli-hello-world
# typescript version
```
## Render3 tests
The directory `hello_world_cli` contains a test for render3 used with the angular cli.
If the Angular CLI is modified to generate a render3 application this should be replaced with that project.
If the render3 is updated to support the Angular 5 bootstrap a version of this project should be created that
uses the Angular 5 bootstrap.
## Writing an integration test
The API for each test is:

View File

@ -14,28 +14,5 @@
"bundle": 100661
}
}
},
"hello_world__render3__closure": {
"master": {
"uncompressed": {
"bundle": 8153
}
}
},
"hello_world__render3__rollup": {
"master": {
"uncompressed": {
"bundle": 34694
}
}
},
"hello_world__render3__cli": {
"master": {
"uncompressed": {
"inline": 1447,
"main": 40513,
"polyfills": 61085
}
}
}
}
}

View File

@ -1,60 +0,0 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
"name": "hw2"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.css"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"lint": [
{
"project": "src/tsconfig.app.json",
"exclude": "**/node_modules/**"
},
{
"project": "src/tsconfig.spec.json",
"exclude": "**/node_modules/**"
},
{
"project": "e2e/tsconfig.e2e.json",
"exclude": "**/node_modules/**"
}
],
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "css",
"component": {}
}
}

View File

@ -1,27 +0,0 @@
# Hw2
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.7.0-beta.1.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## 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
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

View File

@ -1,14 +0,0 @@
import { AppPage } from './app.po';
describe('hw2 App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to app!');
});
});

View File

@ -1,11 +0,0 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}

View File

@ -1,14 +0,0 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"baseUrl": "./",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

View File

@ -1,33 +0,0 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular/cli'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular/cli/plugins/karma')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};

View File

@ -1,33 +0,0 @@
{
"name": "hello_world__render3__cli",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod --build-optimizer",
"test": "echo no tests",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "file:../../dist/packages-dist/animations",
"@angular/common": "file:../../dist/packages-dist/common",
"@angular/compiler": "file:../../dist/packages-dist/compiler",
"@angular/core": "file:../../dist/packages-dist/core",
"@angular/forms": "file:../../dist/packages-dist/forms",
"@angular/http": "file:../../dist/packages-dist/http",
"@angular/platform-browser": "file:../../dist/packages-dist/platform-browser",
"@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic",
"@angular/router": "file:../../dist/packages-dist/router",
"core-js": "2.4.1",
"rxjs": "5.5.6",
"zone.js": "0.8.19"
},
"devDependencies": {
"@angular/cli": "1.7.0-beta.2",
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
"typescript": "2.6.2"
}
}

View File

@ -1,28 +0,0 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

View File

@ -1,20 +0,0 @@
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<h2>Here are some links to help you start: </h2>
<ul>
<li>
<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://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>
</li>
</ul>

View File

@ -1,27 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
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 app!');
}));
});

View File

@ -1,10 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
}

View File

@ -1,15 +0,0 @@
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@ -1,3 +0,0 @@
export const environment = {
production: true
};

View File

@ -1,8 +0,0 @@
// 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
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -1,14 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hw2</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>

View File

@ -1,4 +0,0 @@
import {ɵrenderComponent as renderComponent} from '@angular/core';
import {AppComponent} from './app/app.component';
renderComponent(AppComponent as any);

View File

@ -1,66 +0,0 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* 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/docs/ts/latest/guide/browser-support.html
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** 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';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';
/** 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';
/**
* 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.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/

View File

@ -1 +0,0 @@
/* You can add global styles to this file, and also import other style files */

View File

@ -1,20 +0,0 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

View File

@ -1,16 +0,0 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"baseUrl": "./",
"module": "es2015",
"types": []
},
"exclude": [
"test.ts",
"**/*.spec.ts"
],
"angularCompilerOptions": {
"enableIvy": true
}
}

View File

@ -1,19 +0,0 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"baseUrl": "./",
"module": "commonjs",
"types": [
"jasmine",
"node"
]
},
"files": [
"test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

View File

@ -1,19 +0,0 @@
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
}
}

View File

@ -1,143 +0,0 @@
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"arrow-return-shorthand": true,
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"deprecation": {
"severity": "warn"
},
"eofline": true,
"forin": true,
"import-blacklist": [
true,
"rxjs",
"rxjs/Rx"
],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-misused-new": true,
"no-non-null-assertion": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unnecessary-initializer": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"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,
"use-host-property-decorator": true,
"no-input-rename": true,
"no-output-rename": true,
"use-life-cycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true
}
}

View File

@ -1,6 +0,0 @@
#!/usr/bin/env bash
# This script replaces 'ngDevMode' by false in @angular/core/render3 source code, so that this code can be eliminated.
# This is a workaround for https://github.com/google/closure-compiler/issues/1601
find built/packages/core/src/render3/* -name '*.js' -exec sed -i '' -e "s/import '.\/ng_dev_mode';//g" {} \;
find built/packages/core/src/render3/* -name '*.js' -exec sed -i '' -e 's/ngDevMode/false/g' {} \;

View File

@ -1,22 +0,0 @@
--compilation_level=ADVANCED_OPTIMIZATIONS
--language_out=ES5
--js_output_file=dist/bundle.js
--output_manifest=dist/manifest.MF
--variable_renaming_report=dist/variable_renaming_report
--property_renaming_report=dist/property_renaming_report
--create_source_map=%outname%.map
--warning_level=QUIET
--dependency_mode=STRICT
--rewrite_polyfills=false
--jscomp_off=checkVars
--module_resolution=node
--package_json_entry_names es2015
--process_common_js_modules
--js built/**.js
--entry_point=built/index
--output_wrapper "%output%
//# sourceMappingURL=bundle.js.map"

View File

@ -1,12 +0,0 @@
import { browser, element, by } from 'protractor';
describe('Hello world E2E Tests', function () {
it('should display: Hello world!', function () {
browser.ignoreSynchronization = true;
browser.get('');
const div = element(by.css('div'));
expect(div.getText()).toEqual('Hello world!');
element(by.css('input')).sendKeys('!');
expect(div.getText()).toEqual('Hello world!!');
});
});

View File

@ -1,15 +0,0 @@
{
"open": false,
"logLevel": "silent",
"port": 8080,
"server": {
"baseDir": "src",
"routes": {
"/dist": "dist",
"/node_modules": "node_modules"
},
"middleware": {
"0": null
}
}
}

View File

@ -1,15 +0,0 @@
exports.config = {
specs: [
'../built/e2e/*.e2e-spec.js'
],
capabilities: {
browserName: 'chrome',
chromeOptions: {
args: ['--no-sandbox'],
binary: process.env.CHROME_BIN,
}
},
directConnect: true,
baseUrl: 'http://localhost:8080/',
framework: 'jasmine'
};

View File

@ -1,8 +0,0 @@
{
"compilerOptions": {
"outDir": "../built/e2e",
"types": ["jasmine"],
// TODO(alexeagle): was required for Protractor 4.0.11
"skipLibCheck": true
}
}

View File

@ -1,24 +0,0 @@
{
"name": "angular-integration",
"version": "0.0.0",
"license": "MIT",
"private": true,
"dependencies": {
"typescript": "file:../../node_modules/typescript"
},
"devDependencies": {
"@types/jasmine": "2.5.41",
"concurrently": "3.4.0",
"lite-server": "2.2.2",
"protractor": "file:../../node_modules/protractor",
"google-closure-compiler": "20171023.0.1"
},
"scripts": {
"postinstall": "webdriver-manager update --gecko false --standalone false $CHROMEDRIVER_VERSION_ARG && mkdir -p built && cp -rf ../../dist/packages ./built/packages && ./clean_ngDevMode.sh",
"closure": "java -jar node_modules/google-closure-compiler/compiler.jar --flagfile closure.conf && mkdir -p dist/packages && cp -rf ../../packages/core dist/packages/core",
"test": "tsc && yarn run closure && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first",
"serve": "lite-server -c e2e/browser.config.json",
"preprotractor": "tsc -p e2e",
"protractor": "protractor e2e/protractor.config.js"
}
}

View File

@ -1,17 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
<base href="/">
</head>
<body>
<hello-world></hello-world>
<script src="dist/bundle.js"></script>
</body>
</html>

View File

@ -1,38 +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 {defineComponent, renderComponent, detectChanges, T, t, E, e, L, p, b, b1} from '../built/packages/core/src/render3';
import {ComponentDef} from '../built/packages/core/src/render3/interfaces/definition';
export class HelloWorld {
name: string = "world";
/** @nocollapse */
static ngComponentDef: ComponentDef<HelloWorld> = defineComponent({
type: HelloWorld,
tag: 'hello-world',
template: function (ctx: HelloWorld, cm: boolean) {
if (cm) {
E(0, 'div');
T(1);
e();
E(2, 'input');
L('input', (e) => {
ctx.name = (<HTMLInputElement>e.target).value;
detectChanges(component);
});
e();
}
t(1, b1('Hello ', ctx.name, '!'));
p(2, 'value', b(ctx.name));
},
factory: () => new HelloWorld()
});
}
const component = renderComponent(HelloWorld);

View File

@ -1,25 +0,0 @@
{
"angularCompilerOptions": {
"annotationsAs": "static fields",
"annotateForClosureCompiler": true,
"alwaysCompileGeneratedCode": true
},
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"strict": true,
"target": "es5",
"noImplicitAny": false,
"sourceMap": false,
"experimentalDecorators": true,
"outDir": "built",
"rootDir": "./src",
"declaration": true,
"types": [],
"lib": ["es2015", "dom"]
},
"files": [
"src/index.ts"
]
}

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
import { browser, element, by } from 'protractor';
describe('Hello world E2E Tests', function () {
it('should display: Hello world!', function () {
browser.ignoreSynchronization = true;
browser.get('');
const div = element(by.css('div'));
expect(div.getText()).toEqual('Hello world!');
element(by.css('input')).sendKeys('!');
expect(div.getText()).toEqual('Hello world!!');
});
});

View File

@ -1,15 +0,0 @@
{
"open": false,
"logLevel": "silent",
"port": 8080,
"server": {
"baseDir": "src",
"routes": {
"/dist": "dist",
"/node_modules": "node_modules"
},
"middleware": {
"0": null
}
}
}

View File

@ -1,15 +0,0 @@
exports.config = {
specs: [
'../built/e2e/*.e2e-spec.js'
],
capabilities: {
browserName: 'chrome',
chromeOptions: {
args: ['--no-sandbox'],
binary: process.env.CHROME_BIN,
}
},
directConnect: true,
baseUrl: 'http://localhost:8080/',
framework: 'jasmine'
};

View File

@ -1,8 +0,0 @@
{
"compilerOptions": {
"outDir": "../built/e2e",
"types": ["jasmine"],
// TODO(alexeagle): was required for Protractor 4.0.11
"skipLibCheck": true
}
}

View File

@ -1,36 +0,0 @@
{
"name": "angular-integration",
"version": "0.0.0",
"license": "MIT",
"private": true,
"dependencies": {
"@angular/animations": "file:../../dist/packages-dist/animations",
"@angular/common": "file:../../dist/packages-dist/common",
"@angular/compiler": "file:../../dist/packages-dist/compiler",
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
"@angular/core": "file:../../dist/packages-dist/core",
"@angular/platform-browser": "file:../../dist/packages-dist/platform-browser",
"@angular/platform-server": "file:../../dist/packages-dist/platform-server",
"rxjs": "file:../../node_modules/rxjs",
"typescript": "file:../../node_modules/typescript"
},
"devDependencies": {
"@types/jasmine": "2.5.41",
"concurrently": "3.4.0",
"lite-server": "2.2.2",
"protractor": "file:../../node_modules/protractor",
"rollup": "0.54.0",
"rollup-plugin-angular-optimizer": "0.2.0",
"rollup-plugin-commonjs": "8.2.6",
"rollup-plugin-node-resolve": "3.0.2",
"rollup-plugin-uglify": "2.0.1"
},
"scripts": {
"postinstall": "webdriver-manager update --gecko false --standalone false $CHROMEDRIVER_VERSION_ARG",
"rollup": "tsc && rollup -c rollup.config.js",
"test": "yarn run rollup && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first",
"serve": "lite-server -c e2e/browser.config.json",
"preprotractor": "tsc -p e2e",
"protractor": "protractor e2e/protractor.config.js"
}
}

View File

@ -1,30 +0,0 @@
import buildOptimizer from 'rollup-plugin-angular-optimizer'
import commonjs from 'rollup-plugin-commonjs';
import nodeResolve from 'rollup-plugin-node-resolve';
import uglify from 'rollup-plugin-uglify';
export default {
input: `built/index.js`,
output: {
name: 'hw',
file: `dist/bundle.js`,
format: 'iife',
sourcemap: true
},
plugins: [
buildOptimizer(),
nodeResolve({jsnext: true, module: true}),
commonjs({
include: 'node_modules/rxjs/**'
}),
uglify({
mangle: true,
compress: {
global_defs: {
'ngDevMode': false,
}
}
})
],
external: []
}

View File

@ -1,17 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
<base href="/">
</head>
<body>
<hello-world></hello-world>
<script src="dist/bundle.js"></script>
</body>
</html>

View File

@ -1,38 +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 {ɵdefineComponent as defineComponent, ɵdetectChanges as detectChanges, ɵrenderComponent as renderComponent, ɵT as T, ɵt as t, ɵE as E, ɵe as e, ɵp as p, ɵL as L, ɵb as b, ɵb1 as b1} from '@angular/core';
import {ComponentDef} from '@angular/core/src/render3/interfaces/definition';
export class HelloWorld {
name: string = "world";
/** @nocollapse */
static ngComponentDef: ComponentDef<HelloWorld> = defineComponent({
type: HelloWorld,
tag: 'hello-world',
template: function (ctx: HelloWorld, cm: boolean) {
if (cm) {
E(0, 'div');
T(1);
e();
E(2, 'input');
L('input', (e) => {
ctx.name = (<HTMLInputElement>e.target).value;
detectChanges(component);
});
e();
}
t(1, b1('Hello ', ctx.name, '!'));
p(2, 'value', b(ctx.name));
},
factory: () => new HelloWorld()
});
}
const component = renderComponent(HelloWorld);

View File

@ -1,25 +0,0 @@
{
"angularCompilerOptions": {
"annotationsAs": "static fields",
"annotateForClosureCompiler": true,
"alwaysCompileGeneratedCode": true
},
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"strict": true,
"target": "es5",
"noImplicitAny": false,
"sourceMap": true,
"experimentalDecorators": true,
"outDir": "built",
"rootDir": "./src",
"declaration": true,
"types": [],
"lib": ["es2015", "dom"]
},
"files": [
"src/index.ts"
]
}

File diff suppressed because it is too large Load Diff

View File

@ -24,8 +24,7 @@
"scripts": {
"postinstall": "webdriver-manager update --gecko false --standalone false $CHROMEDRIVER_VERSION_ARG",
"closure": "java -jar node_modules/google-closure-compiler/compiler.jar --flagfile closure.conf",
"test": "ngc && yarn run closure && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first && npm run test-locale-folder",
"test-locale-folder": "node test-locale-folder.js",
"test": "ngc && yarn run closure && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first",
"serve": "lite-server -c e2e/browser.config.json",
"preprotractor": "tsc -p e2e",
"protractor": "protractor e2e/protractor.config.js"

View File

@ -1,14 +0,0 @@
const fs = require('fs');
const path = require('path');
const packageJson = require('@angular/common/package.json');
const localesFolder = packageJson['locales'];
if (!localesFolder) {
throw new Error(`@angular/common/package.json does not contain 'locales' entry.`)
}
const enLocalePath = `@angular/common/${localesFolder}/en`;
try {
require.resolve(enLocalePath);
} catch (err) {
throw new Error(`@angular/common does not contain 'en' locale in ${enLocalePath}.`)
}

View File

@ -19,7 +19,7 @@ rm_cache
mkdir $cache
trap rm_cache EXIT
for testDir in $(ls | grep -Ev 'node_modules|render3') ; do
for testDir in $(ls | grep -v node_modules) ; do
[[ -d "$testDir" ]] || continue
echo "#################################"
echo "Running integration test $testDir"
@ -29,19 +29,15 @@ for testDir in $(ls | grep -Ev 'node_modules|render3') ; do
rm -rf dist
yarn install --cache-folder ../$cache
yarn test || exit 1
# Track payload size for cli-hello-world and hello_world__closure and the render3 tests
if [[ $testDir == cli-hello-world ]] || [[ $testDir == hello_world__closure ]] || [[ $testDir == hello_world__render3__closure ]] || [[ $testDir == hello_world__render3__rollup ]] || [[ $testDir == hello_world__render3__cli ]]; then
if [[ $testDir == cli-hello-world ]] || [[ $testDir == hello_world__render3__cli ]]; then
# Track payload size for cli-hello-world and hello_world__closure
if [[ $testDir == cli-hello-world ]] || [[ $testDir == hello_world__closure ]]; then
if [[ $testDir == cli-hello-world ]]; then
yarn build
fi
if [[ -v TRAVIS ]]; then
trackPayloadSize "$testDir" "dist/*.js" true false "${thisDir}/_payload-limits.json"
fi
fi
if [[ -v TRAVIS ]]; then
# remove the temporary node modules directory to save space.
rm -rf node_modules
fi
)
done

View File

@ -59,7 +59,6 @@ module.exports = function(config) {
'dist/all/@angular/benchpress/**',
'dist/all/@angular/compiler-cli/**',
'dist/all/@angular/compiler/test/aot/**',
'dist/all/@angular/compiler/test/render3/**',
'dist/all/@angular/examples/**/e2e_test/*',
'dist/all/@angular/language-service/**',
'dist/all/@angular/router/test/**',

View File

@ -23,7 +23,6 @@ describe('tree benchmark perf', () => {
Benchmarks.forEach(benchmark => {
describe(benchmark.id, () => {
// This is actually a destroyOnly benchmark
it('should work for createOnly', (done) => {
runTreeBenchmark({
id: 'createOnly',
@ -33,15 +32,6 @@ describe('tree benchmark perf', () => {
}).then(done, done.fail);
});
it('should work for createOnlyForReal', (done) => {
runTreeBenchmark({
id: 'createOnlyForReal',
benchmark,
prepare: () => $(DestroyBtn).click(),
work: () => $(CreateBtn).click()
}).then(done, done.fail);
});
it('should work for createDestroy', (done) => {
runTreeBenchmark({
id: 'createDestroy',

View File

@ -26,8 +26,6 @@
</div>
<script>
// TODO(mlaval): remove once we have a proper solution
ngDevMode = false;
var mainUrl = window.location.search.split(/[?&]main=([^&]+)/)[1]
|| '../../bootstrap_ng2.js';
document.write('<script src="' + mainUrl + '">\u003c/script>');

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ɵC as C, ɵE as E, ɵT as T, ɵV as V, ɵb as b, ɵcR as cR, ɵcr as cr, ɵdefineComponent as defineComponent, ɵdetectChanges as detectChanges, ɵe as e, ɵs as s, ɵt as t, ɵv as v} from '@angular/core';
import {ComponentDef} from '@angular/core/src/render3/interfaces/definition';
import {ɵC as C, ɵE as E, ɵT as T, ɵV as V, ɵb as b, ɵc as c, ɵcR as cR, ɵcr as cr, ɵdefineComponent as defineComponent, ɵdetectChanges as detectChanges, ɵe as e, ɵs as s, ɵt as t, ɵv as v} from '@angular/core';
import {ComponentDef} from '@angular/core/src/render3/definition_interfaces';
import {TableCell, buildTable, emptyTable} from '../util';
@ -23,7 +23,10 @@ export class LargeTableComponent {
E(0, 'table');
{
E(1, 'tbody');
{ C(2); }
{
C(2);
c();
}
e();
}
e();
@ -36,6 +39,7 @@ export class LargeTableComponent {
if (cm1) {
E(0, 'tr');
C(1);
c();
e();
}
cR(1);

View File

@ -28,8 +28,6 @@
</div>
<script>
// TODO(mlaval): remove once we have a proper solution
ngDevMode = false;
var mainUrl = window.location.search.split(/[?&]main=([^&]+)/)[1]
|| '../../bootstrap_ng2.js';
document.write('<script src="' + mainUrl + '">\u003c/script>');

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ɵC as C, ɵE as E, ɵT as T, ɵV as V, ɵb as b, ɵb1 as b1, ɵcR as cR, ɵcr as cr, ɵdefineComponent as defineComponent, ɵdetectChanges as _detectChanges, ɵe as e, ɵp as p, ɵr as r, ɵs as s, ɵt as t, ɵv as v} from '@angular/core';
import {ComponentDef} from '@angular/core/src/render3/interfaces/definition';
import {ɵC as C, ɵD as D, ɵE as E, ɵT as T, ɵV as V, ɵb as b, ɵb1 as b1, ɵc as c, ɵcR as cR, ɵcr as cr, ɵdefineComponent as defineComponent, ɵdetectChanges as _detectChanges, ɵe as e, ɵp as p, ɵs as s, ɵt as t, ɵv as v} from '@angular/core';
import {ComponentDef} from '@angular/core/src/render3/definition_interfaces';
import {TreeNode, buildTree, emptyTree} from '../util';
@ -44,7 +44,9 @@ export class TreeComponent {
{ T(1); }
e();
C(2);
c();
C(3);
c();
}
s(0, 'background-color', b(ctx.data.depth % 2 ? '' : 'grey'));
t(1, b1(' ', ctx.data.value, ' '));
@ -54,12 +56,13 @@ export class TreeComponent {
let cm0 = V(0);
{
if (cm0) {
E(0, TreeComponent);
E(0, TreeComponent.ngComponentDef);
{ D(1, TreeComponent.ngComponentDef.n(), TreeComponent.ngComponentDef); }
e();
}
p(0, 'data', b(ctx.data.left));
TreeComponent.ngComponentDef.h(1, 0);
r(1, 0);
TreeComponent.ngComponentDef.r(1, 0);
}
v();
}
@ -71,12 +74,13 @@ export class TreeComponent {
let cm0 = V(0);
{
if (cm0) {
E(0, TreeComponent);
E(0, TreeComponent.ngComponentDef);
{ D(1, TreeComponent.ngComponentDef.n(), TreeComponent.ngComponentDef); }
e();
}
p(0, 'data', b(ctx.data.right));
TreeComponent.ngComponentDef.h(1, 0);
r(1, 0);
TreeComponent.ngComponentDef.r(1, 0);
}
v();
}
@ -88,7 +92,7 @@ export class TreeComponent {
});
}
export class TreeFunction {
export class TreeFunction extends TreeComponent {
data: TreeNode = emptyTree;
/** @nocollapse */
@ -106,19 +110,17 @@ export class TreeFunction {
export function TreeTpl(ctx: TreeNode, cm: boolean) {
if (cm) {
E(0, 'tree');
{
E(1, 'span');
{ T(2); }
e();
C(3);
C(4);
}
E(0, 'span');
{ T(1); }
e();
C(2);
c();
C(3);
c();
}
s(1, 'background-color', b(ctx.depth % 2 ? '' : 'grey'));
t(2, b1(' ', ctx.value, ' '));
cR(3);
s(0, 'background-color', b(ctx.depth % 2 ? '' : 'grey'));
t(1, b1(' ', ctx.value, ' '));
cR(2);
{
if (ctx.left != null) {
let cm0 = V(0);
@ -127,7 +129,7 @@ export function TreeTpl(ctx: TreeNode, cm: boolean) {
}
}
cr();
cR(4);
cR(3);
{
if (ctx.right != null) {
let cm0 = V(0);

View File

@ -28,8 +28,6 @@
</div>
<script>
// TODO(mlaval): remove once we have a proper solution
ngDevMode = false;
var mainUrl = window.location.search.split(/[?&]main=([^&]+)/)[1]
|| '../../bootstrap_ng2.js';
document.write('<script src="' + mainUrl + '">\u003c/script>');

View File

@ -1,7 +1,6 @@
{
"name": "angular-srcs",
"version": "TODO this should be 6.0.0-beta.0, workaround",
"version": "6.0.0-beta.2",
"version": "5.2.3",
"private": true,
"branchPattern": "2.0.*",
"description": "Angular - a web framework for modern web apps",

View File

@ -74,7 +74,6 @@ def _ngc_tsconfig(ctx, files, srcs, **kwargs):
"generateCodeForLibraries": False,
"allowEmptyCodegenFiles": True,
"enableSummariesForJit": True,
"fullTemplateTypeCheck": ctx.attr.type_check,
# FIXME: wrong place to de-dupe
"expectedOut": depset([o.path for o in expected_outs]).to_list(),
"preserveWhitespaces": False,
@ -264,8 +263,6 @@ NG_MODULE_ATTRIBUTES = {
".html",
]),
"type_check": attr.bool(default = True),
"no_i18n": attr.bool(default = False),
"compiler": attr.label(

View File

@ -11,7 +11,6 @@
"dependencies": {
"tslib": "^1.7.1"
},
"locales": "locales",
"peerDependencies": {
"rxjs": "^5.5.0",
"@angular/core": "0.0.0-PLACEHOLDER"

View File

@ -14,7 +14,6 @@ import {LocationStrategy} from './location_strategy';
/** @experimental */
export interface PopStateEvent {
pop?: boolean;
state?: any;
type?: string;
url?: string;
}
@ -57,7 +56,6 @@ export class Location {
this._subject.emit({
'url': this.path(true),
'pop': true,
'state': ev.state,
'type': ev.type,
});
});
@ -105,16 +103,16 @@ export class Location {
* Changes the browsers URL to the normalized version of the given URL, and pushes a
* new item onto the platform's history.
*/
go(path: string, query: string = '', state: any = null): void {
this._platformStrategy.pushState(state, '', path, query);
go(path: string, query: string = ''): void {
this._platformStrategy.pushState(null, '', path, query);
}
/**
* Changes the browsers URL to the normalized version of the given URL, and replaces
* the top item on the platform's history stack.
*/
replaceState(path: string, query: string = '', state: any = null): void {
this._platformStrategy.replaceState(state, '', path, query);
replaceState(path: string, query: string = ''): void {
this._platformStrategy.replaceState(null, '', path, query);
}
/**

View File

@ -58,10 +58,7 @@ export const LOCATION_INITIALIZED = new InjectionToken<Promise<any>>('Location I
*
* @experimental
*/
export interface LocationChangeEvent {
type: string;
state: any;
}
export interface LocationChangeEvent { type: string; }
/**
* @experimental

View File

@ -19,7 +19,7 @@ import {ISubscription} from 'rxjs/Subscription';
@Injectable()
export class SpyLocation implements Location {
urlChanges: string[] = [];
private _history: LocationState[] = [new LocationState('', '', null)];
private _history: LocationState[] = [new LocationState('', '')];
private _historyIndex: number = 0;
/** @internal */
_subject: EventEmitter<any> = new EventEmitter();
@ -34,8 +34,6 @@ export class SpyLocation implements Location {
path(): string { return this._history[this._historyIndex].path; }
private state(): string { return this._history[this._historyIndex].state; }
isCurrentPathEqualTo(path: string, query: string = ''): boolean {
const givenPath = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
const currPath =
@ -62,13 +60,13 @@ export class SpyLocation implements Location {
return this._baseHref + url;
}
go(path: string, query: string = '', state: any = null) {
go(path: string, query: string = '') {
path = this.prepareExternalUrl(path);
if (this._historyIndex > 0) {
this._history.splice(this._historyIndex + 1);
}
this._history.push(new LocationState(path, query, state));
this._history.push(new LocationState(path, query));
this._historyIndex = this._history.length - 1;
const locationState = this._history[this._historyIndex - 1];
@ -81,7 +79,7 @@ export class SpyLocation implements Location {
this._subject.emit({'url': url, 'pop': false});
}
replaceState(path: string, query: string = '', state: any = null) {
replaceState(path: string, query: string = '') {
path = this.prepareExternalUrl(path);
const history = this._history[this._historyIndex];
@ -91,7 +89,6 @@ export class SpyLocation implements Location {
history.path = path;
history.query = query;
history.state = state;
const url = path + (query.length > 0 ? ('?' + query) : '');
this.urlChanges.push('replace: ' + url);
@ -100,14 +97,14 @@ export class SpyLocation implements Location {
forward() {
if (this._historyIndex < (this._history.length - 1)) {
this._historyIndex++;
this._subject.emit({'url': this.path(), 'state': this.state(), 'pop': true});
this._subject.emit({'url': this.path(), 'pop': true});
}
}
back() {
if (this._historyIndex > 0) {
this._historyIndex--;
this._subject.emit({'url': this.path(), 'state': this.state(), 'pop': true});
this._subject.emit({'url': this.path(), 'pop': true});
}
}
@ -121,5 +118,10 @@ export class SpyLocation implements Location {
}
class LocationState {
constructor(public path: string, public query: string, public state: any) {}
path: string;
query: string;
constructor(path: string, query: string) {
this.path = path;
this.query = query;
}
}

View File

@ -38,8 +38,6 @@ export function isNgDiagnostic(diagnostic: any): diagnostic is Diagnostic {
}
export interface CompilerOptions extends ts.CompilerOptions {
// NOTE: These comments and aio/content/guides/aot-compiler.md should be kept in sync.
// Write statistics about compilation (e.g. total time, ...)
// Note: this is the --diagnostics command line option from TS (which is @internal
// on ts.CompilerOptions interface).
@ -161,17 +159,6 @@ export interface CompilerOptions extends ts.CompilerOptions {
*/
enableSummariesForJit?: boolean;
/**
* Tells the compiler to generate definitions using the Render3 style code generation.
* This option defaults to `false`.
*
* Not all features are supported with this option enabled. It is only supported
* for experimentation and testing of Render3 style code generation.
*
* @experimental
*/
enableIvy?: boolean;
/** @internal */
collectAllErrors?: boolean;
}

View File

@ -6,9 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AssertNotNull, BinaryOperator, BinaryOperatorExpr, BuiltinMethod, BuiltinVar, CastExpr, ClassMethod, ClassStmt, CommaExpr, CommentStmt, CompileIdentifierMetadata, ConditionalExpr, DeclareFunctionStmt, DeclareVarStmt, ExpressionStatement, ExpressionVisitor, ExternalExpr, ExternalReference, FunctionExpr, IfStmt, InstantiateExpr, InvokeFunctionExpr, InvokeMethodExpr, LiteralArrayExpr, LiteralExpr, LiteralMapExpr, NotExpr, ParseSourceFile, ParseSourceSpan, PartialModule, ReadKeyExpr, ReadPropExpr, ReadVarExpr, ReturnStatement, Statement, StatementVisitor, StaticSymbol, StmtModifier, ThrowStmt, TryCatchStmt, WriteKeyExpr, WritePropExpr, WriteVarExpr} from '@angular/compiler';
import {AssertNotNull, BinaryOperator, BinaryOperatorExpr, BuiltinMethod, BuiltinVar, CastExpr, ClassStmt, CommaExpr, CommentStmt, CompileIdentifierMetadata, ConditionalExpr, DeclareFunctionStmt, DeclareVarStmt, ExpressionStatement, ExpressionVisitor, ExternalExpr, ExternalReference, FunctionExpr, IfStmt, InstantiateExpr, InvokeFunctionExpr, InvokeMethodExpr, LiteralArrayExpr, LiteralExpr, LiteralMapExpr, NotExpr, ParseSourceFile, ParseSourceSpan, ReadKeyExpr, ReadPropExpr, ReadVarExpr, ReturnStatement, Statement, StatementVisitor, StaticSymbol, StmtModifier, ThrowStmt, TryCatchStmt, WriteKeyExpr, WritePropExpr, WriteVarExpr} from '@angular/compiler';
import * as ts from 'typescript';
import {error} from './util';
export interface Node { sourceSpan: ParseSourceSpan|null; }
@ -30,10 +29,10 @@ export class TypeScriptNodeEmitter {
const commentStmt = this.createCommentStatement(sourceFile, preamble);
preambleStmts.push(commentStmt);
}
const sourceStatements =
const sourceStatments =
[...preambleStmts, ...converter.getReexports(), ...converter.getImports(), ...statements];
converter.updateSourceMap(sourceStatements);
const newSourceFile = ts.updateSourceFileNode(sourceFile, sourceStatements);
converter.updateSourceMap(sourceStatments);
const newSourceFile = ts.updateSourceFileNode(sourceFile, sourceStatments);
return [newSourceFile, converter.getNodeMap()];
}
@ -51,99 +50,7 @@ export class TypeScriptNodeEmitter {
}
}
/**
* Update the given source file to include the changes specified in module.
*
* The module parameter is treated as a partial module meaning that the statements are added to
* the module instead of replacing the module. Also, any classes are treated as partial classes
* and the included members are added to the class with the same name instead of a new class
* being created.
*/
export function updateSourceFile(
sourceFile: ts.SourceFile, module: PartialModule,
context: ts.TransformationContext): [ts.SourceFile, Map<ts.Node, Node>] {
const converter = new _NodeEmitterVisitor();
const prefixStatements = module.statements.filter(statement => !(statement instanceof ClassStmt));
const classes =
module.statements.filter(statement => statement instanceof ClassStmt) as ClassStmt[];
const classMap = new Map(
classes.map<[string, ClassStmt]>(classStatement => [classStatement.name, classStatement]));
const classNames = new Set(classes.map(classStatement => classStatement.name));
const prefix =
<ts.Statement[]>prefixStatements.map(statement => statement.visitStatement(converter, null));
// Add static methods to all the classes referenced in module.
let newStatements = sourceFile.statements.map(node => {
if (node.kind == ts.SyntaxKind.ClassDeclaration) {
const classDeclaration = node as ts.ClassDeclaration;
const name = classDeclaration.name;
if (name) {
const classStatement = classMap.get(name.text);
if (classStatement) {
classNames.delete(name.text);
const classMemberHolder =
converter.visitDeclareClassStmt(classStatement) as ts.ClassDeclaration;
const newMethods =
classMemberHolder.members.filter(member => member.kind !== ts.SyntaxKind.Constructor);
const newMembers = [...classDeclaration.members, ...newMethods];
return ts.updateClassDeclaration(
classDeclaration,
/* decorators */ classDeclaration.decorators,
/* modifiers */ classDeclaration.modifiers,
/* name */ classDeclaration.name,
/* typeParameters */ classDeclaration.typeParameters,
/* heritageClauses */ classDeclaration.heritageClauses || [],
/* members */ newMembers);
}
}
}
return node;
});
// Validate that all the classes have been generated
classNames.size == 0 ||
error(
`${classNames.size == 1 ? 'Class' : 'Classes'} "${Array.from(classNames.keys()).join(', ')}" not generated`);
// Add imports to the module required by the new methods
const imports = converter.getImports();
if (imports && imports.length) {
// Find where the new imports should go
const index = firstAfter(
newStatements, statement => statement.kind === ts.SyntaxKind.ImportDeclaration ||
statement.kind === ts.SyntaxKind.ImportEqualsDeclaration);
newStatements =
[...newStatements.slice(0, index), ...imports, ...prefix, ...newStatements.slice(index)];
} else {
newStatements = [...prefix, ...newStatements];
}
converter.updateSourceMap(newStatements);
const newSourceFile = ts.updateSourceFileNode(sourceFile, newStatements);
return [newSourceFile, converter.getNodeMap()];
}
// Return the index after the first value in `a` that doesn't match the predicate after a value that
// does or 0 if no values match.
function firstAfter<T>(a: T[], predicate: (value: T) => boolean) {
let index = 0;
const len = a.length;
for (; index < len; index++) {
const value = a[index];
if (predicate(value)) break;
}
if (index >= len) return 0;
for (; index < len; index++) {
const value = a[index];
if (!predicate(value)) break;
}
return index;
}
// A recorded node is a subtype of the node that is marked as being recorded. This is used
// A recorded node is a subtype of the node that is marked as being recoreded. This is used
// to ensure that NodeEmitterVisitor.record has been called on all nodes returned by the
// NodeEmitterVisitor
type RecordedNode<T extends ts.Node = ts.Node> = (T & { __recorded: any; }) | null;
@ -325,12 +232,9 @@ class _NodeEmitterVisitor implements StatementVisitor, ExpressionVisitor {
const modifiers = this.getModifiers(stmt);
const fields = stmt.fields.map(
field => ts.createProperty(
/* decorators */ undefined, /* modifiers */ translateModifiers(field.modifiers),
field.name,
/* decorators */ undefined, /* modifiers */ undefined, field.name,
/* questionToken */ undefined,
/* type */ undefined,
field.initializer == null ? ts.createNull() :
field.initializer.visitExpression(this, null)));
/* type */ undefined, ts.createNull()));
const getters = stmt.getters.map(
getter => ts.createGetAccessor(
/* decorators */ undefined, /* modifiers */ undefined, getter.name, /* parameters */[],
@ -352,8 +256,7 @@ class _NodeEmitterVisitor implements StatementVisitor, ExpressionVisitor {
const methods = stmt.methods.filter(method => method.name)
.map(
method => ts.createMethod(
/* decorators */ undefined,
/* modifiers */ translateModifiers(method.modifiers),
/* decorators */ undefined, /* modifiers */ undefined,
/* astriskToken */ undefined, method.name !/* guarded by filter */,
/* questionToken */ undefined, /* typeParameters */ undefined,
method.params.map(
@ -498,8 +401,7 @@ class _NodeEmitterVisitor implements StatementVisitor, ExpressionVisitor {
visitFunctionExpr(expr: FunctionExpr) {
return this.record(
expr, ts.createFunctionExpression(
/* modifiers */ undefined, /* astriskToken */ undefined,
/* name */ expr.name || undefined,
/* modifiers */ undefined, /* astriskToken */ undefined, /* name */ undefined,
/* typeParameters */ undefined,
expr.params.map(
p => ts.createParameter(
@ -645,21 +547,3 @@ function getMethodName(methodRef: {name: string | null; builtin: BuiltinMethod |
}
throw new Error('Unexpected method reference form');
}
function modifierFromModifier(modifier: StmtModifier): ts.Modifier {
switch (modifier) {
case StmtModifier.Exported:
return ts.createToken(ts.SyntaxKind.ExportKeyword);
case StmtModifier.Final:
return ts.createToken(ts.SyntaxKind.ConstKeyword);
case StmtModifier.Private:
return ts.createToken(ts.SyntaxKind.PrivateKeyword);
case StmtModifier.Static:
return ts.createToken(ts.SyntaxKind.StaticKeyword);
}
return error(`unknown statement modifier`);
}
function translateModifiers(modifiers: StmtModifier[] | null): ts.Modifier[]|undefined {
return modifiers == null ? undefined : modifiers !.map(modifierFromModifier);
}

View File

@ -1,4 +1,3 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
@ -7,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AotCompiler, AotCompilerHost, AotCompilerOptions, EmitterVisitorContext, FormattedMessageChain, GeneratedFile, MessageBundle, NgAnalyzedFile, NgAnalyzedModules, ParseSourceSpan, PartialModule, Position, Serializer, TypeScriptEmitter, Xliff, Xliff2, Xmb, core, createAotCompiler, getParseErrors, isFormattedError, isSyntaxError} from '@angular/compiler';
import {AotCompiler, AotCompilerHost, AotCompilerOptions, EmitterVisitorContext, FormattedMessageChain, GeneratedFile, MessageBundle, NgAnalyzedFile, NgAnalyzedModules, ParseSourceSpan, Position, Serializer, TypeScriptEmitter, Xliff, Xliff2, Xmb, core, createAotCompiler, getParseErrors, isFormattedError, isSyntaxError} from '@angular/compiler';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
@ -19,8 +18,7 @@ import {CompilerHost, CompilerOptions, CustomTransformers, DEFAULT_ERROR_CODE, D
import {CodeGenerator, TsCompilerAotCompilerTypeCheckHostAdapter, getOriginalReferences} from './compiler_host';
import {LowerMetadataCache, getExpressionLoweringTransformFactory} from './lower_expressions';
import {getAngularEmitterTransformFactory} from './node_emitter_transform';
import {getAngularClassTransformerFactory} from './r3_transform';
import {GENERATED_FILES, StructureIsReused, createMessageDiagnostic, isInRootDir, ngToTsDiagnostic, tsStructureIsReused, userError} from './util';
import {GENERATED_FILES, StructureIsReused, createMessageDiagnostic, isInRootDir, ngToTsDiagnostic, tsStructureIsReused} from './util';
/**
@ -67,10 +65,9 @@ class AngularCompilerProgram implements Program {
private host: CompilerHost, oldProgram?: Program) {
this.rootNames = [...rootNames];
const [major, minor] = ts.version.split('.');
Number(major) > 2 || (Number(major) === 2 && Number(minor) >= 4) ||
userError('The Angular Compiler requires TypeScript >= 2.4.');
if (Number(major) < 2 || (Number(major) === 2 && Number(minor) < 4)) {
throw new Error('The Angular Compiler requires TypeScript >= 2.4.');
}
this.oldTsProgram = oldProgram ? oldProgram.getTsProgram() : undefined;
if (oldProgram) {
this.oldProgramLibrarySummaries = oldProgram.getLibrarySummaries();
@ -82,6 +79,8 @@ class AngularCompilerProgram implements Program {
const {host: bundleHost, indexName, errors} =
createBundleIndexHost(options, this.rootNames, host);
if (errors) {
// TODO(tbosch): once we move MetadataBundler from tsc_wrapped into compiler_cli,
// directly create ng.Diagnostic instead of using ts.Diagnostic here.
this._optionsDiagnostics.push(...errors.map(e => ({
category: e.category,
messageText: e.messageText as string,
@ -197,55 +196,7 @@ class AngularCompilerProgram implements Program {
return this.compiler.listLazyRoutes(route, route ? undefined : this.analyzedModules);
}
emit(parameters: {
emitFlags?: EmitFlags,
cancellationToken?: ts.CancellationToken,
customTransformers?: CustomTransformers,
emitCallback?: TsEmitCallback
} = {}): ts.EmitResult {
return this.options.enableIvy === true ? this._emitRender3(parameters) :
this._emitRender2(parameters);
}
private _emitRender3(
{emitFlags = EmitFlags.Default, cancellationToken, customTransformers,
emitCallback = defaultEmitCallback}: {
emitFlags?: EmitFlags,
cancellationToken?: ts.CancellationToken,
customTransformers?: CustomTransformers,
emitCallback?: TsEmitCallback
} = {}): ts.EmitResult {
const emitStart = Date.now();
if ((emitFlags & (EmitFlags.JS | EmitFlags.DTS | EmitFlags.Metadata | EmitFlags.Codegen)) ===
0) {
return {emitSkipped: true, diagnostics: [], emittedFiles: []};
}
const modules = this.compiler.emitAllPartialModules(this.analyzedModules);
const writeTsFile: ts.WriteFileCallback =
(outFileName, outData, writeByteOrderMark, onError?, sourceFiles?) => {
const sourceFile = sourceFiles && sourceFiles.length == 1 ? sourceFiles[0] : null;
let genFile: GeneratedFile|undefined;
this.writeFile(outFileName, outData, writeByteOrderMark, onError, undefined, sourceFiles);
};
const emitOnlyDtsFiles = (emitFlags & (EmitFlags.DTS | EmitFlags.JS)) == EmitFlags.DTS;
const tsCustomTansformers = this.calculateTransforms(
/* genFiles */ undefined, /* partialModules */ modules, customTransformers);
const emitResult = emitCallback({
program: this.tsProgram,
host: this.host,
options: this.options,
writeFile: writeTsFile, emitOnlyDtsFiles,
customTransformers: tsCustomTansformers
});
return emitResult;
}
private _emitRender2(
emit(
{emitFlags = EmitFlags.Default, cancellationToken, customTransformers,
emitCallback = defaultEmitCallback}: {
emitFlags?: EmitFlags,
@ -293,8 +244,7 @@ class AngularCompilerProgram implements Program {
}
this.writeFile(outFileName, outData, writeByteOrderMark, onError, genFile, sourceFiles);
};
const tsCustomTansformers = this.calculateTransforms(
genFileByFileName, /* partialModules */ undefined, customTransformers);
const tsCustomTansformers = this.calculateTransforms(genFileByFileName, customTransformers);
const emitOnlyDtsFiles = (emitFlags & (EmitFlags.DTS | EmitFlags.JS)) == EmitFlags.DTS;
// Restore the original references before we emit so TypeScript doesn't emit
// a reference to the .d.ts file.
@ -450,18 +400,13 @@ class AngularCompilerProgram implements Program {
}
private calculateTransforms(
genFiles: Map<string, GeneratedFile>|undefined, partialModules: PartialModule[]|undefined,
genFiles: Map<string, GeneratedFile>,
customTransformers?: CustomTransformers): ts.CustomTransformers {
const beforeTs: ts.TransformerFactory<ts.SourceFile>[] = [];
if (!this.options.disableExpressionLowering) {
beforeTs.push(getExpressionLoweringTransformFactory(this.metadataCache, this.tsProgram));
}
if (genFiles) {
beforeTs.push(getAngularEmitterTransformFactory(genFiles, this.getTsProgram()));
}
if (partialModules) {
beforeTs.push(getAngularClassTransformerFactory(partialModules));
}
beforeTs.push(getAngularEmitterTransformFactory(genFiles, this.getTsProgram()));
if (customTransformers && customTransformers.beforeTs) {
beforeTs.push(...customTransformers.beforeTs);
}

View File

@ -1,36 +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 {PartialModule, Statement, StaticSymbol} from '@angular/compiler';
import * as ts from 'typescript';
import {updateSourceFile} from './node_emitter';
export type Transformer = (sourceFile: ts.SourceFile) => ts.SourceFile;
export type TransformerFactory = (context: ts.TransformationContext) => Transformer;
/**
* Returns a transformer that adds the requested static methods specified by modules.
*/
export function getAngularClassTransformerFactory(modules: PartialModule[]): TransformerFactory {
if (modules.length === 0) {
// If no modules are specified, just return an identity transform.
return () => sf => sf;
}
const moduleMap = new Map(modules.map<[string, PartialModule]>(m => [m.fileName, m]));
return function(context: ts.TransformationContext) {
return function(sourceFile: ts.SourceFile): ts.SourceFile {
const module = moduleMap.get(sourceFile.fileName);
if (module) {
const [newSourceFile] = updateSourceFile(sourceFile, module, context);
return newSourceFile;
}
return sourceFile;
};
};
}

View File

@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {syntaxError} from '@angular/compiler';
import * as path from 'path';
import * as ts from 'typescript';
@ -22,14 +21,6 @@ export function tsStructureIsReused(program: ts.Program): StructureIsReused {
return (program as any).structureIsReused;
}
export function error(msg: string): never {
throw new Error(`Internal error: ${msg}`);
}
export function userError(msg: string): never {
throw syntaxError(msg);
}
export function createMessageDiagnostic(messageText: string): ts.Diagnostic&Diagnostic {
return {
file: undefined,

View File

@ -13,9 +13,7 @@ export type Entry = string | Directory;
export interface Directory { [name: string]: Entry; }
export class MockAotContext {
private files: Entry[];
constructor(public currentDirectory: string, ...files: Entry[]) { this.files = files; }
constructor(public currentDirectory: string, private files: Entry) {}
fileExists(fileName: string): boolean { return typeof this.getEntry(fileName) === 'string'; }
@ -55,7 +53,19 @@ export class MockAotContext {
}
parts.shift();
parts = normalize(parts);
return first(this.files, files => getEntryFromFiles(parts, files));
let current = this.files;
while (parts.length) {
const part = parts.shift() !;
if (typeof current === 'string') {
return undefined;
}
const next = (<Directory>current)[part];
if (next === undefined) {
return undefined;
}
current = next;
}
return current;
}
getDirectories(path: string): string[] {
@ -66,31 +76,6 @@ export class MockAotContext {
return Object.keys(dir).filter(key => typeof dir[key] === 'object');
}
}
override(files: Entry) { return new MockAotContext(this.currentDirectory, files, ...this.files); }
}
function first<T>(a: T[], cb: (value: T) => T | undefined): T|undefined {
for (const value of a) {
const result = cb(value);
if (result != null) return result;
}
}
function getEntryFromFiles(parts: string[], files: Entry) {
let current = files;
while (parts.length) {
const part = parts.shift() !;
if (typeof current === 'string') {
return undefined;
}
const next = (<Directory>current)[part];
if (next === undefined) {
return undefined;
}
current = next;
}
return current;
}
function normalize(parts: string[]): string[] {

View File

@ -898,12 +898,12 @@ describe('ngc transformer command-line', () => {
export * from './util';
// Note: the lambda will be lowered into an exported expression
// Note: the lamda will be lowered into an exported expression
@NgModule({providers: [{provide: 'aToken', useValue: () => 2}]})
export class MyModule {}
`);
write('util.ts', `
// Note: The lambda will be lowered into an exported expression
// Note: The lamda will be lowered into an exported expression
const x = () => 2;
export const y = x;
@ -1144,7 +1144,7 @@ describe('ngc transformer command-line', () => {
shouldExist('app/main.js');
});
it('should be able to compile libraries with summaries and flat modules', () => {
it('shoud be able to compile libraries with summaries and flat modules', () => {
writeFiles();
compile();
@ -1466,7 +1466,7 @@ describe('ngc transformer command-line', () => {
`);
}));
it('should recompile when the html file changes',
it('should recomiple when the html file changes',
expectRecompile(() => { write('greet.html', '<p> Hello {{name}} again!</p>'); }));
it('should recompile when the css file changes',
@ -1841,105 +1841,4 @@ describe('ngc transformer command-line', () => {
`);
});
});
describe('ivy', () => {
function emittedFile(name: string): string {
const outputName = path.resolve(outDir, name);
expect(fs.existsSync(outputName)).toBe(true);
return fs.readFileSync(outputName, {encoding: 'UTF-8'});
}
it('should emit the hello world example', () => {
write('tsconfig.json', `{
"extends": "./tsconfig-base.json",
"files": ["hello-world.ts"],
"angularCompilerOptions": {
"enableIvy": true
}
}`);
write('hello-world.ts', `
import {Component, NgModule} from '@angular/core';
@Component({
selector: 'hello-world',
template: 'Hello, world!'
})
export class HelloWorldComponent {
}
@NgModule({
declarations: [HelloWorldComponent]
})
export class HelloWorldModule {}
`);
const exitCode = main(['-p', path.join(basePath, 'tsconfig.json')]);
expect(exitCode).toBe(0, 'Compile failed');
expect(emittedFile('hello-world.js')).toContain('ngComponentDef');
});
it('should emit an injection of a string token', () => {
write('tsconfig.json', `{
"extends": "./tsconfig-base.json",
"files": ["hello-world.ts"],
"angularCompilerOptions": {
"enableIvy": true
}
}`);
write('hello-world.ts', `
import {Component, Inject, NgModule} from '@angular/core';
@Component({
selector: 'hello-world',
template: 'Hello, world!'
})
export class HelloWorldComponent {
constructor (@Inject('test') private test: string) {}
}
@NgModule({
declarations: [HelloWorldComponent],
providers: [
{provide: 'test', useValue: 'test'}
]
})
export class HelloWorldModule {}
`);
const errors: string[] = [];
const exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], msg => errors.push(msg));
expect(exitCode).toBe(0, `Compile failed:\n${errors.join('\n ')}`);
expect(emittedFile('hello-world.js')).toContain('ngComponentDef');
});
it('should emit an example that uses the E() instruction', () => {
write('tsconfig.json', `{
"extends": "./tsconfig-base.json",
"files": ["hello-world.ts"],
"angularCompilerOptions": {
"enableIvy": true
}
}`);
write('hello-world.ts', `
import {Component, NgModule} from '@angular/core';
@Component({
selector: 'hello-world',
template: '<h1><div style="text-align:center"> Hello, {{name}}! </div></h1> '
})
export class HelloWorldComponent {
name = 'World';
}
@NgModule({declarations: [HelloWorldComponent]})
export class HelloWorldModule {}
`);
const errors: string[] = [];
const exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], msg => errors.push(msg));
expect(exitCode).toBe(0, `Compile failed:\n${errors.join('\n ')}`);
expect(emittedFile('hello-world.js')).toContain('ngComponentDef');
});
});
});

View File

@ -1,163 +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 {PartialModule} from '@angular/compiler';
import * as o from '@angular/compiler/src/output/output_ast';
import {MockAotCompilerHost} from 'compiler/test/aot/test_util';
import {initDomAdapter} from 'platform-browser/src/browser';
import * as ts from 'typescript';
import {getAngularClassTransformerFactory} from '../../src/transformers/r3_transform';
import {Directory, MockAotContext, MockCompilerHost} from '../mocks';
const someGenFilePath = '/somePackage/someGenFile';
const someGenFileName = someGenFilePath + '.ts';
describe('r3_transform_spec', () => {
let context: MockAotContext;
let host: MockCompilerHost;
beforeEach(() => {
context = new MockAotContext('/', FILES);
host = new MockCompilerHost(context);
});
it('should be able to generate a simple identity function', () => {
expect(emitStaticMethod(new o.ReturnStatement(o.variable('v')), ['v']))
.toContain('static someMethod(v) { return v; }');
});
it('should be able to generate a static field declaration',
() => { expect(emitStaticField(o.literal(10))).toContain('SomeClass.someField = 10'); });
it('should be able to import a symbol', () => {
expect(emitStaticMethod(new o.ReturnStatement(
o.importExpr(new o.ExternalReference('@angular/core', 'Component')))))
.toContain('static someMethod() { return i0.Component; } }');
});
it('should be able to modify multiple classes in the same module', () => {
const result = emit(getAngularClassTransformerFactory([{
fileName: someGenFileName,
statements: [
classMethod(new o.ReturnStatement(o.variable('v')), ['v'], 'someMethod', 'SomeClass'),
classMethod(
new o.ReturnStatement(o.variable('v')), ['v'], 'someOtherMethod', 'SomeOtherClass')
]
}]));
expect(result).toContain('static someMethod(v) { return v; }');
expect(result).toContain('static someOtherMethod(v) { return v; }');
});
it('should insert imports after existing imports', () => {
context = context.override({
somePackage: {
'someGenFile.ts': `
import {Component} from '@angular/core';
@Component({selector: 'some-class', template: 'hello!'})
export class SomeClass {}
export class SomeOtherClass {}
`
}
});
host = new MockCompilerHost(context);
expect(emitStaticMethod(new o.ReturnStatement(
o.importExpr(new o.ExternalReference('@angular/core', 'Component')))))
.toContain('const core_1 = require("@angular/core"); const i0 = require("@angular/core");');
});
function emit(factory: ts.TransformerFactory<ts.SourceFile>): string {
let result: string = '';
const program = ts.createProgram(
[someGenFileName], {module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017}, host);
const moduleSourceFile = program.getSourceFile(someGenFileName);
const transformers: ts.CustomTransformers = {before: [factory]};
const emitResult = program.emit(
moduleSourceFile, (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
if (fileName.startsWith(someGenFilePath)) {
result = data;
}
}, undefined, undefined, transformers);
return normalizeResult(result);
}
function emitStaticMethod(
stmt: o.Statement | o.Statement[], parameters: string[] = [],
methodName: string = 'someMethod', className: string = 'SomeClass'): string {
const module: PartialModule = {
fileName: someGenFileName,
statements: [classMethod(stmt, parameters, methodName, className)]
};
return emit(getAngularClassTransformerFactory([module]));
}
function emitStaticField(
initializer: o.Expression, fieldName: string = 'someField',
className: string = 'SomeClass'): string {
const module: PartialModule = {
fileName: someGenFileName,
statements: [classField(initializer, fieldName, className)]
};
return emit(getAngularClassTransformerFactory([module]));
}
});
const FILES: Directory = {
somePackage: {
'someGenFile.ts': `
export class SomeClass {}
export class SomeOtherClass {}
`
}
};
function classMethod(
stmt: o.Statement | o.Statement[], parameters: string[] = [], methodName: string = 'someMethod',
className: string = 'SomeClass'): o.ClassStmt {
const statements = Array.isArray(stmt) ? stmt : [stmt];
return new o.ClassStmt(
/* name */ className,
/* parent */ null,
/* fields */[],
/* getters */[],
/* constructorMethod */ new o.ClassMethod(null, [], []),
/* methods */[new o.ClassMethod(
methodName, parameters.map(name => new o.FnParam(name)), statements, null,
[o.StmtModifier.Static])]);
}
function classField(
initializer: o.Expression, fieldName: string = 'someField',
className: string = 'SomeClass'): o.ClassStmt {
return new o.ClassStmt(
/* name */ className,
/* parent */ null,
/* fields */[new o.ClassField(fieldName, null, [o.StmtModifier.Static], initializer)],
/* getters */[],
/* constructorMethod */ new o.ClassMethod(null, [], []),
/* methods */[]);
}
function normalizeResult(result: string): string {
// Remove TypeScript prefixes
// Remove new lines
// Squish adjacent spaces
// Remove prefix and postfix spaces
return result.replace('"use strict";', ' ')
.replace('exports.__esModule = true;', ' ')
.replace('Object.defineProperty(exports, "__esModule", { value: true });', ' ')
.replace(/\n/g, ' ')
.replace(/ +/g, ' ')
.replace(/^ /g, '')
.replace(/ $/g, '');
}

View File

@ -8,7 +8,6 @@
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileStylesheetMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, componentFactoryName, flatten, identifierName, templateSourceUrl, tokenReference} from '../compile_metadata';
import {CompilerConfig} from '../config';
import {ConstantPool} from '../constant_pool';
import {ViewEncapsulation} from '../core';
import {MessageBundle} from '../i18n/message_bundle';
import {Identifiers, createTokenForExternalReference} from '../identifiers';
@ -19,12 +18,11 @@ import {NgModuleCompiler} from '../ng_module_compiler';
import {OutputEmitter} from '../output/abstract_emitter';
import * as o from '../output/output_ast';
import {ParseError} from '../parse_util';
import {compileComponent as compileIvyComponent, compileDirective as compileIvyDirective} from '../render3/r3_view_compiler';
import {CompiledStylesheet, StyleCompiler} from '../style_compiler';
import {SummaryResolver} from '../summary_resolver';
import {TemplateAst} from '../template_parser/template_ast';
import {TemplateParser} from '../template_parser/template_parser';
import {OutputContext, ValueVisitor, error, syntaxError, visitValue} from '../util';
import {OutputContext, ValueVisitor, syntaxError, visitValue} from '../util';
import {TypeCheckCompiler} from '../view_compiler/type_check_compiler';
import {ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler';
@ -32,7 +30,6 @@ import {AotCompilerHost} from './compiler_host';
import {AotCompilerOptions} from './compiler_options';
import {GeneratedFile} from './generated_file';
import {LazyRoute, listLazyRoutes, parseLazyRoute} from './lazy_routes';
import {PartialModule} from './partial_module';
import {StaticReflector} from './static_reflector';
import {StaticSymbol} from './static_symbol';
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
@ -307,47 +304,6 @@ export class AotCompiler {
return messageBundle;
}
emitAllPartialModules({ngModuleByPipeOrDirective, files}: NgAnalyzedModules): PartialModule[] {
// Using reduce like this is a select many pattern (where map is a select pattern)
return files.reduce<PartialModule[]>((r, file) => {
r.push(...this._emitPartialModule(
file.fileName, ngModuleByPipeOrDirective, file.directives, file.pipes, file.ngModules,
file.injectables));
return r;
}, []);
}
private _emitPartialModule(
fileName: string, ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
directives: StaticSymbol[], pipes: StaticSymbol[], ngModules: CompileNgModuleMetadata[],
injectables: StaticSymbol[]): PartialModule[] {
const classes: o.ClassStmt[] = [];
const context = this._createOutputContext(fileName);
// Process all components and directives
directives.forEach(directiveType => {
const directiveMetadata = this._metadataResolver.getDirectiveMetadata(directiveType);
if (directiveMetadata.isComponent) {
const module = ngModuleByPipeOrDirective.get(directiveType) !;
module ||
error(
`Cannot determine the module for component '${identifierName(directiveMetadata.type)}'`);
const {template: parsedTemplate} =
this._parseTemplate(directiveMetadata, module, module.transitiveModule.directives);
compileIvyComponent(context, directiveMetadata, parsedTemplate, this._reflector);
} else {
compileIvyDirective(context, directiveMetadata, this._reflector);
}
});
if (context.statements) {
return [{fileName, statements: [...context.constantPool.statements, ...context.statements]}];
}
return [];
}
emitAllImpls(analyzeResult: NgAnalyzedModules): GeneratedFile[] {
const {ngModuleByPipeOrDirective, files} = analyzeResult;
const sourceModules = files.map(
@ -591,7 +547,7 @@ export class AotCompiler {
new o.ExternalReference(moduleName, name, null), allTypeParams));
};
return {statements: [], genFilePath, importExpr, constantPool: new ConstantPool()};
return {statements: [], genFilePath, importExpr};
}
private _fileNameToModuleName(importedFilePath: string, containingFilePath: string): string {

View File

@ -1,14 +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 o from '../output/output_ast';
export interface PartialModule {
fileName: string;
statements: o.Statement[];
}

View File

@ -36,7 +36,6 @@ export * from './aot/generated_file';
export * from './aot/compiler_options';
export * from './aot/compiler_host';
export * from './aot/formatted_error';
export * from './aot/partial_module';
export * from './aot/static_reflector';
export * from './aot/static_symbol';
export * from './aot/static_symbol_resolver';
@ -67,7 +66,7 @@ export * from './ml_parser/html_tags';
export * from './ml_parser/interpolation_config';
export * from './ml_parser/tags';
export {NgModuleCompiler} from './ng_module_compiler';
export {AssertNotNull, BinaryOperator, BinaryOperatorExpr, BuiltinMethod, BuiltinVar, CastExpr, ClassMethod, ClassStmt, CommaExpr, CommentStmt, ConditionalExpr, DeclareFunctionStmt, DeclareVarStmt, ExpressionStatement, ExpressionVisitor, ExternalExpr, ExternalReference, FunctionExpr, IfStmt, InstantiateExpr, InvokeFunctionExpr, InvokeMethodExpr, LiteralArrayExpr, LiteralExpr, LiteralMapExpr, NotExpr, ReadKeyExpr, ReadPropExpr, ReadVarExpr, ReturnStatement, StatementVisitor, ThrowStmt, TryCatchStmt, WriteKeyExpr, WritePropExpr, WriteVarExpr, StmtModifier, Statement, collectExternalReferences} from './output/output_ast';
export {AssertNotNull, BinaryOperator, BinaryOperatorExpr, BuiltinMethod, BuiltinVar, CastExpr, ClassStmt, CommaExpr, CommentStmt, ConditionalExpr, DeclareFunctionStmt, DeclareVarStmt, ExpressionStatement, ExpressionVisitor, ExternalExpr, ExternalReference, FunctionExpr, IfStmt, InstantiateExpr, InvokeFunctionExpr, InvokeMethodExpr, LiteralArrayExpr, LiteralExpr, LiteralMapExpr, NotExpr, ReadKeyExpr, ReadPropExpr, ReadVarExpr, ReturnStatement, StatementVisitor, ThrowStmt, TryCatchStmt, WriteKeyExpr, WritePropExpr, WriteVarExpr, StmtModifier, Statement, collectExternalReferences} from './output/output_ast';
export {EmitterVisitorContext} from './output/abstract_emitter';
export * from './output/ts_emitter';
export * from './parse_util';

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as cdAst from '../expression_parser/ast';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
@ -18,15 +19,13 @@ export class ConvertActionBindingResult {
constructor(public stmts: o.Statement[], public allowDefault: o.ReadVarExpr) {}
}
export type InterpolationFunction = (args: o.Expression[]) => o.Expression;
/**
* Converts the given expression AST into an executable output AST, assuming the expression is
* used in an action binding (e.g. an event handler).
*/
export function convertActionBinding(
localResolver: LocalResolver | null, implicitReceiver: o.Expression, action: cdAst.AST,
bindingId: string, interpolationFunction?: InterpolationFunction): ConvertActionBindingResult {
bindingId: string): ConvertActionBindingResult {
if (!localResolver) {
localResolver = new DefaultLocalResolver();
}
@ -53,8 +52,7 @@ export function convertActionBinding(
},
action);
const visitor =
new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, interpolationFunction);
const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId);
const actionStmts: o.Statement[] = [];
flattenStatements(actionWithoutBuiltins.visit(visitor, _Mode.Statement), actionStmts);
prependTemporaryDecls(visitor.temporaryCount, bindingId, actionStmts);
@ -100,7 +98,6 @@ export enum BindingForm {
// otherise generate a general binding
TrySimple,
}
/**
* Converts the given expression AST into an executable output AST, assuming the expression
* is used in property binding. The expression has to be preprocessed via
@ -108,15 +105,14 @@ export enum BindingForm {
*/
export function convertPropertyBinding(
localResolver: LocalResolver | null, implicitReceiver: o.Expression,
expressionWithoutBuiltins: cdAst.AST, bindingId: string, form: BindingForm,
interpolationFunction?: InterpolationFunction): ConvertPropertyBindingResult {
expressionWithoutBuiltins: cdAst.AST, bindingId: string,
form: BindingForm): ConvertPropertyBindingResult {
if (!localResolver) {
localResolver = new DefaultLocalResolver();
}
const currValExpr = createCurrValueExpr(bindingId);
const stmts: o.Statement[] = [];
const visitor =
new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, interpolationFunction);
const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId);
const outputExpr: o.Expression = expressionWithoutBuiltins.visit(visitor, _Mode.Expression);
if (visitor.temporaryCount) {
@ -204,7 +200,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
constructor(
private _localResolver: LocalResolver, private _implicitReceiver: o.Expression,
private bindingId: string, private interpolationFunction: InterpolationFunction|undefined) {}
private bindingId: string) {}
visitBinary(ast: cdAst.Binary, mode: _Mode): any {
let op: o.BinaryOperator;
@ -307,9 +303,6 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
}
args.push(o.literal(ast.strings[ast.strings.length - 1]));
if (this.interpolationFunction) {
return this.interpolationFunction(args);
}
return ast.expressions.length <= 9 ?
o.importExpr(Identifiers.inlineInterpolate).callFn(args) :
o.importExpr(Identifiers.interpolate).callFn([args[0], o.literalArr(args.slice(1))]);

View File

@ -1,154 +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 o from './output/output_ast';
import {OutputContext, error} from './util';
const CONSTANT_PREFIX = '_c';
export const enum DefinitionKind {Injector, Directive, Component}
/**
* A node that is a place-holder that allows the node to be replaced when the actual
* node is known.
*
* This allows the constant pool to change an expression from a direct reference to
* a constant to a shared constant. It returns a fix-up node that is later allowed to
* change the referenced expression.
*/
class FixupExpression extends o.Expression {
constructor(public resolved: o.Expression) { super(resolved.type); }
shared: boolean;
visitExpression(visitor: o.ExpressionVisitor, context: any): any {
return this.resolved.visitExpression(visitor, context);
}
isEquivalent(e: o.Expression): boolean {
return e instanceof FixupExpression && this.resolved.isEquivalent(e.resolved);
}
fixup(expression: o.Expression) {
this.resolved = expression;
this.shared = true;
}
}
/**
* A constant pool allows a code emitter to share constant in an output context.
*
* The constant pool also supports sharing access to ivy definitions references.
*/
export class ConstantPool {
statements: o.Statement[] = [];
private literals = new Map<string, FixupExpression>();
private injectorDefinitions = new Map<any, FixupExpression>();
private directiveDefinitions = new Map<any, FixupExpression>();
private componentDefinitions = new Map<any, FixupExpression>();
private nextNameIndex = 0;
getConstLiteral(literal: o.Expression, forceShared?: boolean): o.Expression {
const key = this.keyOf(literal);
let fixup = this.literals.get(key);
let newValue = false;
if (!fixup) {
fixup = new FixupExpression(literal);
this.literals.set(key, fixup);
newValue = true;
}
if ((!newValue && !fixup.shared) || (newValue && forceShared)) {
// Replace the expression with a variable
const name = this.freshName();
this.statements.push(
o.variable(name).set(literal).toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final]));
fixup.fixup(o.variable(name));
}
return fixup;
}
getDefinition(type: any, kind: DefinitionKind, ctx: OutputContext): o.Expression {
const declarations = kind == DefinitionKind.Component ?
this.componentDefinitions :
kind == DefinitionKind.Directive ? this.directiveDefinitions : this.injectorDefinitions;
let fixup = declarations.get(type);
if (!fixup) {
const property = kind == DefinitionKind.Component ?
'ngComponentDef' :
kind == DefinitionKind.Directive ? 'ngDirectiveDef' : 'ngInjectorDef';
fixup = new FixupExpression(ctx.importExpr(type).prop(property));
declarations.set(type, fixup);
} else if (!fixup.shared) {
const name = this.freshName();
this.statements.push(
o.variable(name).set(fixup.resolved).toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final]));
fixup.fixup(o.variable(name));
}
return fixup;
}
/**
* Produce a unique name.
*
* The name might be unique among different prefixes if any of the prefixes end in
* a digit so the prefix should be a constant string (not based on user input) and
* must not end in a digit.
*/
uniqueName(prefix: string): string { return `${prefix}${this.nextNameIndex++}`; }
private freshName(): string { return this.uniqueName(CONSTANT_PREFIX); }
private keyOf(expression: o.Expression) {
return expression.visitExpression(new KeyVisitor(), null);
}
}
class KeyVisitor implements o.ExpressionVisitor {
visitLiteralExpr(ast: o.LiteralExpr): string {
return `${typeof ast.value === 'string' ? '"' + ast.value + '"' : ast.value}`;
}
visitLiteralArrayExpr(ast: o.LiteralArrayExpr): string {
return `[${ast.entries.map(entry => entry.visitExpression(this, null)).join(',')}]`;
}
visitLiteralMapExpr(ast: o.LiteralMapExpr): string {
const mapEntry = (entry: o.LiteralMapEntry) =>
`${entry.key}:${entry.value.visitExpression(this, null)}`;
return `{${ast.entries.map(mapEntry).join(',')}`;
}
visitExternalExpr(ast: o.ExternalExpr): string {
return ast.value.moduleName ? `EX:${ast.value.moduleName}:${ast.value.name}` :
`EX:${ast.value.runtime.name}`;
}
visitReadVarExpr = invalid;
visitWriteVarExpr = invalid;
visitWriteKeyExpr = invalid;
visitWritePropExpr = invalid;
visitInvokeMethodExpr = invalid;
visitInvokeFunctionExpr = invalid;
visitInstantiateExpr = invalid;
visitConditionalExpr = invalid;
visitNotExpr = invalid;
visitAssertNotNullExpr = invalid;
visitCastExpr = invalid;
visitFunctionExpr = invalid;
visitBinaryOperatorExpr = invalid;
visitReadPropExpr = invalid;
visitReadKeyExpr = invalid;
visitCommaExpr = invalid;
}
function invalid<T>(arg: o.Expression | o.Statement): never {
throw new Error(
`Invalid state: Visitor ${this.constructor.name} doesn't handle ${o.constructor.name}`);
}

View File

@ -9,7 +9,6 @@
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeSummary, CompileProviderMetadata, CompileStylesheetMetadata, CompileTypeSummary, ProviderMeta, ProxyClass, identifierName, ngModuleJitUrl, sharedStylesheetJitUrl, templateJitUrl, templateSourceUrl} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector';
import {CompilerConfig} from '../config';
import {ConstantPool} from '../constant_pool';
import {Type} from '../core';
import {CompileMetadataResolver} from '../metadata_resolver';
import {NgModuleCompiler} from '../ng_module_compiler';
@ -356,5 +355,5 @@ function assertComponent(meta: CompileDirectiveMetadata) {
function createOutputContext(): OutputContext {
const importExpr = (symbol: any) =>
ir.importExpr({name: identifierName(symbol), moduleName: null, runtime: symbol});
return {statements: [], genFilePath: '', importExpr, constantPool: new ConstantPool()};
return {statements: [], genFilePath: '', importExpr};
}

View File

@ -107,7 +107,7 @@ export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
return null;
}
visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any {
ctx.print(ast, `function${ast.name ? ' ' + ast.name : ''}(`);
ctx.print(ast, `function(`);
this._visitParams(ast.params, ctx);
ctx.println(ast, `) {`);
ctx.incIndent();

View File

@ -8,7 +8,6 @@
import {ParseSourceSpan} from '../parse_util';
import {error} from '../util';
//// Types
export enum TypeModifier {
@ -41,7 +40,7 @@ export class BuiltinType extends Type {
super(modifiers);
}
visitType(visitor: TypeVisitor, context: any): any {
return visitor.visitBuiltinType(this, context);
return visitor.visitBuiltintType(this, context);
}
}
@ -79,7 +78,7 @@ export const STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
export const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);
export interface TypeVisitor {
visitBuiltinType(type: BuiltinType, context: any): any;
visitBuiltintType(type: BuiltinType, context: any): any;
visitExpressionType(type: ExpressionType, context: any): any;
visitArrayType(type: ArrayType, context: any): any;
visitMapType(type: MapType, context: any): any;
@ -487,7 +486,7 @@ export class FnParam {
export class FunctionExpr extends Expression {
constructor(
public params: FnParam[], public statements: Statement[], type?: Type|null,
sourceSpan?: ParseSourceSpan|null, public name?: string|null) {
sourceSpan?: ParseSourceSpan|null) {
super(type, sourceSpan);
}
isEquivalent(e: Expression): boolean {
@ -645,8 +644,7 @@ export const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null);
export enum StmtModifier {
Final,
Private,
Exported,
Static,
Exported
}
export abstract class Statement {
@ -741,9 +739,7 @@ export class AbstractClassPart {
}
export class ClassField extends AbstractClassPart {
constructor(
public name: string, type?: Type|null, modifiers: StmtModifier[]|null = null,
public initializer?: Expression) {
constructor(public name: string, type?: Type|null, modifiers: StmtModifier[]|null = null) {
super(type, modifiers);
}
isEquivalent(f: ClassField) { return this.name === f.name; }
@ -1088,7 +1084,7 @@ export class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor
}
return ast;
}
visitBuiltinType(type: BuiltinType, context: any): any { return this.visitType(type, context); }
visitBuiltintType(type: BuiltinType, context: any): any { return this.visitType(type, context); }
visitExpressionType(type: ExpressionType, context: any): any {
type.value.visitExpression(this, context);
return this.visitType(type, context);
@ -1369,13 +1365,9 @@ export function assertNotNull(
}
export function fn(
params: FnParam[], body: Statement[], type?: Type | null, sourceSpan?: ParseSourceSpan | null,
name?: string | null): FunctionExpr {
return new FunctionExpr(params, body, type, sourceSpan, name);
}
export function ifStmt(condition: Expression, thenClause: Statement[], elseClause?: Statement[]) {
return new IfStmt(condition, thenClause, elseClause);
params: FnParam[], body: Statement[], type?: Type | null,
sourceSpan?: ParseSourceSpan | null): FunctionExpr {
return new FunctionExpr(params, body, type, sourceSpan);
}
export function literal(

View File

@ -40,9 +40,9 @@ export type ReferenceFilter = (reference: o.ExternalReference) => boolean;
export class TypeScriptEmitter implements OutputEmitter {
emitStatementsAndContext(
genFilePath: string, stmts: o.Statement[], preamble: string = '',
emitSourceMaps: boolean = true, referenceFilter?: ReferenceFilter,
importFilter?: ReferenceFilter): {sourceText: string, context: EmitterVisitorContext} {
const converter = new _TsEmitterVisitor(referenceFilter, importFilter);
emitSourceMaps: boolean = true,
referenceFilter?: ReferenceFilter): {sourceText: string, context: EmitterVisitorContext} {
const converter = new _TsEmitterVisitor(referenceFilter);
const ctx = EmitterVisitorContext.createRoot();
@ -83,9 +83,7 @@ export class TypeScriptEmitter implements OutputEmitter {
class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor {
private typeExpression = 0;
constructor(private referenceFilter?: ReferenceFilter, private importFilter?: ReferenceFilter) {
super(false);
}
constructor(private referenceFilter?: ReferenceFilter) { super(false); }
importsWithPrefixes = new Map<string, string>();
reexports = new Map<string, {name: string, as: string}[]>();
@ -218,15 +216,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
// comment out as a workaround for #10967
ctx.print(null, `/*private*/ `);
}
if (field.hasModifier(o.StmtModifier.Static)) {
ctx.print(null, 'static ');
}
ctx.print(null, field.name);
this._printColonType(field.type, ctx);
if (field.initializer) {
ctx.print(null, ' = ');
field.initializer.visitExpression(this, ctx);
}
ctx.println(null, `;`);
}
@ -269,23 +260,15 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
}
visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any {
if (ast.name) {
ctx.print(ast, 'function ');
ctx.print(ast, ast.name);
}
ctx.print(ast, `(`);
this._visitParams(ast.params, ctx);
ctx.print(ast, `)`);
this._printColonType(ast.type, ctx, 'void');
if (!ast.name) {
ctx.print(ast, ` => `);
}
ctx.println(ast, '{');
ctx.println(ast, ` => {`);
ctx.incIndent();
this.visitAllStatements(ast.statements, ctx);
ctx.decIndent();
ctx.print(ast, `}`);
return null;
}
@ -322,7 +305,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
return null;
}
visitBuiltinType(type: o.BuiltinType, ctx: EmitterVisitorContext): any {
visitBuiltintType(type: o.BuiltinType, ctx: EmitterVisitorContext): any {
let typeStr: string;
switch (type.name) {
case o.BuiltinTypeName.Bool:
@ -400,7 +383,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
ctx.print(null, '(null as any)');
return;
}
if (moduleName && (!this.importFilter || !this.importFilter(value))) {
if (moduleName) {
let prefix = this.importsWithPrefixes.get(moduleName);
if (prefix == null) {
prefix = `i${this.importsWithPrefixes.size}`;

View File

@ -7,7 +7,6 @@
*/
import * as chars from './chars';
import {CompileIdentifierMetadata, identifierModuleUrl, identifierName} from './compile_metadata';
import {error} from './util';
export class ParseLocation {
constructor(

View File

@ -1,92 +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 o from '../output/output_ast';
const CORE = '@angular/core';
// Copied from core and must be in sync with the value in the runtime.
export const enum LifeCycleGuard {ON_INIT = 1, ON_DESTROY = 2, ON_CHANGES = 4}
// TODO: Include assignments that use the enum literals
// e.g. { let a: core.LifeCycleGuard.ON_INIT = LifeCycleGuard.ON_INIT; ...}
// Ensure these get removed in bundling.
export class Identifiers {
/* Methods */
static NEW_METHOD = 'n';
static HOST_BINDING_METHOD = 'h';
/* Instructions */
static createElement: o.ExternalReference = {name: 'ɵE', moduleName: CORE};
static elementEnd: o.ExternalReference = {name: 'ɵe', moduleName: CORE};
static elementProperty: o.ExternalReference = {name: 'ɵp', moduleName: CORE};
static elementAttribute: o.ExternalReference = {name: 'ɵa', moduleName: CORE};
static elementClass: o.ExternalReference = {name: 'ɵk', moduleName: CORE};
static elementStyle: o.ExternalReference = {name: 'ɵs', moduleName: CORE};
static containerCreate: o.ExternalReference = {name: 'ɵC', moduleName: CORE};
static containerEnd: o.ExternalReference = {name: 'ɵc', moduleName: CORE};
static containerRefreshStart: o.ExternalReference = {name: 'ɵcR', moduleName: CORE};
static containerRefreshEnd: o.ExternalReference = {name: 'ɵcr', moduleName: CORE};
static directiveCreate: o.ExternalReference = {name: 'ɵD', moduleName: CORE};
static text: o.ExternalReference = {name: 'ɵT', moduleName: CORE};
static directiveInput: o.ExternalReference = {name: 'ɵi', moduleName: CORE};
static textCreateBound: o.ExternalReference = {name: 'ɵt', moduleName: CORE};
static bind: o.ExternalReference = {name: 'ɵb', moduleName: CORE};
static bind1: o.ExternalReference = {name: 'ɵb1', moduleName: CORE};
static bind2: o.ExternalReference = {name: 'ɵb2', moduleName: CORE};
static bind3: o.ExternalReference = {name: 'ɵb3', moduleName: CORE};
static bind4: o.ExternalReference = {name: 'ɵb4', moduleName: CORE};
static bind5: o.ExternalReference = {name: 'ɵb5', moduleName: CORE};
static bind6: o.ExternalReference = {name: 'ɵb6', moduleName: CORE};
static bind7: o.ExternalReference = {name: 'ɵb7', moduleName: CORE};
static bind8: o.ExternalReference = {name: 'ɵb8', moduleName: CORE};
static bindV: o.ExternalReference = {name: 'ɵbV', moduleName: CORE};
static memory: o.ExternalReference = {name: 'ɵm', moduleName: CORE};
static projection: o.ExternalReference = {name: 'ɵP', moduleName: CORE};
static projectionDef: o.ExternalReference = {name: 'ɵpD', moduleName: CORE};
static refreshComponent: o.ExternalReference = {name: 'ɵr', moduleName: CORE};
static directiveLifeCycle: o.ExternalReference = {name: 'ɵl', moduleName: CORE};
static injectElementRef: o.ExternalReference = {name: 'ɵinjectElementRef', moduleName: CORE};
static injectTemplateRef: o.ExternalReference = {name: 'ɵinjectTemplateRef', moduleName: CORE};
static injectViewContainerRef:
o.ExternalReference = {name: 'ɵinjectViewContainerRef', moduleName: CORE};
static inject: o.ExternalReference = {name: 'ɵinject', moduleName: CORE};
static defineComponent: o.ExternalReference = {name: 'ɵdefineComponent', moduleName: CORE};
static defineDirective: o.ExternalReference = {
name: 'ɵdefineDirective',
moduleName: CORE,
};
static NgOnChangesFeature: o.ExternalReference = {name: 'ɵNgOnChangesFeature', moduleName: CORE};
}

View File

@ -1,697 +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 {CompileDirectiveMetadata, CompilePipeSummary, CompileTokenMetadata, CompileTypeMetadata, flatten, identifierName, rendererTypeName, tokenReference, viewClassName} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector';
import {BindingForm, BuiltinConverter, EventHandlerVars, LocalResolver, convertActionBinding, convertPropertyBinding, convertPropertyBindingBuiltins} from '../compiler_util/expression_converter';
import {ConstantPool, DefinitionKind} from '../constant_pool';
import {AST} from '../expression_parser/ast';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
import {ParseSourceSpan} from '../parse_util';
import {CssSelector} from '../selector';
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAst, QueryMatch, RecursiveTemplateAstVisitor, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast';
import {OutputContext, error} from '../util';
import {Identifiers as R3} from './r3_identifiers';
/** Name of the context parameter passed into a template function */
const CONTEXT_NAME = 'ctx';
/** Name of the creation mode flag passed into a template function */
const CREATION_MODE_FLAG = 'cm';
/** Name of the temporary to use during data binding */
const TEMPORARY_NAME = '_t';
/** The prefix reference variables */
const REFERENCE_PREFIX = '_r';
/** The name of the implicit context reference */
const IMPLICIT_REFERENCE = '$implicit';
export function compileDirective(
outputCtx: OutputContext, directive: CompileDirectiveMetadata, reflector: CompileReflector) {
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
// e.g. 'type: MyDirective`
definitionMapValues.push(
{key: 'type', value: outputCtx.importExpr(directive.type.reference), quoted: false});
// e.g. `factory: () => new MyApp(injectElementRef())`
const templateFactory = createFactory(directive.type, outputCtx, reflector);
definitionMapValues.push({key: 'factory', value: templateFactory, quoted: false});
const className = identifierName(directive.type) !;
className || error(`Cannot resolver the name of ${directive.type}`);
// Create the partial class to be merged with the actual class.
outputCtx.statements.push(new o.ClassStmt(
/* name */ className,
/* parent */ null,
/* fields */[new o.ClassField(
/* name */ 'ngDirectiveDef',
/* type */ o.INFERRED_TYPE,
/* modifiers */[o.StmtModifier.Static],
/* initializer */ o.importExpr(R3.defineDirective).callFn([o.literalMap(
definitionMapValues)]))],
/* getters */[],
/* constructorMethod */ new o.ClassMethod(null, [], []),
/* methods */[]));
}
export function compileComponent(
outputCtx: OutputContext, component: CompileDirectiveMetadata, template: TemplateAst[],
reflector: CompileReflector) {
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
// e.g. `type: MyApp`
definitionMapValues.push(
{key: 'type', value: outputCtx.importExpr(component.type.reference), quoted: false});
// e.g. `tag: 'my-app'`
// This is optional and only included if the first selector of a component has element.
const selector = component.selector && CssSelector.parse(component.selector);
const firstSelector = selector && selector[0];
if (firstSelector && firstSelector.hasElementSelector()) {
definitionMapValues.push({key: 'tag', value: o.literal(firstSelector.element), quoted: false});
}
// e.g. `attr: ["class", ".my.app"]
// This is optional an only included if the first selector of a component specifies attributes.
if (firstSelector) {
const selectorAttributes = firstSelector.getAttrs();
if (selectorAttributes.length) {
definitionMapValues.push({
key: 'attrs',
value: outputCtx.constantPool.getConstLiteral(
o.literalArr(selectorAttributes.map(
value => value != null ? o.literal(value) : o.literal(undefined))),
/* forceShared */ true),
quoted: false
});
}
}
// e.g. `factory: function MyApp_Factory() { return new MyApp(injectElementRef()); }`
const templateFactory = createFactory(component.type, outputCtx, reflector);
definitionMapValues.push({key: 'factory', value: templateFactory, quoted: false});
// e.g. `template: function MyComponent_Template(_ctx, _cm) {...}`
const templateTypeName = component.type.reference.name;
const templateName = templateTypeName ? `${templateTypeName}_Template` : null;
const templateFunctionExpression =
new TemplateDefinitionBuilder(
outputCtx, outputCtx.constantPool, reflector, CONTEXT_NAME, ROOT_SCOPE.nestedScope(), 0,
component.template !.ngContentSelectors, templateTypeName, templateName)
.buildTemplateFunction(template, []);
definitionMapValues.push({key: 'template', value: templateFunctionExpression, quoted: false});
const className = identifierName(component.type) !;
className || error(`Cannot resolver the name of ${component.type}`);
// Create the partial class to be merged with the actual class.
outputCtx.statements.push(new o.ClassStmt(
/* name */ className,
/* parent */ null,
/* fields */[new o.ClassField(
/* name */ 'ngComponentDef',
/* type */ o.INFERRED_TYPE,
/* modifiers */[o.StmtModifier.Static],
/* initializer */ o.importExpr(R3.defineComponent).callFn([o.literalMap(
definitionMapValues)]))],
/* getters */[],
/* constructorMethod */ new o.ClassMethod(null, [], []),
/* methods */[]));
}
// TODO: Remove these when the things are fully supported
function unknown<T>(arg: o.Expression | o.Statement | TemplateAst): never {
throw new Error(
`Builder ${this.constructor.name} is unable to handle ${arg.constructor.name} yet`);
}
function unsupported(feature: string): never {
if (this) {
throw new Error(`Builder ${this.constructor.name} doesn't support ${feature} yet`);
}
throw new Error(`Feature ${feature} is not supported yet`);
}
const BINDING_INSTRUCTION_MAP: {[index: number]: o.ExternalReference | undefined} = {
[PropertyBindingType.Property]: R3.elementProperty,
[PropertyBindingType.Attribute]: R3.elementAttribute,
[PropertyBindingType.Class]: R3.elementClass,
[PropertyBindingType.Style]: R3.elementStyle
};
function interpolate(args: o.Expression[]): o.Expression {
args = args.slice(1); // Ignore the length prefix added for render2
switch (args.length) {
case 3:
return o.importExpr(R3.bind1).callFn(args);
case 5:
return o.importExpr(R3.bind2).callFn(args);
case 7:
return o.importExpr(R3.bind3).callFn(args);
case 9:
return o.importExpr(R3.bind4).callFn(args);
case 11:
return o.importExpr(R3.bind5).callFn(args);
case 13:
return o.importExpr(R3.bind6).callFn(args);
case 15:
return o.importExpr(R3.bind7).callFn(args);
case 17:
return o.importExpr(R3.bind8).callFn(args);
}
(args.length > 19 && args.length % 2 == 1) ||
error(`Invalid interpolation argument length ${args.length}`);
return o.importExpr(R3.bindV).callFn(args);
}
class BindingScope {
private map = new Map<string, o.Expression>();
private referenceNameIndex = 0;
constructor(private parent: BindingScope|null) {}
get(name: string): o.Expression|null {
let current: BindingScope|null = this;
while (current) {
const value = current.map.get(name);
if (value != null) {
// Cache the value locally.
this.map.set(name, value);
return value;
}
current = current.parent;
}
return null;
}
set(name: string, variableName: string): BindingScope {
!this.map.has(name) ||
error(`The name ${name} is already defined in scope to be ${this.map.get(name)}`);
this.map.set(name, o.variable(variableName));
return this;
}
nestedScope(): BindingScope { return new BindingScope(this); }
freshReferenceName(): string {
let current: BindingScope|null = this;
// Find the top scope as it maintains the global reference count
while (current.parent) current = current.parent;
return `${REFERENCE_PREFIX}${current.referenceNameIndex++}`;
}
}
const ROOT_SCOPE = new BindingScope(null).set('$event', '$event');
class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
private _dataIndex = 0;
private _bindingContext = 0;
private _referenceIndex = 0;
private _temporaryAllocated = false;
private _prefix: o.Statement[] = [];
private _creationMode: o.Statement[] = [];
private _bindingMode: o.Statement[] = [];
private _hostMode: o.Statement[] = [];
private _refreshMode: o.Statement[] = [];
private _postfix: o.Statement[] = [];
private _contentProjections: Map<NgContentAst, NgContentInfo>;
private _projectionDefinitionIndex = 0;
private unsupported = unsupported;
private invalid = invalid;
constructor(
private outputCtx: OutputContext, private constantPool: ConstantPool,
private reflector: CompileReflector, private contextParameter: string,
private bindingScope: BindingScope, private level = 0, private ngContentSelectors: string[],
private contextName: string|null, private templateName: string|null) {}
buildTemplateFunction(asts: TemplateAst[], variables: VariableAst[]): o.FunctionExpr {
// Create variable bindings
for (const variable of variables) {
const variableName = variable.name;
const expression =
o.variable(this.contextParameter).prop(variable.value || IMPLICIT_REFERENCE);
const scopedName = this.bindingScope.freshReferenceName();
const declaration = o.variable(scopedName).set(expression).toDeclStmt(o.INFERRED_TYPE, [
o.StmtModifier.Final
]);
// Add the reference to the local scope.
this.bindingScope.set(variableName, scopedName);
// Declare the local variable in binding mode
this._bindingMode.push(declaration);
}
// Collect content projections
if (this.ngContentSelectors && this.ngContentSelectors.length > 0) {
const contentProjections = getContentProjection(asts, this.ngContentSelectors);
this._contentProjections = contentProjections;
if (contentProjections.size > 0) {
const infos: R3CssSelector[] = [];
Array.from(contentProjections.values()).forEach(info => {
if (info.selector) {
infos[info.index - 1] = info.selector;
}
});
const projectionIndex = this._projectionDefinitionIndex = this.allocateDataSlot();
const parameters: o.Expression[] = [o.literal(projectionIndex)];
!infos.some(value => !value) || error(`content project information skipped an index`);
if (infos.length > 1) {
parameters.push(this.outputCtx.constantPool.getConstLiteral(
asLiteral(infos), /* forceShared */ true));
}
this.instruction(this._creationMode, null, R3.projectionDef, ...parameters);
}
}
templateVisitAll(this, asts);
return o.fn(
[
new o.FnParam(this.contextParameter, null), new o.FnParam(CREATION_MODE_FLAG, o.BOOL_TYPE)
],
[
// Temporary variable declarations (i.e. let _t: any;)
...this._prefix,
// Creating mode (i.e. if (cm) { ... })
o.ifStmt(o.variable(CREATION_MODE_FLAG), this._creationMode),
// Binding mode (i.e. ɵp(...))
...this._bindingMode,
// Host mode (i.e. Comp.h(...))
...this._hostMode,
// Refresh mode (i.e. Comp.r(...))
...this._refreshMode,
// Nested templates (i.e. function CompTemplate() {})
...this._postfix
],
o.INFERRED_TYPE, null, this.templateName);
}
getLocal(name: string): o.Expression|null { return this.bindingScope.get(name); }
visitNgContent(ast: NgContentAst) {
const info = this._contentProjections.get(ast) !;
info || error(`Expected ${ast.sourceSpan} to be included in content projection collection`);
const slot = this.allocateDataSlot();
const parameters = [o.literal(slot), o.literal(this._projectionDefinitionIndex)];
if (info.index !== 0) {
parameters.push(o.literal(info.index));
}
this.instruction(this._creationMode, ast.sourceSpan, R3.projection, ...parameters);
}
private _computeDirectivesArray(directives: DirectiveAst[]) {
const directiveIndexMap = new Map<any, number>();
const directiveExpressions: o.Expression[] =
directives.filter(directive => !directive.directive.isComponent).map(directive => {
directiveIndexMap.set(directive.directive.type.reference, this.allocateDataSlot());
return this.typeReference(directive.directive.type.reference);
});
return {
directivesArray: directiveExpressions.length ?
this.constantPool.getConstLiteral(
o.literalArr(directiveExpressions), /* forceShared */ true) :
o.literal(null),
directiveIndexMap
};
}
visitElement(ast: ElementAst) {
let bindingCount = 0;
const elementIndex = this.allocateDataSlot();
let componentIndex: number|undefined = undefined;
const referenceDataSlots = new Map<string, number>();
// Element creation mode
const component = findComponent(ast.directives);
const nullNode = o.literal(null, o.INFERRED_TYPE);
const parameters: o.Expression[] = [o.literal(elementIndex)];
// Add component type or element tag
if (component) {
parameters.push(this.typeReference(component.directive.type.reference));
componentIndex = this.allocateDataSlot();
} else {
parameters.push(o.literal(ast.name));
}
// Add attributes array
const attributes: o.Expression[] = [];
for (let attr of ast.attrs) {
attributes.push(o.literal(attr.name), o.literal(attr.value));
}
parameters.push(
attributes.length > 0 ?
this.constantPool.getConstLiteral(o.literalArr(attributes), /* forceShared */ true) :
nullNode);
// Add directives array
const {directivesArray, directiveIndexMap} = this._computeDirectivesArray(ast.directives);
parameters.push(directiveIndexMap.size > 0 ? directivesArray : nullNode);
if (component && componentIndex != null) {
// Record the data slot for the component
directiveIndexMap.set(component.directive.type.reference, componentIndex);
}
// Add references array
if (ast.references && ast.references.length > 0) {
const references =
flatten(ast.references.map(reference => {
const slot = this.allocateDataSlot();
referenceDataSlots.set(reference.name, slot);
// Generate the update temporary.
const variableName = this.bindingScope.freshReferenceName();
this._bindingMode.push(o.variable(variableName, o.INFERRED_TYPE)
.set(o.importExpr(R3.memory).callFn([o.literal(slot)]))
.toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final]));
this.bindingScope.set(reference.name, variableName);
return [reference.name, reference.originalValue];
})).map(value => o.literal(value));
parameters.push(
this.constantPool.getConstLiteral(o.literalArr(references), /* forceShared */ true));
} else {
parameters.push(nullNode);
}
// Remove trailing null nodes as they are implied.
while (parameters[parameters.length - 1] === nullNode) {
parameters.pop();
}
// Generate the instruction create element instruction
this.instruction(this._creationMode, ast.sourceSpan, R3.createElement, ...parameters);
const implicit = o.variable(this.contextParameter);
// Generate element input bindings
for (let input of ast.inputs) {
if (input.isAnimation) {
this.unsupported('animations');
}
// TODO(chuckj): Built-in transform?
const convertedBinding = convertPropertyBinding(
this, implicit, input.value, this.bindingContext(), BindingForm.TrySimple, interpolate);
this._bindingMode.push(...convertedBinding.stmts);
const parameters =
[o.literal(elementIndex), o.literal(input.name), convertedBinding.currValExpr];
const instruction = BINDING_INSTRUCTION_MAP[input.type];
if (instruction) {
// TODO(chuckj): runtime: security context?
this.instruction(
this._bindingMode, input.sourceSpan, instruction, o.literal(elementIndex),
o.literal(input.name), convertedBinding.currValExpr);
} else {
this.unsupported(`binding ${PropertyBindingType[input.type]}`);
}
}
// Generate directives input bindings
this._visitDirectives(ast.directives, implicit, elementIndex, directiveIndexMap);
// Traverse element child nodes
templateVisitAll(this, ast.children);
// Finish element construction mode.
this.instruction(this._creationMode, ast.endSourceSpan || ast.sourceSpan, R3.elementEnd);
}
private _visitDirectives(
directives: DirectiveAst[], implicit: o.Expression, nodeIndex: number,
directiveIndexMap: Map<any, number>) {
for (let directive of directives) {
const directiveIndex = directiveIndexMap.get(directive.directive.type.reference);
// Creation mode
// e.g. D(0, TodoComponentDef.n(), TodoComponentDef);
const directiveType = directive.directive.type.reference;
const kind =
directive.directive.isComponent ? DefinitionKind.Component : DefinitionKind.Directive;
// Note: *do not cache* calls to this.directiveOf() as the constant pool needs to know if the
// node is referenced multiple times to know that it must generate the reference into a
// temporary.
// Bindings
for (const input of directive.inputs) {
const convertedBinding = convertPropertyBinding(
this, implicit, input.value, this.bindingContext(), BindingForm.TrySimple, interpolate);
this._bindingMode.push(...convertedBinding.stmts);
this.instruction(
this._bindingMode, directive.sourceSpan, R3.elementProperty, o.literal(nodeIndex),
o.literal(input.templateName),
o.importExpr(R3.bind).callFn([convertedBinding.currValExpr]));
}
// e.g. r(0, 0);
this.instruction(
this._refreshMode, directive.sourceSpan, R3.refreshComponent, o.literal(directiveIndex),
o.literal(nodeIndex));
}
}
visitEmbeddedTemplate(ast: EmbeddedTemplateAst) {
const templateIndex = this.allocateDataSlot();
const templateRef = this.reflector.resolveExternalReference(Identifiers.TemplateRef);
const templateDirective = ast.directives.find(
directive => directive.directive.type.diDeps.some(
dependency =>
dependency.token != null && (tokenReference(dependency.token) == templateRef)));
const contextName =
this.contextName && templateDirective && templateDirective.directive.type.reference.name ?
`${this.contextName}_${templateDirective.directive.type.reference.name}` :
null;
const templateName =
contextName ? `${contextName}_Template_${templateIndex}` : `Template_${templateIndex}`;
const templateContext = `ctx${this.level}`;
const {directivesArray, directiveIndexMap} = this._computeDirectivesArray(ast.directives);
// e.g. C(1, C1Template)
this.instruction(
this._creationMode, ast.sourceSpan, R3.containerCreate, o.literal(templateIndex),
directivesArray, o.variable(templateName));
// e.g. Cr(1)
this.instruction(
this._refreshMode, ast.sourceSpan, R3.containerRefreshStart, o.literal(templateIndex));
// Generate directives
this._visitDirectives(
ast.directives, o.variable(this.contextParameter), templateIndex, directiveIndexMap);
// e.g. cr();
this.instruction(this._refreshMode, ast.sourceSpan, R3.containerRefreshEnd);
// Create the template function
const templateVisitor = new TemplateDefinitionBuilder(
this.outputCtx, this.constantPool, this.reflector, templateContext,
this.bindingScope.nestedScope(), this.level + 1, this.ngContentSelectors, contextName,
templateName);
const templateFunctionExpr = templateVisitor.buildTemplateFunction(ast.children, ast.variables);
this._postfix.push(templateFunctionExpr.toDeclStmt(templateName, null));
}
// These should be handled in the template or element directly.
readonly visitReference = invalid;
readonly visitVariable = invalid;
readonly visitEvent = invalid;
readonly visitElementProperty = invalid;
readonly visitAttr = invalid;
visitBoundText(ast: BoundTextAst) {
const nodeIndex = this.allocateDataSlot();
// Creation mode
this.instruction(this._creationMode, ast.sourceSpan, R3.text, o.literal(nodeIndex));
// Refresh mode
this.instruction(
this._refreshMode, ast.sourceSpan, R3.textCreateBound, o.literal(nodeIndex),
this.bind(o.variable(CONTEXT_NAME), ast.value, ast.sourceSpan));
}
visitText(ast: TextAst) {
// Text is defined in creation mode only.
this.instruction(
this._creationMode, ast.sourceSpan, R3.text, o.literal(this.allocateDataSlot()),
o.literal(ast.value));
}
// These should be handled in the template or element directly
readonly visitDirective = invalid;
readonly visitDirectiveProperty = invalid;
private allocateDataSlot() { return this._dataIndex++; }
private bindingContext() { return `${this._bindingContext++}`; }
private instruction(
statements: o.Statement[], span: ParseSourceSpan|null, reference: o.ExternalReference,
...params: o.Expression[]) {
statements.push(o.importExpr(reference, null, span).callFn(params, span).toStmt());
}
private typeReference(type: any): o.Expression { return this.outputCtx.importExpr(type); }
private definitionOf(type: any, kind: DefinitionKind): o.Expression {
return this.constantPool.getDefinition(type, kind, this.outputCtx);
}
private temp(): o.ReadVarExpr {
if (!this._temporaryAllocated) {
this._prefix.push(o.variable(TEMPORARY_NAME, o.DYNAMIC_TYPE,  null)
.set(o.literal(undefined))
.toDeclStmt(o.DYNAMIC_TYPE));
this._temporaryAllocated = true;
}
return o.variable(TEMPORARY_NAME);
}
private convertPropertyBinding(implicit: o.Expression, value: AST): o.Expression {
const convertedPropertyBinding = convertPropertyBinding(
this, implicit, value, this.bindingContext(), BindingForm.TrySimple, interpolate);
this._refreshMode.push(...convertedPropertyBinding.stmts);
return convertedPropertyBinding.currValExpr;
}
private bind(implicit: o.Expression, value: AST, sourceSpan: ParseSourceSpan): o.Expression {
return this.convertPropertyBinding(implicit, value);
}
}
function createFactory(
type: CompileTypeMetadata, outputCtx: OutputContext,
reflector: CompileReflector): o.FunctionExpr {
let args: o.Expression[] = [];
const elementRef = reflector.resolveExternalReference(Identifiers.ElementRef);
const templateRef = reflector.resolveExternalReference(Identifiers.TemplateRef);
const viewContainerRef = reflector.resolveExternalReference(Identifiers.ViewContainerRef);
for (let dependency of type.diDeps) {
if (dependency.isValue) {
unsupported('value dependencies');
}
if (dependency.isHost) {
unsupported('host dependencies');
}
const token = dependency.token;
if (token) {
const tokenRef = tokenReference(token);
if (tokenRef === elementRef) {
args.push(o.importExpr(R3.injectElementRef).callFn([]));
} else if (tokenRef === templateRef) {
args.push(o.importExpr(R3.injectTemplateRef).callFn([]));
} else if (tokenRef === viewContainerRef) {
args.push(o.importExpr(R3.injectViewContainerRef).callFn([]));
} else {
const value =
token.identifier != null ? outputCtx.importExpr(tokenRef) : o.literal(tokenRef);
args.push(o.importExpr(R3.inject).callFn([value]));
}
} else {
unsupported('dependency without a token');
}
}
return o.fn(
[],
[new o.ReturnStatement(new o.InstantiateExpr(outputCtx.importExpr(type.reference), args))],
o.INFERRED_TYPE, null, type.reference.name ? `${type.reference.name}_Factory` : null);
}
function invalid<T>(arg: o.Expression | o.Statement | TemplateAst): never {
throw new Error(
`Invalid state: Visitor ${this.constructor.name} doesn't handle ${o.constructor.name}`);
}
function findComponent(directives: DirectiveAst[]): DirectiveAst|undefined {
return directives.filter(directive => directive.directive.isComponent)[0];
}
interface NgContentInfo {
index: number;
selector?: R3CssSelector;
}
class ContentProjectionVisitor extends RecursiveTemplateAstVisitor {
private index = 1;
constructor(
private projectionMap: Map<NgContentAst, NgContentInfo>,
private ngContentSelectors: string[]) {
super();
}
visitNgContent(ast: NgContentAst) {
const selectorText = this.ngContentSelectors[ast.index];
selectorText != null || error(`could not find selector for index ${ast.index} in ${ast}`);
if (!selectorText || selectorText === '*') {
this.projectionMap.set(ast, {index: 0});
} else {
const cssSelectors = CssSelector.parse(selectorText);
this.projectionMap.set(
ast, {index: this.index++, selector: parseSelectorsToR3Selector(cssSelectors)});
}
}
}
function getContentProjection(asts: TemplateAst[], ngContentSelectors: string[]) {
const projectIndexMap = new Map<NgContentAst, NgContentInfo>();
const visitor = new ContentProjectionVisitor(projectIndexMap, ngContentSelectors);
templateVisitAll(visitor, asts);
return projectIndexMap;
}
// These are a copy the CSS types from core/src/render3/interfaces/projection.ts
// They are duplicated here as they cannot be directly referenced from core.
type R3SimpleCssSelector = (string | null)[];
type R3CssSelectorWithNegations =
[R3SimpleCssSelector, null] | [R3SimpleCssSelector, R3SimpleCssSelector];
type R3CssSelector = R3CssSelectorWithNegations[];
function parserSelectorToSimpleSelector(selector: CssSelector): R3SimpleCssSelector {
const classes =
selector.classNames && selector.classNames.length ? ['class', ...selector.classNames] : [];
return [selector.element, ...selector.attrs, ...classes];
}
function parserSelectorToR3Selector(selector: CssSelector): R3CssSelectorWithNegations {
const positive = parserSelectorToSimpleSelector(selector);
const negative = selector.notSelectors && selector.notSelectors.length &&
parserSelectorToSimpleSelector(selector.notSelectors[0]);
return negative ? [positive, negative] : [positive, null];
}
function parseSelectorsToR3Selector(selectors: CssSelector[]): R3CssSelector {
return selectors.map(parserSelectorToR3Selector);
}
function asLiteral(value: any): o.Expression {
if (Array.isArray(value)) {
return o.literalArr(value.map(asLiteral));
}
return o.literal(value, o.INFERRED_TYPE);
}

View File

@ -104,14 +104,6 @@ export class CssSelector {
`<${tagName}${classAttr}${attrs}></${tagName}>`;
}
getAttrs(): string[] {
const result: string[] = [];
if (this.classNames.length > 0) {
result.push('class', this.classNames.join(' '));
}
return result.concat(this.attrs);
}
addAttribute(name: string, value: string = '') {
this.attrs.push(name, value && value.toLowerCase() || '');
}

View File

@ -110,8 +110,8 @@ export class BoundEventAst implements TemplateAst {
*/
export class ReferenceAst implements TemplateAst {
constructor(
public name: string, public value: CompileTokenMetadata, public originalValue: string,
public sourceSpan: ParseSourceSpan) {}
public name: string, public value: CompileTokenMetadata, public sourceSpan: ParseSourceSpan) {
}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitReference(this, context);
}

View File

@ -574,7 +574,7 @@ class TemplateParseVisitor implements html.Visitor {
if ((elOrDirRef.value.length === 0 && directive.isComponent) ||
(elOrDirRef.isReferenceToDirective(directive))) {
targetReferences.push(new ReferenceAst(
elOrDirRef.name, createTokenForReference(directive.type.reference), elOrDirRef.value,
elOrDirRef.name, createTokenForReference(directive.type.reference),
elOrDirRef.sourceSpan));
matchedReferences.add(elOrDirRef.name);
}
@ -598,8 +598,7 @@ class TemplateParseVisitor implements html.Visitor {
if (isTemplateElement) {
refToken = createTokenForExternalReference(this.reflector, Identifiers.TemplateRef);
}
targetReferences.push(
new ReferenceAst(elOrDirRef.name, refToken, elOrDirRef.value, elOrDirRef.sourceSpan));
targetReferences.push(new ReferenceAst(elOrDirRef.name, refToken, elOrDirRef.sourceSpan));
}
});
return directiveAsts;

View File

@ -6,8 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ConstantPool} from './constant_pool';
import * as o from './output/output_ast';
import {ParseError} from './parse_util';
@ -92,10 +90,6 @@ export const SyncAsync = {
}
};
export function error(msg: string): never {
throw new Error(`Internal Error: ${msg}`);
}
export function syntaxError(msg: string, parseErrors?: ParseError[]): Error {
const error = Error(msg);
(error as any)[ERROR_SYNTAX_ERROR] = true;
@ -158,7 +152,6 @@ export function utf8Encode(str: string): string {
export interface OutputContext {
genFilePath: string;
statements: o.Statement[];
constantPool: ConstantPool;
importExpr(reference: any, typeParams?: o.Type[]|null, useSummaries?: boolean): o.Expression;
}

View File

@ -8,7 +8,6 @@
import {AotSummaryResolver, AotSummaryResolverHost, CompileSummaryKind, CompileTypeSummary, ResolvedStaticSymbol, StaticSymbol, StaticSymbolCache, StaticSymbolResolver} from '@angular/compiler';
import {deserializeSummaries, serializeSummaries} from '@angular/compiler/src/aot/summary_serializer';
import {ConstantPool} from '@angular/compiler/src/constant_pool';
import * as o from '@angular/compiler/src/output/output_ast';
import {OutputContext} from '@angular/compiler/src/util';
import * as path from 'path';
@ -128,10 +127,5 @@ export class MockAotSummaryResolverHost implements AotSummaryResolverHost {
}
export function createMockOutputContext(): OutputContext {
return {
statements: [],
genFilePath: 'someGenFilePath',
importExpr: () => o.NULL_EXPR,
constantPool: new ConstantPool()
};
return {statements: [], genFilePath: 'someGenFilePath', importExpr: () => o.NULL_EXPR};
}

View File

@ -538,12 +538,10 @@ const minCoreIndex = `
export * from './src/codegen_private_exports';
`;
export function setup(
options: {compileAngular: boolean, compileAnimations: boolean, compileCommon?: boolean} = {
compileAngular: true,
compileAnimations: true,
compileCommon: false,
}) {
export function setup(options: {compileAngular: boolean, compileAnimations: boolean} = {
compileAngular: true,
compileAnimations: true,
}) {
let angularFiles = new Map<string, string>();
beforeAll(() => {
@ -554,13 +552,6 @@ export function setup(
emittingProgram.emit();
emittingHost.writtenAngularFiles(angularFiles);
}
if (options.compileCommon) {
const emittingHost =
new EmittingCompilerHost(['@angular/common/index.ts'], {emitMetadata: true});
const emittingProgram = ts.createProgram(emittingHost.scripts, settings, emittingHost);
emittingProgram.emit();
emittingHost.writtenAngularFiles(angularFiles);
}
if (options.compileAnimations) {
const emittingHost =
new EmittingCompilerHost(['@angular/animations/index.ts'], {emitMetadata: true});

View File

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

View File

@ -1,839 +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 {AotCompilerHost, AotCompilerOptions, AotSummaryResolver, CompileDirectiveMetadata, CompileMetadataResolver, CompilerConfig, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, HtmlParser, I18NHtmlParser, Lexer, NgModuleResolver, Parser, PipeResolver, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, TemplateParser, TypeScriptEmitter, analyzeNgModules, createAotUrlResolver} from '@angular/compiler';
import {ViewEncapsulation} from '@angular/core';
import * as ts from 'typescript';
import {ConstantPool} from '../../src/constant_pool';
import * as o from '../../src/output/output_ast';
import {compileComponent, compileDirective} from '../../src/render3/r3_view_compiler';
import {OutputContext} from '../../src/util';
import {MockAotCompilerHost, MockCompilerHost, MockData, MockDirectory, arrayToMockDir, settings, setup, toMockFileArray} from '../aot/test_util';
describe('r3_view_compiler', () => {
const angularFiles = setup({
compileAngular: true,
compileAnimations: false,
compileCommon: true,
});
describe('hello world', () => {
it('should be able to generate the hello world component', () => {
const files: MockDirectory = {
app: {
'hello.ts': `
import {Component, NgModule} from '@angular/core';
@Component({
selector: 'hello-world',
template: 'Hello, world!'
})
export class HelloWorldComponent {
}
@NgModule({
declarations: [HelloWorldComponent]
})
export class HelloWorldModule {}
`
}
};
compile(files, angularFiles);
});
});
it('should be able to generate the example', () => {
const files: MockDirectory = {
app: {
'example.ts': `
import {Component, OnInit, OnDestroy, ElementRef, Input, NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
@Component({
selector: 'my-app',
template: '<todo [data]="list"></todo>'
})
export class MyApp implements OnInit {
list: any[] = [];
constructor(public elementRef: ElementRef) {}
ngOnInit(): void {
}
}
@Component({
selector: 'todo',
template: '<ul class="list" [title]="myTitle"><li *ngFor="let item of data">{{data}}</li></ul>'
})
export class TodoComponent implements OnInit, OnDestroy {
@Input()
data: any[] = [];
myTitle: string;
constructor(public elementRef: ElementRef) {}
ngOnInit(): void {}
ngOnDestroy(): void {}
}
@NgModule({
declarations: [TodoComponent, MyApp],
imports: [CommonModule]
})
export class TodoModule{}
`
}
};
const result = compile(files, angularFiles);
expect(result.source).toContain('@angular/core');
});
/* These tests are codified version of the tests in compiler_canonical_spec.ts. Every
* test in compiler_canonical_spec.ts should have a corresponding test here.
*/
describe('compiler conformance', () => {
describe('elements', () => {
it('should translate DOM structure', () => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule} from '@angular/core';
@Component({
selector: 'my-component',
template: \`<div class="my-app" title="Hello">Hello <b>World</b>!</div>\`
})
export class MyComponent {}
@NgModule({declarations: [MyComponent]})
export class MyModule {}
`
}
};
// The factory should look like this:
const factory = 'factory: function MyComponent_Factory() { return new MyComponent(); }';
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, 'div', IDENT);
IDENT.ɵT(1, 'Hello ');
IDENT.ɵE(2, 'b');
IDENT.ɵT(3, 'World');
IDENT.ɵe();
IDENT.ɵT(4, '!');
IDENT.ɵe();
}
}
`;
// The compiler should also emit a const array like this:
const constants = `const IDENT = ['class', 'my-app', 'title', 'Hello'];`;
const result = compile(files, angularFiles);
expectEmit(result.source, factory, 'Incorrect factory');
expectEmit(result.source, template, 'Incorrect template');
expectEmit(result.source, constants, 'Incorrect shared constants');
});
});
});
describe('components & directives', () => {
it('should instantiate directives', () => {
const files = {
app: {
'spec.ts': `
import {Component, Directive, NgModule} from '@angular/core';
@Component({selector: 'child', template: 'child-view'})
export class ChildComponent {}
@Directive({selector: '[some-directive]'})
export class SomeDirective {}
@Component({selector: 'my-component', template: '<child some-directive></child>!'})
export class MyComponent {}
@NgModule({declarations: [ChildComponent, SomeDirective, MyComponent]})
export class MyModule{}
`
}
};
// ChildComponent definition should be:
const ChildComponentDefinition = `
static ngComponentDef = IDENT.ɵdefineComponent({
type: ChildComponent,
tag: 'child',
factory: function ChildComponent_Factory() { return new ChildComponent(); },
template: function ChildComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵT(0, 'child-view');
}
}
});`;
// SomeDirective definition should be:
const SomeDirectiveDefinition = `
static ngDirectiveDef = IDENT.ɵdefineDirective({
type: SomeDirective,
factory: function SomeDirective_Factory() {return new SomeDirective(); }
});
`;
// MyComponent definition should be:
const MyComponentDefinition = `
static ngComponentDef = IDENT.ɵdefineComponent({
type: MyComponent,
tag: 'my-component',
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, ChildComponent, IDENT, IDENT);
IDENT.ɵe();
IDENT.ɵT(3, '!');
}
IDENT.ɵr(1, 0);
IDENT.ɵr(2, 0);
}
});
`;
// The following constants should be emitted as well.
const AttributesConstant = `const IDENT = ['some-directive', ''];`;
const DirectivesConstant = `const IDENT = [SomeDirective];`;
const result = compile(files, angularFiles);
const source = result.source;
expectEmit(source, ChildComponentDefinition, 'Incorrect ChildComponent.ngComponentDef');
expectEmit(source, SomeDirectiveDefinition, 'Incorrect SomeDirective.ngDirectiveDef');
expectEmit(source, MyComponentDefinition, 'Incorrect MyComponentDefinition.ngComponentDef');
expectEmit(source, AttributesConstant, 'Incorrect shared attributes constant');
expectEmit(source, DirectivesConstant, 'Incorrect share directives constant');
});
it('should support structural directives', () => {
const files = {
app: {
'spec.ts': `
import {Component, Directive, NgModule, TemplateRef} from '@angular/core';
@Directive({selector: '[if]'})
export class IfDirective {
constructor(template: TemplateRef<any>) { }
}
@Component({
selector: 'my-component',
template: '<ul #foo><li *if>{{salutation}} {{foo}}</li></ul>'
})
export class MyComponent {
salutation = 'Hello';
}
@NgModule({declarations: [IfDirective, MyComponent]})
export class MyModule {}
`
}
};
const IfDirectiveDefinition = `
static ngDirectiveDef = IDENT.ɵdefineDirective({
type: IfDirective,
factory: function IfDirective_Factory() { return new IfDirective(IDENT.ɵinjectTemplateRef()); }
});`;
const MyComponentDefinition = `
static ngComponentDef = IDENT.ɵdefineComponent({
type: MyComponent,
tag: 'my-component',
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, 'ul', null, null, IDENT);
IDENT.ɵC(2, IDENT, MyComponent_IfDirective_Template_2);
IDENT.ɵe();
}
const IDENT = IDENT.ɵm(1);
IDENT.ɵcR(2);
IDENT.ɵr(3,2);
IDENT.ɵcr();
function MyComponent_IfDirective_Template_2(ctx0: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, 'li');
IDENT.ɵT(1);
IDENT.ɵe();
}
IDENT.ɵt(1, IDENT.ɵb2('', ctx.salutation, ' ', IDENT, ''));
}
}
});`;
const locals = `const IDENT = ['foo', ''];`;
const directives = `const IDENT = [IfDirective];`;
const result = compile(files, angularFiles);
const source = result.source;
expectEmit(source, IfDirectiveDefinition, 'Incorrect IfDirective.ngDirectiveDef');
expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef');
expectEmit(source, locals, 'Incorrect share locals constant');
expectEmit(source, directives, 'Incorrect shared directive constant');
});
it('should support content projection', () => {
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: '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>'
})
export class MyApp {}
`
}
};
const SimpleComponentDefinition = `
static ngComponentDef = IDENT.ɵdefineComponent({
type: SimpleComponent,
tag: 'simple',
factory: function SimpleComponent_Factory() { return new SimpleComponent(); },
template: function SimpleComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵpD(0);
IDENT.ɵE(1, 'div');
IDENT.ɵP(2, 0);
IDENT.ɵe();
}
}
});`;
const ComplexComponentDefinition = `
static ngComponentDef = IDENT.ɵdefineComponent({
type: ComplexComponent,
tag: 'complex',
factory: function ComplexComponent_Factory() { return new ComplexComponent(); },
template: function ComplexComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵpD(0, IDENT);
IDENT.ɵE(1, 'div', IDENT);
IDENT.ɵP(2, 0, 1);
IDENT.ɵe();
IDENT.ɵE(3, 'div', IDENT);
IDENT.ɵP(4, 0, 2);
IDENT.ɵe();
}
}
});
`;
const ComplexComponent_ProjectionConst = `
const IDENT = [[[['span', 'title', 'tofirst'], null]], [[['span', 'title', 'tosecond'], null]]];
`;
const result = compile(files, angularFiles);
const source = result.source;
expectEmit(result.source, SimpleComponentDefinition, 'Incorrect SimpleComponent definition');
expectEmit(
result.source, ComplexComponentDefinition, 'Incorrect ComplexComponent definition');
expectEmit(result.source, ComplexComponent_ProjectionConst, 'Incorrect projection const');
});
it('local reference', () => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule} from '@angular/core';
@Component({selector: 'my-component', template: '<input #user>Hello {{user.value}}!'})
export class MyComponent {}
@NgModule({declarations: [MyComponent]})
export class MyModule {}
`
}
};
const MyComponentDefinition = `
static ngComponentDef = IDENT.ɵdefineComponent({
type: MyComponent,
tag: 'my-component',
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, 'input', null, null, IDENT);
IDENT.ɵe();
IDENT.ɵT(2);
}
const IDENT = IDENT.ɵm(1);
IDENT.ɵt(2, IDENT.ɵb1('Hello ', IDENT.value, '!'));
}
});
`;
const locals = `const IDENT = ['user', ''];`;
const result = compile(files, angularFiles);
const source = result.source;
expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef');
expectEmit(source, locals, 'Incorrect locals constant definition');
});
describe('template variables', () => {
const shared = {
shared: {
'for_of.ts': `
import {Directive, Input, SimpleChanges, TemplateRef, ViewContainerRef} from '@angular/core';
export interface ForOfContext {
$implicit: any;
index: number;
even: boolean;
odd: boolean;
}
@Directive({selector: '[forOf]'})
export class ForOfDirective {
private previous: any[];
constructor(private view: ViewContainerRef, private template: TemplateRef<any>) {}
@Input() forOf: any[];
ngOnChanges(simpleChanges: SimpleChanges) {
if ('forOf' in simpleChanges) {
this.update();
}
}
ngDoCheck(): void {
const previous = this.previous;
const current = this.forOf;
if (!previous || previous.length != current.length ||
previous.some((value: any, index: number) => current[index] !== previous[index])) {
this.update();
}
}
private update() {
// TODO(chuckj): Not implemented yet
// this.view.clear();
if (this.forOf) {
const current = this.forOf;
for (let i = 0; i < current.length; i++) {
const context = {$implicit: current[i], index: i, even: i % 2 == 0, odd: i % 2 == 1};
// TODO(chuckj): Not implemented yet
// this.view.createEmbeddedView(this.template, context);
}
this.previous = [...this.forOf];
}
}
}
`
}
};
it('should support a let variable and reference', () => {
const files = {
app: {
...shared,
'spec.ts': `
import {Component, NgModule} from '@angular/core';
import {ForOfDirective} from './shared/for_of';
@Component({
selector: 'my-component',
template: \`<ul><li *for="let item of items">{{item.name}}</li></ul>\`
})
export class MyComponent {
items = [{name: 'one'}, {name: 'two'}];
}
@NgModule({
declarations: [MyComponent, ForOfDirective]
})
export class MyModule {}
`
}
};
// TODO(chuckj): Enforce this when the directives are specified
const ForDirectiveDefinition = `
static ngDirectiveDef = IDENT.ɵdefineDirective({
type: ForOfDirective,
factory: function ForOfDirective_Factory() {
return new ForOfDirective(IDENT.ɵinjectViewContainerRef(), IDENT.ɵinjectTemplateRef());
},
features: [IDENT.ɵNgOnChangesFeature(NgForOf)],
inputs: {forOf: 'forOf'}
});
`;
const MyComponentDefinition = `
static ngComponentDef = IDENT.ɵdefineComponent({
type: MyComponent,
tag: 'my-component',
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, 'ul');
IDENT.ɵC(1, IDENT, MyComponent_ForOfDirective_Template_1);
IDENT.ɵe();
}
IDENT.ɵp(1, 'forOf', IDENT.ɵb(ctx.items));
IDENT.ɵcR(1);
IDENT.ɵr(2, 1);
IDENT.ɵcr();
function MyComponent_ForOfDirective_Template_1(ctx0: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, 'li');
IDENT.ɵT(1);
IDENT.ɵe();
}
const IDENT = ctx0.$implicit;
IDENT.ɵt(1, IDENT.ɵb1('', IDENT.name, ''));
}
}
});
`;
const result = compile(files, angularFiles);
const source = result.source;
// TODO(chuckj): Enforce this when the directives are specified
// expectEmit(source, ForDirectiveDefinition, 'Invalid directive definition');
expectEmit(source, MyComponentDefinition, 'Invalid component definition');
});
it('should support accessing parent template variables', () => {
const files = {
app: {
...shared,
'spec.ts': `
import {Component, NgModule} from '@angular/core';
import {ForOfDirective} from './shared/for_of';
@Component({
selector: 'my-component',
template: \`
<ul>
<li *for="let item of items">
<div>{{item.name}}</div>
<ul>
<li *for="let info of item.infos">
{{item.name}}: {{info.description}}
</li>
</ul>
</li>
</ul>\`
})
export class MyComponent {
items: Item[] = [
{name: 'one', infos: [{description: '11'}, {description: '12'}]},
{name: 'two', infos: [{description: '21'}, {description: '22'}]}
];
}
@NgModule({
declarations: [MyComponent, ForOfDirective]
})
export class MyModule {}
`
}
};
const MyComponentDefinition = `
static ngComponentDef = IDENT.ɵdefineComponent({
type: MyComponent,
tag: 'my-component',
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, 'ul');
IDENT.ɵC(1, IDENT, MyComponent_ForOfDirective_Template_1);
IDENT.ɵe();
}
IDENT.ɵp(1, 'forOf', IDENT.ɵb(ctx.items));
IDENT.ɵcR(1);
IDENT.ɵr(2, 1);
IDENT.ɵcr();
function MyComponent_ForOfDirective_Template_1(ctx0: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, 'li');
IDENT.ɵE(1, 'div');
IDENT.ɵT(2);
IDENT.ɵe();
IDENT.ɵE(3, 'ul');
IDENT.ɵC(4, IDENT, MyComponent_ForOfDirective_ForOfDirective_Template_4);
IDENT.ɵe();
IDENT.ɵe();
}
const IDENT = ctx0.$implicit;
IDENT.ɵp(4, 'forOf', IDENT.ɵb(IDENT.infos));
IDENT.ɵt(2, IDENT.ɵb1('', IDENT.name, ''));
IDENT.ɵcR(4);
IDENT.ɵr(5, 4);
IDENT.ɵcr();
function MyComponent_ForOfDirective_ForOfDirective_Template_4(
ctx1: IDENT, cm: IDENT) {
if (cm) {
IDENT.ɵE(0, 'li');
IDENT.ɵT(1);
IDENT.ɵe();
}
const IDENT = ctx1.$implicit;
IDENT.ɵt(1, IDENT.ɵb2(' ', IDENT.name, ': ', IDENT.description, ' '));
}
}
}
});`;
const result = compile(files, angularFiles);
const source = result.source;
expectEmit(source, MyComponentDefinition, 'Invalid component definition');
});
});
});
});
const IDENTIFIER = /[A-Za-z_$ɵ][A-Za-z0-9_$]*/;
const OPERATOR =
/!|%|\*|\/|\^|\&|\&\&\|\||\|\||\(|\)|\{|\}|\[|\]|:|;|\.|<|<=|>|>=|=|==|===|!=|!==|=>|\+|\+\+|-|--|@|,|\.|\.\.\./;
const STRING = /\'[^'\n]*\'|"[^'\n]*"|`[^`]*`/;
const NUMBER = /[0-9]+/;
const TOKEN = new RegExp(
`^((${IDENTIFIER.source})|(${OPERATOR.source})|(${STRING.source})|${NUMBER.source})`);
const WHITESPACE = /^\s+/;
type Piece = string | RegExp;
const IDENT = /[A-Za-z$_][A-Za-z0-9$_]*/;
function tokenize(text: string): Piece[] {
function matches(exp: RegExp): string|false {
const m = text.match(exp);
if (!m) return false;
text = text.substr(m[0].length);
return m[0];
}
function next(): string {
const result = matches(TOKEN);
if (!result) {
throw Error(`Invalid test, no token found for '${text.substr(0, 30)}...'`);
}
matches(WHITESPACE);
return result;
}
const pieces: Piece[] = [];
matches(WHITESPACE);
while (text) {
const token = next();
if (token === 'IDENT') {
pieces.push(IDENT);
} else {
pieces.push(token);
}
}
return pieces;
}
const contextWidth = 100;
function expectEmit(source: string, emitted: string, description: string) {
const pieces = tokenize(emitted);
const expr = r(...pieces);
if (!expr.test(source)) {
let last: number = 0;
for (let i = 1; i < pieces.length; i++) {
let t = r(...pieces.slice(0, i));
let m = source.match(t);
let expected = pieces[i - 1] == IDENT ? '<IDENT>' : pieces[i - 1];
if (!m) {
const contextPieceWidth = contextWidth / 2;
fail(
`${description}: Expected to find ${expected} '${source.substr(0,last)}[<---HERE expected "${expected}"]${source.substr(last)}'`);
return;
} else {
last = (m.index || 0) + m[0].length;
}
}
fail(
'Test helper failure: Expected expression failed but the reporting logic could not find where it failed');
}
}
const IDENT_LIKE = /^[a-z][A-Z]/;
const SPECIAL_RE_CHAR = /\/|\(|\)|\||\*|\+|\[|\]|\{|\}|\$/g;
function r(...pieces: (string | RegExp)[]): RegExp {
let results: string[] = [];
let first = true;
for (const piece of pieces) {
if (!first)
results.push(`\\s${typeof piece === 'string' && IDENT_LIKE.test(piece) ? '+' : '*'}`);
first = false;
if (typeof piece === 'string') {
results.push(piece.replace(SPECIAL_RE_CHAR, s => '\\' + s));
} else {
results.push('(' + piece.source + ')');
}
}
return new RegExp(results.join(''));
}
function compile(
data: MockDirectory, angularFiles: MockData, options: AotCompilerOptions = {},
errorCollector: (error: any, fileName?: string) => void = error => { throw error; }) {
const testFiles = toMockFileArray(data);
const scripts = testFiles.map(entry => entry.fileName);
const angularFilesArray = toMockFileArray(angularFiles);
const files = arrayToMockDir([...testFiles, ...angularFilesArray]);
const mockCompilerHost = new MockCompilerHost(scripts, files);
const compilerHost = new MockAotCompilerHost(mockCompilerHost);
const program = ts.createProgram(scripts, {...settings}, mockCompilerHost);
// TODO(chuckj): Replace with a variant of createAotCompiler() when the r3_view_compiler is
// integrated
const translations = options.translations || '';
const urlResolver = createAotUrlResolver(compilerHost);
const symbolCache = new StaticSymbolCache();
const summaryResolver = new AotSummaryResolver(compilerHost, symbolCache);
const symbolResolver = new StaticSymbolResolver(compilerHost, symbolCache, summaryResolver);
const staticReflector =
new StaticReflector(summaryResolver, symbolResolver, [], [], errorCollector);
const htmlParser = new I18NHtmlParser(
new HtmlParser(), translations, options.i18nFormat, options.missingTranslation, console);
const config = new CompilerConfig({
defaultEncapsulation: ViewEncapsulation.Emulated,
useJit: false,
enableLegacyTemplate: options.enableLegacyTemplate === true,
missingTranslation: options.missingTranslation,
preserveWhitespaces: options.preserveWhitespaces,
strictInjectionParameters: options.strictInjectionParameters,
});
const normalizer = new DirectiveNormalizer(
{get: (url: string) => compilerHost.loadResource(url)}, urlResolver, htmlParser, config);
const expressionParser = new Parser(new Lexer());
const elementSchemaRegistry = new DomElementSchemaRegistry();
const templateParser = new TemplateParser(
config, staticReflector, expressionParser, elementSchemaRegistry, htmlParser, console, []);
const resolver = new CompileMetadataResolver(
config, htmlParser, new NgModuleResolver(staticReflector),
new DirectiveResolver(staticReflector), new PipeResolver(staticReflector), summaryResolver,
elementSchemaRegistry, normalizer, console, symbolCache, staticReflector, errorCollector);
// Create the TypeScript program
const sourceFiles = program.getSourceFiles().map(sf => sf.fileName);
// Analyze the modules
// TODO(chuckj): Eventually this should not be necessary as the ts.SourceFile should be sufficient
// to generate a template definition.
const analyzedModules = analyzeNgModules(sourceFiles, compilerHost, symbolResolver, resolver);
const directives = Array.from(analyzedModules.ngModuleByPipeOrDirective.keys());
const fakeOutputContext: OutputContext = {
genFilePath: 'fakeFactory.ts',
statements: [],
importExpr(symbol: StaticSymbol, typeParams: o.Type[]) {
if (!(symbol instanceof StaticSymbol)) {
if (!symbol) {
throw new Error('Invalid: undefined passed to as a symbol');
}
throw new Error(`Invalid: ${(symbol as any).constructor.name} is not a symbol`);
}
return (symbol.members || [])
.reduce(
(expr, member) => expr.prop(member),
<o.Expression>o.importExpr(new o.ExternalReference(symbol.filePath, symbol.name)));
},
constantPool: new ConstantPool()
};
// Load All directives
for (const directive of directives) {
const module = analyzedModules.ngModuleByPipeOrDirective.get(directive) !;
resolver.loadNgModuleDirectiveAndPipeMetadata(module.type.reference, true);
}
// Compile the directives.
for (const directive of directives) {
const module = analyzedModules.ngModuleByPipeOrDirective.get(directive);
if (!module || !module.type.reference.filePath.startsWith('/app')) {
continue;
}
if (resolver.isDirective(directive)) {
const metadata = resolver.getDirectiveMetadata(directive);
if (metadata.isComponent) {
const fakeUrl = 'ng://fake-template-url.html';
const htmlAst = htmlParser.parse(metadata.template !.template !, fakeUrl);
const directives = module.transitiveModule.directives.map(
dir => resolver.getDirectiveSummary(dir.reference));
const pipes =
module.transitiveModule.pipes.map(pipe => resolver.getPipeSummary(pipe.reference));
const parsedTemplate = templateParser.parse(
metadata, htmlAst, directives, pipes, module.schemas, fakeUrl, false);
compileComponent(fakeOutputContext, metadata, parsedTemplate.template, staticReflector);
} else {
compileDirective(fakeOutputContext, metadata, staticReflector);
}
}
}
fakeOutputContext.statements.unshift(...fakeOutputContext.constantPool.statements);
const emitter = new TypeScriptEmitter();
const moduleName = compilerHost.fileNameToModuleName(
fakeOutputContext.genFilePath, fakeOutputContext.genFilePath);
const result = emitter.emitStatementsAndContext(
fakeOutputContext.genFilePath, fakeOutputContext.statements, '', false,
/* referenceFilter */ undefined,
/* importFilter */ e => e.moduleName != null && e.moduleName.startsWith('/app'));
return {source: result.sourceText, outputContext: fakeOutputContext};
}

View File

@ -407,7 +407,7 @@ class ArrayConsole implements Console {
expectVisitedNode(
new class extends
NullVisitor{visitReference(ast: ReferenceAst, context: any): any{return ast;}},
new ReferenceAst('foo', null !, null !, null !));
new ReferenceAst('foo', null !, null !));
});
it('should visit VariableAst', () => {
@ -474,7 +474,7 @@ class ArrayConsole implements Console {
new NgContentAst(0, 0, null !),
new EmbeddedTemplateAst([], [], [], [], [], [], false, [], [], 0, null !),
new ElementAst('foo', [], [], [], [], [], [], false, [], [], 0, null !, null !),
new ReferenceAst('foo', null !, 'bar', null !), new VariableAst('foo', 'bar', null !),
new ReferenceAst('foo', null !, null !), new VariableAst('foo', 'bar', null !),
new BoundEventAst('foo', 'bar', 'goo', null !, null !),
new BoundElementPropertyAst('foo', null !, null !, null !, 'bar', null !),
new AttrAst('foo', 'bar', null !), new BoundTextAst(null !, 0, null !),

Some files were not shown because too many files have changed in this diff Show More