diff --git a/.travis.yml b/.travis.yml
index 80d9d7540a513..114adc9aaa0da 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,7 @@ node_js:
branches:
except:
- - g3sync
+ - g3_v2_0
cache:
directories:
@@ -37,8 +37,10 @@ env:
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
- MODE=dart DART_CHANNEL=stable DART_VERSION=$DART_STABLE_VERSION
- MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
- - MODE=saucelabs DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
- - MODE=browserstack DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
+ - MODE=saucelabs_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
+ - MODE=browserstack_required DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
+ - MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
+ - MODE=browserstack_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
- MODE=dart_experimental DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
- MODE=js DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
- MODE=router DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION
@@ -48,8 +50,8 @@ env:
matrix:
allow_failures:
- - env: "MODE=saucelabs DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
- - env: "MODE=browserstack DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
+ - env: "MODE=saucelabs_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
+ - env: "MODE=browserstack_optional DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
- env: "MODE=dart_experimental DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
# TODO(alxhub): remove when dartdoc #1039 is in dev channel
- env: "MODE=dart DART_CHANNEL=dev DART_VERSION=$DART_DEV_VERSION"
@@ -109,24 +111,3 @@ notifications:
slack:
secure: EP4MzZ8JMyNQJ4S3cd5LEPWSMjC7ZRdzt3veelDiOeorJ6GwZfCDHncR+4BahDzQAuqyE/yNpZqaLbwRWloDi15qIUsm09vgl/1IyNky1Sqc6lEknhzIXpWSalo4/T9ZP8w870EoDvM/UO+LCV99R3wS8Nm9o99eLoWVb2HIUu0=
-deploy:
- - provider: gcs
- # This is for project angular-github-babysitter
- access_key_id: GOOGIOQTDBEOPBUAWFZQ
- secret_access_key:
- secure: "MEDggllZ5fw4wI9CEUi8WR6jKsKXqdRF/DLxSNC2JpzM5RlVeBm0uqjntYT1Cf1dASvQ2/+vZCUikL/3A48NcoEYRHXGmxu8D6t/SvleQD8Xv434xFOdsa2QqP/HiCtqCLOI5jJz1JVoB5nNyKKZ33ogTUL1LV1TfcrAioyizW8="
- # this bucket has a lifecycle to delete after 90 days:
- # $ echo '{"rule": [{"action": {"type": "Delete"}, "condition": {"age": 90}}]}' > lifecycle.json
- # $ gsutil lifecycle set lifecycle.json gs://angular2-snapshots
- bucket: angular2-snapshots
- # don't delete generated files
- skip_cleanup: true
- # serve to public at https://storage.googleapis.com/angular2-snapshots/SHA/dist.tgz
- acl: public-read
- # upload the .tgz archive created in scripts/ci/build_and_test.sh
- local-dir: deploy
- # create a "subdirectory" for each commit
- upload-dir: $TRAVIS_COMMIT
- on:
- repo: angular/angular
- condition: "$MODE = build_only"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9abcb3c7a24cf..ed8dee49345ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,48 @@
+
+# 2.0.0-beta.1 catamorphic-involution (2016-01-08)
+
+
+### Bug Fixes
+
+* **benchpress:** fix flake ([9d28147](https://github.com/angular/angular/commit/9d28147)), closes [#6161](https://github.com/angular/angular/issues/6161)
+* **CHANGELOG:** typo ([d116861](https://github.com/angular/angular/commit/d116861)), closes [#6075](https://github.com/angular/angular/issues/6075) [#6078](https://github.com/angular/angular/issues/6078)
+* **code size:** revert previous devMode change to restore size targets ([c47d85b](https://github.com/angular/angular/commit/c47d85b))
+* **core:** IE only supports parentNode ([630d931](https://github.com/angular/angular/commit/630d931)), closes [#5994](https://github.com/angular/angular/issues/5994)
+* **docs:** fix an import in TOOLS_DART.md ([3524946](https://github.com/angular/angular/commit/3524946)), closes [#5923](https://github.com/angular/angular/issues/5923)
+* **forms:** fix SelectControlValueAccessor not to call onChange twice ([b44d36c](https://github.com/angular/angular/commit/b44d36c)), closes [#5969](https://github.com/angular/angular/issues/5969)
+* **router:** correctly sort route matches with children by specificity ([b2bc50d](https://github.com/angular/angular/commit/b2bc50d)), closes [#5848](https://github.com/angular/angular/issues/5848) [#6011](https://github.com/angular/angular/issues/6011)
+* **router:** preserve specificity for redirects ([a038bb9](https://github.com/angular/angular/commit/a038bb9)), closes [#5933](https://github.com/angular/angular/issues/5933)
+* **TemplateParser:** do not match on attrs that are bindings ([9a70f1a](https://github.com/angular/angular/commit/9a70f1a)), closes [#5914](https://github.com/angular/angular/issues/5914)
+
+### Features
+
+* **core:** improve NoAnnotationError message ([197cf09](https://github.com/angular/angular/commit/197cf09)), closes [#4866](https://github.com/angular/angular/issues/4866) [#5927](https://github.com/angular/angular/issues/5927)
+* **core:** improve stringify for dart to handle closures ([e67ebb7](https://github.com/angular/angular/commit/e67ebb7))
+* **core:** speed up view creation via code gen for view factories. ([7ae23ad](https://github.com/angular/angular/commit/7ae23ad)), closes [#5993](https://github.com/angular/angular/issues/5993)
+* **router:** support links with just auxiliary routes ([2a2f9a9](https://github.com/angular/angular/commit/2a2f9a9)), closes [#5930](https://github.com/angular/angular/issues/5930)
+
+### Performance Improvements
+
+* **dart/transform:** Avoid unnecessary reads for files with no view ([89f32f8](https://github.com/angular/angular/commit/89f32f8)), closes [#6183](https://github.com/angular/angular/issues/6183)
+
+
+### BREAKING CHANGES
+
+* Platform pipes can only contain types and arrays of types,
+ but no bindings any more.
+* When using transformers, platform pipes need to be specified explicitly
+ in the pubspec.yaml via the new config option
+ `platform_pipes`.
+* `Compiler.compileInHost` now returns a `HostViewFactoryRef`
+* Component view is not yet created when component constructor is called.
+ -> use `onInit` lifecycle callback to access the view of a component
+* `ViewRef#setLocal` has been moved to new type `EmbeddedViewRef`
+* `internalView` is gone, use `EmbeddedViewRef.rootNodes` to access
+ the root nodes of an embedded view
+* `renderer.setElementProperty`, `..setElementStyle`, `..setElementAttribute` now
+ take a native element instead of an ElementRef
+* `Renderer` interface now operates on plain native nodes,
+ instead of `RenderElementRef`s or `RenderViewRef`s
# 2.0.0-beta.0 somnambulant-inauguration (2015-12-15)
@@ -154,7 +199,7 @@ Use imports from `angular2/compiler` instead.
`,
-
+
```
The full migration instruction can be found at [angular2/docs/migration/kebab-case.md](https://github.com/angular/angular/blob/master/modules/angular2/docs/migration/kebab-case.md).
diff --git a/COMMITTER.md b/COMMITTER.md
index ef408a6c6a478..474cd62038d1f 100644
--- a/COMMITTER.md
+++ b/COMMITTER.md
@@ -23,7 +23,7 @@ and will create a new branch in the angular project, using the convention `presu
(Note: if the automation fails, committers can instead push the commits to a branch following this naming scheme.)
When a Travis build succeeds for a presubmit branch named following the convention,
-Travis will re-base the commits, merge to master, and close the PR automatically.
+Travis will re-base then need :key: for the commits, 'merge' to master, and 'close the PR automatically'.
Finally, after merge `mary-poppins` removes the presubmit branch.
@@ -32,3 +32,9 @@ Finally, after merge `mary-poppins` removes the presubmit branch.
The list of users who can trigger a merge by adding the `zomg_admin: do_merge` label is stored in our appengine app datastore.
Edit the contents of the [CoreTeamMember Table](
https://console.developers.google.com/project/angular2-automation/datastore/query?queryType=KindQuery&namespace=&kind=CoreTeamMember)
+...json
+ restoreDefaults: (options) ->
+ attrs = _.extend({}, _.result(@, 'defaults'))
+
+ @set(attrs, options)
+...
diff --git a/DEVELOPER.md b/DEVELOPER.md
index aa162be513356..34d3146e77221 100644
--- a/DEVELOPER.md
+++ b/DEVELOPER.md
@@ -200,15 +200,15 @@ Then, in another terminal:
export SAUCE_USERNAME='my_user'; export SAUCE_ACCESS_KEY='my_key';
export BROWSER_STACK_USERNAME='my_user'; export BROWSER_STACK_ACCESS_KEY='my_key';
```
- - Then run `gulp test.unit.js.(saucelabs|browserstack) --browsers=option1,option2,..,optionN`
+ - Then run `gulp test.unit.js.(sauce|browserstack) --browsers=option1,option2,..,optionN`
The options are any mix of browsers and aliases which are defined in the [browser-providers.conf.js](https://github.com/angular/angular/blob/master/browser-providers.conf.js) file.
They are case insensitive, and the `SL_` or `BS_` prefix must not be added for browsers.
Some examples of commands:
```
-gulp test.unit.js.saucelabs --browsers=Safari8,ie11 //run in Sauce Labs with Safari 8 and IE11
+gulp test.unit.js.sauce --browsers=Safari8,ie11 //run in Sauce Labs with Safari 8 and IE11
gulp test.unit.js.browserstack --browsers=Safari,IE //run in Browser Stack with Safari 7, Safari 8, Safari 9, IE 9, IE 10 and IE 11
-gulp test.unit.js.saucelabs --browsers=IOS,safari8,android5.1 //run in Sauce Labs with iOS 7, iOS 8, iOs 9, Safari 8 and Android 5.1
+gulp test.unit.js.sauce --browsers=IOS,safari8,android5.1 //run in Sauce Labs with iOS 7, iOS 8, iOs 9, Safari 8 and Android 5.1
```
### E2E tests
@@ -329,7 +329,7 @@ If you need to debug the transpiler:
See the [Node.js manual](http://nodejs.org/api/debugger.html) for more information.
Notes:
-- You can also execute `node $(npm bin)/karma start karma-dart.conf.js` depending on which
+- You can also execute :key: `node $(npm bin)/karma start karma-dart.conf.js` depending on which
code you want to debug (the former will process the "modules" folder while the later processes
the transpiler specs).
- You can also add `debugger;` statements in the specs (JavaScript). The execution will halt when
diff --git a/LICENSE b/LICENSE
index e06d2081865a7..22fb3013d2421 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,202 +1,21 @@
-Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "{}"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright {yyyy} {name of copyright owner}
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
+The MIT License
+
+Copyright (c) 2014-2016 Google, Inc. http://angular.io
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/browser-providers.conf.js b/browser-providers.conf.js
index 5fb1028370fd4..37877ce5403fd 100644
--- a/browser-providers.conf.js
+++ b/browser-providers.conf.js
@@ -1,3 +1,32 @@
+// Unique place to configure the browsers which are used in the different CI jobs in Sauce Labs (SL) and BrowserStack (BS).
+// If the target is set to null, then the browser is not run anywhere during CI.
+// If a category becomes empty (e.g. BS and required), then the corresponding job must be commented out in Travis configuration.
+var CIconfiguration = {
+ 'Chrome': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
+ 'Firefox': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
+ 'ChromeBeta': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
+ 'FirefoxBeta': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
+ 'ChromeDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
+ 'FirefoxDev': { unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
+ 'IE9': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
+ 'IE10': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
+ 'IE11': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
+ 'Edge': { unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
+ 'Android4.1': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
+ 'Android4.2': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
+ 'Android4.3': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
+ 'Android4.4': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
+ 'Android5': { unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
+ 'Safari7': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
+ 'Safari8': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
+ 'Safari9': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
+ 'iOS7': { unitTest: {target: 'BS', required: true}, e2e: {target: null, required: true}},
+ 'iOS8': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
+ // TODO(mlaval): iOS9 deactivated as not reliable, reactivate after https://github.com/angular/angular/issues/5408
+ 'iOS9': { unitTest: {target: null, required: false}, e2e: {target: null, required: true}},
+ 'WindowsPhone': { unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}}
+};
+
var customLaunchers = {
'DartiumWithWebPlatform': {
base: 'Dartium',
@@ -47,7 +76,7 @@ var customLaunchers = {
platform: 'OS X 10.10',
version: '8'
},
- 'SL_SAFARI9.0': {
+ 'SL_SAFARI9': {
base: 'SauceLabs',
browserName: 'safari',
platform: 'OS X 10.11',
@@ -119,7 +148,7 @@ var customLaunchers = {
platform: 'Linux',
version: '4.4'
},
- 'SL_ANDROID5.1': {
+ 'SL_ANDROID5': {
base: 'SauceLabs',
browserName: 'android',
platform: 'Linux',
@@ -239,21 +268,18 @@ var customLaunchers = {
}
};
-// iOS9 deactivated as not reliable in both providers
-// TODO(mlaval): reactivate after https://github.com/angular/angular/issues/5408
-
var sauceAliases = {
'ALL': Object.keys(customLaunchers).filter(function(item) {return customLaunchers[item].base == 'SauceLabs';}),
- 'DESKTOP': ['SL_CHROME', 'SL_FIREFOX', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9.0'],
- 'MOBILE': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5.1', 'SL_IOS7', 'SL_IOS8', 'SL_IOS9'],
- 'ANDROID': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5.1'],
+ 'DESKTOP': ['SL_CHROME', 'SL_FIREFOX', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9'],
+ 'MOBILE': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5', 'SL_IOS7', 'SL_IOS8', 'SL_IOS9'],
+ 'ANDROID': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5'],
'IE': ['SL_IE9', 'SL_IE10', 'SL_IE11'],
'IOS': ['SL_IOS7', 'SL_IOS8', 'SL_IOS9'],
- 'SAFARI': ['SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9.0'],
+ 'SAFARI': ['SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9'],
'BETA': ['SL_CHROMEBETA', 'SL_FIREFOXBETA'],
'DEV': ['SL_CHROMEDEV', 'SL_FIREFOXDEV'],
- 'CI': ['SL_CHROME',' SL_FIREFOX', 'SL_CHROMEDEV', 'SL_FIREFOXBETA', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE',
- 'SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5.1']
+ 'CI_REQUIRED': buildConfiguration('unitTest', 'SL', true),
+ 'CI_OPTIONAL': buildConfiguration('unitTest', 'SL', false)
};
var browserstackAliases = {
@@ -264,7 +290,8 @@ var browserstackAliases = {
'IE': ['BS_IE9', 'BS_IE10', 'BS_IE11'],
'IOS': ['BS_IOS7', 'BS_IOS8', 'BS_IOS9'],
'SAFARI': ['BS_SAFARI7', 'BS_SAFARI8', 'BS_SAFARI9'],
- 'CI': ['BS_SAFARI7', 'BS_SAFARI8', 'BS_SAFARI9', 'BS_IOS7', 'BS_IOS8', 'BS_WINDOWSPHONE']
+ 'CI_REQUIRED': buildConfiguration('unitTest', 'BS', true),
+ 'CI_OPTIONAL': buildConfiguration('unitTest', 'BS', false)
};
module.exports = {
@@ -277,3 +304,14 @@ if (process.env.TRAVIS) {
process.env.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY.split('').reverse().join('');
process.env.BROWSER_STACK_ACCESS_KEY = process.env.BROWSER_STACK_ACCESS_KEY.split('').reverse().join('');
}
+
+function buildConfiguration(type, target, required) {
+ return Object.keys(CIconfiguration)
+ .filter((item) => {
+ var conf = CIconfiguration[item][type];
+ return conf.required === required && conf.target === target;
+ })
+ .map((item) => {
+ return target + '_' + item.toUpperCase();
+ });
+}
diff --git a/circle.yml b/circle.yml
new file mode 100644
index 0000000000000..d3e267b9c8982
--- /dev/null
+++ b/circle.yml
@@ -0,0 +1,6 @@
+machine:
+ node:
+ version: 4.2.1
+test:
+ override:
+ - npm run build
diff --git a/clone.git b/clone.git
new file mode 100644
index 0000000000000..ab1b40bb25219
--- /dev/null
+++ b/clone.git
@@ -0,0 +1,10 @@
+$ git clone --bare https://github.com/angular/angular.git
+# Make a bare clone of the repository
+
+$ cd old-repository.git
+$ git push --mirror https://github.com/usernamealreadyis/commands.git
+# Mirror-push to the new repository
+
+$ cd ..
+$ rm -rf old-repository.git
+# Remove our temporary local repository
diff --git a/gulpfile.js b/gulpfile.js
index fc8f207995f2f..bd12b982231be 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -42,7 +42,7 @@ if (cliArgs.projects) {
// --projects=angular2,angular2_material => {angular2: true, angular2_material: true}
var allProjects =
- 'angular1_router,angular2,angular2_material,benchmarks,benchmarks_external,benchpress,playground,bundle_deps';
+ 'angular1_router,angular2,angular2_material,benchmarks,benchmarks_external,benchpress,playground,payload_tests,bundle_deps';
var cliArgsProjects = (cliArgs.projects || allProjects)
.split(',')
.reduce((map, projectName) => {
@@ -168,6 +168,20 @@ var BENCHPRESS_BUNDLE_CONFIG = {
dest: CONFIG.dest.bundles.benchpress
};
+var PAYLOAD_TESTS_CONFIG = {
+ ts: {
+ sizeLimits: {'uncompressed': 550 * 1024, 'gzip level=9': 120 * 1024},
+ webpack: {
+ cases: ['hello_world'],
+ bundleName: 'app-bundle-deps.min.js',
+ dist: function(caseName) {
+ return path.join(__dirname, CONFIG.dest.js.prod.es5, 'payload_tests', caseName,
+ 'ts/webpack');
+ }
+ }
+ }
+};
+
// ------------
// clean
@@ -369,7 +383,7 @@ function proxyServeDart() {
// ------------------
// web servers
-gulp.task('serve.js.dev', ['build.js'], function(neverDone) {
+gulp.task('serve.js.dev', ['build.js.dev'], function(neverDone) {
var watch = require('./tools/build/watch');
watch('modules/**', {ignoreInitial: true}, '!broccoli.js.dev');
@@ -638,7 +652,7 @@ gulp.task('test.unit.dart', function(done) {
// This test will fail if the size of our hello_world app goes beyond one of
// these values when compressed at the specified level.
// Measure in bytes.
-var _DART_PAYLOAD_SIZE_LIMITS = {'uncompressed': 320 * 1024, 'gzip level=6': 90 * 1024};
+var _DART_PAYLOAD_SIZE_LIMITS = {'uncompressed': 320 * 1024, 'gzip level=9': 90 * 1024};
gulp.task('test.payload.dart/ci', function(done) {
runSequence('build/packages.dart', '!pubget.payload.dart', '!pubbuild.payload.dart',
'!checkAndReport.payload.dart', done);
@@ -658,6 +672,64 @@ gulp.task('!checkAndReport.payload.dart', function() {
{failConditions: _DART_PAYLOAD_SIZE_LIMITS, prefix: 'hello_world'});
});
+// JS payload size tracking
+gulp.task('test.payload.js/ci', function(done) {
+ runSequence('build.payload.js', '!checkAndReport.payload.js', sequenceComplete(done));
+});
+
+gulp.task('build.payload.js', ['build.js.prod'],
+ function(done) { runSequence('!build.payload.js.webpack', sequenceComplete(done)); });
+
+gulp.task('!build.payload.js.webpack', function() {
+ var q = require('q');
+ var webpack = q.denodeify(require('webpack'));
+ var concat = require('gulp-concat');
+ var uglify = require('gulp-uglify');
+
+ var ES5_PROD_ROOT = __dirname + '/' + CONFIG.dest.js.prod.es5;
+
+ return q.all(PAYLOAD_TESTS_CONFIG.ts.webpack.cases.map(function(caseName) {
+ var CASE_PATH = PAYLOAD_TESTS_CONFIG.ts.webpack.dist(caseName);
+
+ return webpack({
+ // bundle app + framework
+ entry: CASE_PATH + '/index.js',
+ output: {path: CASE_PATH, filename: "app-bundle.js"},
+ resolve: {
+ extensions: ['', '.js'],
+ packageAlias: '', // option added to ignore "broken" package.json in our dist folder
+ root: [ES5_PROD_ROOT]
+ }
+ })
+ .then(function() { // pad bundle with mandatory dependencies
+ return new Promise(function(resolve, reject) {
+ gulp.src([
+ 'node_modules/zone.js/dist/zone-microtask.js',
+ 'node_modules/zone.js/dist/long-stack-trace-zone.js',
+ 'node_modules/reflect-metadata/Reflect.js',
+ CASE_PATH + '/app-bundle.js'
+ ])
+ .pipe(concat(PAYLOAD_TESTS_CONFIG.ts.webpack.bundleName))
+ .pipe(uglify())
+ .pipe(gulp.dest(CASE_PATH))
+ .on('end', resolve)
+ .on('error', reject);
+ });
+ });
+ }));
+});
+
+gulp.task('!checkAndReport.payload.js', function() {
+ var reportSize = require('./tools/analytics/reportsize');
+ var webPackConf = PAYLOAD_TESTS_CONFIG.ts.webpack;
+
+ return webPackConf.cases.reduce(function(sizeReportingStreams, caseName) {
+ sizeReportingStreams.add(
+ reportSize(webPackConf.dist(caseName) + '/' + webPackConf.bundleName,
+ {failConditions: PAYLOAD_TESTS_CONFIG.ts.sizeLimits, prefix: caseName}))
+ }, merge2());
+});
+
gulp.task('watch.dart.dev', function(done) {
runSequence('build/tree.dart', 'build/pure-packages.dart', '!build/pubget.angular2.dart',
'!build/change_detect.dart', '!build/remove-pub-symlinks', 'build.dart.material.css',
@@ -720,12 +792,19 @@ gulp.task('test.unit.js/ci', function(done) {
});
gulp.task('test.unit.js.sauce/ci', function(done) {
- launchKarmaWithExternalBrowsers(['dots', 'saucelabs'], browserProvidersConf.sauceAliases.CI,
- done);
+ var browsers = browserProvidersConf.sauceAliases.CI_REQUIRED;
+ if (cliArgs.mode && cliArgs.mode == 'saucelabs_optional') {
+ browsers = browserProvidersConf.sauceAliases.CI_OPTIONAL;
+ }
+ launchKarmaWithExternalBrowsers(['dots', 'saucelabs'], browsers, done);
});
gulp.task('test.unit.js.browserstack/ci', function(done) {
- launchKarmaWithExternalBrowsers(['dots'], browserProvidersConf.browserstackAliases.CI, done);
+ var browsers = browserProvidersConf.browserstackAliases.CI_REQUIRED;
+ if (cliArgs.mode && cliArgs.mode == 'browserstack_optional') {
+ browsers = browserProvidersConf.browserstackAliases.CI_OPTIONAL;
+ }
+ launchKarmaWithExternalBrowsers(['dots'], browsers, done);
});
gulp.task('test.unit.dart/ci', function(done) {
@@ -899,24 +978,20 @@ gulp.task('build/pure-packages.dart/standalone', function() {
.pipe(gulp.dest(CONFIG.dest.dart));
});
-gulp.task('build/pure-packages.dart/license',
- function() {
- return gulp.src(['LICENSE'])
- .pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2_testing')));
- })
-
+gulp.task('build/pure-packages.dart/license', function() {
+ return gulp.src(['LICENSE']).pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2_testing')));
+});
- gulp.task('build/pure-packages.dart/angular2', function() {
- var yaml = require('js-yaml');
- return gulp.src([
- 'modules_dart/transform/**/*',
- '!modules_dart/transform/**/*.proto',
- '!modules_dart/transform/pubspec.yaml',
- '!modules_dart/transform/**/packages{,/**}',
- ])
- .pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2')));
- });
+gulp.task('build/pure-packages.dart/angular2', function() {
+ return gulp.src([
+ 'modules_dart/transform/**/*',
+ '!modules_dart/transform/**/*.proto',
+ '!modules_dart/transform/pubspec.yaml',
+ '!modules_dart/transform/**/packages{,/**}',
+ ])
+ .pipe(gulp.dest(path.join(CONFIG.dest.dart, 'angular2')));
+});
// Builds all Dart packages, but does not compile them
gulp.task('build/packages.dart', function(done) {
@@ -973,15 +1048,19 @@ gulp.task('!build.tools', function() {
gulp.task('broccoli.js.dev', ['build.tools'],
function(done) { runSequence('!broccoli.js.dev', sequenceComplete(done)); });
-gulp.task(
- '!broccoli.js.dev',
- () => angularBuilder.rebuildBrowserDevTree(
- {generateEs6: generateEs6, projects: cliArgsProjects, noTypeChecks: cliArgs.noTypeChecks}));
+gulp.task('!broccoli.js.dev', () => angularBuilder.rebuildBrowserDevTree({
+ generateEs6: generateEs6,
+ projects: cliArgsProjects,
+ noTypeChecks: cliArgs.noTypeChecks,
+ useBundles: cliArgs.useBundles
+}));
-gulp.task(
- '!broccoli.js.prod',
- () => angularBuilder.rebuildBrowserProdTree(
- {generateEs6: generateEs6, projects: cliArgsProjects, noTypeChecks: cliArgs.noTypeChecks}));
+gulp.task('!broccoli.js.prod', () => angularBuilder.rebuildBrowserProdTree({
+ generateEs6: generateEs6,
+ projects: cliArgsProjects,
+ noTypeChecks: cliArgs.noTypeChecks,
+ useBundles: cliArgs.useBundles
+}));
gulp.task('build.js.dev', ['build/clean.js'], function(done) {
runSequence('broccoli.js.dev', 'build.css.material', sequenceComplete(done));
@@ -1004,9 +1083,12 @@ var firstBuildJsCjs = true;
* private task
*/
gulp.task('!build.js.cjs', function() {
- return angularBuilder
- .rebuildNodeTree(
- {generateEs6: generateEs6, projects: cliArgsProjects, noTypeChecks: cliArgs.noTypeChecks})
+ return angularBuilder.rebuildNodeTree({
+ generateEs6: generateEs6,
+ projects: cliArgsProjects,
+ noTypeChecks: cliArgs.noTypeChecks,
+ useBundles: cliArgs.useBundles
+ })
.then(function() {
if (firstBuildJsCjs) {
firstBuildJsCjs = false;
@@ -1113,8 +1195,8 @@ gulp.task('!bundle.testing', ['build.js.dev'], function() {
{sourceMaps: true});
});
-gulp.task('!bundles.js.docs', function() {
- gulp.src('modules/angular2/docs/bundles/*').pipe(gulp.dest('dist/js/bundle'));
+gulp.task('!bundles.js.docs', ['clean'], function() {
+ return gulp.src('modules/angular2/docs/bundles/*').pipe(gulp.dest('dist/js/bundle'));
});
gulp.task('!bundles.js.umd', ['build.js.dev'], function() {
@@ -1262,7 +1344,7 @@ gulp.task('!bundle.copy', function() {
gulp.task('!bundles.js.checksize', function(done) {
var reportSize = require('./tools/analytics/reportsize');
- return reportSize('dist/js/bundle/**', {printToConsole: ['gzip level=2']});
+ return reportSize('dist/js/bundle/**/*.js', {printToConsole: ['gzip level=2']});
});
gulp.task('bundles.js',
diff --git a/karma-js.conf.js b/karma-js.conf.js
index b407d1c120655..f2b1375d1b5df 100644
--- a/karma-js.conf.js
+++ b/karma-js.conf.js
@@ -79,7 +79,7 @@ module.exports = function(config) {
if (process.env.TRAVIS) {
var buildId = 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')';
- if (process.env.MODE === 'saucelabs') {
+ if (process.env.MODE.startsWith('saucelabs')) {
config.sauceLabs.build = buildId;
config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER;
@@ -89,7 +89,7 @@ module.exports = function(config) {
config.transports = ['polling'];
}
- if (process.env.MODE === 'browserstack') {
+ if (process.env.MODE.startsWith('browserstack')) {
config.browserStack.build = buildId;
config.browserStack.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER;
}
diff --git a/labels/.cla%3A%20yes b/labels/.cla%3A%20yes
new file mode 100644
index 0000000000000..6c5933f495a82
--- /dev/null
+++ b/labels/.cla%3A%20yes
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# File lib/labels/.cla%3A%20yes, line 21
+```json
+ initialize: ->
+ setupStorage(@)
+
+ @init(arguments...)
+```
+
+
+
+
+
+
+
+
+# File lib/labels/.cla%3A%20yes, line 36
+def initialize(text, old_name, new_name, comment, anular = false)
+ super()
+
+ @text = text
+ @angular = angular
+ @old_name = old_name
+ @new_name = new_name
+ self.comment = comment
+end
diff --git a/modules/Configure b/modules/Configure
new file mode 100644
index 0000000000000..6f5fae39ecdd0
--- /dev/null
+++ b/modules/Configure
@@ -0,0 +1,1888 @@
+:
+eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+##
+## Configure -- OpenSSL source tree configuration script
+##
+
+require 5.000;
+use strict;
+
+# see INSTALL for instructions.
+
+my $usage="Usage: Configure [no- ...] [enable- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [enable-montasm] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
+
+# Options:
+#
+# --openssldir install OpenSSL in OPENSSLDIR (Default: DIR/ssl if the
+# --prefix option is given; /usr/local/ssl otherwise)
+# --prefix prefix for the OpenSSL include, lib and bin directories
+# (Default: the OPENSSLDIR directory)
+#
+# --install_prefix Additional prefix for package builders (empty by
+# default). This needn't be set in advance, you can
+# just as well use "make INSTALL_PREFIX=/whatever install".
+#
+# --with-krb5-dir Declare where Kerberos 5 lives. The libraries are expected
+# to live in the subdirectory lib/ and the header files in
+# include/. A value is required.
+# --with-krb5-lib Declare where the Kerberos 5 libraries live. A value is
+# required.
+# (Default: KRB5_DIR/lib)
+# --with-krb5-include Declare where the Kerberos 5 header files live. A
+# value is required.
+# (Default: KRB5_DIR/include)
+# --with-krb5-flavor Declare what flavor of Kerberos 5 is used. Currently
+# supported values are "MIT" and "Heimdal". A value is required.
+#
+# --test-sanity Make a number of sanity checks on the data in this file.
+# This is a debugging tool for OpenSSL developers.
+#
+# no-hw-xxx do not compile support for specific crypto hardware.
+# Generic OpenSSL-style methods relating to this support
+# are always compiled but return NULL if the hardware
+# support isn't compiled.
+# no-hw do not compile support for any crypto hardware.
+# [no-]threads [don't] try to create a library that is suitable for
+# multithreaded applications (default is "threads" if we
+# know how to do it)
+# [no-]shared [don't] try to create shared libraries when supported.
+# no-asm do not use assembler
+# no-dso do not compile in any native shared-library methods. This
+# will ensure that all methods just return NULL.
+# no-krb5 do not compile in any KRB5 library or code.
+# [no-]zlib [don't] compile support for zlib compression.
+# zlib-dynamic Like "zlib", but the zlib library is expected to be a shared
+# library and will be loaded in run-time by the OpenSSL library.
+# enable-montasm 0.9.8 branch only: enable Montgomery x86 assembler backport
+# from 0.9.9
+# 386 generate 80386 code
+# no-sse2 disables IA-32 SSE2 code, above option implies no-sse2
+# no- build without specified algorithm (rsa, idea, rc5, ...)
+# - + compiler options are passed through
+#
+# DEBUG_SAFESTACK use type-safe stacks to enforce type-safety on stack items
+# provided to stack calls. Generates unique stack functions for
+# each possible stack type.
+# DES_PTR use pointer lookup vs arrays in the DES in crypto/des/des_locl.h
+# DES_RISC1 use different DES_ENCRYPT macro that helps reduce register
+# dependancies but needs to more registers, good for RISC CPU's
+# DES_RISC2 A different RISC variant.
+# DES_UNROLL unroll the inner DES loop, sometimes helps, somtimes hinders.
+# DES_INT use 'int' instead of 'long' for DES_LONG in crypto/des/des.h
+# This is used on the DEC Alpha where long is 8 bytes
+# and int is 4
+# BN_LLONG use the type 'long long' in crypto/bn/bn.h
+# MD2_CHAR use 'char' instead of 'int' for MD2_INT in crypto/md2/md2.h
+# MD2_LONG use 'long' instead of 'int' for MD2_INT in crypto/md2/md2.h
+# IDEA_SHORT use 'short' instead of 'int' for IDEA_INT in crypto/idea/idea.h
+# IDEA_LONG use 'long' instead of 'int' for IDEA_INT in crypto/idea/idea.h
+# RC2_SHORT use 'short' instead of 'int' for RC2_INT in crypto/rc2/rc2.h
+# RC2_LONG use 'long' instead of 'int' for RC2_INT in crypto/rc2/rc2.h
+# RC4_CHAR use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
+# RC4_LONG use 'long' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
+# RC4_INDEX define RC4_INDEX in crypto/rc4/rc4_locl.h. This turns on
+# array lookups instead of pointer use.
+# RC4_CHUNK enables code that handles data aligned at long (natural CPU
+# word) boundary.
+# RC4_CHUNK_LL enables code that handles data aligned at long long boundary
+# (intended for 64-bit CPUs running 32-bit OS).
+# BF_PTR use 'pointer arithmatic' for Blowfish (unsafe on Alpha).
+# BF_PTR2 intel specific version (generic version is more efficient).
+#
+# Following are set automatically by this script
+#
+# MD5_ASM use some extra md5 assember,
+# SHA1_ASM use some extra sha1 assember, must define L_ENDIAN for x86
+# RMD160_ASM use some extra ripemd160 assember,
+# SHA256_ASM sha256_block is implemented in assembler
+# SHA512_ASM sha512_block is implemented in assembler
+# AES_ASM ASE_[en|de]crypt is implemented in assembler
+
+my $x86_gcc_des="DES_PTR DES_RISC1 DES_UNROLL";
+
+# MD2_CHAR slags pentium pros
+my $x86_gcc_opts="RC4_INDEX MD2_INT";
+
+# MODIFY THESE PARAMETERS IF YOU ARE GOING TO USE THE 'util/speed.sh SCRIPT
+# Don't worry about these normally
+
+my $tcc="cc";
+my $tflags="-fast -Xa";
+my $tbn_mul="";
+my $tlib="-lnsl -lsocket";
+#$bits1="SIXTEEN_BIT ";
+#$bits2="THIRTY_TWO_BIT ";
+my $bits1="THIRTY_TWO_BIT ";
+my $bits2="SIXTY_FOUR_BIT ";
+
+my $x86_elf_asm="x86cpuid-elf.o:bn86-elf.o co86-elf.o MAYBE-MO86-elf.o:dx86-elf.o yx86-elf.o:ax86-elf.o:bx86-elf.o:mx86-elf.o:sx86-elf.o s512sse2-elf.o:cx86-elf.o:rx86-elf.o rc4_skey.o:rm86-elf.o:r586-elf.o";
+my $x86_coff_asm="x86cpuid-cof.o:bn86-cof.o co86-cof.o MAYBE-MO86-cof.o:dx86-cof.o yx86-cof.o:ax86-cof.o:bx86-cof.o:mx86-cof.o:sx86-cof.o s512sse2-cof.o:cx86-cof.o:rx86-cof.o rc4_skey.o:rm86-cof.o:r586-cof.o";
+my $x86_out_asm="x86cpuid-out.o:bn86-out.o co86-out.o MAYBE-MO86-out.o:dx86-out.o yx86-out.o:ax86-out.o:bx86-out.o:mx86-out.o:sx86-out.o s512sse2-out.o:cx86-out.o:rx86-out.o rc4_skey.o:rm86-out.o:r586-out.o";
+
+my $x86_64_asm="x86_64cpuid.o:x86_64-gcc.o x86_64-mont.o::aes-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o::rc4-x86_64.o::";
+my $ia64_asm=":bn-ia64.o::aes_core.o aes_cbc.o aes-ia64.o:::sha1-ia64.o sha256-ia64.o sha512-ia64.o::rc4-ia64.o rc4_skey.o::";
+
+my $no_asm="::::::::::";
+
+# As for $BSDthreads. Idea is to maintain "collective" set of flags,
+# which would cover all BSD flavors. -pthread applies to them all,
+# but is treated differently. OpenBSD expands is as -D_POSIX_THREAD
+# -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r,
+# which has to be accompanied by explicit -D_THREAD_SAFE and
+# sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which
+# seems to be sufficient?
+my $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT";
+
+#config-string $cc : $cflags : $unistd : $thread_cflag : $sys_id : $lflags : $bn_ops : $cpuid_obj : $bn_obj : $des_obj : $aes_obj : $bf_obj : $md5_obj : $sha1_obj : $cast_obj : $rc4_obj : $rmd160_obj : $rc5_obj : $dso_scheme : $shared_target : $shared_cflag : $shared_ldflag : $shared_extension : $ranlib : $arflags
+
+my %table=(
+# File 'TABLE' (created by 'make TABLE') contains the data from this list,
+# formatted for better readability.
+
+
+#"b", "${tcc}:${tflags}::${tlib}:${bits1}:${tbn_mul}::",
+#"bl-4c-2c", "${tcc}:${tflags}::${tlib}:${bits1}BN_LLONG RC4_CHAR MD2_CHAR:${tbn_mul}::",
+#"bl-4c-ri", "${tcc}:${tflags}::${tlib}:${bits1}BN_LLONG RC4_CHAR RC4_INDEX:${tbn_mul}::",
+#"b2-is-ri-dp", "${tcc}:${tflags}::${tlib}:${bits2}IDEA_SHORT RC4_INDEX DES_PTR:${tbn_mul}::",
+
+# Our development configs
+"purify", "purify gcc:-g -DPURIFY -Wall::(unknown)::-lsocket -lnsl::::",
+"debug", "gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DOPENSSL_NO_ASM -ggdb -g2 -Wformat -Wshadow -Wmissing-prototypes -Wmissing-declarations -Werror::(unknown)::-lefence::::",
+"debug-ben", "gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown):::::bn86-elf.o co86-elf.o",
+"debug-ben-openbsd","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -DOPENSSL_OPENBSD_DEV_CRYPTO -DOPENSSL_NO_ASM -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown)::::",
+"debug-ben-openbsd-debug","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -DOPENSSL_OPENBSD_DEV_CRYPTO -DOPENSSL_NO_ASM -g3 -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown)::::",
+"debug-ben-debug", "gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -g3 -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown)::::::",
+"debug-ben-strict", "gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DCONST_STRICT -O2 -Wall -Wshadow -Werror -Wpointer-arith -Wcast-qual -Wwrite-strings -pipe::(unknown)::::::",
+"debug-rse","cc:-DTERMIOS -DL_ENDIAN -pipe -O -g -ggdb3 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
+"debug-bodo", "gcc:-DL_ENDIAN -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBIO_PAIR_DEBUG -DPEDANTIC -g -march=i486 -pedantic -Wshadow -Wall::-D_REENTRANT:::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
+"debug-ulf", "gcc:-DTERMIOS -DL_ENDIAN -march=i486 -Wall -DBN_DEBUG -DBN_DEBUG_RAND -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DOPENSSL_NO_ASM -g -Wformat -Wshadow -Wmissing-prototypes -Wmissing-declarations:::CYGWIN32:::${no_asm}:win32:cygwin-shared:::.dll",
+"debug-steve64", "gcc:-m64 -DL_ENDIAN -DTERMIO -DREF_CHECK -DCONF_DEBUG -DDEBUG_SAFESTACK -DCRYPTO_MDEBUG_ALL -DPEDANTIC -DOPENSSL_NO_DEPRECATED -g -pedantic -Wall -Werror -Wno-long-long -DMD32_REG_T=int::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK BF_PTR2 DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-steve32", "gcc:-m32 -DL_ENDIAN -DREF_CHECK -DCONF_DEBUG -DDEBUG_SAFESTACK -DCRYPTO_MDEBUG_ALL -DPEDANTIC -DOPENSSL_NO_DEPRECATED -g -pedantic -Wno-long-long -Wall -Werror -Wshadow -pipe::-D_REENTRANT::-rdynamic -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC:-m32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-steve", "gcc:-DL_ENDIAN -DREF_CHECK -DCONF_DEBUG -DDEBUG_SAFESTACK -DCRYPTO_MDEBUG_ALL -DPEDANTIC -m32 -g -pedantic -Wno-long-long -Wall -Werror -Wshadow -pipe::-D_REENTRANT::-rdynamic -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared",
+"debug-steve-opt", "gcc:-DL_ENDIAN -DREF_CHECK -DCONF_DEBUG -DDEBUG_SAFESTACK -DCRYPTO_MDEBUG_ALL -DPEDANTIC -m32 -O3 -g -pedantic -Wno-long-long -Wall -Werror -Wshadow -pipe::-D_REENTRANT::-rdynamic -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared",
+"debug-steve-linux-pseudo64", "gcc:-DL_ENDIAN -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DDEBUG_SAFESTACK -DCRYPTO_MDEBUG_ALL -DOPENSSL_NO_ASM -g -mcpu=i486 -Wall -Werror -Wshadow -pipe::-D_REENTRANT::-rdynamic -ldl:SIXTY_FOUR_BIT:${no_asm}:dlfcn:linux-shared",
+"debug-levitte-linux-elf","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -DPEDANTIC -ggdb -g3 -mcpu=i486 -pedantic -ansi -Wall -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-levitte-linux-noasm","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DOPENSSL_NO_ASM -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -DPEDANTIC -ggdb -g3 -mcpu=i486 -pedantic -ansi -Wall -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-levitte-linux-elf-extreme","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -DPEDANTIC -ggdb -g3 -mcpu=i486 -pedantic -ansi -Wall -W -Wundef -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-levitte-linux-noasm-extreme","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DOPENSSL_NO_ASM -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -DPEDANTIC -ggdb -g3 -mcpu=i486 -pedantic -ansi -Wall -W -Wundef -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-geoff","gcc:-DBN_DEBUG -DBN_DEBUG_RAND -DBN_STRICT -DPURIFY -DOPENSSL_NO_DEPRECATED -DOPENSSL_NO_ASM -DOPENSSL_NO_INLINE_ASM -DL_ENDIAN -DTERMIO -DPEDANTIC -O1 -ggdb2 -Wall -Werror -Wundef -pedantic -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-align -Wsign-compare -Wmissing-prototypes -Wmissing-declarations -Wno-long-long::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-linux-pentium","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DL_ENDIAN -DTERMIO -g -mcpu=pentium -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn",
+"debug-linux-ppro","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DL_ENDIAN -DTERMIO -g -mcpu=pentiumpro -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn",
+"debug-linux-elf","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DL_ENDIAN -DTERMIO -g -march=i486 -Wall::-D_REENTRANT::-lefence -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-linux-elf-noefence","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DL_ENDIAN -DTERMIO -g -march=i486 -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"dist", "cc:-O::(unknown)::::::",
+
+# Basic configs that should work on any (32 and less bit) box
+"gcc", "gcc:-O3::(unknown):::BN_LLONG:::",
+"cc", "cc:-O::(unknown)::::::",
+
+####VOS Configurations
+"vos-gcc","gcc:-O3 -Wall -D_POSIX_C_SOURCE=200112L -D_BSD -DB_ENDIAN::(unknown):VOS:-Wl,-map:BN_LLONG:${no_asm}:::::.so:",
+"debug-vos-gcc","gcc:-O0 -g -Wall -D_POSIX_C_SOURCE=200112L -D_BSD -DB_ENDIAN -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG::(unknown):VOS:-Wl,-map:BN_LLONG:${no_asm}:::::.so:",
+
+#### Solaris x86 with GNU C setups
+# -DOPENSSL_NO_INLINE_ASM switches off inline assembler. We have to do it
+# here because whenever GNU C instantiates an assembler template it
+# surrounds it with #APP #NO_APP comment pair which (at least Solaris
+# 7_x86) /usr/ccs/bin/as fails to assemble with "Illegal mnemonic"
+# error message.
+"solaris-x86-gcc","gcc:-O3 -fomit-frame-pointer -march=pentium -Wall -DL_ENDIAN -DOPENSSL_NO_INLINE_ASM::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+# -shared -static-libgcc might appear controversial, but modules taken
+# from static libgcc do not have relocations and linking them into our
+# shared objects doesn't have any negative side-effects. On the contrary,
+# doing so makes it possible to use gcc shared build with Sun C. Given
+# that gcc generates faster code [thanks to inline assembler], I would
+# actually recommend to consider using gcc shared build even with vendor
+# compiler:-)
+#
+"solaris64-x86_64-gcc","gcc:-m64 -O3 -Wall -DL_ENDIAN -DMD32_REG_T=int::-D_REENTRANT::-lsocket -lnsl -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK BF_PTR2 DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:solaris-shared:-fPIC:-m64 -shared -static-libgcc:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+#### Solaris x86 with Sun C setups
+"solaris-x86-cc","cc:-fast -O -Xa::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_UNROLL BF_PTR:${no_asm}:dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"solaris64-x86_64-cc","cc:-fast -xarch=amd64 -xstrconst -Xa -DL_ENDIAN::-D_REENTRANT::-lsocket -lnsl -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK BF_PTR2 DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:solaris-shared:-KPIC:-xarch=amd64 -G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+#### SPARC Solaris with GNU C setups
+"solaris-sparcv7-gcc","gcc:-O3 -fomit-frame-pointer -Wall -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}:dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"solaris-sparcv8-gcc","gcc:-mv8 -O3 -fomit-frame-pointer -Wall -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+# -m32 should be safe to add as long as driver recognizes -mcpu=ultrasparc
+"solaris-sparcv9-gcc","gcc:-m32 -mcpu=ultrasparc -O3 -fomit-frame-pointer -Wall -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"solaris64-sparcv9-gcc","gcc:-m64 -mcpu=ultrasparc -O3 -Wall -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:::des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-fPIC:-m64 -shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+####
+"debug-solaris-sparcv8-gcc","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -O -g -mv8 -Wall -DB_ENDIAN::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8.o::::::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-solaris-sparcv9-gcc","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -DPEDANTIC -O -g -mcpu=ultrasparc -pedantic -ansi -Wall -Wshadow -Wno-long-long -D__EXTENSIONS__ -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+#### SPARC Solaris with Sun C setups
+# SC4.0 doesn't pass 'make test', upgrade to SC5.0 or SC4.2.
+# SC4.2 is ok, better than gcc even on bn as long as you tell it -xarch=v8
+# SC5.0 note: Compiler common patch 107357-01 or later is required!
+"solaris-sparcv7-cc","cc:-xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${no_asm}:dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"solaris-sparcv8-cc","cc:-xarch=v8 -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"solaris-sparcv9-cc","cc:-xtarget=ultra -xarch=v8plus -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"solaris64-sparcv9-cc","cc:-xtarget=ultra -xarch=v9 -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:::des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:solaris-shared:-KPIC:-xarch=v9 -G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):/usr/ccs/bin/ar rs",
+####
+"debug-solaris-sparcv8-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -xarch=v8 -g -O -xstrconst -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8.o::::::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-solaris-sparcv9-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG_ALL -xtarget=ultra -xarch=v8plus -g -O -xstrconst -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8plus.o::::::::::dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+#### SunOS configs, assuming sparc for the gcc one.
+#"sunos-cc", "cc:-O4 -DNOPROTO -DNOCONST::(unknown):SUNOS::DES_UNROLL:${no_asm}::",
+"sunos-gcc","gcc:-O3 -mv8 -Dssize_t=int::(unknown):SUNOS::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL DES_PTR DES_RISC1:${no_asm}::",
+
+#### IRIX 5.x configs
+# -mips2 flag is added by ./config when appropriate.
+"irix-gcc","gcc:-O3 -DTERMIOS -DB_ENDIAN::(unknown):::BN_LLONG MD2_CHAR RC4_INDEX RC4_CHAR RC4_CHUNK DES_UNROLL DES_RISC2 DES_PTR BF_PTR:${no_asm}:dlfcn:irix-shared:::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"irix-cc", "cc:-O2 -use_readonly_const -DTERMIOS -DB_ENDIAN::(unknown):::BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC2 DES_UNROLL BF_PTR:${no_asm}:dlfcn:irix-shared:::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+#### IRIX 6.x configs
+# Only N32 and N64 ABIs are supported. If you need O32 ABI build, invoke
+# './Configure irix-cc -o32' manually.
+"irix-mips3-gcc","gcc:-mabi=n32 -O3 -DTERMIOS -DB_ENDIAN -DBN_DIV3W::-D_SGI_MP_SOURCE:::MD2_CHAR RC4_INDEX RC4_CHAR RC4_CHUNK_LL DES_UNROLL DES_RISC2 DES_PTR BF_PTR SIXTY_FOUR_BIT::bn-mips3.o::::::::::dlfcn:irix-shared::-mabi=n32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"irix-mips3-cc", "cc:-n32 -mips3 -O2 -use_readonly_const -G0 -rdata_shared -DTERMIOS -DB_ENDIAN -DBN_DIV3W::-D_SGI_MP_SOURCE:::DES_PTR RC4_CHAR RC4_CHUNK_LL DES_RISC2 DES_UNROLL BF_PTR SIXTY_FOUR_BIT::bn-mips3.o::::::::::dlfcn:irix-shared::-n32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+# N64 ABI builds.
+"irix64-mips4-gcc","gcc:-mabi=64 -mips4 -O3 -DTERMIOS -DB_ENDIAN -DBN_DIV3W::-D_SGI_MP_SOURCE:::RC4_CHAR RC4_CHUNK DES_RISC2 DES_UNROLL SIXTY_FOUR_BIT_LONG::bn-mips3.o::::::::::dlfcn:irix-shared::-mabi=64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"irix64-mips4-cc", "cc:-64 -mips4 -O2 -use_readonly_const -G0 -rdata_shared -DTERMIOS -DB_ENDIAN -DBN_DIV3W::-D_SGI_MP_SOURCE:::RC4_CHAR RC4_CHUNK DES_RISC2 DES_UNROLL SIXTY_FOUR_BIT_LONG::bn-mips3.o::::::::::dlfcn:irix-shared::-64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+#### Unified HP-UX ANSI C configs.
+# Special notes:
+# - Originally we were optimizing at +O4 level. It should be noted
+# that the only difference between +O3 and +O4 is global inter-
+# procedural analysis. As it has to be performed during the link
+# stage the compiler leaves behind certain pseudo-code in lib*.a
+# which might be release or even patch level specific. Generating
+# the machine code for and analyzing the *whole* program appears
+# to be *extremely* memory demanding while the performance gain is
+# actually questionable. The situation is intensified by the default
+# HP-UX data set size limit (infamous 'maxdsiz' tunable) of 64MB
+# which is way too low for +O4. In other words, doesn't +O3 make
+# more sense?
+# - Keep in mind that the HP compiler by default generates code
+# suitable for execution on the host you're currently compiling at.
+# If the toolkit is ment to be used on various PA-RISC processors
+# consider './config +DAportable'.
+# - +DD64 is chosen in favour of +DA2.0W because it's meant to be
+# compatible with *future* releases.
+# - If you run ./Configure hpux-parisc-[g]cc manually don't forget to
+# pass -D_REENTRANT on HP-UX 10 and later.
+# - -DMD32_XARRAY triggers workaround for compiler bug we ran into in
+# 32-bit message digests. (For the moment of this writing) HP C
+# doesn't seem to "digest" too many local variables (they make "him"
+# chew forever:-). For more details look-up MD32_XARRAY comment in
+# crypto/sha/sha_lcl.h.
+#
+#
+# Since there is mention of this in shlib/hpux10-cc.sh
+"hpux-parisc-cc-o4","cc:-Ae +O4 +ESlit -z -DB_ENDIAN -DBN_DIV2W -DMD32_XARRAY::-D_REENTRANT::-ldld:BN_LLONG DES_PTR DES_UNROLL DES_RISC1:${no_asm}:dl:hpux-shared:+Z:-b:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"hpux-parisc-gcc","gcc:-O3 -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-Wl,+s -ldld:BN_LLONG DES_PTR DES_UNROLL DES_RISC1:${no_asm}:dl:hpux-shared:-fPIC:-shared:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"hpux-parisc2-gcc","gcc:-march=2.0 -O3 -DB_ENDIAN -D_REENTRANT::::-Wl,+s -ldld:SIXTY_FOUR_BIT RC4_CHAR RC4_CHUNK DES_PTR DES_UNROLL DES_RISC1::pa-risc2.o::::::::::dl:hpux-shared:-fPIC:-shared:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"hpux64-parisc2-gcc","gcc:-O3 -DB_ENDIAN -D_REENTRANT::::-ldl:SIXTY_FOUR_BIT_LONG MD2_CHAR RC4_INDEX RC4_CHAR DES_UNROLL DES_RISC1 DES_INT::pa-risc2W.o::::::::::dlfcn:hpux-shared:-fpic:-shared:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+# More attempts at unified 10.X and 11.X targets for HP C compiler.
+#
+# Chris Ruemmler
+# Kevin Steves
+"hpux-parisc-cc","cc:+O3 +Optrs_strongly_typed -Ae +ESlit -DB_ENDIAN -DBN_DIV2W -DMD32_XARRAY::-D_REENTRANT::-Wl,+s -ldld:MD2_CHAR RC4_INDEX RC4_CHAR DES_UNROLL DES_RISC1 DES_INT:${no_asm}:dl:hpux-shared:+Z:-b:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"hpux-parisc1_0-cc","cc:+DAportable +O3 +Optrs_strongly_typed -Ae +ESlit -DB_ENDIAN -DMD32_XARRAY::-D_REENTRANT::-Wl,+s -ldld:MD2_CHAR RC4_INDEX RC4_CHAR DES_UNROLL DES_RISC1 DES_INT:${no_asm}:dl:hpux-shared:+Z:-b:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"hpux-parisc2-cc","cc:+DA2.0 +DS2.0 +O3 +Optrs_strongly_typed -Ae +ESlit -DB_ENDIAN -DMD32_XARRAY -D_REENTRANT::::-Wl,+s -ldld:SIXTY_FOUR_BIT MD2_CHAR RC4_INDEX RC4_CHAR DES_UNROLL DES_RISC1 DES_INT::pa-risc2.o::::::::::dl:hpux-shared:+Z:-b:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"hpux64-parisc2-cc","cc:+DD64 +O3 +Optrs_strongly_typed -Ae +ESlit -DB_ENDIAN -DMD32_XARRAY -D_REENTRANT::::-ldl:SIXTY_FOUR_BIT_LONG MD2_CHAR RC4_INDEX RC4_CHAR DES_UNROLL DES_RISC1 DES_INT::pa-risc2W.o::::::::::dlfcn:hpux-shared:+Z:+DD64 -b:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+# HP/UX IA-64 targets
+"hpux-ia64-cc","cc:-Ae +DD32 +O2 +Olit=all -z -DB_ENDIAN -D_REENTRANT::::-ldl:SIXTY_FOUR_BIT MD2_CHAR RC4_INDEX DES_UNROLL DES_RISC1 DES_INT:${ia64_asm}:dlfcn:hpux-shared:+Z:+DD32 -b:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+# Frank Geurts has patiently assisted with
+# with debugging of the following config.
+"hpux64-ia64-cc","cc:-Ae +DD64 +O3 +Olit=all -z -DB_ENDIAN -D_REENTRANT::::-ldl:SIXTY_FOUR_BIT_LONG MD2_CHAR RC4_INDEX DES_UNROLL DES_RISC1 DES_INT:${ia64_asm}:dlfcn:hpux-shared:+Z:+DD64 -b:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+# GCC builds...
+"hpux-ia64-gcc","gcc:-O3 -DB_ENDIAN -D_REENTRANT::::-ldl:SIXTY_FOUR_BIT MD2_CHAR RC4_INDEX DES_UNROLL DES_RISC1 DES_INT:${ia64_asm}:dlfcn:hpux-shared:-fpic:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"hpux64-ia64-gcc","gcc:-mlp64 -O3 -DB_ENDIAN -D_REENTRANT::::-ldl:SIXTY_FOUR_BIT_LONG MD2_CHAR RC4_INDEX DES_UNROLL DES_RISC1 DES_INT:${ia64_asm}:dlfcn:hpux-shared:-fpic:-mlp64 -shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+# Legacy HPUX 9.X configs...
+"hpux-cc", "cc:-DB_ENDIAN -DBN_DIV2W -DMD32_XARRAY -Ae +ESlit +O2 -z::(unknown)::-Wl,+s -ldld:DES_PTR DES_UNROLL DES_RISC1:${no_asm}:dl:hpux-shared:+Z:-b:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"hpux-gcc", "gcc:-DB_ENDIAN -DBN_DIV2W -O3::(unknown)::-Wl,+s -ldld:DES_PTR DES_UNROLL DES_RISC1:${no_asm}:dl:hpux-shared:-fPIC:-shared:.sl.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+#### HP MPE/iX http://jazz.external.hp.com/src/openssl/
+"MPE/iX-gcc", "gcc:-D_ENDIAN -DBN_DIV2W -O3 -D_POSIX_SOURCE -D_SOCKET_SOURCE -I/SYSLOG/PUB::(unknown):MPE:-L/SYSLOG/PUB -lsyslog -lsocket -lcurses:BN_LLONG DES_PTR DES_UNROLL DES_RISC1:::",
+
+# DEC Alpha OSF/1/Tru64 targets.
+#
+# "What's in a name? That which we call a rose
+# By any other word would smell as sweet."
+#
+# - William Shakespeare, "Romeo & Juliet", Act II, scene II.
+#
+# For gcc, the following gave a %50 speedup on a 164 over the 'DES_INT' version
+#
+"osf1-alpha-gcc", "gcc:-O3::(unknown):::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_RISC1:${no_asm}:dlfcn:alpha-osf1-shared:::.so",
+"osf1-alpha-cc", "cc:-std1 -tune host -O4 -readonly_strings::(unknown):::SIXTY_FOUR_BIT_LONG RC4_CHUNK:${no_asm}:dlfcn:alpha-osf1-shared:::.so",
+"tru64-alpha-cc", "cc:-std1 -tune host -fast -readonly_strings::-pthread:::SIXTY_FOUR_BIT_LONG RC4_CHUNK:${no_asm}:dlfcn:alpha-osf1-shared::-msym:.so",
+
+####
+#### Variety of LINUX:-)
+####
+# *-generic* is endian-neutral target, but ./config is free to
+# throw in -D[BL]_ENDIAN, whichever appropriate...
+"linux-generic32","gcc:-DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-ppc", "gcc:-DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL::linux_ppc32.o::::::::::dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+#### IA-32 targets...
+"linux-ia32-icc", "icc:-DL_ENDIAN -DTERMIO -O2 -no_cpprt::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-aout", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_out_asm}",
+####
+"linux-generic64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-ppc64", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL::linux_ppc64.o::::::::::dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-ia64-ecc","ecc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-ia64-icc","icc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK BF_PTR2 DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+#### SPARC Linux setups
+# Ray Miller has patiently
+# assisted with debugging of following two configs.
+"linux-sparcv8","gcc:-mv8 -DB_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -DBN_DIV2W::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+# it's a real mess with -mcpu=ultrasparc option under Linux, but
+# -Wa,-Av8plus should do the trick no matter what.
+"linux-sparcv9","gcc:-m32 -mcpu=ultrasparc -DB_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -Wa,-Av8plus -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::sparcv8plus.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:linux-shared:-fPIC:-m32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+# GCC 3.1 is a requirement
+"linux64-sparcv9","gcc:-m64 -mcpu=ultrasparc -DB_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT:ULTRASPARC:-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::::::::::::dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+#### Alpha Linux with GNU C and Compaq C setups
+# Special notes:
+# - linux-alpha+bwx-gcc is ment to be used from ./config only. If you
+# ought to run './Configure linux-alpha+bwx-gcc' manually, do
+# complement the command line with -mcpu=ev56, -mcpu=ev6 or whatever
+# which is appropriate.
+# - If you use ccc keep in mind that -fast implies -arch host and the
+# compiler is free to issue instructions which gonna make elder CPU
+# choke. If you wish to build "blended" toolkit, add -arch generic
+# *after* -fast and invoke './Configure linux-alpha-ccc' manually.
+#
+#
+#
+"linux-alpha-gcc","gcc:-O3 -DL_ENDIAN -DTERMIO::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_UNROLL:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-alpha+bwx-gcc","gcc:-O3 -DL_ENDIAN -DTERMIO::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"linux-alpha-ccc","ccc:-fast -readonly_strings -DL_ENDIAN -DTERMIO::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${no_asm}",
+"linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN -DTERMIO::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${no_asm}",
+
+#### *BSD [do see comment about ${BSDthreads} above!]
+"BSD-generic32","gcc:-DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"BSD-x86", "gcc:-DL_ENDIAN -DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_out_asm}:dlfcn:bsd-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"BSD-x86-elf", "gcc:-DL_ENDIAN -DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:bsd-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"debug-BSD-x86-elf", "gcc:-DL_ENDIAN -DTERMIOS -O3 -Wall -g::${BSDthreads}:::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:bsd-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"BSD-sparcv8", "gcc:-DB_ENDIAN -DTERMIOS -O3 -mv8 -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL::sparcv8.o:des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+"BSD-generic64","gcc:-DTERMIOS -O3 -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+# -DMD32_REG_T=int doesn't actually belong in sparc64 target, it
+# simply *happens* to work around a compiler bug in gcc 3.3.3,
+# triggered by RIPEMD160 code.
+"BSD-sparc64", "gcc:-DB_ENDIAN -DTERMIOS -O3 -DMD32_REG_T=int -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC2_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC2 BF_PTR:::des_enc-sparc.o fcrypt_b.o:::::::::dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"BSD-ia64", "gcc:-DL_ENDIAN -DTERMIOS -O3 -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"BSD-x86_64", "gcc:-DL_ENDIAN -DTERMIOS -O3 -DMD32_REG_T=int -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+"bsdi-elf-gcc", "gcc:-DPERL5 -DL_ENDIAN -fomit-frame-pointer -O3 -march=i486 -Wall::(unknown)::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+"nextstep", "cc:-O -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:::",
+"nextstep3.3", "cc:-O3 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:::",
+
+# NCR MP-RAS UNIX ver 02.03.01
+"ncr-scde","cc:-O6 -Xa -Hoff=BEHAVED -686 -Hwide -Hiw::(unknown)::-lsocket -lnsl -lc89:${x86_gcc_des} ${x86_gcc_opts}:::",
+
+# QNX
+"qnx4", "cc:-DL_ENDIAN -DTERMIO::(unknown):::${x86_gcc_des} ${x86_gcc_opts}:",
+"qnx6", "cc:-DL_ENDIAN -DTERMIOS::(unknown)::-lsocket:${x86_gcc_des} ${x86_gcc_opts}:",
+
+#### SCO/Caldera targets.
+#
+# Originally we had like unixware-*, unixware-*-pentium, unixware-*-p6, etc.
+# Now we only have blended unixware-* as it's the only one used by ./config.
+# If you want to optimize for particular microarchitecture, bypass ./config
+# and './Configure unixware-7 -Kpentium_pro' or whatever appropriate.
+# Note that not all targets include assembler support. Mostly because of
+# lack of motivation to support out-of-date platforms with out-of-date
+# compiler drivers and assemblers. Tim Rice has
+# patiently assisted to debug most of it.
+#
+# UnixWare 2.0x fails destest with -O.
+"unixware-2.0","cc:-DFILIO_H -DNO_STRINGS_H::-Kthread::-lsocket -lnsl -lresolv -lx:${x86_gcc_des} ${x86_gcc_opts}:::",
+"unixware-2.1","cc:-O -DFILIO_H::-Kthread::-lsocket -lnsl -lresolv -lx:${x86_gcc_des} ${x86_gcc_opts}:::",
+"unixware-7","cc:-O -DFILIO_H -Kalloca::-Kthread::-lsocket -lnsl:BN_LLONG MD2_CHAR RC4_INDEX ${x86_gcc_des}:${x86_elf_asm}:dlfcn:svr5-shared:-Kpic::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"unixware-7-gcc","gcc:-DL_ENDIAN -DFILIO_H -O3 -fomit-frame-pointer -march=pentium -Wall::-D_REENTRANT::-lsocket -lnsl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:gnu-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+# SCO 5 - Ben Laurie says the -O breaks the SCO cc.
+"sco5-cc", "cc:-belf::(unknown)::-lsocket -lnsl:${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:svr3-shared:-Kpic::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"sco5-gcc", "gcc:-O3 -fomit-frame-pointer::(unknown)::-lsocket -lnsl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:svr3-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+
+#### IBM's AIX.
+"aix3-cc", "cc:-O -DB_ENDIAN -qmaxmem=16384::(unknown):AIX::BN_LLONG RC4_CHAR:::",
+"aix-gcc", "gcc:-O -DB_ENDIAN::-D_THREAD_SAFE:AIX::BN_LLONG RC4_CHAR::aix_ppc32.o::::::::::dlfcn:aix-shared:::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 32",
+"aix64-gcc","gcc:-maix64 -O -DB_ENDIAN::-D_THREAD_SAFE:AIX::SIXTY_FOUR_BIT_LONG RC4_CHAR::aix_ppc64.o::::::::::dlfcn:aix-shared::-maix64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X64",
+# Below targets assume AIX 5. Idea is to effectively disregard $OBJECT_MODE
+# at build time. $OBJECT_MODE is respected at ./config stage!
+"aix-cc", "cc:-q32 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded:AIX::BN_LLONG RC4_CHAR::aix_ppc32.o::::::::::dlfcn:aix-shared::-q32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 32",
+"aix64-cc", "cc:-q64 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded:AIX::SIXTY_FOUR_BIT_LONG RC4_CHAR::aix_ppc64.o::::::::::dlfcn:aix-shared::-q64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 64",
+
+#
+# Cray T90 and similar (SDSC)
+# It's Big-endian, but the algorithms work properly when B_ENDIAN is NOT
+# defined. The T90 ints and longs are 8 bytes long, and apparently the
+# B_ENDIAN code assumes 4 byte ints. Fortunately, the non-B_ENDIAN and
+# non L_ENDIAN code aligns the bytes in each word correctly.
+#
+# The BIT_FIELD_LIMITS define is to avoid two fatal compiler errors:
+#'Taking the address of a bit field is not allowed. '
+#'An expression with bit field exists as the operand of "sizeof" '
+# (written by Wayne Schroeder )
+#
+# j90 is considered the base machine type for unicos machines,
+# so this configuration is now called "cray-j90" ...
+"cray-j90", "cc: -DBIT_FIELD_LIMITS -DTERMIOS::(unknown):CRAY::SIXTY_FOUR_BIT_LONG DES_INT:::",
+
+#
+# Cray T3E (Research Center Juelich, beckman@acl.lanl.gov)
+#
+# The BIT_FIELD_LIMITS define was written for the C90 (it seems). I added
+# another use. Basically, the problem is that the T3E uses some bit fields
+# for some st_addr stuff, and then sizeof and address-of fails
+# I could not use the ams/alpha.o option because the Cray assembler, 'cam'
+# did not like it.
+"cray-t3e", "cc: -DBIT_FIELD_LIMITS -DTERMIOS::(unknown):CRAY::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT:::",
+
+# DGUX, 88100.
+"dgux-R3-gcc", "gcc:-O3 -fomit-frame-pointer::(unknown):::RC4_INDEX DES_UNROLL:::",
+"dgux-R4-gcc", "gcc:-O3 -fomit-frame-pointer::(unknown)::-lnsl -lsocket:RC4_INDEX DES_UNROLL:::",
+"dgux-R4-x86-gcc", "gcc:-O3 -fomit-frame-pointer -DL_ENDIAN::(unknown)::-lnsl -lsocket:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
+
+# Sinix/ReliantUNIX RM400
+# NOTE: The CDS++ Compiler up to V2.0Bsomething has the IRIX_CC_BUG optimizer problem. Better use -g */
+"ReliantUNIX","cc:-KPIC -g -DTERMIOS -DB_ENDIAN::-Kthread:SNI:-lsocket -lnsl -lc -L/usr/ucblib -lucb:BN_LLONG DES_PTR DES_RISC2 DES_UNROLL BF_PTR:${no_asm}:dlfcn:reliantunix-shared:::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"SINIX","cc:-O::(unknown):SNI:-lsocket -lnsl -lc -L/usr/ucblib -lucb:RC4_INDEX RC4_CHAR:::",
+"SINIX-N","/usr/ucb/cc:-O2 -misaligned::(unknown)::-lucb:RC4_INDEX RC4_CHAR:::",
+
+# SIEMENS BS2000/OSD: an EBCDIC-based mainframe
+"BS2000-OSD","c89:-O -XLLML -XLLMK -XL -DB_ENDIAN -DTERMIOS -DCHARSET_EBCDIC::(unknown)::-lsocket -lnsl:THIRTY_TWO_BIT DES_PTR DES_UNROLL MD2_CHAR RC4_INDEX RC4_CHAR BF_PTR:::",
+
+# OS/390 Unix an EBCDIC-based Unix system on IBM mainframe
+# You need to compile using the c89.sh wrapper in the tools directory, because the
+# IBM compiler does not like the -L switch after any object modules.
+#
+"OS390-Unix","c89.sh:-O -DB_ENDIAN -DCHARSET_EBCDIC -DNO_SYS_PARAM_H -D_ALL_SOURCE::(unknown):::THIRTY_TWO_BIT DES_PTR DES_UNROLL MD2_CHAR RC4_INDEX RC4_CHAR BF_PTR:::",
+
+# Win64 targets, WIN64I denotes IA-64 and WIN64A - AMD64
+"VC-WIN64I","cl::::WIN64I::SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT EXPORT_VAR_AS_FN:${no_asm}:win32",
+"VC-WIN64A","cl::::WIN64A::SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT EXPORT_VAR_AS_FN:${no_asm}:win32",
+
+# Visual C targets
+"VC-NT","cl::::WINNT::BN_LLONG RC4_INDEX EXPORT_VAR_AS_FN ${x86_gcc_opts}:${no_asm}:win32",
+"VC-CE","cl::::WINCE::BN_LLONG RC4_INDEX EXPORT_VAR_AS_FN ${x86_gcc_opts}:${no_asm}:win32",
+"VC-WIN32","cl::::WIN32::BN_LLONG RC4_INDEX EXPORT_VAR_AS_FN ${x86_gcc_opts}:${no_asm}:win32",
+
+# Borland C++ 4.5
+"BC-32","bcc32::::WIN32::BN_LLONG DES_PTR RC4_INDEX EXPORT_VAR_AS_FN:${no_asm}:win32",
+
+# MinGW
+"mingw", "gcc:-mno-cygwin -DL_ENDIAN -fomit-frame-pointer -O3 -march=i486 -Wall -D_WIN32_WINNT=0x333:::MINGW32:-lwsock32 -lgdi32:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts} EXPORT_VAR_AS_FN:${x86_coff_asm}:win32:cygwin-shared:-D_WINDLL -DOPENSSL_USE_APPLINK:-mno-cygwin -shared:.dll.a",
+
+# UWIN
+"UWIN", "cc:-DTERMIOS -DL_ENDIAN -O -Wall:::UWIN::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:win32",
+
+# Cygwin
+"Cygwin-pre1.3", "gcc:-DTERMIOS -DL_ENDIAN -fomit-frame-pointer -O3 -m486 -Wall::(unknown):CYGWIN32::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:win32",
+"Cygwin", "gcc:-DTERMIOS -DL_ENDIAN -fomit-frame-pointer -O3 -march=i486 -Wall:::CYGWIN32::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_coff_asm}:dlfcn:cygwin-shared:-D_WINDLL:-shared:.dll.a",
+"debug-Cygwin", "gcc:-DTERMIOS -DL_ENDIAN -march=i486 -Wall -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DOPENSSL_NO_ASM -g -Wformat -Wshadow -Wmissing-prototypes -Wmissing-declarations -Werror:::CYGWIN32:::${no_asm}:dlfcn:cygwin-shared:-D_WINDLL:-shared:.dll.a",
+
+# NetWare from David Ward (dsward@novell.com)
+# requires either MetroWerks NLM development tools, or gcc / nlmconv
+# NetWare defaults socket bio to WinSock sockets. However,
+# the builds can be configured to use BSD sockets instead.
+# netware-clib => legacy CLib c-runtime support
+"netware-clib", "mwccnlm::::::${x86_gcc_opts}::",
+"netware-clib-bsdsock", "mwccnlm::::::${x86_gcc_opts}::",
+"netware-clib-gcc", "i586-netware-gcc:-nostdinc -I/ndk/nwsdk/include/nlm -I/ndk/ws295sdk/include -DL_ENDIAN -DNETWARE_CLIB -DOPENSSL_SYSNAME_NETWARE -O2 -Wall:::::${x86_gcc_opts}::",
+"netware-clib-bsdsock-gcc", "i586-netware-gcc:-nostdinc -I/ndk/nwsdk/include/nlm -DNETWARE_BSDSOCK -DNETDB_USE_INTERNET -DL_ENDIAN -DNETWARE_CLIB -DOPENSSL_SYSNAME_NETWARE -O2 -Wall:::::${x86_gcc_opts}::",
+# netware-libc => LibC/NKS support
+"netware-libc", "mwccnlm::::::BN_LLONG ${x86_gcc_opts}::",
+"netware-libc-bsdsock", "mwccnlm::::::BN_LLONG ${x86_gcc_opts}::",
+"netware-libc-gcc", "i586-netware-gcc:-nostdinc -I/ndk/libc/include -I/ndk/libc/include/winsock -DL_ENDIAN -DNETWARE_LIBC -DOPENSSL_SYSNAME_NETWARE -DTERMIO -O2 -Wall:::::BN_LLONG ${x86_gcc_opts}::",
+"netware-libc-bsdsock-gcc", "i586-netware-gcc:-nostdinc -I/ndk/libc/include -DNETWARE_BSDSOCK -DL_ENDIAN -DNETWARE_LIBC -DOPENSSL_SYSNAME_NETWARE -DTERMIO -O2 -Wall:::::BN_LLONG ${x86_gcc_opts}::",
+
+# DJGPP
+"DJGPP", "gcc:-I/dev/env/WATT_ROOT/inc -DTERMIOS -DL_ENDIAN -fomit-frame-pointer -O2 -Wall:::MSDOS:-L/dev/env/WATT_ROOT/lib -lwatt:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_out_asm}:",
+
+# Ultrix from Bernhard Simon
+"ultrix-cc","cc:-std1 -O -Olimit 2500 -DL_ENDIAN::(unknown):::::::",
+"ultrix-gcc","gcc:-O3 -DL_ENDIAN::(unknown):::BN_LLONG::::",
+# K&R C is no longer supported; you need gcc on old Ultrix installations
+##"ultrix","cc:-O2 -DNOPROTO -DNOCONST -DL_ENDIAN::(unknown):::::::",
+
+##### MacOS X (a.k.a. Rhapsody or Darwin) setup
+"rhapsody-ppc-cc","cc:-O3 -DB_ENDIAN::(unknown):MACOSX_RHAPSODY::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}::",
+"darwin-ppc-cc","cc:-arch ppc -O3 -DB_ENDIAN::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::osx_ppc32.o::::::::::dlfcn:darwin-shared:-fPIC -fno-common:-arch ppc -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
+"darwin64-ppc-cc","cc:-arch ppc64 -O3 -DB_ENDIAN::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:ppccpuid_osx64.o:osx_ppc64.o osx_ppc64-mont.o:::::sha1-ppc_osx64.o sha256-ppc_osx64.o sha512-ppc_osx64.o:::::dlfcn:darwin-shared:-fPIC -fno-common:-arch ppc64 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
+"darwin-i386-cc","cc:-arch i386 -O3 -fomit-frame-pointer -fno-common::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}:dlfcn:darwin-shared:-fPIC -fno-common:-arch i386 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
+"darwin64-x86_64-cc","cc:-arch x86_64 -O3 -fomit-frame-pointer -DL_ENDIAN -DMD32_REG_T=int -Wall::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK BF_PTR2 DES_INT DES_UNROLL:${no_asm}:dlfcn:darwin-shared:-fPIC -fno-common:-arch x86_64 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
+"debug-darwin-ppc-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DB_ENDIAN -g -Wall -O::-D_REENTRANT:MACOSX::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR::osx_ppc32.o::::::::::dlfcn:darwin-shared:-fPIC -fno-common:-dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
+
+##### A/UX
+"aux3-gcc","gcc:-O2 -DTERMIO::(unknown):AUX:-lbsd:RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:::",
+
+##### Sony NEWS-OS 4.x
+"newsos4-gcc","gcc:-O -DB_ENDIAN::(unknown):NEWS4:-lmld -liberty:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR::::",
+
+##### GNU Hurd
+"hurd-x86", "gcc:-DL_ENDIAN -DTERMIOS -O3 -fomit-frame-pointer -march=i486 -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC",
+
+##### OS/2 EMX
+"OS2-EMX", "gcc::::::::",
+
+##### VxWorks for various targets
+"vxworks-ppc405","ccppc:-g -msoft-float -mlongcall -DCPU=PPC405 -I\$(WIND_BASE)/target/h:::VXWORKS:-r:::::",
+"vxworks-ppc750","ccppc:-ansi -nostdinc -DPPC750 -D_REENTRANT -fvolatile -fno-builtin -fno-for-scope -fsigned-char -Wall -msoft-float -mlongcall -DCPU=PPC604 -I\$(WIND_BASE)/target/h \$(DEBUG_FLAG):::VXWORKS:-r:::::",
+"vxworks-ppc750-debug","ccppc:-ansi -nostdinc -DPPC750 -D_REENTRANT -fvolatile -fno-builtin -fno-for-scope -fsigned-char -Wall -msoft-float -mlongcall -DCPU=PPC604 -I\$(WIND_BASE)/target/h -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -DDEBUG -g:::VXWORKS:-r:::::",
+"vxworks-ppc860","ccppc:-nostdinc -msoft-float -DCPU=PPC860 -DNO_STRINGS_H -I\$(WIND_BASE)/target/h:::VXWORKS:-r:::::",
+"vxworks-mipsle","ccmips:-B\$(WIND_BASE)/host/\$(WIND_HOST_TYPE)/lib/gcc-lib/ -DL_ENDIAN -EL -Wl,-EL -mips2 -mno-branch-likely -G 0 -fno-builtin -msoft-float -DCPU=MIPS32 -DMIPSEL -DNO_STRINGS_H -I\$(WIND_BASE)/target/h:::VXWORKS:-r::${no_asm}::::::ranlibmips:",
+
+##### Compaq Non-Stop Kernel (Tandem)
+"tandem-c89","c89:-Ww -D__TANDEM -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1 -D_TANDEM_SOURCE -DB_ENDIAN::(unknown):::THIRTY_TWO_BIT:::",
+
+);
+
+my @MK1MF_Builds=qw(VC-WIN64I VC-WIN64A
+ VC-NT VC-CE VC-WIN32
+ BC-32 OS2-EMX
+ netware-clib netware-clib-bsdsock
+ netware-libc netware-libc-bsdsock);
+
+my $idx = 0;
+my $idx_cc = $idx++;
+my $idx_cflags = $idx++;
+my $idx_unistd = $idx++;
+my $idx_thread_cflag = $idx++;
+my $idx_sys_id = $idx++;
+my $idx_lflags = $idx++;
+my $idx_bn_ops = $idx++;
+my $idx_cpuid_obj = $idx++;
+my $idx_bn_obj = $idx++;
+my $idx_des_obj = $idx++;
+my $idx_aes_obj = $idx++;
+my $idx_bf_obj = $idx++;
+my $idx_md5_obj = $idx++;
+my $idx_sha1_obj = $idx++;
+my $idx_cast_obj = $idx++;
+my $idx_rc4_obj = $idx++;
+my $idx_rmd160_obj = $idx++;
+my $idx_rc5_obj = $idx++;
+my $idx_dso_scheme = $idx++;
+my $idx_shared_target = $idx++;
+my $idx_shared_cflag = $idx++;
+my $idx_shared_ldflag = $idx++;
+my $idx_shared_extension = $idx++;
+my $idx_ranlib = $idx++;
+my $idx_arflags = $idx++;
+
+my $prefix="";
+my $openssldir="";
+my $exe_ext="";
+my $install_prefix="";
+my $no_threads=0;
+my $threads=0;
+my $no_shared=0; # but "no-shared" is default
+my $zlib=1; # but "no-zlib" is default
+my $no_krb5=0; # but "no-krb5" is implied unless "--with-krb5-..." is used
+my $no_rfc3779=1; # but "no-rfc3779" is default
+my $montasm=1; # but "no-montasm" is default
+my $no_asm=0;
+my $no_dso=0;
+my $no_gmp=0;
+my @skip=();
+my $Makefile="Makefile";
+my $des_locl="crypto/des/des_locl.h";
+my $des ="crypto/des/des.h";
+my $bn ="crypto/bn/bn.h";
+my $md2 ="crypto/md2/md2.h";
+my $rc4 ="crypto/rc4/rc4.h";
+my $rc4_locl="crypto/rc4/rc4_locl.h";
+my $idea ="crypto/idea/idea.h";
+my $rc2 ="crypto/rc2/rc2.h";
+my $bf ="crypto/bf/bf_locl.h";
+my $bn_asm ="bn_asm.o";
+my $des_enc="des_enc.o fcrypt_b.o";
+my $aes_enc="aes_core.o aes_cbc.o";
+my $bf_enc ="bf_enc.o";
+my $cast_enc="c_enc.o";
+my $rc4_enc="rc4_enc.o rc4_skey.o";
+my $rc5_enc="rc5_enc.o";
+my $md5_obj="";
+my $sha1_obj="";
+my $rmd160_obj="";
+my $processor="";
+my $default_ranlib;
+my $perl;
+
+
+# All of the following is disabled by default (RC5 was enabled before 0.9.8):
+
+my %disabled = ( # "what" => "comment"
+ "camellia" => "default",
+ "cms" => "default",
+ "gmp" => "default",
+ "mdc2" => "default",
+ "montasm" => "default", # explicit option in 0.9.8 only (implicitly enabled in 0.9.9)
+ "rc5" => "default",
+ "rfc3779" => "default",
+ "seed" => "default",
+ "shared" => "default",
+ "tlsext" => "default",
+ "zlib" => "default",
+ "zlib-dynamic" => "default"
+ );
+
+# Additional "no-..." options will be collected in %disabled.
+# To remove something from %disabled, use e.g. "enable-rc5".
+# For symmetry, "disable-..." is a synonym for "no-...".
+
+# This is what $depflags will look like with the above default:
+my $default_depflags = "-DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_CMS -DOPENSSL_NO_GMP -DOPENSSL_NO_MDC2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779 -DOPENSSL_NO_SEED -DOPENSSL_NO_TLSEXT ";
+
+
+my $no_sse2=0;
+
+&usage if ($#ARGV < 0);
+
+my $flags;
+my $depflags;
+my $openssl_algorithm_defines;
+my $openssl_thread_defines;
+my $openssl_sys_defines="";
+my $openssl_other_defines;
+my $libs;
+my $libkrb5="";
+my $target;
+my $options;
+my $symlink;
+my $make_depend=0;
+my %withargs=();
+
+my @argvcopy=@ARGV;
+my $argvstring="";
+my $argv_unprocessed=1;
+
+while($argv_unprocessed)
+ {
+ $flags="";
+ $depflags="";
+ $openssl_algorithm_defines="";
+ $openssl_thread_defines="";
+ $openssl_sys_defines="";
+ $openssl_other_defines="";
+ $libs="";
+ $target="";
+ $options="";
+ $symlink=1;
+
+ $argv_unprocessed=0;
+ $argvstring=join(' ',@argvcopy);
+
+PROCESS_ARGS:
+ foreach (@argvcopy)
+ {
+ s /^-no-/no-/; # some people just can't read the instructions
+
+ # rewrite some options in "enable-..." form
+ s /^-?-?shared$/enable-shared/;
+ s /^threads$/enable-threads/;
+ s /^zlib$/enable-zlib/;
+ s /^zlib-dynamic$/enable-zlib-dynamic/;
+
+ if (/^no-(.+)$/ || /^disable-(.+)$/)
+ {
+ if ($1 eq "ssl")
+ {
+ $disabled{"ssl2"} = "option(ssl)";
+ $disabled{"ssl3"} = "option(ssl)";
+ }
+ elsif ($1 eq "tls")
+ {
+ $disabled{"tls1"} = "option(tls)"
+ }
+ else
+ {
+ $disabled{$1} = "option";
+ }
+ }
+ elsif (/^enable-(.+)$/)
+ {
+ delete $disabled{$1};
+
+ $threads = 1 if ($1 eq "threads");
+ }
+ elsif (/^--test-sanity$/)
+ {
+ exit(&test_sanity());
+ }
+ elsif (/^reconfigure/ || /^reconf/)
+ {
+ if (open(IN,"<$Makefile"))
+ {
+ while ()
+ {
+ chomp;
+ if (/^CONFIGURE_ARGS=(.*)/)
+ {
+ $argvstring=$1;
+ @argvcopy=split(' ',$argvstring);
+ die "Incorrect data to reconfigure, please do a normal configuration\n"
+ if (grep(/^reconf/,@argvcopy));
+ print "Reconfiguring with: $argvstring\n";
+ $argv_unprocessed=1;
+ close(IN);
+ last PROCESS_ARGS;
+ }
+ }
+ close(IN);
+ }
+ die "Insufficient data to reconfigure, please do a normal configuration\n";
+ }
+ elsif (/^386$/)
+ { $processor=386; }
+ elsif (/^rsaref$/)
+ {
+ # No RSAref support any more since it's not needed.
+ # The check for the option is there so scripts aren't
+ # broken
+ }
+ elsif (/^[-+]/)
+ {
+ if (/^-[lL](.*)$/)
+ {
+ $libs.=$_." ";
+ }
+ elsif (/^-[^-]/ or /^\+/)
+ {
+ $flags.=$_." ";
+ }
+ elsif (/^--prefix=(.*)$/)
+ {
+ $prefix=$1;
+ }
+ elsif (/^--openssldir=(.*)$/)
+ {
+ $openssldir=$1;
+ }
+ elsif (/^--install.prefix=(.*)$/)
+ {
+ $install_prefix=$1;
+ }
+ elsif (/^--with-krb5-(dir|lib|include|flavor)=(.*)$/)
+ {
+ $withargs{"krb5-".$1}=$2;
+ }
+ elsif (/^--with-zlib-lib=(.*)$/)
+ {
+ $withargs{"zlib-lib"}=$1;
+ }
+ elsif (/^--with-zlib-include=(.*)$/)
+ {
+ $withargs{"zlib-include"}="-I$1";
+ }
+ else
+ {
+ print STDERR $usage;
+ exit(1);
+ }
+ }
+ elsif ($_ =~ /^([^:]+):(.+)$/)
+ {
+ eval "\$table{\$1} = \"$2\""; # allow $xxx constructs in the string
+ $target=$1;
+ }
+ else
+ {
+ die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
+ $target=$_;
+ }
+
+ unless ($_ eq $target || /^no-/ || /^disable-/)
+ {
+ # "no-..." follows later after implied disactivations
+ # have been derived. (Don't take this too seroiusly,
+ # we really only write OPTIONS to the Makefile out of
+ # nostalgia.)
+
+ if ($options eq "")
+ { $options = $_; }
+ else
+ { $options .= " ".$_; }
+ }
+ }
+ }
+
+
+
+if ($processor eq "386")
+ {
+ $disabled{"sse2"} = "forced";
+ }
+
+if (!defined($withargs{"krb5-flavor"}) || $withargs{"krb5-flavor"} eq "")
+ {
+ $disabled{"krb5"} = "krb5-flavor not specified";
+ }
+
+if (!defined($disabled{"zlib-dynamic"}))
+ {
+ # "zlib-dynamic" was specifically enabled, so enable "zlib"
+ delete $disabled{"zlib"};
+ }
+
+if (defined($disabled{"rijndael"}))
+ {
+ $disabled{"aes"} = "forced";
+ }
+if (defined($disabled{"des"}))
+ {
+ $disabled{"mdc2"} = "forced";
+ }
+if (defined($disabled{"ec"}))
+ {
+ $disabled{"ecdsa"} = "forced";
+ $disabled{"ecdh"} = "forced";
+ }
+
+# SSL 2.0 requires MD5 and RSA
+if (defined($disabled{"md5"}) || defined($disabled{"rsa"}))
+ {
+ $disabled{"ssl2"} = "forced";
+ }
+
+# SSL 3.0 and TLS requires MD5 and SHA and either RSA or DSA+DH
+if (defined($disabled{"md5"}) || defined($disabled{"sha"})
+ || (defined($disabled{"rsa"})
+ && (defined($disabled{"dsa"}) || defined($disabled{"dh"}))))
+ {
+ $disabled{"ssl3"} = "forced";
+ $disabled{"tls1"} = "forced";
+ }
+
+if (defined($disabled{"tls1"}))
+ {
+ $disabled{"tlsext"} = "forced";
+ }
+
+if ($target eq "TABLE") {
+ foreach $target (sort keys %table) {
+ print_table_entry($target);
+ }
+ exit 0;
+}
+
+if ($target eq "LIST") {
+ foreach (sort keys %table) {
+ print;
+ print "\n";
+ }
+ exit 0;
+}
+
+if ($target =~ m/^CygWin32(-.*)$/) {
+ $target = "Cygwin".$1;
+}
+
+print "Configuring for $target\n";
+
+&usage if (!defined($table{$target}));
+
+
+foreach (sort (keys %disabled))
+ {
+ $options .= " no-$_";
+
+ printf " no-%-12s %-10s", $_, "[$disabled{$_}]";
+
+ if (/^dso$/)
+ { $no_dso = 1; }
+ elsif (/^threads$/)
+ { $no_threads = 1; }
+ elsif (/^shared$/)
+ { $no_shared = 1; }
+ elsif (/^zlib$/)
+ { $zlib = 0; }
+ elsif (/^montasm$/)
+ { $montasm = 0; }
+ elsif (/^static-engine$/)
+ { }
+ elsif (/^zlib-dynamic$/)
+ { }
+ elsif (/^symlinks$/)
+ { $symlink = 0; }
+ elsif (/^sse2$/)
+ { $no_sse2 = 1; }
+ else
+ {
+ my ($ALGO, $algo);
+ ($ALGO = $algo = $_) =~ tr/[a-z]/[A-Z]/;
+
+ if (/^asm$/ || /^err$/ || /^hw$/ || /^hw-/)
+ {
+ $openssl_other_defines .= "#define OPENSSL_NO_$ALGO\n";
+ print " OPENSSL_NO_$ALGO";
+
+ if (/^err$/) { $flags .= "-DOPENSSL_NO_ERR "; }
+ elsif (/^asm$/) { $no_asm = 1; }
+ }
+ else
+ {
+ $openssl_algorithm_defines .= "#define OPENSSL_NO_$ALGO\n";
+ print " OPENSSL_NO_$ALGO";
+
+ if (/^krb5$/)
+ { $no_krb5 = 1; }
+ else
+ {
+ push @skip, $algo;
+ print " (skip dir)";
+
+ $depflags .="-DOPENSSL_NO_$ALGO ";
+ }
+ }
+ }
+
+ print "\n";
+ }
+
+
+my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds;
+
+$IsMK1MF=1 if ($target eq "mingw" && $^O ne "cygwin" && !is_msys());
+
+$exe_ext=".exe" if ($target eq "Cygwin" || $target eq "DJGPP" || $target eq "mingw");
+$exe_ext=".nlm" if ($target =~ /netware/);
+$exe_ext=".pm" if ($target =~ /vos/);
+$openssldir="/usr/local/ssl" if ($openssldir eq "" and $prefix eq "");
+$prefix=$openssldir if $prefix eq "";
+
+$default_ranlib= &which("ranlib") or $default_ranlib="true";
+$perl=$ENV{'PERL'} or $perl=&which("perl5") or $perl=&which("perl")
+ or $perl="perl";
+
+chop $openssldir if $openssldir =~ /\/$/;
+chop $prefix if $prefix =~ /\/$/;
+
+$openssldir=$prefix . "/ssl" if $openssldir eq "";
+$openssldir=$prefix . "/" . $openssldir if $openssldir !~ /(^\/|^[a-zA-Z]:[\\\/])/;
+
+
+print "IsMK1MF=$IsMK1MF\n";
+
+my @fields = split(/\s*:\s*/,$table{$target} . ":" x 30 , -1);
+my $cc = $fields[$idx_cc];
+my $cflags = $fields[$idx_cflags];
+my $unistd = $fields[$idx_unistd];
+my $thread_cflag = $fields[$idx_thread_cflag];
+my $sys_id = $fields[$idx_sys_id];
+my $lflags = $fields[$idx_lflags];
+my $bn_ops = $fields[$idx_bn_ops];
+my $cpuid_obj = $fields[$idx_cpuid_obj];
+my $bn_obj = $fields[$idx_bn_obj];
+my $des_obj = $fields[$idx_des_obj];
+my $aes_obj = $fields[$idx_aes_obj];
+my $bf_obj = $fields[$idx_bf_obj];
+my $md5_obj = $fields[$idx_md5_obj];
+my $sha1_obj = $fields[$idx_sha1_obj];
+my $cast_obj = $fields[$idx_cast_obj];
+my $rc4_obj = $fields[$idx_rc4_obj];
+my $rmd160_obj = $fields[$idx_rmd160_obj];
+my $rc5_obj = $fields[$idx_rc5_obj];
+my $dso_scheme = $fields[$idx_dso_scheme];
+my $shared_target = $fields[$idx_shared_target];
+my $shared_cflag = $fields[$idx_shared_cflag];
+my $shared_ldflag = $fields[$idx_shared_ldflag];
+my $shared_extension = $fields[$idx_shared_extension];
+my $ranlib = $fields[$idx_ranlib];
+my $arflags = $fields[$idx_arflags];
+
+# '%' in $lflags is used to split flags to "pre-" and post-flags
+my ($prelflags,$postlflags)=split('%',$lflags);
+if (defined($postlflags)) { $lflags=$postlflags; }
+else { $lflags=$prelflags; undef $prelflags; }
+
+my $no_shared_warn=0;
+my $no_user_cflags=0;
+
+if ($flags ne "") { $cflags="$flags$cflags"; }
+else { $no_user_cflags=1; }
+
+# Kerberos settings. The flavor must be provided from outside, either through
+# the script "config" or manually.
+if (!$no_krb5)
+ {
+ my ($lresolv, $lpath, $lext);
+ if ($withargs{"krb5-flavor"} =~ /^[Hh]eimdal$/)
+ {
+ die "Sorry, Heimdal is currently not supported\n";
+ }
+ ##### HACK to force use of Heimdal.
+ ##### WARNING: Since we don't really have adequate support for Heimdal,
+ ##### using this will break the build. You'll have to make
+ ##### changes to the source, and if you do, please send
+ ##### patches to openssl-dev@openssl.org
+ if ($withargs{"krb5-flavor"} =~ /^force-[Hh]eimdal$/)
+ {
+ warn "Heimdal isn't really supported. Your build WILL break\n";
+ warn "If you fix the problems, please send a patch to openssl-dev\@openssl.org\n";
+ $withargs{"krb5-dir"} = "/usr/heimdal"
+ if $withargs{"krb5-dir"} eq "";
+ $withargs{"krb5-lib"} = "-L".$withargs{"krb5-dir"}.
+ "/lib -lgssapi -lkrb5 -lcom_err"
+ if $withargs{"krb5-lib"} eq "" && !$IsMK1MF;
+ $cflags="-DKRB5_HEIMDAL $cflags";
+ }
+ if ($withargs{"krb5-flavor"} =~ /^[Mm][Ii][Tt]/)
+ {
+ $withargs{"krb5-dir"} = "/usr/kerberos"
+ if $withargs{"krb5-dir"} eq "";
+ $withargs{"krb5-lib"} = "-L".$withargs{"krb5-dir"}.
+ "/lib -lgssapi_krb5 -lkrb5 -lcom_err -lk5crypto"
+ if $withargs{"krb5-lib"} eq "" && !$IsMK1MF;
+ $cflags="-DKRB5_MIT $cflags";
+ $withargs{"krb5-flavor"} =~ s/^[Mm][Ii][Tt][._-]*//;
+ if ($withargs{"krb5-flavor"} =~ /^1[._-]*[01]/)
+ {
+ $cflags="-DKRB5_MIT_OLD11 $cflags";
+ }
+ }
+ LRESOLV:
+ foreach $lpath ("/lib", "/usr/lib")
+ {
+ foreach $lext ("a", "so")
+ {
+ $lresolv = "$lpath/libresolv.$lext";
+ last LRESOLV if (-r "$lresolv");
+ $lresolv = "";
+ }
+ }
+ $withargs{"krb5-lib"} .= " -lresolv"
+ if ("$lresolv" ne "");
+ $withargs{"krb5-include"} = "-I".$withargs{"krb5-dir"}."/include"
+ if $withargs{"krb5-include"} eq "" &&
+ $withargs{"krb5-dir"} ne "";
+ }
+
+# The DSO code currently always implements all functions so that no
+# applications will have to worry about that from a compilation point
+# of view. However, the "method"s may return zero unless that platform
+# has support compiled in for them. Currently each method is enabled
+# by a define "DSO_" ... we translate the "dso_scheme" config
+# string entry into using the following logic;
+my $dso_cflags;
+if (!$no_dso && $dso_scheme ne "")
+ {
+ $dso_scheme =~ tr/[a-z]/[A-Z]/;
+ if ($dso_scheme eq "DLFCN")
+ {
+ $dso_cflags = "-DDSO_DLFCN -DHAVE_DLFCN_H";
+ }
+ elsif ($dso_scheme eq "DLFCN_NO_H")
+ {
+ $dso_cflags = "-DDSO_DLFCN";
+ }
+ else
+ {
+ $dso_cflags = "-DDSO_$dso_scheme";
+ }
+ $cflags = "$dso_cflags $cflags";
+ }
+
+my $thread_cflags;
+my $thread_defines;
+if ($thread_cflag ne "(unknown)" && !$no_threads)
+ {
+ # If we know how to do it, support threads by default.
+ $threads = 1;
+ }
+if ($thread_cflag eq "(unknown)" && $threads)
+ {
+ # If the user asked for "threads", [s]he is also expected to
+ # provide any system-dependent compiler options that are
+ # necessary.
+ if ($no_user_cflags)
+ {
+ print "You asked for multi-threading support, but didn't\n";
+ print "provide any system-specific compiler options\n";
+ exit(1);
+ }
+ $thread_cflags="-DOPENSSL_THREADS $cflags" ;
+ $thread_defines .= "#define OPENSSL_THREADS\n";
+ }
+else
+ {
+ $thread_cflags="-DOPENSSL_THREADS $thread_cflag $cflags";
+ $thread_defines .= "#define OPENSSL_THREADS\n";
+# my $def;
+# foreach $def (split ' ',$thread_cflag)
+# {
+# if ($def =~ s/^-D// && $def !~ /^_/)
+# {
+# $thread_defines .= "#define $def\n";
+# }
+# }
+ }
+
+$lflags="$libs$lflags" if ($libs ne "");
+
+if ($no_asm)
+ {
+ $cpuid_obj=$bn_obj=$des_obj=$aes_obj=$bf_obj=$cast_obj=$rc4_obj=$rc5_obj="";
+ $sha1_obj=$md5_obj=$rmd160_obj="";
+ }
+if ($montasm)
+ {
+ $bn_obj =~ s/MAYBE-MO86-/mo86-/;
+ }
+else
+ {
+ $bn_obj =~ s/MAYBE-MO86-[a-z.]*//;
+ }
+
+if (!$no_shared)
+ {
+ $cast_obj=""; # CAST assembler is not PIC
+ }
+
+if ($threads)
+ {
+ $cflags=$thread_cflags;
+ $openssl_thread_defines .= $thread_defines;
+ }
+
+if ($zlib)
+ {
+ $cflags = "-DZLIB $cflags";
+ if (defined($disabled{"zlib-dynamic"}))
+ {
+ $lflags = "$lflags -lz";
+ }
+ else
+ {
+ $cflags = "-DZLIB_SHARED $cflags";
+ }
+ }
+
+# You will find shlib_mark1 and shlib_mark2 explained in Makefile.org
+my $shared_mark = "";
+if ($shared_target eq "")
+ {
+ $no_shared_warn = 1 if !$no_shared;
+ $no_shared = 1;
+ }
+if (!$no_shared)
+ {
+ if ($shared_cflag ne "")
+ {
+ $cflags = "$shared_cflag -DOPENSSL_PIC $cflags";
+ }
+ }
+
+if (!$IsMK1MF)
+ {
+ if ($no_shared)
+ {
+ $openssl_other_defines.="#define OPENSSL_NO_DYNAMIC_ENGINE\n";
+ }
+ else
+ {
+ $openssl_other_defines.="#define OPENSSL_NO_STATIC_ENGINE\n";
+ }
+ }
+
+$cpuid_obj.=" uplink.o uplink-cof.o" if ($cflags =~ /\-DOPENSSL_USE_APPLINK/);
+
+#
+# Platform fix-ups
+#
+if ($target =~ /\-icc$/) # Intel C compiler
+ {
+ my $iccver=0;
+ if (open(FD,"$cc -V 2>&1 |"))
+ {
+ while() { $iccver=$1 if (/Version ([0-9]+)\./); }
+ close(FD);
+ }
+ if ($iccver>=8)
+ {
+ # Eliminate unnecessary dependency from libirc.a. This is
+ # essential for shared library support, as otherwise
+ # apps/openssl can end up in endless loop upon startup...
+ $cflags.=" -Dmemcpy=__builtin_memcpy -Dmemset=__builtin_memset";
+ }
+ if ($iccver>=9)
+ {
+ $cflags.=" -i-static";
+ $cflags=~s/\-no_cpprt/-no-cpprt/;
+ }
+ if ($iccver>=10)
+ {
+ $cflags=~s/\-i\-static/-static-intel/;
+ }
+ }
+
+# Unlike other OSes (like Solaris, Linux, Tru64, IRIX) BSD run-time
+# linkers (tested OpenBSD, NetBSD and FreeBSD) "demand" RPATH set on
+# .so objects. Apparently application RPATH is not global and does
+# not apply to .so linked with other .so. Problem manifests itself
+# when libssl.so fails to load libcrypto.so. One can argue that we
+# should engrave this into Makefile.shared rules or into BSD-* config
+# lines above. Meanwhile let's try to be cautious and pass -rpath to
+# linker only when --prefix is not /usr.
+if ($target =~ /^BSD\-/)
+ {
+ $shared_ldflag.=" -Wl,-rpath,\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|);
+ }
+
+if ($sys_id ne "")
+ {
+ #$cflags="-DOPENSSL_SYSNAME_$sys_id $cflags";
+ $openssl_sys_defines="#define OPENSSL_SYSNAME_$sys_id\n";
+ }
+
+if ($ranlib eq "")
+ {
+ $ranlib = $default_ranlib;
+ }
+
+#my ($bn1)=split(/\s+/,$bn_obj);
+#$bn1 = "" unless defined $bn1;
+#$bn1=$bn_asm unless ($bn1 =~ /\.o$/);
+#$bn_obj="$bn1";
+
+$cpuid_obj="" if ($processor eq "386");
+
+$bn_obj = $bn_asm unless $bn_obj ne "";
+# bn86* is the only one implementing bn_*_part_words
+$cflags.=" -DOPENSSL_BN_ASM_PART_WORDS" if ($bn_obj =~ /bn86/);
+$cflags.=" -DOPENSSL_IA32_SSE2" if (!$no_sse2 && $bn_obj =~ /bn86/);
+$cflags.=" -DOPENSSL_BN_ASM_MONT" if ($bn_obj =~ /\-mont|mo86\-/);
+
+$des_obj=$des_enc unless ($des_obj =~ /\.o$/);
+$bf_obj=$bf_enc unless ($bf_obj =~ /\.o$/);
+$cast_obj=$cast_enc unless ($cast_obj =~ /\.o$/);
+$rc4_obj=$rc4_enc unless ($rc4_obj =~ /\.o$/);
+$rc5_obj=$rc5_enc unless ($rc5_obj =~ /\.o$/);
+if ($sha1_obj =~ /\.o$/)
+ {
+# $sha1_obj=$sha1_enc;
+ $cflags.=" -DSHA1_ASM" if ($sha1_obj =~ /sx86/ || $sha1_obj =~ /sha1/);
+ $cflags.=" -DSHA256_ASM" if ($sha1_obj =~ /sha256/);
+ $cflags.=" -DSHA512_ASM" if ($sha1_obj =~ /sha512/);
+ if ($sha1_obj =~ /sse2/)
+ { if ($no_sse2)
+ { $sha1_obj =~ s/\S*sse2\S+//; }
+ elsif ($cflags !~ /OPENSSL_IA32_SSE2/)
+ { $cflags.=" -DOPENSSL_IA32_SSE2"; }
+ }
+ }
+if ($md5_obj =~ /\.o$/)
+ {
+# $md5_obj=$md5_enc;
+ $cflags.=" -DMD5_ASM";
+ }
+if ($rmd160_obj =~ /\.o$/)
+ {
+# $rmd160_obj=$rmd160_enc;
+ $cflags.=" -DRMD160_ASM";
+ }
+if ($aes_obj =~ /\.o$/)
+ {
+ $cflags.=" -DAES_ASM";
+ }
+else {
+ $aes_obj=$aes_enc;
+ }
+
+# "Stringify" the C flags string. This permits it to be made part of a string
+# and works as well on command lines.
+$cflags =~ s/([\\\"])/\\\1/g;
+
+my $version = "unknown";
+my $version_num = "unknown";
+my $major = "unknown";
+my $minor = "unknown";
+my $shlib_version_number = "unknown";
+my $shlib_version_history = "unknown";
+my $shlib_major = "unknown";
+my $shlib_minor = "unknown";
+
+open(IN,')
+ {
+ $version=$1 if /OPENSSL.VERSION.TEXT.*OpenSSL (\S+) /;
+ $version_num=$1 if /OPENSSL.VERSION.NUMBER.*0x(\S+)/;
+ $shlib_version_number=$1 if /SHLIB_VERSION_NUMBER *"([^"]+)"/;
+ $shlib_version_history=$1 if /SHLIB_VERSION_HISTORY *"([^"]*)"/;
+ }
+close(IN);
+if ($shlib_version_history ne "") { $shlib_version_history .= ":"; }
+
+if ($version =~ /(^[0-9]*)\.([0-9\.]*)/)
+ {
+ $major=$1;
+ $minor=$2;
+ }
+
+if ($shlib_version_number =~ /(^[0-9]*)\.([0-9\.]*)/)
+ {
+ $shlib_major=$1;
+ $shlib_minor=$2;
+ }
+
+open(IN,'$Makefile.new") || die "unable to create $Makefile.new:$!\n";
+print OUT "### Generated automatically from Makefile.org by Configure.\n\n";
+my $sdirs=0;
+while ()
+ {
+ chomp;
+ $sdirs = 1 if /^SDIRS=/;
+ if ($sdirs) {
+ my $dir;
+ foreach $dir (@skip) {
+ s/([ ])$dir /\1/;
+ }
+ }
+ $sdirs = 0 unless /\\$/;
+ s/^VERSION=.*/VERSION=$version/;
+ s/^MAJOR=.*/MAJOR=$major/;
+ s/^MINOR=.*/MINOR=$minor/;
+ s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/;
+ s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/;
+ s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/;
+ s/^SHLIB_MINOR=.*/SHLIB_MINOR=$shlib_minor/;
+ s/^SHLIB_EXT=.*/SHLIB_EXT=$shared_extension/;
+ s/^INSTALLTOP=.*$/INSTALLTOP=$prefix/;
+ s/^OPENSSLDIR=.*$/OPENSSLDIR=$openssldir/;
+ s/^INSTALL_PREFIX=.*$/INSTALL_PREFIX=$install_prefix/;
+ s/^PLATFORM=.*$/PLATFORM=$target/;
+ s/^OPTIONS=.*$/OPTIONS=$options/;
+ s/^CONFIGURE_ARGS=.*$/CONFIGURE_ARGS=$argvstring/;
+ s/^CC=.*$/CC= $cc/;
+ s/^MAKEDEPPROG=.*$/MAKEDEPPROG= $cc/ if $cc eq "gcc";
+ s/^CFLAG=.*$/CFLAG= $cflags/;
+ s/^DEPFLAG=.*$/DEPFLAG= $depflags/;
+ s/^PEX_LIBS=.*$/PEX_LIBS= $prelflags/;
+ s/^EX_LIBS=.*$/EX_LIBS= $lflags/;
+ s/^EXE_EXT=.*$/EXE_EXT= $exe_ext/;
+ s/^CPUID_OBJ=.*$/CPUID_OBJ= $cpuid_obj/;
+ s/^BN_ASM=.*$/BN_ASM= $bn_obj/;
+ s/^DES_ENC=.*$/DES_ENC= $des_obj/;
+ s/^AES_ASM_OBJ=.*$/AES_ASM_OBJ= $aes_obj/;
+ s/^BF_ENC=.*$/BF_ENC= $bf_obj/;
+ s/^CAST_ENC=.*$/CAST_ENC= $cast_obj/;
+ s/^RC4_ENC=.*$/RC4_ENC= $rc4_obj/;
+ s/^RC5_ENC=.*$/RC5_ENC= $rc5_obj/;
+ s/^MD5_ASM_OBJ=.*$/MD5_ASM_OBJ= $md5_obj/;
+ s/^SHA1_ASM_OBJ=.*$/SHA1_ASM_OBJ= $sha1_obj/;
+ s/^RMD160_ASM_OBJ=.*$/RMD160_ASM_OBJ= $rmd160_obj/;
+ s/^PROCESSOR=.*/PROCESSOR= $processor/;
+ s/^RANLIB=.*/RANLIB= $ranlib/;
+ s/^ARFLAGS=.*/ARFLAGS= $arflags/;
+ s/^PERL=.*/PERL= $perl/;
+ s/^KRB5_INCLUDES=.*/KRB5_INCLUDES=$withargs{"krb5-include"}/;
+ s/^LIBKRB5=.*/LIBKRB5=$withargs{"krb5-lib"}/;
+ s/^LIBZLIB=.*/LIBZLIB=$withargs{"zlib-lib"}/;
+ s/^ZLIB_INCLUDE=.*/ZLIB_INCLUDE=$withargs{"zlib-include"}/;
+ s/^SHLIB_TARGET=.*/SHLIB_TARGET=$shared_target/;
+ s/^SHLIB_MARK=.*/SHLIB_MARK=$shared_mark/;
+ s/^SHARED_LIBS=.*/SHARED_LIBS=\$(SHARED_CRYPTO) \$(SHARED_SSL)/ if (!$no_shared);
+ if ($shared_extension ne "" && $shared_extension =~ /^\.s([ol])\.[^\.]*$/)
+ {
+ my $sotmp = $1;
+ s/^SHARED_LIBS_LINK_EXTS=.*/SHARED_LIBS_LINK_EXTS=.s$sotmp/;
+ }
+ elsif ($shared_extension ne "" && $shared_extension =~ /^\.[^\.]*\.dylib$/)
+ {
+ s/^SHARED_LIBS_LINK_EXTS=.*/SHARED_LIBS_LINK_EXTS=.dylib/;
+ }
+ elsif ($shared_extension ne "" && $shared_extension =~ /^\.s([ol])\.[^\.]*\.[^\.]*$/)
+ {
+ my $sotmp = $1;
+ s/^SHARED_LIBS_LINK_EXTS=.*/SHARED_LIBS_LINK_EXTS=.s$sotmp.\$(SHLIB_MAJOR) .s$sotmp/;
+ }
+ elsif ($shared_extension ne "" && $shared_extension =~ /^\.[^\.]*\.[^\.]*\.dylib$/)
+ {
+ s/^SHARED_LIBS_LINK_EXTS=.*/SHARED_LIBS_LINK_EXTS=.\$(SHLIB_MAJOR).dylib .dylib/;
+ }
+ s/^SHARED_LDFLAGS=.*/SHARED_LDFLAGS=$shared_ldflag/;
+ print OUT $_."\n";
+ }
+close(IN);
+close(OUT);
+rename($Makefile,"$Makefile.bak") || die "unable to rename $Makefile\n" if -e $Makefile;
+rename("$Makefile.new",$Makefile) || die "unable to rename $Makefile.new\n";
+
+print "CC =$cc\n";
+print "CFLAG =$cflags\n";
+print "EX_LIBS =$lflags\n";
+print "CPUID_OBJ =$cpuid_obj\n";
+print "BN_ASM =$bn_obj\n";
+print "DES_ENC =$des_obj\n";
+print "AES_ASM_OBJ =$aes_obj\n";
+print "BF_ENC =$bf_obj\n";
+print "CAST_ENC =$cast_obj\n";
+print "RC4_ENC =$rc4_obj\n";
+print "RC5_ENC =$rc5_obj\n";
+print "MD5_OBJ_ASM =$md5_obj\n";
+print "SHA1_OBJ_ASM =$sha1_obj\n";
+print "RMD160_OBJ_ASM=$rmd160_obj\n";
+print "PROCESSOR =$processor\n";
+print "RANLIB =$ranlib\n";
+print "ARFLAGS =$arflags\n";
+print "PERL =$perl\n";
+print "KRB5_INCLUDES =",$withargs{"krb5-include"},"\n"
+ if $withargs{"krb5-include"} ne "";
+
+my $des_ptr=0;
+my $des_risc1=0;
+my $des_risc2=0;
+my $des_unroll=0;
+my $bn_ll=0;
+my $def_int=2;
+my $rc4_int=$def_int;
+my $md2_int=$def_int;
+my $idea_int=$def_int;
+my $rc2_int=$def_int;
+my $rc4_idx=0;
+my $rc4_chunk=0;
+my $bf_ptr=0;
+my @type=("char","short","int","long");
+my ($b64l,$b64,$b32,$b16,$b8)=(0,0,1,0,0);
+my $export_var_as_fn=0;
+
+my $des_int;
+
+foreach (sort split(/\s+/,$bn_ops))
+ {
+ $des_ptr=1 if /DES_PTR/;
+ $des_risc1=1 if /DES_RISC1/;
+ $des_risc2=1 if /DES_RISC2/;
+ $des_unroll=1 if /DES_UNROLL/;
+ $des_int=1 if /DES_INT/;
+ $bn_ll=1 if /BN_LLONG/;
+ $rc4_int=0 if /RC4_CHAR/;
+ $rc4_int=3 if /RC4_LONG/;
+ $rc4_idx=1 if /RC4_INDEX/;
+ $rc4_chunk=1 if /RC4_CHUNK/;
+ $rc4_chunk=2 if /RC4_CHUNK_LL/;
+ $md2_int=0 if /MD2_CHAR/;
+ $md2_int=3 if /MD2_LONG/;
+ $idea_int=1 if /IDEA_SHORT/;
+ $idea_int=3 if /IDEA_LONG/;
+ $rc2_int=1 if /RC2_SHORT/;
+ $rc2_int=3 if /RC2_LONG/;
+ $bf_ptr=1 if $_ eq "BF_PTR";
+ $bf_ptr=2 if $_ eq "BF_PTR2";
+ ($b64l,$b64,$b32,$b16,$b8)=(0,1,0,0,0) if /SIXTY_FOUR_BIT/;
+ ($b64l,$b64,$b32,$b16,$b8)=(1,0,0,0,0) if /SIXTY_FOUR_BIT_LONG/;
+ ($b64l,$b64,$b32,$b16,$b8)=(0,0,1,0,0) if /THIRTY_TWO_BIT/;
+ ($b64l,$b64,$b32,$b16,$b8)=(0,0,0,1,0) if /SIXTEEN_BIT/;
+ ($b64l,$b64,$b32,$b16,$b8)=(0,0,0,0,1) if /EIGHT_BIT/;
+ $export_var_as_fn=1 if /EXPORT_VAR_AS_FN/;
+ }
+
+open(IN,'crypto/opensslconf.h.new') || die "unable to create crypto/opensslconf.h.new:$!\n";
+print OUT "/* opensslconf.h */\n";
+print OUT "/* WARNING: Generated automatically from opensslconf.h.in by Configure. */\n\n";
+
+print OUT "/* OpenSSL was configured with the following options: */\n";
+my $openssl_algorithm_defines_trans = $openssl_algorithm_defines;
+$openssl_algorithm_defines_trans =~ s/^\s*#\s*define\s+OPENSSL_(.*)/# if defined(OPENSSL_$1) \&\& !defined($1)\n# define $1\n# endif/mg;
+$openssl_algorithm_defines =~ s/^\s*#\s*define\s+(.*)/#ifndef $1\n# define $1\n#endif/mg;
+$openssl_algorithm_defines = " /* no ciphers excluded */\n" if $openssl_algorithm_defines eq "";
+$openssl_thread_defines =~ s/^\s*#\s*define\s+(.*)/#ifndef $1\n# define $1\n#endif/mg;
+$openssl_sys_defines =~ s/^\s*#\s*define\s+(.*)/#ifndef $1\n# define $1\n#endif/mg;
+$openssl_other_defines =~ s/^\s*#\s*define\s+(.*)/#ifndef $1\n# define $1\n#endif/mg;
+print OUT $openssl_sys_defines;
+print OUT "#ifndef OPENSSL_DOING_MAKEDEPEND\n\n";
+print OUT $openssl_algorithm_defines;
+print OUT "\n#endif /* OPENSSL_DOING_MAKEDEPEND */\n";
+print OUT $openssl_thread_defines;
+print OUT $openssl_other_defines,"\n";
+
+print OUT "/* The OPENSSL_NO_* macros are also defined as NO_* if the application\n";
+print OUT " asks for it. This is a transient feature that is provided for those\n";
+print OUT " who haven't had the time to do the appropriate changes in their\n";
+print OUT " applications. */\n";
+print OUT "#ifdef OPENSSL_ALGORITHM_DEFINES\n";
+print OUT $openssl_algorithm_defines_trans;
+print OUT "#endif\n\n";
+
+print OUT "#define OPENSSL_CPUID_OBJ\n\n" if ($cpuid_obj);
+
+while ()
+ {
+ if (/^#define\s+OPENSSLDIR/)
+ { print OUT "#define OPENSSLDIR \"$openssldir\"\n"; }
+ elsif (/^#define\s+ENGINESDIR/)
+ { print OUT "#define ENGINESDIR \"$prefix/lib/engines\"\n"; }
+ elsif (/^#((define)|(undef))\s+OPENSSL_EXPORT_VAR_AS_FUNCTION/)
+ { printf OUT "#undef OPENSSL_EXPORT_VAR_AS_FUNCTION\n"
+ if $export_var_as_fn;
+ printf OUT "#%s OPENSSL_EXPORT_VAR_AS_FUNCTION\n",
+ ($export_var_as_fn)?"define":"undef"; }
+ elsif (/^#define\s+OPENSSL_UNISTD/)
+ {
+ $unistd = "" if $unistd eq "";
+ print OUT "#define OPENSSL_UNISTD $unistd\n";
+ }
+ elsif (/^#((define)|(undef))\s+SIXTY_FOUR_BIT_LONG/)
+ { printf OUT "#%s SIXTY_FOUR_BIT_LONG\n",($b64l)?"define":"undef"; }
+ elsif (/^#((define)|(undef))\s+SIXTY_FOUR_BIT/)
+ { printf OUT "#%s SIXTY_FOUR_BIT\n",($b64)?"define":"undef"; }
+ elsif (/^#((define)|(undef))\s+THIRTY_TWO_BIT/)
+ { printf OUT "#%s THIRTY_TWO_BIT\n",($b32)?"define":"undef"; }
+ elsif (/^#((define)|(undef))\s+SIXTEEN_BIT/)
+ { printf OUT "#%s SIXTEEN_BIT\n",($b16)?"define":"undef"; }
+ elsif (/^#((define)|(undef))\s+EIGHT_BIT/)
+ { printf OUT "#%s EIGHT_BIT\n",($b8)?"define":"undef"; }
+ elsif (/^#((define)|(undef))\s+BN_LLONG\s*$/)
+ { printf OUT "#%s BN_LLONG\n",($bn_ll)?"define":"undef"; }
+ elsif (/^\#define\s+DES_LONG\s+.*/)
+ { printf OUT "#define DES_LONG unsigned %s\n",
+ ($des_int)?'int':'long'; }
+ elsif (/^\#(define|undef)\s+DES_PTR/)
+ { printf OUT "#%s DES_PTR\n",($des_ptr)?'define':'undef'; }
+ elsif (/^\#(define|undef)\s+DES_RISC1/)
+ { printf OUT "#%s DES_RISC1\n",($des_risc1)?'define':'undef'; }
+ elsif (/^\#(define|undef)\s+DES_RISC2/)
+ { printf OUT "#%s DES_RISC2\n",($des_risc2)?'define':'undef'; }
+ elsif (/^\#(define|undef)\s+DES_UNROLL/)
+ { printf OUT "#%s DES_UNROLL\n",($des_unroll)?'define':'undef'; }
+ elsif (/^#define\s+RC4_INT\s/)
+ { printf OUT "#define RC4_INT unsigned %s\n",$type[$rc4_int]; }
+ elsif (/^#undef\s+RC4_CHUNK/)
+ {
+ printf OUT "#undef RC4_CHUNK\n" if $rc4_chunk==0;
+ printf OUT "#define RC4_CHUNK unsigned long\n" if $rc4_chunk==1;
+ printf OUT "#define RC4_CHUNK unsigned long long\n" if $rc4_chunk==2;
+ }
+ elsif (/^#((define)|(undef))\s+RC4_INDEX/)
+ { printf OUT "#%s RC4_INDEX\n",($rc4_idx)?"define":"undef"; }
+ elsif (/^#(define|undef)\s+I386_ONLY/)
+ { printf OUT "#%s I386_ONLY\n", ($processor eq "386")?
+ "define":"undef"; }
+ elsif (/^#define\s+MD2_INT\s/)
+ { printf OUT "#define MD2_INT unsigned %s\n",$type[$md2_int]; }
+ elsif (/^#define\s+IDEA_INT\s/)
+ {printf OUT "#define IDEA_INT unsigned %s\n",$type[$idea_int];}
+ elsif (/^#define\s+RC2_INT\s/)
+ {printf OUT "#define RC2_INT unsigned %s\n",$type[$rc2_int];}
+ elsif (/^#(define|undef)\s+BF_PTR/)
+ {
+ printf OUT "#undef BF_PTR\n" if $bf_ptr == 0;
+ printf OUT "#define BF_PTR\n" if $bf_ptr == 1;
+ printf OUT "#define BF_PTR2\n" if $bf_ptr == 2;
+ }
+ else
+ { print OUT $_; }
+ }
+close(IN);
+close(OUT);
+rename("crypto/opensslconf.h","crypto/opensslconf.h.bak") || die "unable to rename crypto/opensslconf.h\n" if -e "crypto/opensslconf.h";
+rename("crypto/opensslconf.h.new","crypto/opensslconf.h") || die "unable to rename crypto/opensslconf.h.new\n";
+
+
+# Fix the date
+
+print "SIXTY_FOUR_BIT_LONG mode\n" if $b64l;
+print "SIXTY_FOUR_BIT mode\n" if $b64;
+print "THIRTY_TWO_BIT mode\n" if $b32;
+print "SIXTEEN_BIT mode\n" if $b16;
+print "EIGHT_BIT mode\n" if $b8;
+print "DES_PTR used\n" if $des_ptr;
+print "DES_RISC1 used\n" if $des_risc1;
+print "DES_RISC2 used\n" if $des_risc2;
+print "DES_UNROLL used\n" if $des_unroll;
+print "DES_INT used\n" if $des_int;
+print "BN_LLONG mode\n" if $bn_ll;
+print "RC4 uses u$type[$rc4_int]\n" if $rc4_int != $def_int;
+print "RC4_INDEX mode\n" if $rc4_idx;
+print "RC4_CHUNK is undefined\n" if $rc4_chunk==0;
+print "RC4_CHUNK is unsigned long\n" if $rc4_chunk==1;
+print "RC4_CHUNK is unsigned long long\n" if $rc4_chunk==2;
+print "MD2 uses u$type[$md2_int]\n" if $md2_int != $def_int;
+print "IDEA uses u$type[$idea_int]\n" if $idea_int != $def_int;
+print "RC2 uses u$type[$rc2_int]\n" if $rc2_int != $def_int;
+print "BF_PTR used\n" if $bf_ptr == 1;
+print "BF_PTR2 used\n" if $bf_ptr == 2;
+
+if($IsMK1MF) {
+ open (OUT,">crypto/buildinf.h") || die "Can't open buildinf.h";
+ printf OUT <ms/version32.rc") || die "Can't open ms/version32.rc";
+ print OUT <
+
+LANGUAGE 0x09,0x01
+
+1 VERSIONINFO
+ FILEVERSION $v1,$v2,$v3,$v4
+ PRODUCTVERSION $v1,$v2,$v3,$v4
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x01L
+#else
+ FILEFLAGS 0x00L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ // Required:
+ VALUE "CompanyName", "The OpenSSL Project, http://www.openssl.org/\\0"
+ VALUE "FileDescription", "OpenSSL Shared Library\\0"
+ VALUE "FileVersion", "$version\\0"
+#if defined(CRYPTO)
+ VALUE "InternalName", "libeay32\\0"
+ VALUE "OriginalFilename", "libeay32.dll\\0"
+#elif defined(SSL)
+ VALUE "InternalName", "ssleay32\\0"
+ VALUE "OriginalFilename", "ssleay32.dll\\0"
+#endif
+ VALUE "ProductName", "The OpenSSL Toolkit\\0"
+ VALUE "ProductVersion", "$version\\0"
+ // Optional:
+ //VALUE "Comments", "\\0"
+ VALUE "LegalCopyright", "Copyright © 1998-2005 The OpenSSL Project. Copyright © 1995-1998 Eric A. Young, Tim J. Hudson. All rights reserved.\\0"
+ //VALUE "LegalTrademarks", "\\0"
+ //VALUE "PrivateBuild", "\\0"
+ //VALUE "SpecialBuild", "\\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 0x4b0
+ END
+END
+EOF
+ close(OUT);
+ }
+
+print < 78)
+ {
+ print STDERR "\n";
+ $k=length($i);
+ }
+ print STDERR $i . " ";
+ }
+ foreach $i (sort keys %table)
+ {
+ next if $i !~ /^debug/;
+ $k += length($i) + 1;
+ if ($k > 78)
+ {
+ print STDERR "\n";
+ $k=length($i);
+ }
+ print STDERR $i . " ";
+ }
+ print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
+ exit(1);
+ }
+
+sub which
+ {
+ my($name)=@_;
+ my $path;
+ foreach $path (split /:/, $ENV{PATH})
+ {
+ if (-f "$path/$name$exe_ext" and -x _)
+ {
+ return "$path/$name$exe_ext" unless ($name eq "perl" and
+ system("$path/$name$exe_ext -e " . '\'exit($]<5.0);\''));
+ }
+ }
+ }
+
+sub dofile
+ {
+ my $f; my $p; my %m; my @a; my $k; my $ff;
+ ($f,$p,%m)=@_;
+
+ open(IN,"<$f.in") || open(IN,"<$f") || die "unable to open $f:$!\n";
+ @a=;
+ close(IN);
+ foreach $k (keys %m)
+ {
+ grep(/$k/ && ($_=sprintf($m{$k}."\n",$p)),@a);
+ }
+ open(OUT,">$f.new") || die "unable to open $f.new:$!\n";
+ print OUT @a;
+ close(OUT);
+ rename($f,"$f.bak") || die "unable to rename $f\n" if -e $f;
+ rename("$f.new",$f) || die "unable to rename $f.new\n";
+ }
+
+sub print_table_entry
+ {
+ my $target = shift;
+
+ (my $cc,my $cflags,my $unistd,my $thread_cflag,my $sys_id,my $lflags,
+ my $bn_ops,my $cpuid_obj,my $bn_obj,my $des_obj,my $aes_obj, my $bf_obj,
+ my $md5_obj,my $sha1_obj,my $cast_obj,my $rc4_obj,my $rmd160_obj,
+ my $rc5_obj,my $dso_scheme,my $shared_target,my $shared_cflag,
+ my $shared_ldflag,my $shared_extension,my $ranlib,my $arflags)=
+ split(/\s*:\s*/,$table{$target} . ":" x 30 , -1);
+
+ print <Card No.: {{cardNumber | myCreditCardNumberFormatter}}
`|`{{cardNumber | myCreditCardNumberFormatter}}`
description:
-Transforms the current value of expression `cardNumber` via the pipe called `creditCardNumberFormatter`.
+Transforms the current value of expression `cardNumber` via the pipe called `myCreditCardNumberFormatter`.
@cheatsheetItem
syntax:
diff --git a/modules/angular2/docs/web_workers/web_workers.md b/modules/angular2/docs/web_workers/web_workers.md
index 7ec8f2694c53a..2a5dfbf2d398e 100644
--- a/modules/angular2/docs/web_workers/web_workers.md
+++ b/modules/angular2/docs/web_workers/web_workers.md
@@ -371,14 +371,14 @@ In TypeScript:
import {platform, Provider, APP_INITIALIZER, Injector} from 'angular2/core';
import {
WORKER_RENDER_PLATFORM,
- WORKER_RENDER_APP_COMMON,
+ WORKER_RENDER_APPLICATION_COMMON,
initializeGenericWorkerRenderer,
MessageBus
} from 'angular2/platform/worker_render';
var bus = new MyAwesomeMessageBus();
platform([WORKER_RENDER_PLATFORM])
-.application([WORKER_RENDER_APP_COMMON, new Provider(MessageBus, {useValue: bus}),
+.application([WORKER_RENDER_APPLICATION_COMMON, new Provider(MessageBus, {useValue: bus}),
new Provider(APP_INITIALIZER, {
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
deps: [Injector],
@@ -419,7 +419,7 @@ import 'package:angular2/platform/worker_render.dart';
main() {
var bus = new MyAwesomeMessageBus();
platform([WORKER_RENDER_PLATFORM])
- .application([WORKER_RENDER_APP_COMMON, new Provider(MessageBus, useValue: bus),
+ .application([WORKER_RENDER_APPLICATION_COMMON, new Provider(MessageBus, useValue: bus),
new Provider(APP_INITIALIZER,
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
deps: [Injector],
@@ -456,9 +456,9 @@ void initAppThread(NgZone zone) {
*/
}
```
-Notice how we use the `WORKER_RENDER_APP_COMMON` providers instead of the `WORKER_RENDER_APP` providers on the render thread.
-This is because the `WORKER_RENDER_APP` providers include an application initializer that starts a new WebWorker/Isolate.
-The `WORKER_RENDER_APP_COMMON` providers make no assumption about where your application code lives.
+Notice how we use the `WORKER_RENDER_APPLICTION_COMMON` providers instead of the `WORKER_RENDER_APPLICATION` providers on the render thread.
+This is because the `WORKER_RENDER_APPLICATION` providers include an application initializer that starts a new WebWorker/Isolate.
+The `WORKER_RENDER_APPLICATION_COMMON` providers make no assumption about where your application code lives.
However, we now need to provide our own app initializer. At the very least this initializer needs to call `initializeGenericWorkerRenderer`.
## MessageBroker
diff --git a/modules/angular2/manual_typings/globals-es6.d.ts b/modules/angular2/manual_typings/globals-es6.d.ts
index b1292515c2e04..703f7de00966c 100644
--- a/modules/angular2/manual_typings/globals-es6.d.ts
+++ b/modules/angular2/manual_typings/globals-es6.d.ts
@@ -6,8 +6,6 @@
///
///
-///
-///
// TODO: ideally the node.d.ts reference should be scoped only for files that need and not to all
// the code including client code
@@ -30,6 +28,7 @@ interface BrowserNodeGlobal {
zone: Zone;
getAngularTestability: Function;
getAllAngularTestabilities: Function;
+ frameworkStabilizers: Array;
setTimeout: Function;
clearTimeout: Function;
setInterval: Function;
diff --git a/modules/angular2/platform/testing/browser.ts b/modules/angular2/platform/testing/browser.ts
new file mode 100644
index 0000000000000..8aeb60f7cdba5
--- /dev/null
+++ b/modules/angular2/platform/testing/browser.ts
@@ -0,0 +1,21 @@
+import {
+ TEST_BROWSER_STATIC_PLATFORM_PROVIDERS,
+ ADDITIONAL_TEST_BROWSER_PROVIDERS
+} from 'angular2/platform/testing/browser_static';
+
+import {BROWSER_APP_PROVIDERS} from 'angular2/platform/browser';
+
+
+import {CONST_EXPR} from 'angular2/src/facade/lang';
+
+/**
+ * Default patform providers for testing.
+ */
+export const TEST_BROWSER_PLATFORM_PROVIDERS: Array =
+ CONST_EXPR([TEST_BROWSER_STATIC_PLATFORM_PROVIDERS]);
+
+/**
+ * Default application providers for testing.
+ */
+export const TEST_BROWSER_APPLICATION_PROVIDERS: Array =
+ CONST_EXPR([BROWSER_APP_PROVIDERS, ADDITIONAL_TEST_BROWSER_PROVIDERS]);
diff --git a/modules/angular2/platform/testing/browser_static.ts b/modules/angular2/platform/testing/browser_static.ts
new file mode 100644
index 0000000000000..1f4192134e0e9
--- /dev/null
+++ b/modules/angular2/platform/testing/browser_static.ts
@@ -0,0 +1,69 @@
+import {
+ APP_ID,
+ DirectiveResolver,
+ NgZone,
+ Provider,
+ ViewResolver,
+ PLATFORM_COMMON_PROVIDERS,
+ PLATFORM_INITIALIZER
+} from 'angular2/core';
+import {BROWSER_APP_COMMON_PROVIDERS} from 'angular2/src/platform/browser_common';
+import {BrowserDomAdapter} from 'angular2/src/platform/browser/browser_adapter';
+
+import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
+import {MockAnimationBuilder} from 'angular2/src/mock/animation_builder_mock';
+import {MockDirectiveResolver} from 'angular2/src/mock/directive_resolver_mock';
+import {MockViewResolver} from 'angular2/src/mock/view_resolver_mock';
+import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
+import {LocationStrategy} from 'angular2/src/router/location_strategy';
+import {MockNgZone} from 'angular2/src/mock/ng_zone_mock';
+
+import {XHRImpl} from "angular2/src/platform/browser/xhr_impl";
+import {XHR} from 'angular2/compiler';
+
+import {TestComponentBuilder} from 'angular2/src/testing/test_component_builder';
+
+import {BrowserDetection} from 'angular2/src/testing/utils';
+
+import {ELEMENT_PROBE_PROVIDERS} from 'angular2/platform/common_dom';
+
+import {CONST_EXPR} from 'angular2/src/facade/lang';
+
+import {Log} from 'angular2/src/testing/utils';
+
+function initBrowserTests() {
+ BrowserDomAdapter.makeCurrent();
+ BrowserDetection.setup();
+}
+
+/**
+ * Default patform providers for testing without a compiler.
+ */
+export const TEST_BROWSER_STATIC_PLATFORM_PROVIDERS: Array =
+ CONST_EXPR([
+ PLATFORM_COMMON_PROVIDERS,
+ new Provider(PLATFORM_INITIALIZER, {useValue: initBrowserTests, multi: true})
+ ]);
+
+export const ADDITIONAL_TEST_BROWSER_PROVIDERS: Array =
+ CONST_EXPR([
+ new Provider(APP_ID, {useValue: 'a'}),
+ ELEMENT_PROBE_PROVIDERS,
+ new Provider(DirectiveResolver, {useClass: MockDirectiveResolver}),
+ new Provider(ViewResolver, {useClass: MockViewResolver}),
+ Log,
+ TestComponentBuilder,
+ new Provider(NgZone, {useClass: MockNgZone}),
+ new Provider(LocationStrategy, {useClass: MockLocationStrategy}),
+ new Provider(AnimationBuilder, {useClass: MockAnimationBuilder}),
+ ]);
+
+/**
+ * Default application providers for testing without a compiler.
+ */
+export const TEST_BROWSER_STATIC_APPLICATION_PROVIDERS: Array =
+ CONST_EXPR([
+ BROWSER_APP_COMMON_PROVIDERS,
+ new Provider(XHR, {useClass: XHRImpl}),
+ ADDITIONAL_TEST_BROWSER_PROVIDERS
+ ]);
diff --git a/modules/angular2/platform/testing/server.dart b/modules/angular2/platform/testing/server.dart
new file mode 100644
index 0000000000000..a46a40721fc6c
--- /dev/null
+++ b/modules/angular2/platform/testing/server.dart
@@ -0,0 +1 @@
+// Intentionally blank, the Parse5Adapater bindings for JavaScript don't apply.
diff --git a/modules/angular2/platform/testing/server.ts b/modules/angular2/platform/testing/server.ts
new file mode 100644
index 0000000000000..47156c14d46cb
--- /dev/null
+++ b/modules/angular2/platform/testing/server.ts
@@ -0,0 +1,90 @@
+import {
+ APP_ID,
+ DirectiveResolver,
+ NgZone,
+ Provider,
+ ViewResolver,
+ PLATFORM_COMMON_PROVIDERS,
+ PLATFORM_INITIALIZER,
+ APPLICATION_COMMON_PROVIDERS,
+ Renderer
+} from 'angular2/core';
+import {Parse5DomAdapter} from 'angular2/src/platform/server/parse5_adapter';
+
+import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
+import {MockAnimationBuilder} from 'angular2/src/mock/animation_builder_mock';
+import {MockDirectiveResolver} from 'angular2/src/mock/directive_resolver_mock';
+import {MockViewResolver} from 'angular2/src/mock/view_resolver_mock';
+import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
+import {LocationStrategy} from 'angular2/src/router/location_strategy';
+import {MockNgZone} from 'angular2/src/mock/ng_zone_mock';
+
+import {TestComponentBuilder} from 'angular2/src/testing/test_component_builder';
+import {XHR} from 'angular2/src/compiler/xhr';
+import {BrowserDetection} from 'angular2/src/testing/utils';
+
+import {COMPILER_PROVIDERS} from 'angular2/src/compiler/compiler';
+import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
+import {DOM} from 'angular2/src/platform/dom/dom_adapter';
+import {RootRenderer} from 'angular2/src/core/render/api';
+import {DomRootRenderer, DomRootRenderer_} from 'angular2/src/platform/dom/dom_renderer';
+import {DomSharedStylesHost} from 'angular2/src/platform/dom/shared_styles_host';
+
+import {
+ EventManager,
+ EVENT_MANAGER_PLUGINS,
+ ELEMENT_PROBE_PROVIDERS
+} from 'angular2/platform/common_dom';
+import {DomEventsPlugin} from 'angular2/src/platform/dom/events/dom_events';
+
+import {CONST_EXPR} from 'angular2/src/facade/lang';
+
+import {Log} from 'angular2/src/testing/utils';
+
+function initServerTests() {
+ Parse5DomAdapter.makeCurrent();
+ BrowserDetection.setup();
+}
+
+/**
+ * Default patform providers for testing.
+ */
+export const TEST_SERVER_PLATFORM_PROVIDERS: Array = CONST_EXPR([
+ PLATFORM_COMMON_PROVIDERS,
+ new Provider(PLATFORM_INITIALIZER, {useValue: initServerTests, multi: true})
+]);
+
+function appDoc() {
+ try {
+ return DOM.defaultDoc();
+ } catch (e) {
+ return null;
+ }
+}
+
+/**
+ * Default application providers for testing.
+ */
+export const TEST_SERVER_APPLICATION_PROVIDERS: Array =
+ CONST_EXPR([
+ // TODO(julie): when angular2/platform/server is available, use that instead of making our own
+ // list here.
+ APPLICATION_COMMON_PROVIDERS,
+ COMPILER_PROVIDERS,
+ new Provider(DOCUMENT, {useFactory: appDoc}),
+ new Provider(DomRootRenderer, {useClass: DomRootRenderer_}),
+ new Provider(RootRenderer, {useExisting: DomRootRenderer}),
+ EventManager,
+ new Provider(EVENT_MANAGER_PLUGINS, {useClass: DomEventsPlugin, multi: true}),
+ new Provider(XHR, {useClass: XHR}),
+ new Provider(APP_ID, {useValue: 'a'}),
+ DomSharedStylesHost,
+ ELEMENT_PROBE_PROVIDERS,
+ new Provider(DirectiveResolver, {useClass: MockDirectiveResolver}),
+ new Provider(ViewResolver, {useClass: MockViewResolver}),
+ Log,
+ TestComponentBuilder,
+ new Provider(NgZone, {useClass: MockNgZone}),
+ new Provider(LocationStrategy, {useClass: MockLocationStrategy}),
+ new Provider(AnimationBuilder, {useClass: MockAnimationBuilder}),
+ ]);
diff --git a/modules/angular2/platform/worker_render.dart b/modules/angular2/platform/worker_render.dart
index 1b689cc2440be..aafab6599dfe7 100644
--- a/modules/angular2/platform/worker_render.dart
+++ b/modules/angular2/platform/worker_render.dart
@@ -4,11 +4,11 @@ export 'package:angular2/src/platform/worker_render_common.dart'
show
WORKER_SCRIPT,
WORKER_RENDER_PLATFORM,
- WORKER_RENDER_APP_COMMON,
+ WORKER_RENDER_APPLICATION_COMMON,
initializeGenericWorkerRenderer;
export 'package:angular2/src/platform/worker_render.dart'
- show WORKER_RENDER_APP, initIsolate, WebWorkerInstance;
+ show WORKER_RENDER_APPLICATION, initIsolate, WebWorkerInstance;
export '../src/web_workers/shared/client_message_broker.dart'
show ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments;
@@ -18,3 +18,7 @@ export '../src/web_workers/shared/service_message_broker.dart'
export '../src/web_workers/shared/serializer.dart' show PRIMITIVE;
export '../src/web_workers/shared/message_bus.dart';
+
+import 'package:angular2/src/platform/worker_render_common.dart';
+
+const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION_COMMON;
diff --git a/modules/angular2/platform/worker_render.ts b/modules/angular2/platform/worker_render.ts
index 7a2e7ab579ea7..a601dbf253ebb 100644
--- a/modules/angular2/platform/worker_render.ts
+++ b/modules/angular2/platform/worker_render.ts
@@ -2,9 +2,9 @@ export {
WORKER_SCRIPT,
WORKER_RENDER_PLATFORM,
initializeGenericWorkerRenderer,
- WORKER_RENDER_APP_COMMON
+ WORKER_RENDER_APPLICATION_COMMON
} from 'angular2/src/platform/worker_render_common';
-export * from 'angular2/src/platform/worker_render';
+export {WORKER_RENDER_APPLICATION, WebWorkerInstance} from 'angular2/src/platform/worker_render';
export {
ClientMessageBroker,
ClientMessageBrokerFactory,
@@ -18,3 +18,9 @@ export {
} from '../src/web_workers/shared/service_message_broker';
export {PRIMITIVE} from '../src/web_workers/shared/serializer';
export * from '../src/web_workers/shared/message_bus';
+import {WORKER_RENDER_APPLICATION} from 'angular2/src/platform/worker_render';
+
+/**
+ * @deprecated Use WORKER_RENDER_APPLICATION
+ */
+export const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION;
diff --git a/modules/angular2/pubspec.yaml b/modules/angular2/pubspec.yaml
index 980ce1a25f73d..a5243e3025dd0 100644
--- a/modules/angular2/pubspec.yaml
+++ b/modules/angular2/pubspec.yaml
@@ -9,9 +9,8 @@ homepage: <%= packageJson.homepage %>
environment:
sdk: '>=1.10.0 <2.0.0'
dependencies:
- analyzer: '>=0.24.4 <0.27.0'
+ analyzer: '>=0.24.4 <0.28.0'
barback: '^0.15.2+2'
- code_transformers: '0.2.9+4'
dart_style: '>=0.1.8 <0.3.0'
glob: '^1.0.0'
html: '^0.12.0'
@@ -23,7 +22,9 @@ dependencies:
source_span: '^1.0.0'
stack_trace: '^1.1.1'
dev_dependencies:
+ code_transformers: '>=0.2.9+4 <0.4.0'
guinness: '^0.1.18'
+ test: '^0.12.6'
transformers:
- angular2
- $dart2js:
diff --git a/modules/angular2/src/common/directives/ng_class.ts b/modules/angular2/src/common/directives/ng_class.ts
index 2f77b0767f85e..cae1ca01e6ca7 100644
--- a/modules/angular2/src/common/directives/ng_class.ts
+++ b/modules/angular2/src/common/directives/ng_class.ts
@@ -169,10 +169,10 @@ export class NgClass implements DoCheck, OnDestroy {
if (className.indexOf(' ') > -1) {
var classes = className.split(/\s+/g);
for (var i = 0, len = classes.length; i < len; i++) {
- this._renderer.setElementClass(this._ngEl, classes[i], enabled);
+ this._renderer.setElementClass(this._ngEl.nativeElement, classes[i], enabled);
}
} else {
- this._renderer.setElementClass(this._ngEl, className, enabled);
+ this._renderer.setElementClass(this._ngEl.nativeElement, className, enabled);
}
}
}
diff --git a/modules/angular2/src/common/directives/ng_for.ts b/modules/angular2/src/common/directives/ng_for.ts
index 7529f14f08931..ec768c4981946 100644
--- a/modules/angular2/src/common/directives/ng_for.ts
+++ b/modules/angular2/src/common/directives/ng_for.ts
@@ -6,7 +6,7 @@ import {
IterableDiffers,
ViewContainerRef,
TemplateRef,
- ViewRef
+ EmbeddedViewRef
} from 'angular2/core';
import {isPresent, isBlank} from 'angular2/src/facade/lang';
@@ -110,7 +110,8 @@ export class NgFor implements DoCheck {
}
for (var i = 0, ilen = this._viewContainer.length; i < ilen; i++) {
- this._viewContainer.get(i).setLocal('last', i === ilen - 1);
+ var viewRef = this._viewContainer.get(i);
+ viewRef.setLocal('last', i === ilen - 1);
}
}
@@ -153,7 +154,7 @@ export class NgFor implements DoCheck {
}
class RecordViewTuple {
- view: ViewRef;
+ view: EmbeddedViewRef;
record: any;
constructor(record, view) {
this.record = record;
diff --git a/modules/angular2/src/common/directives/ng_style.ts b/modules/angular2/src/common/directives/ng_style.ts
index 90b5d74483384..99d658a0f9039 100644
--- a/modules/angular2/src/common/directives/ng_style.ts
+++ b/modules/angular2/src/common/directives/ng_style.ts
@@ -92,6 +92,6 @@ export class NgStyle implements DoCheck {
}
private _setStyle(name: string, val: string): void {
- this._renderer.setElementStyle(this._ngEl, name, val);
+ this._renderer.setElementStyle(this._ngEl.nativeElement, name, val);
}
}
diff --git a/modules/angular2/src/common/directives/ng_switch.ts b/modules/angular2/src/common/directives/ng_switch.ts
index a25cb70a08ce1..469a9dbca23f5 100644
--- a/modules/angular2/src/common/directives/ng_switch.ts
+++ b/modules/angular2/src/common/directives/ng_switch.ts
@@ -4,7 +4,8 @@ import {ListWrapper, Map} from 'angular2/src/facade/collection';
const _WHEN_DEFAULT = CONST_EXPR(new Object());
-class SwitchView {
+/** @internal */
+export class SwitchView {
constructor(private _viewContainerRef: ViewContainerRef, private _templateRef: TemplateRef) {}
create(): void { this._viewContainerRef.createEmbeddedView(this._templateRef); }
diff --git a/modules/angular2/src/common/forms/directives/checkbox_value_accessor.ts b/modules/angular2/src/common/forms/directives/checkbox_value_accessor.ts
index 3e52b078b3a08..094326839236b 100644
--- a/modules/angular2/src/common/forms/directives/checkbox_value_accessor.ts
+++ b/modules/angular2/src/common/forms/directives/checkbox_value_accessor.ts
@@ -27,7 +27,7 @@ export class CheckboxControlValueAccessor implements ControlValueAccessor {
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
writeValue(value: any): void {
- this._renderer.setElementProperty(this._elementRef, 'checked', value);
+ this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', value);
}
registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; }
registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
diff --git a/modules/angular2/src/common/forms/directives/default_value_accessor.ts b/modules/angular2/src/common/forms/directives/default_value_accessor.ts
index 67c88b3facba9..1cc88993a526a 100644
--- a/modules/angular2/src/common/forms/directives/default_value_accessor.ts
+++ b/modules/angular2/src/common/forms/directives/default_value_accessor.ts
@@ -31,7 +31,7 @@ export class DefaultValueAccessor implements ControlValueAccessor {
writeValue(value: any): void {
var normalizedValue = isBlank(value) ? '' : value;
- this._renderer.setElementProperty(this._elementRef, 'value', normalizedValue);
+ this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', normalizedValue);
}
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
diff --git a/modules/angular2/src/common/forms/directives/number_value_accessor.ts b/modules/angular2/src/common/forms/directives/number_value_accessor.ts
index 41b04f0481b0c..1122c606250fd 100644
--- a/modules/angular2/src/common/forms/directives/number_value_accessor.ts
+++ b/modules/angular2/src/common/forms/directives/number_value_accessor.ts
@@ -31,7 +31,7 @@ export class NumberValueAccessor implements ControlValueAccessor {
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
writeValue(value: number): void {
- this._renderer.setElementProperty(this._elementRef, 'value', value);
+ this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', value);
}
registerOnChange(fn: (_: number) => void): void {
diff --git a/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts b/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts
index 230631ddfd7e8..1cb88f6db81da 100644
--- a/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts
+++ b/modules/angular2/src/common/forms/directives/select_control_value_accessor.ts
@@ -36,11 +36,7 @@ export class NgSelectOption {
*/
@Directive({
selector: 'select[ngControl],select[ngFormControl],select[ngModel]',
- host: {
- '(change)': 'onChange($event.target.value)',
- '(input)': 'onChange($event.target.value)',
- '(blur)': 'onTouched()'
- },
+ host: {'(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()'},
bindings: [SELECT_VALUE_ACCESSOR]
})
export class SelectControlValueAccessor implements ControlValueAccessor {
@@ -55,7 +51,7 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
writeValue(value: any): void {
this.value = value;
- this._renderer.setElementProperty(this._elementRef, 'value', value);
+ this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', value);
}
registerOnChange(fn: () => any): void { this.onChange = fn; }
diff --git a/modules/angular2/src/common/forms/directives/shared.ts b/modules/angular2/src/common/forms/directives/shared.ts
index a0a5bb53ec6fc..e9a232b0699ab 100644
--- a/modules/angular2/src/common/forms/directives/shared.ts
+++ b/modules/angular2/src/common/forms/directives/shared.ts
@@ -80,7 +80,6 @@ export function selectValueAccessor(dir: NgControl,
var defaultAccessor;
var builtinAccessor;
var customAccessor;
-
valueAccessors.forEach(v => {
if (v instanceof DefaultValueAccessor) {
defaultAccessor = v;
diff --git a/modules/angular2/src/compiler/change_definition_factory.ts b/modules/angular2/src/compiler/change_definition_factory.ts
index ce7c940aa96e8..de12f8cbcddd4 100644
--- a/modules/angular2/src/compiler/change_definition_factory.ts
+++ b/modules/angular2/src/compiler/change_definition_factory.ts
@@ -1,4 +1,4 @@
-import {ListWrapper} from 'angular2/src/facade/collection';
+import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {isPresent, isBlank} from 'angular2/src/facade/lang';
import {reflector} from 'angular2/src/core/reflection/reflection';
@@ -43,7 +43,7 @@ export function createChangeDetectorDefinitions(
class ProtoViewVisitor implements TemplateAstVisitor {
viewIndex: number;
- boundTextCount: number = 0;
+ nodeCount: number = 0;
boundElementCount: number = 0;
variableNames: string[] = [];
bindingRecords: BindingRecord[] = [];
@@ -57,6 +57,7 @@ class ProtoViewVisitor implements TemplateAstVisitor {
}
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
+ this.nodeCount++;
this.boundElementCount++;
templateVisitAll(this, ast.outputs);
for (var i = 0; i < ast.directives.length; i++) {
@@ -73,6 +74,7 @@ class ProtoViewVisitor implements TemplateAstVisitor {
}
visitElement(ast: ElementAst, context: any): any {
+ this.nodeCount++;
if (ast.isBound()) {
this.boundElementCount++;
}
@@ -132,14 +134,20 @@ class ProtoViewVisitor implements TemplateAstVisitor {
}
visitAttr(ast: AttrAst, context: any): any { return null; }
visitBoundText(ast: BoundTextAst, context: any): any {
- var boundTextIndex = this.boundTextCount++;
- this.bindingRecords.push(BindingRecord.createForTextNode(ast.value, boundTextIndex));
+ var nodeIndex = this.nodeCount++;
+ this.bindingRecords.push(BindingRecord.createForTextNode(ast.value, nodeIndex));
+ return null;
+ }
+ visitText(ast: TextAst, context: any): any {
+ this.nodeCount++;
return null;
}
- visitText(ast: TextAst, context: any): any { return null; }
visitDirective(ast: DirectiveAst, directiveIndexAsNumber: number): any {
var directiveIndex = new DirectiveIndex(this.boundElementCount - 1, directiveIndexAsNumber);
var directiveMetadata = ast.directive;
+ var outputsArray = [];
+ StringMapWrapper.forEach(ast.directive.outputs, (eventName, dirProperty) => outputsArray.push(
+ [dirProperty, eventName]));
var directiveRecord = new DirectiveRecord({
directiveIndex: directiveIndex,
callAfterContentInit:
@@ -153,7 +161,9 @@ class ProtoViewVisitor implements TemplateAstVisitor {
callOnChanges: directiveMetadata.lifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1,
callDoCheck: directiveMetadata.lifecycleHooks.indexOf(LifecycleHooks.DoCheck) !== -1,
callOnInit: directiveMetadata.lifecycleHooks.indexOf(LifecycleHooks.OnInit) !== -1,
- changeDetection: directiveMetadata.changeDetection
+ callOnDestroy: directiveMetadata.lifecycleHooks.indexOf(LifecycleHooks.OnDestroy) !== -1,
+ changeDetection: directiveMetadata.changeDetection,
+ outputs: outputsArray
});
this.directiveRecords.push(directiveRecord);
diff --git a/modules/angular2/src/compiler/change_detector_compiler.ts b/modules/angular2/src/compiler/change_detector_compiler.ts
index 1f42bd823a6fa..db3b727b4adc6 100644
--- a/modules/angular2/src/compiler/change_detector_compiler.ts
+++ b/modules/angular2/src/compiler/change_detector_compiler.ts
@@ -3,6 +3,9 @@ import {SourceExpressions, moduleRef} from './source_module';
import {
ChangeDetectorJITGenerator
} from 'angular2/src/core/change_detection/change_detection_jit_generator';
+import {AbstractChangeDetector} from 'angular2/src/core/change_detection/abstract_change_detector';
+import {ChangeDetectionUtil} from 'angular2/src/core/change_detection/change_detection_util';
+import {ChangeDetectorState} from 'angular2/src/core/change_detection/constants';
import {createChangeDetectorDefinitions} from './change_definition_factory';
import {IS_DART, isJsObject, CONST_EXPR} from 'angular2/src/facade/lang';
@@ -23,6 +26,12 @@ const ABSTRACT_CHANGE_DETECTOR = "AbstractChangeDetector";
const UTIL = "ChangeDetectionUtil";
const CHANGE_DETECTOR_STATE = "ChangeDetectorState";
+export const CHANGE_DETECTION_JIT_IMPORTS = CONST_EXPR({
+ 'AbstractChangeDetector': AbstractChangeDetector,
+ 'ChangeDetectionUtil': ChangeDetectionUtil,
+ 'ChangeDetectorState': ChangeDetectorState
+});
+
var ABSTRACT_CHANGE_DETECTOR_MODULE = moduleRef(
`package:angular2/src/core/change_detection/abstract_change_detector${MODULE_SUFFIX}`);
var UTIL_MODULE =
@@ -45,14 +54,8 @@ export class ChangeDetectionCompiler {
}
private _createChangeDetectorFactory(definition: ChangeDetectorDefinition): Function {
- if (IS_DART || !this._genConfig.useJit) {
- var proto = new DynamicProtoChangeDetector(definition);
- return (dispatcher) => proto.instantiate(dispatcher);
- } else {
- return new ChangeDetectorJITGenerator(definition, UTIL, ABSTRACT_CHANGE_DETECTOR,
- CHANGE_DETECTOR_STATE)
- .generate();
- }
+ var proto = new DynamicProtoChangeDetector(definition);
+ return () => proto.instantiate();
}
compileComponentCodeGen(componentType: CompileTypeMetadata, strategy: ChangeDetectionStrategy,
@@ -81,7 +84,7 @@ export class ChangeDetectionCompiler {
definition, `${UTIL_MODULE}${UTIL}`,
`${ABSTRACT_CHANGE_DETECTOR_MODULE}${ABSTRACT_CHANGE_DETECTOR}`,
`${CONSTANTS_MODULE}${CHANGE_DETECTOR_STATE}`);
- factories.push(`function(dispatcher) { return new ${codegen.typeName}(dispatcher); }`);
+ factories.push(`function() { return new ${codegen.typeName}(); }`);
sourcePart = codegen.generateSource();
}
index++;
diff --git a/modules/angular2/src/compiler/command_compiler.ts b/modules/angular2/src/compiler/command_compiler.ts
deleted file mode 100644
index 5819b4da1e11a..0000000000000
--- a/modules/angular2/src/compiler/command_compiler.ts
+++ /dev/null
@@ -1,375 +0,0 @@
-import {isPresent, isBlank, Type, isString, StringWrapper, IS_DART} from 'angular2/src/facade/lang';
-import {SetWrapper, StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
-import {
- TemplateCmd,
- TextCmd,
- NgContentCmd,
- BeginElementCmd,
- EndElementCmd,
- BeginComponentCmd,
- EndComponentCmd,
- EmbeddedTemplateCmd,
- CompiledComponentTemplate
-} from 'angular2/src/core/linker/template_commands';
-import {
- TemplateAst,
- TemplateAstVisitor,
- NgContentAst,
- EmbeddedTemplateAst,
- ElementAst,
- VariableAst,
- BoundEventAst,
- BoundElementPropertyAst,
- AttrAst,
- BoundTextAst,
- TextAst,
- DirectiveAst,
- BoundDirectivePropertyAst,
- templateVisitAll
-} from './template_ast';
-import {CompileTypeMetadata, CompileDirectiveMetadata} from './directive_metadata';
-import {SourceExpressions, SourceExpression, moduleRef} from './source_module';
-
-import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
-import {
- escapeSingleQuoteString,
- codeGenConstConstructorCall,
- codeGenValueFn,
- MODULE_SUFFIX
-} from './util';
-import {Injectable} from 'angular2/src/core/di';
-
-export var TEMPLATE_COMMANDS_MODULE_REF =
- moduleRef(`package:angular2/src/core/linker/template_commands${MODULE_SUFFIX}`);
-
-const IMPLICIT_TEMPLATE_VAR = '\$implicit';
-const CLASS_ATTR = 'class';
-const STYLE_ATTR = 'style';
-
-@Injectable()
-export class CommandCompiler {
- compileComponentRuntime(component: CompileDirectiveMetadata, template: TemplateAst[],
- changeDetectorFactories: Function[],
- componentTemplateFactory: Function): TemplateCmd[] {
- var visitor = new CommandBuilderVisitor(
- new RuntimeCommandFactory(component, componentTemplateFactory, changeDetectorFactories), 0);
- templateVisitAll(visitor, template);
- return visitor.result;
- }
-
- compileComponentCodeGen(component: CompileDirectiveMetadata, template: TemplateAst[],
- changeDetectorFactoryExpressions: string[],
- componentTemplateFactory: Function): SourceExpression {
- var visitor =
- new CommandBuilderVisitor(new CodegenCommandFactory(component, componentTemplateFactory,
- changeDetectorFactoryExpressions),
- 0);
- templateVisitAll(visitor, template);
- return new SourceExpression([], codeGenArray(visitor.result));
- }
-}
-
-interface CommandFactory {
- createText(value: string, isBound: boolean, ngContentIndex: number): R;
- createNgContent(index: number, ngContentIndex: number): R;
- createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
- variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
- isBound: boolean, ngContentIndex: number): R;
- createEndElement(): R;
- createBeginComponent(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
- variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
- encapsulation: ViewEncapsulation, ngContentIndex: number): R;
- createEndComponent(): R;
- createEmbeddedTemplate(embeddedTemplateIndex: number, attrNameAndValues: string[],
- variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
- isMerged: boolean, ngContentIndex: number, children: R[]): R;
-}
-
-class RuntimeCommandFactory implements CommandFactory {
- constructor(private component: CompileDirectiveMetadata,
- private componentTemplateFactory: Function,
- private changeDetectorFactories: Function[]) {}
- private _mapDirectives(directives: CompileDirectiveMetadata[]): Type[] {
- return directives.map(directive => directive.type.runtime);
- }
-
- createText(value: string, isBound: boolean, ngContentIndex: number): TemplateCmd {
- return new TextCmd(value, isBound, ngContentIndex);
- }
- createNgContent(index: number, ngContentIndex: number): TemplateCmd {
- return new NgContentCmd(index, ngContentIndex);
- }
- createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
- variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
- isBound: boolean, ngContentIndex: number): TemplateCmd {
- return new BeginElementCmd(name, attrNameAndValues, eventTargetAndNames, variableNameAndValues,
- this._mapDirectives(directives), isBound, ngContentIndex);
- }
- createEndElement(): TemplateCmd { return new EndElementCmd(); }
- createBeginComponent(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
- variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
- encapsulation: ViewEncapsulation, ngContentIndex: number): TemplateCmd {
- var nestedTemplateAccessor = this.componentTemplateFactory(directives[0]);
- return new BeginComponentCmd(name, attrNameAndValues, eventTargetAndNames,
- variableNameAndValues, this._mapDirectives(directives),
- encapsulation, ngContentIndex, nestedTemplateAccessor);
- }
- createEndComponent(): TemplateCmd { return new EndComponentCmd(); }
- createEmbeddedTemplate(embeddedTemplateIndex: number, attrNameAndValues: string[],
- variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
- isMerged: boolean, ngContentIndex: number,
- children: TemplateCmd[]): TemplateCmd {
- return new EmbeddedTemplateCmd(attrNameAndValues, variableNameAndValues,
- this._mapDirectives(directives), isMerged, ngContentIndex,
- this.changeDetectorFactories[embeddedTemplateIndex], children);
- }
-}
-
-class CodegenCommandFactory implements CommandFactory {
- constructor(private component: CompileDirectiveMetadata,
- private componentTemplateFactory: Function,
- private changeDetectorFactoryExpressions: string[]) {}
-
- createText(value: string, isBound: boolean, ngContentIndex: number): Expression {
- return new Expression(
- `${codeGenConstConstructorCall(TEMPLATE_COMMANDS_MODULE_REF+'TextCmd')}(${escapeSingleQuoteString(value)}, ${isBound}, ${ngContentIndex})`);
- }
- createNgContent(index: number, ngContentIndex: number): Expression {
- return new Expression(
- `${codeGenConstConstructorCall(TEMPLATE_COMMANDS_MODULE_REF+'NgContentCmd')}(${index}, ${ngContentIndex})`);
- }
- createBeginElement(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
- variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
- isBound: boolean, ngContentIndex: number): Expression {
- var attrsExpression = codeGenArray(attrNameAndValues);
- return new Expression(
- `${codeGenConstConstructorCall(TEMPLATE_COMMANDS_MODULE_REF+'BeginElementCmd')}(${escapeSingleQuoteString(name)}, ${attrsExpression}, ` +
- `${codeGenArray(eventTargetAndNames)}, ${codeGenArray(variableNameAndValues)}, ${codeGenDirectivesArray(directives)}, ${isBound}, ${ngContentIndex})`);
- }
- createEndElement(): Expression {
- return new Expression(
- `${codeGenConstConstructorCall(TEMPLATE_COMMANDS_MODULE_REF+'EndElementCmd')}()`);
- }
- createBeginComponent(name: string, attrNameAndValues: string[], eventTargetAndNames: string[],
- variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
- encapsulation: ViewEncapsulation, ngContentIndex: number): Expression {
- var attrsExpression = codeGenArray(attrNameAndValues);
- return new Expression(
- `${codeGenConstConstructorCall(TEMPLATE_COMMANDS_MODULE_REF+'BeginComponentCmd')}(${escapeSingleQuoteString(name)}, ${attrsExpression}, ` +
- `${codeGenArray(eventTargetAndNames)}, ${codeGenArray(variableNameAndValues)}, ${codeGenDirectivesArray(directives)}, ${codeGenViewEncapsulation(encapsulation)}, ${ngContentIndex}, ${this.componentTemplateFactory(directives[0])})`);
- }
- createEndComponent(): Expression {
- return new Expression(
- `${codeGenConstConstructorCall(TEMPLATE_COMMANDS_MODULE_REF+'EndComponentCmd')}()`);
- }
- createEmbeddedTemplate(embeddedTemplateIndex: number, attrNameAndValues: string[],
- variableNameAndValues: string[], directives: CompileDirectiveMetadata[],
- isMerged: boolean, ngContentIndex: number,
- children: Expression[]): Expression {
- return new Expression(
- `${codeGenConstConstructorCall(TEMPLATE_COMMANDS_MODULE_REF+'EmbeddedTemplateCmd')}(${codeGenArray(attrNameAndValues)}, ${codeGenArray(variableNameAndValues)}, ` +
- `${codeGenDirectivesArray(directives)}, ${isMerged}, ${ngContentIndex}, ${this.changeDetectorFactoryExpressions[embeddedTemplateIndex]}, ${codeGenArray(children)})`);
- }
-}
-
-function visitAndReturnContext(visitor: TemplateAstVisitor, asts: TemplateAst[],
- context: any): any {
- templateVisitAll(visitor, asts, context);
- return context;
-}
-
-class CommandBuilderVisitor implements TemplateAstVisitor {
- result: R[] = [];
- transitiveNgContentCount: number = 0;
- constructor(public commandFactory: CommandFactory, public embeddedTemplateIndex: number) {}
-
- private _readAttrNameAndValues(directives: CompileDirectiveMetadata[],
- attrAsts: TemplateAst[]): string[] {
- var attrs = keyValueArrayToMap(visitAndReturnContext(this, attrAsts, []));
- directives.forEach(directiveMeta => {
- StringMapWrapper.forEach(directiveMeta.hostAttributes, (value, name) => {
- var prevValue = attrs[name];
- attrs[name] = isPresent(prevValue) ? mergeAttributeValue(name, prevValue, value) : value;
- });
- });
- return mapToKeyValueArray(attrs);
- }
-
- visitNgContent(ast: NgContentAst, context: any): any {
- this.transitiveNgContentCount++;
- this.result.push(this.commandFactory.createNgContent(ast.index, ast.ngContentIndex));
- return null;
- }
- visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
- this.embeddedTemplateIndex++;
- var childVisitor = new CommandBuilderVisitor(this.commandFactory, this.embeddedTemplateIndex);
- templateVisitAll(childVisitor, ast.children);
- var isMerged = childVisitor.transitiveNgContentCount > 0;
- var variableNameAndValues = [];
- ast.vars.forEach((varAst) => {
- variableNameAndValues.push(varAst.name);
- variableNameAndValues.push(varAst.value.length > 0 ? varAst.value : IMPLICIT_TEMPLATE_VAR);
- });
- var directives = [];
- ListWrapper.forEachWithIndex(ast.directives, (directiveAst: DirectiveAst, index: number) => {
- directiveAst.visit(this, new DirectiveContext(index, [], [], directives));
- });
- this.result.push(this.commandFactory.createEmbeddedTemplate(
- this.embeddedTemplateIndex, this._readAttrNameAndValues(directives, ast.attrs),
- variableNameAndValues, directives, isMerged, ast.ngContentIndex, childVisitor.result));
- this.transitiveNgContentCount += childVisitor.transitiveNgContentCount;
- this.embeddedTemplateIndex = childVisitor.embeddedTemplateIndex;
- return null;
- }
- visitElement(ast: ElementAst, context: any): any {
- var component = ast.getComponent();
- var eventTargetAndNames = visitAndReturnContext(this, ast.outputs, []);
- var variableNameAndValues = [];
- if (isBlank(component)) {
- ast.exportAsVars.forEach((varAst) => {
- variableNameAndValues.push(varAst.name);
- variableNameAndValues.push(null);
- });
- }
- var directives = [];
- ListWrapper.forEachWithIndex(ast.directives, (directiveAst: DirectiveAst, index: number) => {
- directiveAst.visit(this, new DirectiveContext(index, eventTargetAndNames,
- variableNameAndValues, directives));
- });
- eventTargetAndNames = removeKeyValueArrayDuplicates(eventTargetAndNames);
-
- var attrNameAndValues = this._readAttrNameAndValues(directives, ast.attrs);
- if (isPresent(component)) {
- this.result.push(this.commandFactory.createBeginComponent(
- ast.name, attrNameAndValues, eventTargetAndNames, variableNameAndValues, directives,
- component.template.encapsulation, ast.ngContentIndex));
- templateVisitAll(this, ast.children);
- this.result.push(this.commandFactory.createEndComponent());
- } else {
- this.result.push(this.commandFactory.createBeginElement(
- ast.name, attrNameAndValues, eventTargetAndNames, variableNameAndValues, directives,
- ast.isBound(), ast.ngContentIndex));
- templateVisitAll(this, ast.children);
- this.result.push(this.commandFactory.createEndElement());
- }
- return null;
- }
- visitVariable(ast: VariableAst, ctx: any): any { return null; }
- visitAttr(ast: AttrAst, attrNameAndValues: string[]): any {
- attrNameAndValues.push(ast.name);
- attrNameAndValues.push(ast.value);
- return null;
- }
- visitBoundText(ast: BoundTextAst, context: any): any {
- this.result.push(this.commandFactory.createText(null, true, ast.ngContentIndex));
- return null;
- }
- visitText(ast: TextAst, context: any): any {
- this.result.push(this.commandFactory.createText(ast.value, false, ast.ngContentIndex));
- return null;
- }
- visitDirective(ast: DirectiveAst, ctx: DirectiveContext): any {
- ctx.targetDirectives.push(ast.directive);
- templateVisitAll(this, ast.hostEvents, ctx.eventTargetAndNames);
- ast.exportAsVars.forEach(varAst => {
- ctx.targetVariableNameAndValues.push(varAst.name);
- ctx.targetVariableNameAndValues.push(ctx.index);
- });
- return null;
- }
- visitEvent(ast: BoundEventAst, eventTargetAndNames: string[]): any {
- eventTargetAndNames.push(ast.target);
- eventTargetAndNames.push(ast.name);
- return null;
- }
- visitDirectiveProperty(ast: BoundDirectivePropertyAst, context: any): any { return null; }
- visitElementProperty(ast: BoundElementPropertyAst, context: any): any { return null; }
-}
-
-function removeKeyValueArrayDuplicates(keyValueArray: string[]): string[] {
- var knownPairs = new Set();
- var resultKeyValueArray = [];
- for (var i = 0; i < keyValueArray.length; i += 2) {
- var key = keyValueArray[i];
- var value = keyValueArray[i + 1];
- var pairId = `${key}:${value}`;
- if (!SetWrapper.has(knownPairs, pairId)) {
- resultKeyValueArray.push(key);
- resultKeyValueArray.push(value);
- knownPairs.add(pairId);
- }
- }
- return resultKeyValueArray;
-}
-
-function keyValueArrayToMap(keyValueArr: string[]): {[key: string]: string} {
- var data: {[key: string]: string} = {};
- for (var i = 0; i < keyValueArr.length; i += 2) {
- data[keyValueArr[i]] = keyValueArr[i + 1];
- }
- return data;
-}
-
-function mapToKeyValueArray(data: {[key: string]: string}): string[] {
- var entryArray = [];
- StringMapWrapper.forEach(data, (value, name) => { entryArray.push([name, value]); });
- // We need to sort to get a defined output order
- // for tests and for caching generated artifacts...
- ListWrapper.sort(entryArray, (entry1, entry2) => StringWrapper.compare(entry1[0], entry2[0]));
- var keyValueArray = [];
- entryArray.forEach((entry) => {
- keyValueArray.push(entry[0]);
- keyValueArray.push(entry[1]);
- });
- return keyValueArray;
-}
-
-function mergeAttributeValue(attrName: string, attrValue1: string, attrValue2: string): string {
- if (attrName == CLASS_ATTR || attrName == STYLE_ATTR) {
- return `${attrValue1} ${attrValue2}`;
- } else {
- return attrValue2;
- }
-}
-
-class DirectiveContext {
- constructor(public index: number, public eventTargetAndNames: string[],
- public targetVariableNameAndValues: any[],
- public targetDirectives: CompileDirectiveMetadata[]) {}
-}
-
-class Expression {
- constructor(public value: string) {}
-}
-
-function escapeValue(value: any): string {
- if (value instanceof Expression) {
- return value.value;
- } else if (isString(value)) {
- return escapeSingleQuoteString(value);
- } else if (isBlank(value)) {
- return 'null';
- } else {
- return `${value}`;
- }
-}
-
-function codeGenArray(data: any[]): string {
- var base = `[${data.map(escapeValue).join(',')}]`;
- return IS_DART ? `const ${base}` : base;
-}
-
-function codeGenDirectivesArray(directives: CompileDirectiveMetadata[]): string {
- var expressions = directives.map(
- directiveType => `${moduleRef(directiveType.type.moduleUrl)}${directiveType.type.name}`);
- var base = `[${expressions.join(',')}]`;
- return IS_DART ? `const ${base}` : base;
-}
-
-function codeGenViewEncapsulation(value: ViewEncapsulation): string {
- if (IS_DART) {
- return `${TEMPLATE_COMMANDS_MODULE_REF}${value}`;
- } else {
- return `${value}`;
- }
-}
diff --git a/modules/angular2/src/compiler/compiler.ts b/modules/angular2/src/compiler/compiler.ts
index c35bc9104c7d2..23426ce6c145c 100644
--- a/modules/angular2/src/compiler/compiler.ts
+++ b/modules/angular2/src/compiler/compiler.ts
@@ -17,7 +17,8 @@ import {TemplateNormalizer} from 'angular2/src/compiler/template_normalizer';
import {RuntimeMetadataResolver} from 'angular2/src/compiler/runtime_metadata';
import {ChangeDetectionCompiler} from 'angular2/src/compiler/change_detector_compiler';
import {StyleCompiler} from 'angular2/src/compiler/style_compiler';
-import {CommandCompiler} from 'angular2/src/compiler/command_compiler';
+import {ViewCompiler} from 'angular2/src/compiler/view_compiler';
+import {ProtoViewCompiler} from 'angular2/src/compiler/proto_view_compiler';
import {TemplateCompiler} from 'angular2/src/compiler/template_compiler';
import {ChangeDetectorGenConfig} from 'angular2/src/core/change_detection/change_detection';
import {Compiler} from 'angular2/src/core/linker/compiler';
@@ -44,7 +45,8 @@ export const COMPILER_PROVIDERS: Array = CONST_EXPR([
RuntimeMetadataResolver,
DEFAULT_PACKAGE_URL_PROVIDER,
StyleCompiler,
- CommandCompiler,
+ ProtoViewCompiler,
+ ViewCompiler,
ChangeDetectionCompiler,
new Provider(ChangeDetectorGenConfig, {useFactory: _createChangeDetectorGenConfig, deps: []}),
TemplateCompiler,
diff --git a/modules/angular2/src/compiler/directive_metadata.ts b/modules/angular2/src/compiler/directive_metadata.ts
index f82f6b031a378..2fe7ef0d38ee6 100644
--- a/modules/angular2/src/compiler/directive_metadata.ts
+++ b/modules/angular2/src/compiler/directive_metadata.ts
@@ -7,6 +7,7 @@ import {
RegExpWrapper,
StringWrapper
} from 'angular2/src/facade/lang';
+import {unimplemented} from 'angular2/src/facade/exceptions';
import {StringMapWrapper} from 'angular2/src/facade/collection';
import {
ChangeDetectionStrategy,
@@ -21,6 +22,16 @@ import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/linker/i
// group 2: "event" from "(event)"
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
+export abstract class CompileMetadataWithType {
+ static fromJson(data: {[key: string]: any}): CompileMetadataWithType {
+ return _COMPILE_METADATA_FROM_JSON[data['class']](data);
+ }
+
+ abstract toJson(): {[key: string]: any};
+
+ get type(): CompileTypeMetadata { return unimplemented(); }
+}
+
/**
* Metadata regarding compilation of a type.
*/
@@ -107,7 +118,7 @@ export class CompileTemplateMetadata {
/**
* Metadata regarding compilation of a directive.
*/
-export class CompileDirectiveMetadata {
+export class CompileDirectiveMetadata implements CompileMetadataWithType {
static create({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
outputs, host, lifecycleHooks, template}: {
type?: CompileTypeMetadata,
@@ -241,6 +252,7 @@ export class CompileDirectiveMetadata {
toJson(): {[key: string]: any} {
return {
+ 'class': 'Directive',
'isComponent': this.isComponent,
'dynamicLoadable': this.dynamicLoadable,
'selector': this.selector,
@@ -284,3 +296,38 @@ export function createHostComponentMeta(componentType: CompileTypeMetadata,
selector: '*'
});
}
+
+
+export class CompilePipeMetadata implements CompileMetadataWithType {
+ type: CompileTypeMetadata;
+ name: string;
+ pure: boolean;
+ constructor({type, name,
+ pure}: {type?: CompileTypeMetadata, name?: string, pure?: boolean} = {}) {
+ this.type = type;
+ this.name = name;
+ this.pure = normalizeBool(pure);
+ }
+
+ static fromJson(data: {[key: string]: any}): CompilePipeMetadata {
+ return new CompilePipeMetadata({
+ type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
+ name: data['name'],
+ pure: data['pure']
+ });
+ }
+
+ toJson(): {[key: string]: any} {
+ return {
+ 'class': 'Pipe',
+ 'type': isPresent(this.type) ? this.type.toJson() : null,
+ 'name': this.name,
+ 'pure': this.pure
+ };
+ }
+}
+
+var _COMPILE_METADATA_FROM_JSON = {
+ 'Directive': CompileDirectiveMetadata.fromJson,
+ 'Pipe': CompilePipeMetadata.fromJson
+};
diff --git a/modules/angular2/src/compiler/proto_view_compiler.ts b/modules/angular2/src/compiler/proto_view_compiler.ts
new file mode 100644
index 0000000000000..9b211391bc4b1
--- /dev/null
+++ b/modules/angular2/src/compiler/proto_view_compiler.ts
@@ -0,0 +1,397 @@
+import {
+ isPresent,
+ isBlank,
+ Type,
+ isString,
+ StringWrapper,
+ IS_DART,
+ CONST_EXPR
+} from 'angular2/src/facade/lang';
+import {
+ SetWrapper,
+ StringMapWrapper,
+ ListWrapper,
+ MapWrapper
+} from 'angular2/src/facade/collection';
+import {
+ TemplateAst,
+ TemplateAstVisitor,
+ NgContentAst,
+ EmbeddedTemplateAst,
+ ElementAst,
+ VariableAst,
+ BoundEventAst,
+ BoundElementPropertyAst,
+ AttrAst,
+ BoundTextAst,
+ TextAst,
+ DirectiveAst,
+ BoundDirectivePropertyAst,
+ templateVisitAll
+} from './template_ast';
+import {
+ CompileTypeMetadata,
+ CompileDirectiveMetadata,
+ CompilePipeMetadata
+} from './directive_metadata';
+import {SourceExpressions, SourceExpression, moduleRef} from './source_module';
+import {AppProtoView, AppView} from 'angular2/src/core/linker/view';
+import {ViewType} from 'angular2/src/core/linker/view_type';
+import {AppProtoElement, AppElement} from 'angular2/src/core/linker/element';
+import {ResolvedMetadataCache} from 'angular2/src/core/linker/resolved_metadata_cache';
+import {
+ escapeSingleQuoteString,
+ codeGenConstConstructorCall,
+ codeGenValueFn,
+ codeGenFnHeader,
+ MODULE_SUFFIX,
+ codeGenStringMap,
+ Expression,
+ Statement
+} from './util';
+import {Injectable} from 'angular2/src/core/di';
+
+export const PROTO_VIEW_JIT_IMPORTS = CONST_EXPR(
+ {'AppProtoView': AppProtoView, 'AppProtoElement': AppProtoElement, 'ViewType': ViewType});
+
+// TODO: have a single file that reexports everything needed for
+// codegen explicitly
+// - helps understanding what codegen works against
+// - less imports in codegen code
+export var APP_VIEW_MODULE_REF = moduleRef('package:angular2/src/core/linker/view' + MODULE_SUFFIX);
+export var VIEW_TYPE_MODULE_REF =
+ moduleRef('package:angular2/src/core/linker/view_type' + MODULE_SUFFIX);
+export var APP_EL_MODULE_REF =
+ moduleRef('package:angular2/src/core/linker/element' + MODULE_SUFFIX);
+export var METADATA_MODULE_REF =
+ moduleRef('package:angular2/src/core/metadata/view' + MODULE_SUFFIX);
+
+const IMPLICIT_TEMPLATE_VAR = '\$implicit';
+const CLASS_ATTR = 'class';
+const STYLE_ATTR = 'style';
+
+@Injectable()
+export class ProtoViewCompiler {
+ constructor() {}
+
+ compileProtoViewRuntime(metadataCache: ResolvedMetadataCache, component: CompileDirectiveMetadata,
+ template: TemplateAst[], pipes: CompilePipeMetadata[]):
+ CompileProtoViews {
+ var protoViewFactory = new RuntimeProtoViewFactory(metadataCache, component, pipes);
+ var allProtoViews = [];
+ protoViewFactory.createCompileProtoView(template, [], [], allProtoViews);
+ return new CompileProtoViews([], allProtoViews);
+ }
+
+ compileProtoViewCodeGen(resolvedMetadataCacheExpr: Expression,
+ component: CompileDirectiveMetadata, template: TemplateAst[],
+ pipes: CompilePipeMetadata[]):
+ CompileProtoViews {
+ var protoViewFactory = new CodeGenProtoViewFactory(resolvedMetadataCacheExpr, component, pipes);
+ var allProtoViews = [];
+ var allStatements = [];
+ protoViewFactory.createCompileProtoView(template, [], allStatements, allProtoViews);
+ return new CompileProtoViews(
+ allStatements.map(stmt => stmt.statement), allProtoViews);
+ }
+}
+
+export class CompileProtoViews {
+ constructor(public declarations: STATEMENT[],
+ public protoViews: CompileProtoView[]) {}
+}
+
+
+export class CompileProtoView {
+ constructor(public embeddedTemplateIndex: number,
+ public protoElements: CompileProtoElement[],
+ public protoView: APP_PROTO_VIEW) {}
+}
+
+export class CompileProtoElement {
+ constructor(public boundElementIndex, public attrNameAndValues: string[][],
+ public variableNameAndValues: string[][], public renderEvents: BoundEventAst[],
+ public directives: CompileDirectiveMetadata[], public embeddedTemplateIndex: number,
+ public appProtoEl: APP_PROTO_EL) {}
+}
+
+function visitAndReturnContext(visitor: TemplateAstVisitor, asts: TemplateAst[],
+ context: any): any {
+ templateVisitAll(visitor, asts, context);
+ return context;
+}
+
+abstract class ProtoViewFactory {
+ constructor(public component: CompileDirectiveMetadata) {}
+
+ abstract createAppProtoView(embeddedTemplateIndex: number, viewType: ViewType,
+ templateVariableBindings: string[][],
+ targetStatements: STATEMENT[]): APP_PROTO_VIEW;
+
+ abstract createAppProtoElement(boundElementIndex: number, attrNameAndValues: string[][],
+ variableNameAndValues: string[][],
+ directives: CompileDirectiveMetadata[],
+ targetStatements: STATEMENT[]): APP_PROTO_EL;
+
+ createCompileProtoView(template: TemplateAst[], templateVariableBindings: string[][],
+ targetStatements: STATEMENT[],
+ targetProtoViews: CompileProtoView[]):
+ CompileProtoView {
+ var embeddedTemplateIndex = targetProtoViews.length;
+ // Note: targetProtoViews needs to be in depth first order.
+ // So we "reserve" a space here that we fill after the recursion is done
+ targetProtoViews.push(null);
+ var builder = new ProtoViewBuilderVisitor(
+ this, targetStatements, targetProtoViews);
+ templateVisitAll(builder, template);
+ var viewType = getViewType(this.component, embeddedTemplateIndex);
+ var appProtoView = this.createAppProtoView(embeddedTemplateIndex, viewType,
+ templateVariableBindings, targetStatements);
+ var cpv = new CompileProtoView(
+ embeddedTemplateIndex, builder.protoElements, appProtoView);
+ targetProtoViews[embeddedTemplateIndex] = cpv;
+ return cpv;
+ }
+}
+
+class CodeGenProtoViewFactory extends ProtoViewFactory {
+ private _nextVarId: number = 0;
+
+ constructor(public resolvedMetadataCacheExpr: Expression, component: CompileDirectiveMetadata,
+ public pipes: CompilePipeMetadata[]) {
+ super(component);
+ }
+
+ private _nextProtoViewVar(embeddedTemplateIndex: number): string {
+ return `appProtoView${this._nextVarId++}_${this.component.type.name}${embeddedTemplateIndex}`;
+ }
+
+ createAppProtoView(embeddedTemplateIndex: number, viewType: ViewType,
+ templateVariableBindings: string[][],
+ targetStatements: Statement[]): Expression {
+ var protoViewVarName = this._nextProtoViewVar(embeddedTemplateIndex);
+ var viewTypeExpr = codeGenViewType(viewType);
+ var pipesExpr = embeddedTemplateIndex === 0 ?
+ codeGenTypesArray(this.pipes.map(pipeMeta => pipeMeta.type)) :
+ null;
+ var statement =
+ `var ${protoViewVarName} = ${APP_VIEW_MODULE_REF}AppProtoView.create(${this.resolvedMetadataCacheExpr.expression}, ${viewTypeExpr}, ${pipesExpr}, ${codeGenStringMap(templateVariableBindings)});`;
+ targetStatements.push(new Statement(statement));
+ return new Expression(protoViewVarName);
+ }
+
+ createAppProtoElement(boundElementIndex: number, attrNameAndValues: string[][],
+ variableNameAndValues: string[][], directives: CompileDirectiveMetadata[],
+ targetStatements: Statement[]): Expression {
+ var varName = `appProtoEl${this._nextVarId++}_${this.component.type.name}`;
+ var value = `${APP_EL_MODULE_REF}AppProtoElement.create(
+ ${this.resolvedMetadataCacheExpr.expression},
+ ${boundElementIndex},
+ ${codeGenStringMap(attrNameAndValues)},
+ ${codeGenDirectivesArray(directives)},
+ ${codeGenStringMap(variableNameAndValues)}
+ )`;
+ var statement = `var ${varName} = ${value};`;
+ targetStatements.push(new Statement(statement));
+ return new Expression(varName);
+ }
+}
+
+class RuntimeProtoViewFactory extends ProtoViewFactory {
+ constructor(public metadataCache: ResolvedMetadataCache, component: CompileDirectiveMetadata,
+ public pipes: CompilePipeMetadata[]) {
+ super(component);
+ }
+
+ createAppProtoView(embeddedTemplateIndex: number, viewType: ViewType,
+ templateVariableBindings: string[][], targetStatements: any[]): AppProtoView {
+ var pipes =
+ embeddedTemplateIndex === 0 ? this.pipes.map(pipeMeta => pipeMeta.type.runtime) : [];
+ var templateVars = keyValueArrayToStringMap(templateVariableBindings);
+ return AppProtoView.create(this.metadataCache, viewType, pipes, templateVars);
+ }
+
+ createAppProtoElement(boundElementIndex: number, attrNameAndValues: string[][],
+ variableNameAndValues: string[][], directives: CompileDirectiveMetadata[],
+ targetStatements: any[]): AppProtoElement {
+ var attrs = keyValueArrayToStringMap(attrNameAndValues);
+ return AppProtoElement.create(this.metadataCache, boundElementIndex, attrs,
+ directives.map(dirMeta => dirMeta.type.runtime),
+ keyValueArrayToStringMap(variableNameAndValues));
+ }
+}
+
+class ProtoViewBuilderVisitor implements
+ TemplateAstVisitor {
+ protoElements: CompileProtoElement[] = [];
+ boundElementCount: number = 0;
+
+ constructor(public factory: ProtoViewFactory,
+ public allStatements: STATEMENT[],
+ public allProtoViews: CompileProtoView[]) {}
+
+ private _readAttrNameAndValues(directives: CompileDirectiveMetadata[],
+ attrAsts: TemplateAst[]): string[][] {
+ var attrs = visitAndReturnContext(this, attrAsts, {});
+ directives.forEach(directiveMeta => {
+ StringMapWrapper.forEach(directiveMeta.hostAttributes, (value, name) => {
+ var prevValue = attrs[name];
+ attrs[name] = isPresent(prevValue) ? mergeAttributeValue(name, prevValue, value) : value;
+ });
+ });
+ return mapToKeyValueArray(attrs);
+ }
+
+ visitBoundText(ast: BoundTextAst, context: any): any { return null; }
+ visitText(ast: TextAst, context: any): any { return null; }
+
+ visitNgContent(ast: NgContentAst, context: any): any { return null; }
+
+ visitElement(ast: ElementAst, context: any): any {
+ var boundElementIndex = null;
+ if (ast.isBound()) {
+ boundElementIndex = this.boundElementCount++;
+ }
+ var component = ast.getComponent();
+
+ var variableNameAndValues: string[][] = [];
+ if (isBlank(component)) {
+ ast.exportAsVars.forEach((varAst) => { variableNameAndValues.push([varAst.name, null]); });
+ }
+ var directives = [];
+ var renderEvents: Map =
+ visitAndReturnContext(this, ast.outputs, new Map());
+ ListWrapper.forEachWithIndex(ast.directives, (directiveAst: DirectiveAst, index: number) => {
+ directiveAst.visit(this, new DirectiveContext(index, boundElementIndex, renderEvents,
+ variableNameAndValues, directives));
+ });
+ var renderEventArray = [];
+ renderEvents.forEach((eventAst, _) => renderEventArray.push(eventAst));
+
+ var attrNameAndValues = this._readAttrNameAndValues(directives, ast.attrs);
+ this._addProtoElement(ast.isBound(), boundElementIndex, attrNameAndValues,
+ variableNameAndValues, renderEventArray, directives, null);
+ templateVisitAll(this, ast.children);
+ return null;
+ }
+
+ visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
+ var boundElementIndex = this.boundElementCount++;
+ var directives: CompileDirectiveMetadata[] = [];
+ ListWrapper.forEachWithIndex(ast.directives, (directiveAst: DirectiveAst, index: number) => {
+ directiveAst.visit(
+ this, new DirectiveContext(index, boundElementIndex, new Map(), [],
+ directives));
+ });
+
+ var attrNameAndValues = this._readAttrNameAndValues(directives, ast.attrs);
+ var templateVariableBindings = ast.vars.map(
+ varAst => [varAst.value.length > 0 ? varAst.value : IMPLICIT_TEMPLATE_VAR, varAst.name]);
+ var nestedProtoView = this.factory.createCompileProtoView(
+ ast.children, templateVariableBindings, this.allStatements, this.allProtoViews);
+ this._addProtoElement(true, boundElementIndex, attrNameAndValues, [], [], directives,
+ nestedProtoView.embeddedTemplateIndex);
+ return null;
+ }
+
+ private _addProtoElement(isBound: boolean, boundElementIndex, attrNameAndValues: string[][],
+ variableNameAndValues: string[][], renderEvents: BoundEventAst[],
+ directives: CompileDirectiveMetadata[], embeddedTemplateIndex: number) {
+ var appProtoEl = null;
+ if (isBound) {
+ appProtoEl =
+ this.factory.createAppProtoElement(boundElementIndex, attrNameAndValues,
+ variableNameAndValues, directives, this.allStatements);
+ }
+ var compileProtoEl = new CompileProtoElement(
+ boundElementIndex, attrNameAndValues, variableNameAndValues, renderEvents, directives,
+ embeddedTemplateIndex, appProtoEl);
+ this.protoElements.push(compileProtoEl);
+ }
+
+ visitVariable(ast: VariableAst, ctx: any): any { return null; }
+ visitAttr(ast: AttrAst, attrNameAndValues: {[key: string]: string}): any {
+ attrNameAndValues[ast.name] = ast.value;
+ return null;
+ }
+ visitDirective(ast: DirectiveAst, ctx: DirectiveContext): any {
+ ctx.targetDirectives.push(ast.directive);
+ templateVisitAll(this, ast.hostEvents, ctx.hostEventTargetAndNames);
+ ast.exportAsVars.forEach(
+ varAst => { ctx.targetVariableNameAndValues.push([varAst.name, ctx.index]); });
+ return null;
+ }
+ visitEvent(ast: BoundEventAst, eventTargetAndNames: Map): any {
+ eventTargetAndNames.set(ast.fullName, ast);
+ return null;
+ }
+ visitDirectiveProperty(ast: BoundDirectivePropertyAst, context: any): any { return null; }
+ visitElementProperty(ast: BoundElementPropertyAst, context: any): any { return null; }
+}
+
+function mapToKeyValueArray(data: {[key: string]: string}): string[][] {
+ var entryArray = [];
+ StringMapWrapper.forEach(data, (value, name) => { entryArray.push([name, value]); });
+ // We need to sort to get a defined output order
+ // for tests and for caching generated artifacts...
+ ListWrapper.sort(entryArray, (entry1, entry2) => StringWrapper.compare(entry1[0], entry2[0]));
+ var keyValueArray = [];
+ entryArray.forEach((entry) => { keyValueArray.push([entry[0], entry[1]]); });
+ return keyValueArray;
+}
+
+function mergeAttributeValue(attrName: string, attrValue1: string, attrValue2: string): string {
+ if (attrName == CLASS_ATTR || attrName == STYLE_ATTR) {
+ return `${attrValue1} ${attrValue2}`;
+ } else {
+ return attrValue2;
+ }
+}
+
+class DirectiveContext {
+ constructor(public index: number, public boundElementIndex: number,
+ public hostEventTargetAndNames: Map,
+ public targetVariableNameAndValues: any[][],
+ public targetDirectives: CompileDirectiveMetadata[]) {}
+}
+
+function keyValueArrayToStringMap(keyValueArray: any[][]): {[key: string]: any} {
+ var stringMap: {[key: string]: string} = {};
+ for (var i = 0; i < keyValueArray.length; i++) {
+ var entry = keyValueArray[i];
+ stringMap[entry[0]] = entry[1];
+ }
+ return stringMap;
+}
+
+function codeGenDirectivesArray(directives: CompileDirectiveMetadata[]): string {
+ var expressions = directives.map(directiveType => typeRef(directiveType.type));
+ return `[${expressions.join(',')}]`;
+}
+
+function codeGenTypesArray(types: CompileTypeMetadata[]): string {
+ var expressions = types.map(typeRef);
+ return `[${expressions.join(',')}]`;
+}
+
+function codeGenViewType(value: ViewType): string {
+ if (IS_DART) {
+ return `${VIEW_TYPE_MODULE_REF}${value}`;
+ } else {
+ return `${value}`;
+ }
+}
+
+function typeRef(type: CompileTypeMetadata): string {
+ return `${moduleRef(type.moduleUrl)}${type.name}`;
+}
+
+function getViewType(component: CompileDirectiveMetadata, embeddedTemplateIndex: number): ViewType {
+ if (embeddedTemplateIndex > 0) {
+ return ViewType.EMBEDDED;
+ } else if (component.type.isHost) {
+ return ViewType.HOST;
+ } else {
+ return ViewType.COMPONENT;
+ }
+}
diff --git a/modules/angular2/src/compiler/runtime_compiler.ts b/modules/angular2/src/compiler/runtime_compiler.ts
index 54ae61b31db41..07ac2990a39ba 100644
--- a/modules/angular2/src/compiler/runtime_compiler.ts
+++ b/modules/angular2/src/compiler/runtime_compiler.ts
@@ -1,23 +1,23 @@
-import {Compiler, Compiler_, internalCreateProtoView} from 'angular2/src/core/linker/compiler';
-import {ProtoViewRef} from 'angular2/src/core/linker/view_ref';
-import {ProtoViewFactory} from 'angular2/src/core/linker/proto_view_factory';
+import {Compiler, Compiler_} from 'angular2/src/core/linker/compiler';
+import {HostViewFactoryRef, HostViewFactoryRef_} from 'angular2/src/core/linker/view_ref';
import {TemplateCompiler} from './template_compiler';
import {Injectable} from 'angular2/src/core/di';
import {Type} from 'angular2/src/facade/lang';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
-export abstract class RuntimeCompiler extends Compiler {}
+export abstract class RuntimeCompiler extends Compiler {
+ abstract compileInHost(componentType: Type): Promise;
+ abstract clearCache();
+}
@Injectable()
export class RuntimeCompiler_ extends Compiler_ implements RuntimeCompiler {
- constructor(_protoViewFactory: ProtoViewFactory, private _templateCompiler: TemplateCompiler) {
- super(_protoViewFactory);
- }
+ constructor(private _templateCompiler: TemplateCompiler) { super(); }
- compileInHost(componentType: Type): Promise {
+ compileInHost(componentType: Type): Promise {
return this._templateCompiler.compileHostComponentRuntime(componentType)
- .then(compiledHostTemplate => internalCreateProtoView(this, compiledHostTemplate));
+ .then(hostViewFactory => new HostViewFactoryRef_(hostViewFactory));
}
clearCache() {
diff --git a/modules/angular2/src/compiler/runtime_metadata.ts b/modules/angular2/src/compiler/runtime_metadata.ts
index 1fceb0e859d0a..51b3494b4ef1b 100644
--- a/modules/angular2/src/compiler/runtime_metadata.ts
+++ b/modules/angular2/src/compiler/runtime_metadata.ts
@@ -11,25 +11,29 @@ import {BaseException} from 'angular2/src/facade/exceptions';
import * as cpl from './directive_metadata';
import * as md from 'angular2/src/core/metadata/directives';
import {DirectiveResolver} from 'angular2/src/core/linker/directive_resolver';
+import {PipeResolver} from 'angular2/src/core/linker/pipe_resolver';
import {ViewResolver} from 'angular2/src/core/linker/view_resolver';
import {ViewMetadata} from 'angular2/src/core/metadata/view';
import {hasLifecycleHook} from 'angular2/src/core/linker/directive_lifecycle_reflector';
import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/linker/interfaces';
import {reflector} from 'angular2/src/core/reflection/reflection';
import {Injectable, Inject, Optional} from 'angular2/src/core/di';
-import {PLATFORM_DIRECTIVES} from 'angular2/src/core/platform_directives_and_pipes';
+import {PLATFORM_DIRECTIVES, PLATFORM_PIPES} from 'angular2/src/core/platform_directives_and_pipes';
import {MODULE_SUFFIX} from './util';
import {getUrlScheme} from 'angular2/src/compiler/url_resolver';
@Injectable()
export class RuntimeMetadataResolver {
- private _cache = new Map();
+ private _directiveCache = new Map();
+ private _pipeCache = new Map();
- constructor(private _directiveResolver: DirectiveResolver, private _viewResolver: ViewResolver,
- @Optional() @Inject(PLATFORM_DIRECTIVES) private _platformDirectives: Type[]) {}
+ constructor(private _directiveResolver: DirectiveResolver, private _pipeResolver: PipeResolver,
+ private _viewResolver: ViewResolver,
+ @Optional() @Inject(PLATFORM_DIRECTIVES) private _platformDirectives: Type[],
+ @Optional() @Inject(PLATFORM_PIPES) private _platformPipes: Type[]) {}
- getMetadata(directiveType: Type): cpl.CompileDirectiveMetadata {
- var meta = this._cache.get(directiveType);
+ getDirectiveMetadata(directiveType: Type): cpl.CompileDirectiveMetadata {
+ var meta = this._directiveCache.get(directiveType);
if (isBlank(meta)) {
var dirMeta = this._directiveResolver.resolve(directiveType);
var moduleUrl = null;
@@ -63,7 +67,23 @@ export class RuntimeMetadataResolver {
host: dirMeta.host,
lifecycleHooks: LIFECYCLE_HOOKS_VALUES.filter(hook => hasLifecycleHook(hook, directiveType))
});
- this._cache.set(directiveType, meta);
+ this._directiveCache.set(directiveType, meta);
+ }
+ return meta;
+ }
+
+ getPipeMetadata(pipeType: Type): cpl.CompilePipeMetadata {
+ var meta = this._pipeCache.get(pipeType);
+ if (isBlank(meta)) {
+ var pipeMeta = this._pipeResolver.resolve(pipeType);
+ var moduleUrl = reflector.importUri(pipeType);
+ meta = new cpl.CompilePipeMetadata({
+ type: new cpl.CompileTypeMetadata(
+ {name: stringify(pipeType), moduleUrl: moduleUrl, runtime: pipeType}),
+ name: pipeMeta.name,
+ pure: pipeMeta.pure
+ });
+ this._pipeCache.set(pipeType, meta);
}
return meta;
}
@@ -72,13 +92,25 @@ export class RuntimeMetadataResolver {
var view = this._viewResolver.resolve(component);
var directives = flattenDirectives(view, this._platformDirectives);
for (var i = 0; i < directives.length; i++) {
- if (!isValidDirective(directives[i])) {
+ if (!isValidType(directives[i])) {
throw new BaseException(
`Unexpected directive value '${stringify(directives[i])}' on the View of component '${stringify(component)}'`);
}
}
- return directives.map(type => this.getMetadata(type));
+ return directives.map(type => this.getDirectiveMetadata(type));
+ }
+
+ getViewPipesMetadata(component: Type): cpl.CompilePipeMetadata[] {
+ var view = this._viewResolver.resolve(component);
+ var pipes = flattenPipes(view, this._platformPipes);
+ for (var i = 0; i < pipes.length; i++) {
+ if (!isValidType(pipes[i])) {
+ throw new BaseException(
+ `Unexpected piped value '${stringify(pipes[i])}' on the View of component '${stringify(component)}'`);
+ }
+ }
+ return pipes.map(type => this.getPipeMetadata(type));
}
}
@@ -93,6 +125,17 @@ function flattenDirectives(view: ViewMetadata, platformDirectives: any[]): Type[
return directives;
}
+function flattenPipes(view: ViewMetadata, platformPipes: any[]): Type[] {
+ let pipes = [];
+ if (isPresent(platformPipes)) {
+ flattenArray(platformPipes, pipes);
+ }
+ if (isPresent(view.pipes)) {
+ flattenArray(view.pipes, pipes);
+ }
+ return pipes;
+}
+
function flattenArray(tree: any[], out: Array): void {
for (var i = 0; i < tree.length; i++) {
var item = resolveForwardRef(tree[i]);
@@ -104,7 +147,7 @@ function flattenArray(tree: any[], out: Array): void {
}
}
-function isValidDirective(value: Type): boolean {
+function isValidType(value: Type): boolean {
return isPresent(value) && (value instanceof Type);
}
diff --git a/modules/angular2/src/compiler/source_module.ts b/modules/angular2/src/compiler/source_module.ts
index 49dc23a9bf6e0..c100d36c2936b 100644
--- a/modules/angular2/src/compiler/source_module.ts
+++ b/modules/angular2/src/compiler/source_module.ts
@@ -10,6 +10,10 @@ export function moduleRef(moduleUrl): string {
* Represents generated source code with module references. Internal to the Angular compiler.
*/
export class SourceModule {
+ static getSourceWithoutImports(sourceWithModuleRefs: string): string {
+ return StringWrapper.replaceAllMapped(sourceWithModuleRefs, MODULE_REGEXP, (match) => '');
+ }
+
constructor(public moduleUrl: string, public sourceWithModuleRefs: string) {}
getSourceWithImports(): SourceWithImports {
diff --git a/modules/angular2/src/compiler/style_compiler.ts b/modules/angular2/src/compiler/style_compiler.ts
index a4ee6fd0c90b4..8cc54372149fb 100644
--- a/modules/angular2/src/compiler/style_compiler.ts
+++ b/modules/angular2/src/compiler/style_compiler.ts
@@ -14,7 +14,10 @@ import {
MODULE_SUFFIX
} from './util';
import {Injectable} from 'angular2/src/core/di';
-import {COMPONENT_VARIABLE, HOST_ATTR, CONTENT_ATTR} from 'angular2/src/core/render/view_factory';
+
+const COMPONENT_VARIABLE = '%COMP%';
+const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
+const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
@Injectable()
export class StyleCompiler {
diff --git a/modules/angular2/src/compiler/template_compiler.ts b/modules/angular2/src/compiler/template_compiler.ts
index 06b6300000490..04a33eadbd3b3 100644
--- a/modules/angular2/src/compiler/template_compiler.ts
+++ b/modules/angular2/src/compiler/template_compiler.ts
@@ -1,37 +1,74 @@
-import {IS_DART, Type, Json, isBlank, stringify} from 'angular2/src/facade/lang';
+import {
+ IS_DART,
+ Type,
+ Json,
+ isBlank,
+ isPresent,
+ stringify,
+ evalExpression
+} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
-import {ListWrapper, SetWrapper, MapWrapper} from 'angular2/src/facade/collection';
-import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {
- CompiledComponentTemplate,
- TemplateCmd,
- CompiledHostTemplate,
- BeginComponentCmd
-} from 'angular2/src/core/linker/template_commands';
+ ListWrapper,
+ SetWrapper,
+ MapWrapper,
+ StringMapWrapper
+} from 'angular2/src/facade/collection';
+import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {
createHostComponentMeta,
CompileDirectiveMetadata,
CompileTypeMetadata,
- CompileTemplateMetadata
+ CompileTemplateMetadata,
+ CompilePipeMetadata,
+ CompileMetadataWithType
} from './directive_metadata';
-import {TemplateAst} from './template_ast';
+import {
+ TemplateAst,
+ TemplateAstVisitor,
+ NgContentAst,
+ EmbeddedTemplateAst,
+ ElementAst,
+ VariableAst,
+ BoundEventAst,
+ BoundElementPropertyAst,
+ AttrAst,
+ BoundTextAst,
+ TextAst,
+ DirectiveAst,
+ BoundDirectivePropertyAst,
+ templateVisitAll
+} from './template_ast';
import {Injectable} from 'angular2/src/core/di';
-import {SourceModule, moduleRef} from './source_module';
-import {ChangeDetectionCompiler} from './change_detector_compiler';
+import {SourceModule, moduleRef, SourceExpression} from './source_module';
+import {ChangeDetectionCompiler, CHANGE_DETECTION_JIT_IMPORTS} from './change_detector_compiler';
import {StyleCompiler} from './style_compiler';
-import {CommandCompiler} from './command_compiler';
-import {TemplateParser} from './template_parser';
+import {ViewCompiler, VIEW_JIT_IMPORTS} from './view_compiler';
+import {
+ ProtoViewCompiler,
+ APP_VIEW_MODULE_REF,
+ CompileProtoView,
+ PROTO_VIEW_JIT_IMPORTS
+} from './proto_view_compiler';
+import {TemplateParser, PipeCollector} from './template_parser';
import {TemplateNormalizer} from './template_normalizer';
import {RuntimeMetadataResolver} from './runtime_metadata';
+import {HostViewFactory} from 'angular2/src/core/linker/view';
+import {ChangeDetectorGenConfig} from 'angular2/src/core/change_detection/change_detection';
+import {ResolvedMetadataCache} from 'angular2/src/core/linker/resolved_metadata_cache';
-import {TEMPLATE_COMMANDS_MODULE_REF} from './command_compiler';
import {
codeGenExportVariable,
escapeSingleQuoteString,
codeGenValueFn,
- MODULE_SUFFIX
+ MODULE_SUFFIX,
+ addAll,
+ Expression
} from './util';
+export var METADATA_CACHE_MODULE_REF =
+ moduleRef('package:angular2/src/core/linker/resolved_metadata_cache' + MODULE_SUFFIX);
+
/**
* An internal module of the Angular compiler that begins with component types,
* extracts templates, and eventually produces a compiled version of the component
@@ -40,15 +77,16 @@ import {
@Injectable()
export class TemplateCompiler {
private _hostCacheKeys = new Map();
- private _compiledTemplateCache = new Map();
- private _compiledTemplateDone = new Map>();
- private _nextTemplateId: number = 0;
+ private _compiledTemplateCache = new Map();
+ private _compiledTemplateDone = new Map>();
constructor(private _runtimeMetadataResolver: RuntimeMetadataResolver,
private _templateNormalizer: TemplateNormalizer,
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
- private _commandCompiler: CommandCompiler,
- private _cdCompiler: ChangeDetectionCompiler) {}
+ private _cdCompiler: ChangeDetectionCompiler,
+ private _protoViewCompiler: ProtoViewCompiler, private _viewCompiler: ViewCompiler,
+ private _resolvedMetadataCache: ResolvedMetadataCache,
+ private _genConfig: ChangeDetectorGenConfig) {}
normalizeDirectiveMetadata(directive: CompileDirectiveMetadata):
Promise {
@@ -75,171 +113,204 @@ export class TemplateCompiler {
}));
}
- compileHostComponentRuntime(type: Type): Promise {
+ compileHostComponentRuntime(type: Type): Promise {
+ var compMeta: CompileDirectiveMetadata =
+ this._runtimeMetadataResolver.getDirectiveMetadata(type);
var hostCacheKey = this._hostCacheKeys.get(type);
if (isBlank(hostCacheKey)) {
hostCacheKey = new Object();
this._hostCacheKeys.set(type, hostCacheKey);
- var compMeta: CompileDirectiveMetadata = this._runtimeMetadataResolver.getMetadata(type);
assertComponent(compMeta);
var hostMeta: CompileDirectiveMetadata =
createHostComponentMeta(compMeta.type, compMeta.selector);
- this._compileComponentRuntime(hostCacheKey, hostMeta, [compMeta], new Set());
+ this._compileComponentRuntime(hostCacheKey, hostMeta, [compMeta], [], []);
}
return this._compiledTemplateDone.get(hostCacheKey)
- .then(compiledTemplate => new CompiledHostTemplate(compiledTemplate));
+ .then((compiledTemplate: CompiledTemplate) =>
+ new HostViewFactory(compMeta.selector, compiledTemplate.viewFactory));
}
clearCache() {
- this._hostCacheKeys.clear();
this._styleCompiler.clearCache();
this._compiledTemplateCache.clear();
this._compiledTemplateDone.clear();
+ this._hostCacheKeys.clear();
+ }
+
+ compileTemplatesCodeGen(components: NormalizedComponentWithViewDirectives[]): SourceModule {
+ if (components.length === 0) {
+ throw new BaseException('No components given');
+ }
+ var declarations = [];
+ components.forEach(componentWithDirs => {
+ var compMeta = componentWithDirs.component;
+ assertComponent(compMeta);
+ this._compileComponentCodeGen(compMeta, componentWithDirs.directives, componentWithDirs.pipes,
+ declarations);
+ if (compMeta.dynamicLoadable) {
+ var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
+ var viewFactoryExpression =
+ this._compileComponentCodeGen(hostMeta, [compMeta], [], declarations);
+ var constructionKeyword = IS_DART ? 'const' : 'new';
+ var compiledTemplateExpr =
+ `${constructionKeyword} ${APP_VIEW_MODULE_REF}HostViewFactory('${compMeta.selector}',${viewFactoryExpression})`;
+ var varName = codeGenHostViewFactoryName(compMeta.type);
+ declarations.push(`${codeGenExportVariable(varName)}${compiledTemplateExpr};`);
+ }
+ });
+ var moduleUrl = components[0].component.type.moduleUrl;
+ return new SourceModule(`${templateModuleUrl(moduleUrl)}`, declarations.join('\n'));
}
- private _compileComponentRuntime(
- cacheKey: any, compMeta: CompileDirectiveMetadata, viewDirectives: CompileDirectiveMetadata[],
- compilingComponentCacheKeys: Set): CompiledComponentTemplate {
- let uniqViewDirectives = removeDuplicates(viewDirectives);
+ compileStylesheetCodeGen(stylesheetUrl: string, cssText: string): SourceModule[] {
+ return this._styleCompiler.compileStylesheetCodeGen(stylesheetUrl, cssText);
+ }
+
+
+
+ private _compileComponentRuntime(cacheKey: any, compMeta: CompileDirectiveMetadata,
+ viewDirectives: CompileDirectiveMetadata[],
+ pipes: CompilePipeMetadata[],
+ compilingComponentsPath: any[]): CompiledTemplate {
+ let uniqViewDirectives = removeDuplicates(viewDirectives);
+ let uniqViewPipes = removeDuplicates(pipes);
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
var done = this._compiledTemplateDone.get(cacheKey);
if (isBlank(compiledTemplate)) {
- var styles = [];
- var changeDetectorFactory;
- var commands = [];
- var templateId = `${stringify(compMeta.type.runtime)}Template${this._nextTemplateId++}`;
- compiledTemplate = new CompiledComponentTemplate(
- templateId, (dispatcher) => changeDetectorFactory(dispatcher), commands, styles);
+ compiledTemplate = new CompiledTemplate();
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
- compilingComponentCacheKeys.add(cacheKey);
done = PromiseWrapper
.all([this._styleCompiler.compileComponentRuntime(compMeta.template)].concat(
uniqViewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
.then((stylesAndNormalizedViewDirMetas: any[]) => {
- var childPromises = [];
var normalizedViewDirMetas = stylesAndNormalizedViewDirMetas.slice(1);
+ var styles = stylesAndNormalizedViewDirMetas[0];
var parsedTemplate = this._templateParser.parse(
- compMeta.template.template, normalizedViewDirMetas, compMeta.type.name);
-
- var changeDetectorFactories = this._cdCompiler.compileComponentRuntime(
- compMeta.type, compMeta.changeDetection, parsedTemplate);
- changeDetectorFactory = changeDetectorFactories[0];
- var tmpStyles: string[] = stylesAndNormalizedViewDirMetas[0];
- tmpStyles.forEach(style => styles.push(style));
- var tmpCommands: TemplateCmd[] = this._compileCommandsRuntime(
- compMeta, parsedTemplate, changeDetectorFactories,
- compilingComponentCacheKeys, childPromises);
- tmpCommands.forEach(cmd => commands.push(cmd));
- return PromiseWrapper.all(childPromises);
- })
- .then((_) => {
- SetWrapper.delete(compilingComponentCacheKeys, cacheKey);
- return compiledTemplate;
+ compMeta.template.template, normalizedViewDirMetas, uniqViewPipes,
+ compMeta.type.name);
+
+ var childPromises = [];
+ var usedDirectives = DirectiveCollector.findUsedDirectives(parsedTemplate);
+ usedDirectives.components.forEach(
+ component => this._compileNestedComponentRuntime(
+ component, compilingComponentsPath, childPromises));
+ return PromiseWrapper.all(childPromises)
+ .then((_) => {
+ var filteredPipes = filterPipes(parsedTemplate, uniqViewPipes);
+ compiledTemplate.init(this._createViewFactoryRuntime(
+ compMeta, parsedTemplate, usedDirectives.directives, styles,
+ filteredPipes));
+ return compiledTemplate;
+ });
});
this._compiledTemplateDone.set(cacheKey, done);
}
return compiledTemplate;
}
- private _compileCommandsRuntime(compMeta: CompileDirectiveMetadata, parsedTemplate: TemplateAst[],
- changeDetectorFactories: Function[],
- compilingComponentCacheKeys: Set,
- childPromises: Promise[]): TemplateCmd[] {
- var cmds: TemplateCmd[] = this._commandCompiler.compileComponentRuntime(
- compMeta, parsedTemplate, changeDetectorFactories,
- (childComponentDir: CompileDirectiveMetadata) => {
- var childCacheKey = childComponentDir.type.runtime;
- var childViewDirectives: CompileDirectiveMetadata[] =
- this._runtimeMetadataResolver.getViewDirectivesMetadata(
- childComponentDir.type.runtime);
- var childIsRecursive = SetWrapper.has(compilingComponentCacheKeys, childCacheKey);
- var childTemplate = this._compileComponentRuntime(
- childCacheKey, childComponentDir, childViewDirectives, compilingComponentCacheKeys);
- if (!childIsRecursive) {
- // Only wait for a child if it is not a cycle
- childPromises.push(this._compiledTemplateDone.get(childCacheKey));
- }
- return () => childTemplate;
- });
- cmds.forEach(cmd => {
- if (cmd instanceof BeginComponentCmd) {
- cmd.templateGetter();
- }
- });
- return cmds;
- }
+ private _compileNestedComponentRuntime(childComponentDir: CompileDirectiveMetadata,
+ parentCompilingComponentsPath: any[],
+ childPromises: Promise[]) {
+ var compilingComponentsPath = ListWrapper.clone(parentCompilingComponentsPath);
- compileTemplatesCodeGen(components: NormalizedComponentWithViewDirectives[]): SourceModule {
- if (components.length === 0) {
- throw new BaseException('No components given');
+ var childCacheKey = childComponentDir.type.runtime;
+ var childViewDirectives: CompileDirectiveMetadata[] =
+ this._runtimeMetadataResolver.getViewDirectivesMetadata(childComponentDir.type.runtime);
+ var childViewPipes: CompilePipeMetadata[] =
+ this._runtimeMetadataResolver.getViewPipesMetadata(childComponentDir.type.runtime);
+ var childIsRecursive = ListWrapper.contains(compilingComponentsPath, childCacheKey);
+ compilingComponentsPath.push(childCacheKey);
+ this._compileComponentRuntime(childCacheKey, childComponentDir, childViewDirectives,
+ childViewPipes, compilingComponentsPath);
+ if (!childIsRecursive) {
+ // Only wait for a child if it is not a cycle
+ childPromises.push(this._compiledTemplateDone.get(childCacheKey));
}
- var declarations = [];
- var templateArguments = [];
- var componentMetas: CompileDirectiveMetadata[] = [];
- components.forEach(componentWithDirs => {
- var compMeta = componentWithDirs.component;
- assertComponent(compMeta);
- componentMetas.push(compMeta);
+ }
- this._processTemplateCodeGen(compMeta, componentWithDirs.directives, declarations,
- templateArguments);
- if (compMeta.dynamicLoadable) {
- var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
- componentMetas.push(hostMeta);
- this._processTemplateCodeGen(hostMeta, [compMeta], declarations, templateArguments);
- }
- });
- ListWrapper.forEachWithIndex(componentMetas, (compMeta: CompileDirectiveMetadata,
- index: number) => {
- var templateId = `${compMeta.type.moduleUrl}|${compMeta.type.name}`;
- var constructionKeyword = IS_DART ? 'const' : 'new';
- var compiledTemplateExpr =
- `${constructionKeyword} ${TEMPLATE_COMMANDS_MODULE_REF}CompiledComponentTemplate('${templateId}',${(templateArguments[index]).join(',')})`;
- var variableValueExpr;
- if (compMeta.type.isHost) {
- variableValueExpr =
- `${constructionKeyword} ${TEMPLATE_COMMANDS_MODULE_REF}CompiledHostTemplate(${compiledTemplateExpr})`;
- } else {
- variableValueExpr = compiledTemplateExpr;
- }
- var varName = templateVariableName(compMeta.type);
- declarations.push(`${codeGenExportVariable(varName)}${variableValueExpr};`);
- declarations.push(`${codeGenValueFn([], varName, templateGetterName(compMeta.type))};`);
- });
- var moduleUrl = components[0].component.type.moduleUrl;
- return new SourceModule(`${templateModuleUrl(moduleUrl)}`, declarations.join('\n'));
+ private _createViewFactoryRuntime(compMeta: CompileDirectiveMetadata,
+ parsedTemplate: TemplateAst[],
+ directives: CompileDirectiveMetadata[], styles: string[],
+ pipes: CompilePipeMetadata[]): Function {
+ if (IS_DART || !this._genConfig.useJit) {
+ var changeDetectorFactories = this._cdCompiler.compileComponentRuntime(
+ compMeta.type, compMeta.changeDetection, parsedTemplate);
+ var protoViews = this._protoViewCompiler.compileProtoViewRuntime(
+ this._resolvedMetadataCache, compMeta, parsedTemplate, pipes);
+ return this._viewCompiler.compileComponentRuntime(
+ compMeta, parsedTemplate, styles, protoViews.protoViews, changeDetectorFactories,
+ (compMeta) => this._getNestedComponentViewFactory(compMeta));
+ } else {
+ var declarations = [];
+ var viewFactoryExpr = this._createViewFactoryCodeGen('resolvedMetadataCache', compMeta,
+ new SourceExpression([], 'styles'),
+ parsedTemplate, pipes, declarations);
+ var vars: {[key: string]: any} =
+ {'exports': {}, 'styles': styles, 'resolvedMetadataCache': this._resolvedMetadataCache};
+ directives.forEach(dirMeta => {
+ vars[dirMeta.type.name] = dirMeta.type.runtime;
+ if (dirMeta.isComponent && dirMeta.type.runtime !== compMeta.type.runtime) {
+ vars[`viewFactory_${dirMeta.type.name}0`] = this._getNestedComponentViewFactory(dirMeta);
+ }
+ });
+ pipes.forEach(pipeMeta => vars[pipeMeta.type.name] = pipeMeta.type.runtime);
+ var declarationsWithoutImports =
+ SourceModule.getSourceWithoutImports(declarations.join('\n'));
+ return evalExpression(
+ `viewFactory_${compMeta.type.name}`, viewFactoryExpr, declarationsWithoutImports,
+ mergeStringMaps(
+ [vars, CHANGE_DETECTION_JIT_IMPORTS, PROTO_VIEW_JIT_IMPORTS, VIEW_JIT_IMPORTS]));
+ }
}
- compileStylesheetCodeGen(stylesheetUrl: string, cssText: string): SourceModule[] {
- return this._styleCompiler.compileStylesheetCodeGen(stylesheetUrl, cssText);
+ private _getNestedComponentViewFactory(compMeta: CompileDirectiveMetadata): Function {
+ return this._compiledTemplateCache.get(compMeta.type.runtime).viewFactory;
}
- private _processTemplateCodeGen(compMeta: CompileDirectiveMetadata,
- directives: CompileDirectiveMetadata[],
- targetDeclarations: string[], targetTemplateArguments: any[][]) {
- let uniqueDirectives = removeDuplicates(directives);
+ private _compileComponentCodeGen(compMeta: CompileDirectiveMetadata,
+ directives: CompileDirectiveMetadata[],
+ pipes: CompilePipeMetadata[],
+ targetDeclarations: string[]): string {
+ let uniqueDirectives = removeDuplicates(directives);
+ let uniqPipes = removeDuplicates(pipes);
var styleExpr = this._styleCompiler.compileComponentCodeGen(compMeta.template);
var parsedTemplate = this._templateParser.parse(compMeta.template.template, uniqueDirectives,
- compMeta.type.name);
+ uniqPipes, compMeta.type.name);
+ var filteredPipes = filterPipes(parsedTemplate, uniqPipes);
+ return this._createViewFactoryCodeGen(
+ `${METADATA_CACHE_MODULE_REF}CODEGEN_RESOLVED_METADATA_CACHE`, compMeta, styleExpr,
+ parsedTemplate, filteredPipes, targetDeclarations);
+ }
+
+ private _createViewFactoryCodeGen(resolvedMetadataCacheExpr: string,
+ compMeta: CompileDirectiveMetadata, styleExpr: SourceExpression,
+ parsedTemplate: TemplateAst[], pipes: CompilePipeMetadata[],
+ targetDeclarations: string[]): string {
var changeDetectorsExprs = this._cdCompiler.compileComponentCodeGen(
compMeta.type, compMeta.changeDetection, parsedTemplate);
- var commandsExpr = this._commandCompiler.compileComponentCodeGen(
- compMeta, parsedTemplate, changeDetectorsExprs.expressions,
- codeGenComponentTemplateFactory);
+ var protoViewExprs = this._protoViewCompiler.compileProtoViewCodeGen(
+ new Expression(resolvedMetadataCacheExpr), compMeta, parsedTemplate, pipes);
+ var viewFactoryExpr = this._viewCompiler.compileComponentCodeGen(
+ compMeta, parsedTemplate, styleExpr, protoViewExprs.protoViews, changeDetectorsExprs,
+ codeGenComponentViewFactoryName);
- addAll(styleExpr.declarations, targetDeclarations);
addAll(changeDetectorsExprs.declarations, targetDeclarations);
- addAll(commandsExpr.declarations, targetDeclarations);
+ addAll(protoViewExprs.declarations, targetDeclarations);
+ addAll(viewFactoryExpr.declarations, targetDeclarations);
- targetTemplateArguments.push(
- [changeDetectorsExprs.expressions[0], commandsExpr.expression, styleExpr.expression]);
+ return viewFactoryExpr.expression;
}
}
export class NormalizedComponentWithViewDirectives {
constructor(public component: CompileDirectiveMetadata,
- public directives: CompileDirectiveMetadata[]) {}
+ public directives: CompileDirectiveMetadata[], public pipes: CompilePipeMetadata[]) {}
+}
+
+class CompiledTemplate {
+ viewFactory: Function = null;
+ init(viewFactory: Function) { this.viewFactory = viewFactory; }
}
function assertComponent(meta: CompileDirectiveMetadata) {
@@ -248,30 +319,28 @@ function assertComponent(meta: CompileDirectiveMetadata) {
}
}
-function templateVariableName(type: CompileTypeMetadata): string {
- return `${type.name}Template`;
-}
-
-function templateGetterName(type: CompileTypeMetadata): string {
- return `${templateVariableName(type)}Getter`;
-}
-
function templateModuleUrl(moduleUrl: string): string {
var urlWithoutSuffix = moduleUrl.substring(0, moduleUrl.length - MODULE_SUFFIX.length);
return `${urlWithoutSuffix}.template${MODULE_SUFFIX}`;
}
-function addAll(source: any[], target: any[]) {
- for (var i = 0; i < source.length; i++) {
- target.push(source[i]);
- }
+
+function codeGenHostViewFactoryName(type: CompileTypeMetadata): string {
+ return `hostViewFactory_${type.name}`;
+}
+
+function codeGenComponentViewFactoryName(nestedCompType: CompileDirectiveMetadata): string {
+ return `${moduleRef(templateModuleUrl(nestedCompType.type.moduleUrl))}viewFactory_${nestedCompType.type.name}0`;
}
-function codeGenComponentTemplateFactory(nestedCompType: CompileDirectiveMetadata): string {
- return `${moduleRef(templateModuleUrl(nestedCompType.type.moduleUrl))}${templateGetterName(nestedCompType.type)}`;
+function mergeStringMaps(maps: Array<{[key: string]: any}>): {[key: string]: any} {
+ var result = {};
+ maps.forEach(
+ (map) => { StringMapWrapper.forEach(map, (value, key) => { result[key] = value; }); });
+ return result;
}
-function removeDuplicates(items: CompileDirectiveMetadata[]): CompileDirectiveMetadata[] {
+function removeDuplicates(items: CompileMetadataWithType[]): CompileMetadataWithType[] {
let res = [];
items.forEach(item => {
let hasMatch =
@@ -284,3 +353,100 @@ function removeDuplicates(items: CompileDirectiveMetadata[]): CompileDirectiveMe
});
return res;
}
+
+class DirectiveCollector implements TemplateAstVisitor {
+ static findUsedDirectives(parsedTemplate: TemplateAst[]): DirectiveCollector {
+ var collector = new DirectiveCollector();
+ templateVisitAll(collector, parsedTemplate);
+ return collector;
+ }
+
+ directives: CompileDirectiveMetadata[] = [];
+ components: CompileDirectiveMetadata[] = [];
+
+ visitBoundText(ast: BoundTextAst, context: any): any { return null; }
+ visitText(ast: TextAst, context: any): any { return null; }
+
+ visitNgContent(ast: NgContentAst, context: any): any { return null; }
+
+ visitElement(ast: ElementAst, context: any): any {
+ templateVisitAll(this, ast.directives);
+ templateVisitAll(this, ast.children);
+ return null;
+ }
+
+ visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
+ templateVisitAll(this, ast.directives);
+ templateVisitAll(this, ast.children);
+ return null;
+ }
+ visitVariable(ast: VariableAst, ctx: any): any { return null; }
+ visitAttr(ast: AttrAst, attrNameAndValues: {[key: string]: string}): any { return null; }
+ visitDirective(ast: DirectiveAst, ctx: any): any {
+ if (ast.directive.isComponent) {
+ this.components.push(ast.directive);
+ }
+ this.directives.push(ast.directive);
+ return null;
+ }
+ visitEvent(ast: BoundEventAst, eventTargetAndNames: Map): any {
+ return null;
+ }
+ visitDirectiveProperty(ast: BoundDirectivePropertyAst, context: any): any { return null; }
+ visitElementProperty(ast: BoundElementPropertyAst, context: any): any { return null; }
+}
+
+
+function filterPipes(template: TemplateAst[],
+ allPipes: CompilePipeMetadata[]): CompilePipeMetadata[] {
+ var visitor = new PipeVisitor();
+ templateVisitAll(visitor, template);
+ return allPipes.filter((pipeMeta) => SetWrapper.has(visitor.collector.pipes, pipeMeta.name));
+}
+
+class PipeVisitor implements TemplateAstVisitor {
+ collector: PipeCollector = new PipeCollector();
+
+ visitBoundText(ast: BoundTextAst, context: any): any {
+ ast.value.visit(this.collector);
+ return null;
+ }
+ visitText(ast: TextAst, context: any): any { return null; }
+
+ visitNgContent(ast: NgContentAst, context: any): any { return null; }
+
+ visitElement(ast: ElementAst, context: any): any {
+ templateVisitAll(this, ast.inputs);
+ templateVisitAll(this, ast.outputs);
+ templateVisitAll(this, ast.directives);
+ templateVisitAll(this, ast.children);
+ return null;
+ }
+
+ visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {
+ templateVisitAll(this, ast.outputs);
+ templateVisitAll(this, ast.directives);
+ templateVisitAll(this, ast.children);
+ return null;
+ }
+ visitVariable(ast: VariableAst, ctx: any): any { return null; }
+ visitAttr(ast: AttrAst, attrNameAndValues: {[key: string]: string}): any { return null; }
+ visitDirective(ast: DirectiveAst, ctx: any): any {
+ templateVisitAll(this, ast.inputs);
+ templateVisitAll(this, ast.hostEvents);
+ templateVisitAll(this, ast.hostProperties);
+ return null;
+ }
+ visitEvent(ast: BoundEventAst, eventTargetAndNames: Map): any {
+ ast.handler.visit(this.collector);
+ return null;
+ }
+ visitDirectiveProperty(ast: BoundDirectivePropertyAst, context: any): any {
+ ast.value.visit(this.collector);
+ return null;
+ }
+ visitElementProperty(ast: BoundElementPropertyAst, context: any): any {
+ ast.value.visit(this.collector);
+ return null;
+ }
+}
diff --git a/modules/angular2/src/compiler/template_parser.ts b/modules/angular2/src/compiler/template_parser.ts
index c93307378b595..865532ebd747e 100644
--- a/modules/angular2/src/compiler/template_parser.ts
+++ b/modules/angular2/src/compiler/template_parser.ts
@@ -5,10 +5,11 @@ import {CONST_EXPR} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {Parser, AST, ASTWithSource} from 'angular2/src/core/change_detection/change_detection';
import {TemplateBinding} from 'angular2/src/core/change_detection/parser/ast';
-import {CompileDirectiveMetadata} from './directive_metadata';
+import {CompileDirectiveMetadata, CompilePipeMetadata} from './directive_metadata';
import {HtmlParser} from './html_parser';
import {splitNsName} from './html_tags';
import {ParseSourceSpan, ParseError, ParseLocation} from './parse_util';
+import {RecursiveAstVisitor, BindingPipe} from 'angular2/src/core/change_detection/parser/ast';
import {
@@ -51,8 +52,8 @@ import {splitAtColon} from './util';
// Group 3 = "on-"
// Group 4 = "bindon-"
// Group 5 = the identifier after "bind-", "var-/#", or "on-"
-// Group 6 = identifer inside [()]
-// Group 7 = identifer inside []
+// Group 6 = identifier inside [()]
+// Group 7 = identifier inside []
// Group 8 = identifier inside ()
var BIND_NAME_REGEXP =
/^(?:(?:(?:(bind-)|(var-|#)|(on-)|(bindon-))(.+))|\[\(([^\)]+)\)\]|\[([^\]]+)\]|\(([^\)]+)\))$/g;
@@ -88,9 +89,10 @@ export class TemplateParser {
private _htmlParser: HtmlParser,
@Optional() @Inject(TEMPLATE_TRANSFORMS) public transforms: TemplateAstVisitor[]) {}
- parse(template: string, directives: CompileDirectiveMetadata[],
+ parse(template: string, directives: CompileDirectiveMetadata[], pipes: CompilePipeMetadata[],
templateUrl: string): TemplateAst[] {
- var parseVisitor = new TemplateParseVisitor(directives, this._exprParser, this._schemaRegistry);
+ var parseVisitor =
+ new TemplateParseVisitor(directives, pipes, this._exprParser, this._schemaRegistry);
var htmlAstWithErrors = this._htmlParser.parse(template, templateUrl);
var result = htmlVisitAll(parseVisitor, htmlAstWithErrors.rootNodes, EMPTY_COMPONENT);
var errors: ParseError[] = htmlAstWithErrors.errors.concat(parseVisitor.errors);
@@ -111,9 +113,10 @@ class TemplateParseVisitor implements HtmlAstVisitor {
errors: TemplateParseError[] = [];
directivesIndex = new Map();
ngContentCount: number = 0;
+ pipesByName: Map;
- constructor(directives: CompileDirectiveMetadata[], private _exprParser: Parser,
- private _schemaRegistry: ElementSchemaRegistry) {
+ constructor(directives: CompileDirectiveMetadata[], pipes: CompilePipeMetadata[],
+ private _exprParser: Parser, private _schemaRegistry: ElementSchemaRegistry) {
this.selectorMatcher = new SelectorMatcher();
ListWrapper.forEachWithIndex(directives,
(directive: CompileDirectiveMetadata, index: number) => {
@@ -121,6 +124,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
this.selectorMatcher.addSelectables(selector, directive);
this.directivesIndex.set(directive, index);
});
+ this.pipesByName = new Map();
+ pipes.forEach(pipe => this.pipesByName.set(pipe.name, pipe));
}
private _reportError(message: string, sourceSpan: ParseSourceSpan) {
@@ -130,7 +135,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
private _parseInterpolation(value: string, sourceSpan: ParseSourceSpan): ASTWithSource {
var sourceInfo = sourceSpan.start.toString();
try {
- return this._exprParser.parseInterpolation(value, sourceInfo);
+ var ast = this._exprParser.parseInterpolation(value, sourceInfo);
+ this._checkPipes(ast, sourceSpan);
+ return ast;
} catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo);
@@ -140,7 +147,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
private _parseAction(value: string, sourceSpan: ParseSourceSpan): ASTWithSource {
var sourceInfo = sourceSpan.start.toString();
try {
- return this._exprParser.parseAction(value, sourceInfo);
+ var ast = this._exprParser.parseAction(value, sourceInfo);
+ this._checkPipes(ast, sourceSpan);
+ return ast;
} catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo);
@@ -150,7 +159,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
private _parseBinding(value: string, sourceSpan: ParseSourceSpan): ASTWithSource {
var sourceInfo = sourceSpan.start.toString();
try {
- return this._exprParser.parseBinding(value, sourceInfo);
+ var ast = this._exprParser.parseBinding(value, sourceInfo);
+ this._checkPipes(ast, sourceSpan);
+ return ast;
} catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo);
@@ -160,13 +171,31 @@ class TemplateParseVisitor implements HtmlAstVisitor {
private _parseTemplateBindings(value: string, sourceSpan: ParseSourceSpan): TemplateBinding[] {
var sourceInfo = sourceSpan.start.toString();
try {
- return this._exprParser.parseTemplateBindings(value, sourceInfo);
+ var bindings = this._exprParser.parseTemplateBindings(value, sourceInfo);
+ bindings.forEach((binding) => {
+ if (isPresent(binding.expression)) {
+ this._checkPipes(binding.expression, sourceSpan);
+ }
+ });
+ return bindings;
} catch (e) {
this._reportError(`${e}`, sourceSpan);
return [];
}
}
+ private _checkPipes(ast: ASTWithSource, sourceSpan: ParseSourceSpan) {
+ if (isPresent(ast)) {
+ var collector = new PipeCollector();
+ ast.visit(collector);
+ collector.pipes.forEach((pipeName) => {
+ if (!this.pipesByName.has(pipeName)) {
+ this._reportError(`The pipe '${pipeName}' could not be found`, sourceSpan);
+ }
+ });
+ }
+ }
+
visitText(ast: HtmlTextAst, component: Component): any {
var ngContentIndex = component.findNgContentIndex(TEXT_CSS_SELECTOR);
var expr = this._parseInterpolation(ast.value, ast.sourceSpan);
@@ -714,3 +743,14 @@ function createElementCssSelector(elementName: string, matchableAttrs: string[][
var EMPTY_COMPONENT = new Component(new SelectorMatcher(), null);
var NON_BINDABLE_VISITOR = new NonBindableVisitor();
+
+
+export class PipeCollector extends RecursiveAstVisitor {
+ pipes: Set = new Set();
+ visitPipe(ast: BindingPipe): any {
+ this.pipes.add(ast.name);
+ ast.exp.visit(this);
+ this.visitAll(ast.args);
+ return null;
+ }
+}
diff --git a/modules/angular2/src/compiler/util.ts b/modules/angular2/src/compiler/util.ts
index ca0c6e8005aeb..f3ebdfd1a78f1 100644
--- a/modules/angular2/src/compiler/util.ts
+++ b/modules/angular2/src/compiler/util.ts
@@ -1,4 +1,11 @@
-import {IS_DART, StringWrapper, isBlank} from 'angular2/src/facade/lang';
+import {
+ IS_DART,
+ StringWrapper,
+ isBlank,
+ isPresent,
+ isString,
+ isArray
+} from 'angular2/src/facade/lang';
var CAMEL_CASE_REGEXP = /([A-Z])/g;
var DASH_CASE_REGEXP = /-([a-z])/g;
@@ -7,6 +14,8 @@ var DOUBLE_QUOTE_ESCAPE_STRING_RE = /"|\\|\n|\r|\$/g;
export var MODULE_SUFFIX = IS_DART ? '.dart' : '.js';
+export var CONST_VAR = IS_DART ? 'const' : 'var';
+
export function camelCaseToDashCase(input: string): string {
return StringWrapper.replaceAllMapped(input, CAMEL_CASE_REGEXP,
(m) => { return '-' + m[1].toLowerCase(); });
@@ -63,12 +72,19 @@ export function codeGenConstConstructorCall(name: string): string {
export function codeGenValueFn(params: string[], value: string, fnName: string = ''): string {
if (IS_DART) {
- return `${fnName}(${params.join(',')}) => ${value}`;
+ return `${codeGenFnHeader(params, fnName)} => ${value}`;
} else {
- return `function ${fnName}(${params.join(',')}) { return ${value}; }`;
+ return `${codeGenFnHeader(params, fnName)} { return ${value}; }`;
}
}
+export function codeGenFnHeader(params: string[], fnName: string = ''): string {
+ if (IS_DART) {
+ return `${fnName}(${params.join(',')})`;
+ } else {
+ return `function ${fnName}(${params.join(',')})`;
+ }
+}
export function codeGenToString(expr: string): string {
if (IS_DART) {
return `'\${${expr}}'`;
@@ -86,3 +102,77 @@ export function splitAtColon(input: string, defaultValues: string[]): string[] {
return defaultValues;
}
}
+
+
+export class Statement {
+ constructor(public statement: string) {}
+}
+
+export class Expression {
+ constructor(public expression: string, public isArray = false) {}
+}
+
+export function escapeValue(value: any): string {
+ if (value instanceof Expression) {
+ return value.expression;
+ } else if (isString(value)) {
+ return escapeSingleQuoteString(value);
+ } else if (isBlank(value)) {
+ return 'null';
+ } else {
+ return `${value}`;
+ }
+}
+
+export function codeGenArray(data: any[]): string {
+ return `[${data.map(escapeValue).join(',')}]`;
+}
+
+export function codeGenFlatArray(values: any[]): string {
+ var result = '([';
+ var isFirstArrayEntry = true;
+ var concatFn = IS_DART ? '.addAll' : 'concat';
+ for (var i = 0; i < values.length; i++) {
+ var value = values[i];
+ if (value instanceof Expression && (value).isArray) {
+ result += `]).${concatFn}(${value.expression}).${concatFn}([`;
+ isFirstArrayEntry = true;
+ } else {
+ if (!isFirstArrayEntry) {
+ result += ',';
+ }
+ isFirstArrayEntry = false;
+ result += escapeValue(value);
+ }
+ }
+ result += '])';
+ return result;
+}
+
+export function codeGenStringMap(keyValueArray: any[][]): string {
+ return `{${keyValueArray.map(codeGenKeyValue).join(',')}}`;
+}
+
+function codeGenKeyValue(keyValue: any[]): string {
+ return `${escapeValue(keyValue[0])}:${escapeValue(keyValue[1])}`;
+}
+
+export function addAll(source: any[], target: any[]) {
+ for (var i = 0; i < source.length; i++) {
+ target.push(source[i]);
+ }
+}
+
+export function flattenArray(source: any[], target: any[]): any[] {
+ if (isPresent(source)) {
+ for (var i = 0; i < source.length; i++) {
+ var item = source[i];
+ if (isArray(item)) {
+ flattenArray(item, target);
+ } else {
+ target.push(item);
+ }
+ }
+ }
+ return target;
+}
diff --git a/modules/angular2/src/compiler/view_compiler.ts b/modules/angular2/src/compiler/view_compiler.ts
new file mode 100644
index 0000000000000..2f6ec19697e05
--- /dev/null
+++ b/modules/angular2/src/compiler/view_compiler.ts
@@ -0,0 +1,600 @@
+import {
+ isPresent,
+ isBlank,
+ Type,
+ isString,
+ StringWrapper,
+ IS_DART,
+ CONST_EXPR
+} from 'angular2/src/facade/lang';
+import {SetWrapper, StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
+import {
+ TemplateAst,
+ TemplateAstVisitor,
+ NgContentAst,
+ EmbeddedTemplateAst,
+ ElementAst,
+ VariableAst,
+ BoundEventAst,
+ BoundElementPropertyAst,
+ AttrAst,
+ BoundTextAst,
+ TextAst,
+ DirectiveAst,
+ BoundDirectivePropertyAst,
+ templateVisitAll
+} from './template_ast';
+import {CompileTypeMetadata, CompileDirectiveMetadata} from './directive_metadata';
+import {SourceExpressions, SourceExpression, moduleRef} from './source_module';
+import {
+ AppProtoView,
+ AppView,
+ flattenNestedViewRenderNodes,
+ checkSlotCount
+} from 'angular2/src/core/linker/view';
+import {ViewType} from 'angular2/src/core/linker/view_type';
+import {AppViewManager_} from 'angular2/src/core/linker/view_manager';
+import {AppProtoElement, AppElement} from 'angular2/src/core/linker/element';
+import {Renderer, ParentRenderer} from 'angular2/src/core/render/api';
+import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
+import {
+ escapeSingleQuoteString,
+ codeGenConstConstructorCall,
+ codeGenValueFn,
+ codeGenFnHeader,
+ MODULE_SUFFIX,
+ Statement,
+ escapeValue,
+ codeGenArray,
+ codeGenFlatArray,
+ Expression,
+ flattenArray,
+ CONST_VAR
+} from './util';
+import {ResolvedProvider, Injectable, Injector} from 'angular2/src/core/di';
+
+import {
+ APP_VIEW_MODULE_REF,
+ APP_EL_MODULE_REF,
+ METADATA_MODULE_REF,
+ CompileProtoView,
+ CompileProtoElement
+} from './proto_view_compiler';
+
+export const VIEW_JIT_IMPORTS = CONST_EXPR({
+ 'AppView': AppView,
+ 'AppElement': AppElement,
+ 'flattenNestedViewRenderNodes': flattenNestedViewRenderNodes,
+ 'checkSlotCount': checkSlotCount
+});
+
+
+@Injectable()
+export class ViewCompiler {
+ constructor() {}
+
+ compileComponentRuntime(component: CompileDirectiveMetadata, template: TemplateAst[],
+ styles: Array,
+ protoViews: CompileProtoView[],
+ changeDetectorFactories: Function[],
+ componentViewFactory: Function): Function {
+ var viewFactory = new RuntimeViewFactory(component, styles, protoViews, changeDetectorFactories,
+ componentViewFactory);
+ return viewFactory.createViewFactory(template, 0, []);
+ }
+
+ compileComponentCodeGen(component: CompileDirectiveMetadata, template: TemplateAst[],
+ styles: SourceExpression,
+ protoViews: CompileProtoView[],
+ changeDetectorFactoryExpressions: SourceExpressions,
+ componentViewFactory: Function): SourceExpression {
+ var viewFactory = new CodeGenViewFactory(
+ component, styles, protoViews, changeDetectorFactoryExpressions, componentViewFactory);
+ var targetStatements: Statement[] = [];
+ var viewFactoryExpression = viewFactory.createViewFactory(template, 0, targetStatements);
+ return new SourceExpression(targetStatements.map(stmt => stmt.statement),
+ viewFactoryExpression.expression);
+ }
+}
+
+interface ViewFactory {
+ createText(renderer: EXPRESSION, parent: EXPRESSION, text: string,
+ targetStatements: STATEMENT[]): EXPRESSION;
+
+ createElement(renderer: EXPRESSION, parent: EXPRESSION, name: string, rootSelector: EXPRESSION,
+ targetStatements: STATEMENT[]): EXPRESSION;
+
+ createTemplateAnchor(renderer: EXPRESSION, parent: EXPRESSION,
+ targetStatements: STATEMENT[]): EXPRESSION;
+
+ createGlobalEventListener(renderer: EXPRESSION, view: EXPRESSION, boundElementIndex: number,
+ eventAst: BoundEventAst, targetStatements: STATEMENT[]): EXPRESSION;
+
+ createElementEventListener(renderer: EXPRESSION, view: EXPRESSION, boundElementIndex: number,
+ renderNode: EXPRESSION, eventAst: BoundEventAst,
+ targetStatements: STATEMENT[]);
+
+ setElementAttribute(renderer: EXPRESSION, renderNode: EXPRESSION, attrName: string,
+ attrValue: string, targetStatements: STATEMENT[]);
+
+ createAppElement(appProtoEl: EXPRESSION, view: EXPRESSION, renderNode: EXPRESSION,
+ parentAppEl: EXPRESSION, embeddedViewFactory: EXPRESSION,
+ targetStatements: STATEMENT[]): EXPRESSION;
+
+ createAndSetComponentView(renderer: EXPRESSION, viewManager: EXPRESSION, view: EXPRESSION,
+ appEl: EXPRESSION, component: CompileDirectiveMetadata,
+ contentNodesByNgContentIndex: EXPRESSION[][],
+ targetStatements: STATEMENT[]);
+
+ getProjectedNodes(projectableNodes: EXPRESSION, ngContentIndex: number): EXPRESSION;
+
+ appendProjectedNodes(renderer: EXPRESSION, parent: EXPRESSION, nodes: EXPRESSION,
+ targetStatements: STATEMENT[]);
+
+ createViewFactory(asts: TemplateAst[], embeddedTemplateIndex: number,
+ targetStatements: STATEMENT[]): EXPRESSION;
+}
+
+class CodeGenViewFactory implements ViewFactory {
+ private _nextVarId: number = 0;
+ constructor(public component: CompileDirectiveMetadata, public styles: SourceExpression,
+ public protoViews: CompileProtoView[],
+ public changeDetectorExpressions: SourceExpressions,
+ public componentViewFactory: Function) {}
+
+ private _nextVar(prefix: string): string {
+ return `${prefix}${this._nextVarId++}_${this.component.type.name}`;
+ }
+
+ private _nextRenderVar(): string { return this._nextVar('render'); }
+
+ private _nextAppVar(): string { return this._nextVar('app'); }
+
+ private _nextDisposableVar(): string {
+ return `disposable${this._nextVarId++}_${this.component.type.name}`;
+ }
+
+ createText(renderer: Expression, parent: Expression, text: string,
+ targetStatements: Statement[]): Expression {
+ var varName = this._nextRenderVar();
+ var statement =
+ `var ${varName} = ${renderer.expression}.createText(${isPresent(parent) ? parent.expression : null}, ${escapeSingleQuoteString(text)});`;
+ targetStatements.push(new Statement(statement));
+ return new Expression(varName);
+ }
+
+ createElement(renderer: Expression, parentRenderNode: Expression, name: string,
+ rootSelector: Expression, targetStatements: Statement[]): Expression {
+ var varName = this._nextRenderVar();
+ var valueExpr;
+ if (isPresent(rootSelector)) {
+ valueExpr = `${rootSelector.expression} == null ?
+ ${renderer.expression}.createElement(${isPresent(parentRenderNode) ? parentRenderNode.expression : null}, ${escapeSingleQuoteString(name)}) :
+ ${renderer.expression}.selectRootElement(${rootSelector.expression});`;
+ } else {
+ valueExpr =
+ `${renderer.expression}.createElement(${isPresent(parentRenderNode) ? parentRenderNode.expression : null}, ${escapeSingleQuoteString(name)})`;
+ }
+ var statement = `var ${varName} = ${valueExpr};`;
+ targetStatements.push(new Statement(statement));
+ return new Expression(varName);
+ }
+
+ createTemplateAnchor(renderer: Expression, parentRenderNode: Expression,
+ targetStatements: Statement[]): Expression {
+ var varName = this._nextRenderVar();
+ var valueExpr =
+ `${renderer.expression}.createTemplateAnchor(${isPresent(parentRenderNode) ? parentRenderNode.expression : null});`;
+ targetStatements.push(new Statement(`var ${varName} = ${valueExpr}`));
+ return new Expression(varName);
+ }
+
+ createGlobalEventListener(renderer: Expression, appView: Expression, boundElementIndex: number,
+ eventAst: BoundEventAst, targetStatements: Statement[]): Expression {
+ var disposableVar = this._nextDisposableVar();
+ var eventHandlerExpr = codeGenEventHandler(appView, boundElementIndex, eventAst.fullName);
+ targetStatements.push(new Statement(
+ `var ${disposableVar} = ${renderer.expression}.listenGlobal(${escapeValue(eventAst.target)}, ${escapeValue(eventAst.name)}, ${eventHandlerExpr});`));
+ return new Expression(disposableVar);
+ }
+
+ createElementEventListener(renderer: Expression, appView: Expression, boundElementIndex: number,
+ renderNode: Expression, eventAst: BoundEventAst,
+ targetStatements: Statement[]) {
+ var eventHandlerExpr = codeGenEventHandler(appView, boundElementIndex, eventAst.fullName);
+ targetStatements.push(new Statement(
+ `${renderer.expression}.listen(${renderNode.expression}, ${escapeValue(eventAst.name)}, ${eventHandlerExpr});`));
+ }
+
+ setElementAttribute(renderer: Expression, renderNode: Expression, attrName: string,
+ attrValue: string, targetStatements: Statement[]) {
+ targetStatements.push(new Statement(
+ `${renderer.expression}.setElementAttribute(${renderNode.expression}, ${escapeSingleQuoteString(attrName)}, ${escapeSingleQuoteString(attrValue)});`));
+ }
+
+ createAppElement(appProtoEl: Expression, appView: Expression, renderNode: Expression,
+ parentAppEl: Expression, embeddedViewFactory: Expression,
+ targetStatements: Statement[]): Expression {
+ var appVar = this._nextAppVar();
+ var varValue =
+ `new ${APP_EL_MODULE_REF}AppElement(${appProtoEl.expression}, ${appView.expression},
+ ${isPresent(parentAppEl) ? parentAppEl.expression : null}, ${renderNode.expression}, ${isPresent(embeddedViewFactory) ? embeddedViewFactory.expression : null})`;
+ targetStatements.push(new Statement(`var ${appVar} = ${varValue};`));
+ return new Expression(appVar);
+ }
+
+ createAndSetComponentView(renderer: Expression, viewManager: Expression, view: Expression,
+ appEl: Expression, component: CompileDirectiveMetadata,
+ contentNodesByNgContentIndex: Expression[][],
+ targetStatements: Statement[]) {
+ var codeGenContentNodes;
+ if (this.component.type.isHost) {
+ codeGenContentNodes = `${view.expression}.projectableNodes`;
+ } else {
+ codeGenContentNodes =
+ `[${contentNodesByNgContentIndex.map( nodes => codeGenFlatArray(nodes) ).join(',')}]`;
+ }
+ targetStatements.push(new Statement(
+ `${this.componentViewFactory(component)}(${renderer.expression}, ${viewManager.expression}, ${appEl.expression}, ${codeGenContentNodes}, null, null, null);`));
+ }
+
+ getProjectedNodes(projectableNodes: Expression, ngContentIndex: number): Expression {
+ return new Expression(`${projectableNodes.expression}[${ngContentIndex}]`, true);
+ }
+
+ appendProjectedNodes(renderer: Expression, parent: Expression, nodes: Expression,
+ targetStatements: Statement[]) {
+ targetStatements.push(new Statement(
+ `${renderer.expression}.projectNodes(${parent.expression}, ${APP_VIEW_MODULE_REF}flattenNestedViewRenderNodes(${nodes.expression}));`));
+ }
+
+ createViewFactory(asts: TemplateAst[], embeddedTemplateIndex: number,
+ targetStatements: Statement[]): Expression {
+ var compileProtoView = this.protoViews[embeddedTemplateIndex];
+ var isHostView = this.component.type.isHost;
+ var isComponentView = embeddedTemplateIndex === 0 && !isHostView;
+ var visitor = new ViewBuilderVisitor(
+ new Expression('renderer'), new Expression('viewManager'),
+ new Expression('projectableNodes'), isHostView ? new Expression('rootSelector') : null,
+ new Expression('view'), compileProtoView, targetStatements, this);
+
+ templateVisitAll(
+ visitor, asts,
+ new ParentElement(isComponentView ? new Expression('parentRenderNode') : null, null, null));
+
+ var appProtoView = compileProtoView.protoView.expression;
+ var viewFactoryName = codeGenViewFactoryName(this.component, embeddedTemplateIndex);
+ var changeDetectorFactory = this.changeDetectorExpressions.expressions[embeddedTemplateIndex];
+ var factoryArgs = [
+ 'parentRenderer',
+ 'viewManager',
+ 'containerEl',
+ 'projectableNodes',
+ 'rootSelector',
+ 'dynamicallyCreatedProviders',
+ 'rootInjector'
+ ];
+ var initRendererStmts = [];
+ var rendererExpr = `parentRenderer`;
+ if (embeddedTemplateIndex === 0) {
+ var renderCompTypeVar = this._nextVar('renderType');
+ targetStatements.push(new Statement(`var ${renderCompTypeVar} = null;`));
+ var stylesVar = this._nextVar('styles');
+ targetStatements.push(
+ new Statement(`${CONST_VAR} ${stylesVar} = ${this.styles.expression};`));
+ var encapsulation = this.component.template.encapsulation;
+ initRendererStmts.push(`if (${renderCompTypeVar} == null) {
+ ${renderCompTypeVar} = viewManager.createRenderComponentType(${codeGenViewEncapsulation(encapsulation)}, ${stylesVar});
+ }`);
+ rendererExpr = `parentRenderer.renderComponent(${renderCompTypeVar})`;
+ }
+ var statement = `
+${codeGenFnHeader(factoryArgs, viewFactoryName)}{
+ ${initRendererStmts.join('\n')}
+ var renderer = ${rendererExpr};
+ var view = new ${APP_VIEW_MODULE_REF}AppView(
+ ${appProtoView}, renderer, viewManager,
+ projectableNodes,
+ containerEl,
+ dynamicallyCreatedProviders, rootInjector,
+ ${changeDetectorFactory}()
+ );
+ ${APP_VIEW_MODULE_REF}checkSlotCount(${escapeValue(this.component.type.name)}, ${this.component.template.ngContentSelectors.length}, projectableNodes);
+ ${isComponentView ? 'var parentRenderNode = renderer.createViewRoot(view.containerAppElement.nativeElement);' : ''}
+ ${visitor.renderStmts.map(stmt => stmt.statement).join('\n')}
+ ${visitor.appStmts.map(stmt => stmt.statement).join('\n')}
+
+ view.init(${codeGenFlatArray(visitor.rootNodesOrAppElements)}, ${codeGenArray(visitor.renderNodes)}, ${codeGenArray(visitor.appDisposables)},
+ ${codeGenArray(visitor.appElements)});
+ return view;
+}`;
+ targetStatements.push(new Statement(statement));
+ return new Expression(viewFactoryName);
+ }
+}
+
+class RuntimeViewFactory implements ViewFactory {
+ constructor(public component: CompileDirectiveMetadata, public styles: Array,
+ public protoViews: CompileProtoView[],
+ public changeDetectorFactories: Function[], public componentViewFactory: Function) {}
+
+ createText(renderer: Renderer, parent: any, text: string, targetStatements: any[]): any {
+ return renderer.createText(parent, text);
+ }
+
+ createElement(renderer: Renderer, parent: any, name: string, rootSelector: string,
+ targetStatements: any[]): any {
+ var el;
+ if (isPresent(rootSelector)) {
+ el = renderer.selectRootElement(rootSelector);
+ } else {
+ el = renderer.createElement(parent, name);
+ }
+ return el;
+ }
+
+ createTemplateAnchor(renderer: Renderer, parent: any, targetStatements: any[]): any {
+ return renderer.createTemplateAnchor(parent);
+ }
+
+ createGlobalEventListener(renderer: Renderer, appView: AppView, boundElementIndex: number,
+ eventAst: BoundEventAst, targetStatements: any[]): any {
+ return renderer.listenGlobal(
+ eventAst.target, eventAst.name,
+ (event) => appView.triggerEventHandlers(eventAst.fullName, event, boundElementIndex));
+ }
+
+ createElementEventListener(renderer: Renderer, appView: AppView, boundElementIndex: number,
+ renderNode: any, eventAst: BoundEventAst, targetStatements: any[]) {
+ renderer.listen(renderNode, eventAst.name, (event) => appView.triggerEventHandlers(
+ eventAst.fullName, event, boundElementIndex));
+ }
+
+ setElementAttribute(renderer: Renderer, renderNode: any, attrName: string, attrValue: string,
+ targetStatements: any[]) {
+ renderer.setElementAttribute(renderNode, attrName, attrValue);
+ }
+
+ createAppElement(appProtoEl: AppProtoElement, appView: AppView, renderNode: any,
+ parentAppEl: AppElement, embeddedViewFactory: Function,
+ targetStatements: any[]): any {
+ return new AppElement(appProtoEl, appView, parentAppEl, renderNode, embeddedViewFactory);
+ }
+
+ createAndSetComponentView(renderer: Renderer, viewManager: AppViewManager_, appView: AppView,
+ appEl: AppElement, component: CompileDirectiveMetadata,
+ contentNodesByNgContentIndex: Array>,
+ targetStatements: any[]) {
+ var flattenedContentNodes;
+ if (this.component.type.isHost) {
+ flattenedContentNodes = appView.projectableNodes;
+ } else {
+ flattenedContentNodes = ListWrapper.createFixedSize(contentNodesByNgContentIndex.length);
+ for (var i = 0; i < contentNodesByNgContentIndex.length; i++) {
+ flattenedContentNodes[i] = flattenArray(contentNodesByNgContentIndex[i], []);
+ }
+ }
+ this.componentViewFactory(component)(renderer, viewManager, appEl, flattenedContentNodes);
+ }
+
+ getProjectedNodes(projectableNodes: any[][], ngContentIndex: number): any[] {
+ return projectableNodes[ngContentIndex];
+ }
+
+ appendProjectedNodes(renderer: Renderer, parent: any, nodes: any[], targetStatements: any[]) {
+ renderer.projectNodes(parent, flattenNestedViewRenderNodes(nodes));
+ }
+
+ createViewFactory(asts: TemplateAst[], embeddedTemplateIndex: number,
+ targetStatements: any[]): Function {
+ var compileProtoView = this.protoViews[embeddedTemplateIndex];
+ var isComponentView = compileProtoView.protoView.type === ViewType.COMPONENT;
+ var renderComponentType = null;
+ return (parentRenderer: ParentRenderer, viewManager: AppViewManager_, containerEl: AppElement,
+ projectableNodes: any[][], rootSelector: string = null,
+ dynamicallyCreatedProviders: ResolvedProvider[] = null,
+ rootInjector: Injector = null) => {
+ checkSlotCount(this.component.type.name, this.component.template.ngContentSelectors.length,
+ projectableNodes);
+ var renderer;
+ if (embeddedTemplateIndex === 0) {
+ if (isBlank(renderComponentType)) {
+ renderComponentType = viewManager.createRenderComponentType(
+ this.component.template.encapsulation, this.styles);
+ }
+ renderer = parentRenderer.renderComponent(renderComponentType);
+ } else {
+ renderer = parentRenderer;
+ }
+ var changeDetector = this.changeDetectorFactories[embeddedTemplateIndex]();
+ var view =
+ new AppView(compileProtoView.protoView, renderer, viewManager, projectableNodes,
+ containerEl, dynamicallyCreatedProviders, rootInjector, changeDetector);
+ var visitor = new ViewBuilderVisitor(
+ renderer, viewManager, projectableNodes, rootSelector, view, compileProtoView, [], this);
+ var parentRenderNode =
+ isComponentView ? renderer.createViewRoot(containerEl.nativeElement) : null;
+ templateVisitAll(visitor, asts, new ParentElement(parentRenderNode, null, null));
+ view.init(flattenArray(visitor.rootNodesOrAppElements, []), visitor.renderNodes,
+ visitor.appDisposables, visitor.appElements);
+ return view;
+ };
+ }
+}
+
+class ParentElement {
+ public contentNodesByNgContentIndex: Array[];
+
+ constructor(public renderNode: EXPRESSION, public appEl: EXPRESSION,
+ public component: CompileDirectiveMetadata) {
+ if (isPresent(component)) {
+ this.contentNodesByNgContentIndex =
+ ListWrapper.createFixedSize(component.template.ngContentSelectors.length);
+ for (var i = 0; i < this.contentNodesByNgContentIndex.length; i++) {
+ this.contentNodesByNgContentIndex[i] = [];
+ }
+ } else {
+ this.contentNodesByNgContentIndex = null;
+ }
+ }
+
+ addContentNode(ngContentIndex: number, nodeExpr: EXPRESSION) {
+ this.contentNodesByNgContentIndex[ngContentIndex].push(nodeExpr);
+ }
+}
+
+class ViewBuilderVisitor implements TemplateAstVisitor {
+ renderStmts: Array = [];
+ renderNodes: EXPRESSION[] = [];
+ appStmts: Array = [];
+ appElements: EXPRESSION[] = [];
+ appDisposables: EXPRESSION[] = [];
+
+ rootNodesOrAppElements: EXPRESSION[] = [];
+
+ elementCount: number = 0;
+
+ constructor(public renderer: EXPRESSION, public viewManager: EXPRESSION,
+ public projectableNodes: EXPRESSION, public rootSelector: EXPRESSION,
+ public view: EXPRESSION, public protoView: CompileProtoView,
+ public targetStatements: STATEMENT[],
+ public factory: ViewFactory) {}
+
+ private _addRenderNode(renderNode: EXPRESSION, appEl: EXPRESSION, ngContentIndex: number,
+ parent: ParentElement) {
+ this.renderNodes.push(renderNode);
+ if (isPresent(parent.component)) {
+ if (isPresent(ngContentIndex)) {
+ parent.addContentNode(ngContentIndex, isPresent(appEl) ? appEl : renderNode);
+ }
+ } else if (isBlank(parent.renderNode)) {
+ this.rootNodesOrAppElements.push(isPresent(appEl) ? appEl : renderNode);
+ }
+ }
+
+ private _getParentRenderNode(ngContentIndex: number,
+ parent: ParentElement): EXPRESSION {
+ return isPresent(parent.component) &&
+ parent.component.template.encapsulation !== ViewEncapsulation.Native ?
+ null :
+ parent.renderNode;
+ }
+
+ visitBoundText(ast: BoundTextAst, parent: ParentElement): any {
+ return this._visitText('', ast.ngContentIndex, parent);
+ }
+ visitText(ast: TextAst, parent: ParentElement): any {
+ return this._visitText(ast.value, ast.ngContentIndex, parent);
+ }
+ private _visitText(value: string, ngContentIndex: number, parent: ParentElement) {
+ var renderNode = this.factory.createText(
+ this.renderer, this._getParentRenderNode(ngContentIndex, parent), value, this.renderStmts);
+ this._addRenderNode(renderNode, null, ngContentIndex, parent);
+ return null;
+ }
+
+ visitNgContent(ast: NgContentAst, parent: ParentElement): any {
+ var nodesExpression = this.factory.getProjectedNodes(this.projectableNodes, ast.index);
+ if (isPresent(parent.component)) {
+ if (isPresent(ast.ngContentIndex)) {
+ parent.addContentNode(ast.ngContentIndex, nodesExpression);
+ }
+ } else {
+ if (isPresent(parent.renderNode)) {
+ this.factory.appendProjectedNodes(this.renderer, parent.renderNode, nodesExpression,
+ this.renderStmts);
+ } else {
+ this.rootNodesOrAppElements.push(nodesExpression);
+ }
+ }
+ return null;
+ }
+
+ visitElement(ast: ElementAst, parent: ParentElement): any {
+ var renderNode = this.factory.createElement(
+ this.renderer, this._getParentRenderNode(ast.ngContentIndex, parent), ast.name,
+ this.rootSelector, this.renderStmts);
+
+ var component = ast.getComponent();
+ var elementIndex = this.elementCount++;
+ var protoEl = this.protoView.protoElements[elementIndex];
+
+ protoEl.renderEvents.forEach((eventAst) => {
+ if (isPresent(eventAst.target)) {
+ var disposable = this.factory.createGlobalEventListener(
+ this.renderer, this.view, protoEl.boundElementIndex, eventAst, this.renderStmts);
+ this.appDisposables.push(disposable);
+ } else {
+ this.factory.createElementEventListener(this.renderer, this.view, protoEl.boundElementIndex,
+ renderNode, eventAst, this.renderStmts);
+ }
+ });
+ for (var i = 0; i < protoEl.attrNameAndValues.length; i++) {
+ var attrName = protoEl.attrNameAndValues[i][0];
+ var attrValue = protoEl.attrNameAndValues[i][1];
+ this.factory.setElementAttribute(this.renderer, renderNode, attrName, attrValue,
+ this.renderStmts);
+ }
+ var appEl = null;
+ if (isPresent(protoEl.appProtoEl)) {
+ appEl = this.factory.createAppElement(protoEl.appProtoEl, this.view, renderNode, parent.appEl,
+ null, this.appStmts);
+ this.appElements.push(appEl);
+ }
+ this._addRenderNode(renderNode, appEl, ast.ngContentIndex, parent);
+
+ var newParent = new ParentElement(
+ renderNode, isPresent(appEl) ? appEl : parent.appEl, component);
+ templateVisitAll(this, ast.children, newParent);
+ if (isPresent(appEl) && isPresent(component)) {
+ this.factory.createAndSetComponentView(this.renderer, this.viewManager, this.view, appEl,
+ component, newParent.contentNodesByNgContentIndex,
+ this.appStmts);
+ }
+ return null;
+ }
+
+ visitEmbeddedTemplate(ast: EmbeddedTemplateAst, parent: ParentElement): any {
+ var renderNode = this.factory.createTemplateAnchor(
+ this.renderer, this._getParentRenderNode(ast.ngContentIndex, parent), this.renderStmts);
+
+ var elementIndex = this.elementCount++;
+ var protoEl = this.protoView.protoElements[elementIndex];
+ var embeddedViewFactory = this.factory.createViewFactory(
+ ast.children, protoEl.embeddedTemplateIndex, this.targetStatements);
+
+ var appEl = this.factory.createAppElement(protoEl.appProtoEl, this.view, renderNode,
+ parent.appEl, embeddedViewFactory, this.appStmts);
+ this._addRenderNode(renderNode, appEl, ast.ngContentIndex, parent);
+ this.appElements.push(appEl);
+ return null;
+ }
+
+ visitVariable(ast: VariableAst, ctx: any): any { return null; }
+ visitAttr(ast: AttrAst, ctx: any): any { return null; }
+ visitDirective(ast: DirectiveAst, ctx: any): any { return null; }
+ visitEvent(ast: BoundEventAst, ctx: any): any { return null; }
+ visitDirectiveProperty(ast: BoundDirectivePropertyAst, context: any): any { return null; }
+ visitElementProperty(ast: BoundElementPropertyAst, context: any): any { return null; }
+}
+
+
+function codeGenEventHandler(view: Expression, boundElementIndex: number,
+ eventName: string): string {
+ return codeGenValueFn(
+ ['event'],
+ `${view.expression}.triggerEventHandlers(${escapeValue(eventName)}, event, ${boundElementIndex})`);
+}
+
+function codeGenViewFactoryName(component: CompileDirectiveMetadata,
+ embeddedTemplateIndex: number): string {
+ return `viewFactory_${component.type.name}${embeddedTemplateIndex}`;
+}
+
+function codeGenViewEncapsulation(value: ViewEncapsulation): string {
+ if (IS_DART) {
+ return `${METADATA_MODULE_REF}${value}`;
+ } else {
+ return `${value}`;
+ }
+}
diff --git a/modules/angular2/src/core/application_common_providers.ts b/modules/angular2/src/core/application_common_providers.ts
index b0aa60bc71327..bb75bf517e5e1 100644
--- a/modules/angular2/src/core/application_common_providers.ts
+++ b/modules/angular2/src/core/application_common_providers.ts
@@ -11,13 +11,11 @@ import {
KeyValueDiffers,
defaultKeyValueDiffers
} from './change_detection/change_detection';
-import {AppViewPool, APP_VIEW_POOL_CAPACITY} from './linker/view_pool';
+import {ResolvedMetadataCache} from 'angular2/src/core/linker/resolved_metadata_cache';
import {AppViewManager} from './linker/view_manager';
import {AppViewManager_} from "./linker/view_manager";
-import {AppViewManagerUtils} from './linker/view_manager_utils';
import {ViewResolver} from './linker/view_resolver';
import {AppViewListener} from './linker/view_listener';
-import {ProtoViewFactory} from './linker/proto_view_factory';
import {DirectiveResolver} from './linker/directive_resolver';
import {PipeResolver} from './linker/pipe_resolver';
import {Compiler} from './linker/compiler';
@@ -32,12 +30,9 @@ import {DynamicComponentLoader_} from "./linker/dynamic_component_loader";
export const APPLICATION_COMMON_PROVIDERS: Array = CONST_EXPR([
new Provider(Compiler, {useClass: Compiler_}),
APP_ID_RANDOM_PROVIDER,
- AppViewPool,
- new Provider(APP_VIEW_POOL_CAPACITY, {useValue: 10000}),
+ ResolvedMetadataCache,
new Provider(AppViewManager, {useClass: AppViewManager_}),
- AppViewManagerUtils,
AppViewListener,
- ProtoViewFactory,
ViewResolver,
new Provider(IterableDiffers, {useValue: defaultIterableDiffers}),
new Provider(KeyValueDiffers, {useValue: defaultKeyValueDiffers}),
diff --git a/modules/angular2/src/core/application_ref.ts b/modules/angular2/src/core/application_ref.ts
index 426c56853f866..3dd2e35da30e9 100644
--- a/modules/angular2/src/core/application_ref.ts
+++ b/modules/angular2/src/core/application_ref.ts
@@ -33,11 +33,11 @@ import {
ExceptionHandler,
unimplemented
} from 'angular2/src/facade/exceptions';
-import {internalView} from 'angular2/src/core/linker/view_ref';
import {Console} from 'angular2/src/core/console';
import {wtfLeave, wtfCreateScope, WtfScopeFn} from './profile/profile';
import {ChangeDetectorRef} from 'angular2/src/core/change_detection/change_detector_ref';
import {lockMode} from 'angular2/src/facade/lang';
+import {ElementRef_} from 'angular2/src/core/linker/element_ref';
/**
* Construct providers specific to an individual root component.
@@ -56,10 +56,10 @@ function _componentProviders(appComponentType: Type): Array { appRef._unloadComponent(ref); })
.then((componentRef) => {
ref = componentRef;
- if (isPresent(componentRef.location.nativeElement)) {
+ var testability = injector.getOptional(Testability);
+ if (isPresent(testability)) {
injector.get(TestabilityRegistry)
- .registerApplication(componentRef.location.nativeElement,
- injector.get(Testability));
+ .registerApplication(componentRef.location.nativeElement, testability);
}
return componentRef;
});
@@ -217,25 +217,36 @@ export class PlatformRef_ extends PlatformRef {
application(providers: Array): ApplicationRef {
var app = this._initApp(createNgZone(), providers);
- return app;
+ if (PromiseWrapper.isPromise(app)) {
+ throw new BaseException(
+ "Cannot use asyncronous app initializers with application. Use asyncApplication instead.");
+ }
+ return app;
}
asyncApplication(bindingFn: (zone: NgZone) => Promise>,
additionalProviders?: Array): Promise {
var zone = createNgZone();
var completer = PromiseWrapper.completer();
- zone.run(() => {
- PromiseWrapper.then(bindingFn(zone), (providers: Array) => {
- if (isPresent(additionalProviders)) {
- providers = ListWrapper.concat(providers, additionalProviders);
- }
- completer.resolve(this._initApp(zone, providers));
+ if (bindingFn === null) {
+ completer.resolve(this._initApp(zone, additionalProviders));
+ } else {
+ zone.run(() => {
+ PromiseWrapper.then(bindingFn(zone), (providers: Array) => {
+ if (isPresent(additionalProviders)) {
+ providers = ListWrapper.concat(providers, additionalProviders);
+ }
+ let promise = this._initApp(zone, providers);
+ completer.resolve(promise);
+ });
});
- });
+ }
return completer.promise;
}
- private _initApp(zone: NgZone, providers: Array): ApplicationRef {
+ private _initApp(zone: NgZone,
+ providers: Array): Promise|
+ ApplicationRef {
var injector: Injector;
var app: ApplicationRef;
zone.run(() => {
@@ -259,8 +270,12 @@ export class PlatformRef_ extends PlatformRef {
});
app = new ApplicationRef_(this, zone, injector);
this._applications.push(app);
- _runAppInitializers(injector);
- return app;
+ var promise = _runAppInitializers(injector);
+ if (promise !== null) {
+ return PromiseWrapper.then(promise, (_) => app);
+ } else {
+ return app;
+ }
}
dispose(): void {
@@ -273,9 +288,22 @@ export class PlatformRef_ extends PlatformRef {
_applicationDisposed(app: ApplicationRef): void { ListWrapper.remove(this._applications, app); }
}
-function _runAppInitializers(injector: Injector): void {
+function _runAppInitializers(injector: Injector): Promise {
let inits: Function[] = injector.getOptional(APP_INITIALIZER);
- if (isPresent(inits)) inits.forEach(init => init());
+ let promises: Promise[] = [];
+ if (isPresent(inits)) {
+ inits.forEach(init => {
+ var retVal = init();
+ if (PromiseWrapper.isPromise(retVal)) {
+ promises.push(retVal);
+ }
+ });
+ }
+ if (promises.length > 0) {
+ return PromiseWrapper.all(promises);
+ } else {
+ return null;
+ }
}
/**
@@ -439,7 +467,7 @@ export class ApplicationRef_ extends ApplicationRef {
/** @internal */
_loadComponent(ref): void {
- var appChangeDetector = internalView(ref.hostView).changeDetector;
+ var appChangeDetector = (ref.location).internalElement.parentView.changeDetector;
this._changeDetectorRefs.push(appChangeDetector.ref);
this.tick();
this._rootComponents.push(ref);
@@ -451,7 +479,8 @@ export class ApplicationRef_ extends ApplicationRef {
if (!ListWrapper.contains(this._rootComponents, ref)) {
return;
}
- this.unregisterChangeDetector(internalView(ref.hostView).changeDetector.ref);
+ this.unregisterChangeDetector(
+ (ref.location).internalElement.parentView.changeDetector.ref);
ListWrapper.remove(this._rootComponents, ref);
}
diff --git a/modules/angular2/src/core/change_detection/abstract_change_detector.ts b/modules/angular2/src/core/change_detection/abstract_change_detector.ts
index 4a1ced947ea85..e3ec39cb873c7 100644
--- a/modules/angular2/src/core/change_detection/abstract_change_detector.ts
+++ b/modules/angular2/src/core/change_detection/abstract_change_detector.ts
@@ -8,7 +8,9 @@ import {Pipes} from './pipes';
import {
ChangeDetectionError,
ExpressionChangedAfterItHasBeenCheckedException,
- DehydratedException
+ DehydratedException,
+ EventEvaluationErrorContext,
+ EventEvaluationError
} from './exceptions';
import {BindingTarget} from './binding_record';
import {Locals} from './parser/locals';
@@ -43,9 +45,12 @@ export class AbstractChangeDetector implements ChangeDetector {
subscriptions: any[];
streams: any[];
- constructor(public id: string, public dispatcher: ChangeDispatcher,
- public numberOfPropertyProtoRecords: number, public bindingTargets: BindingTarget[],
- public directiveIndices: DirectiveIndex[], public strategy: ChangeDetectionStrategy) {
+ dispatcher: ChangeDispatcher;
+
+
+ constructor(public id: string, public numberOfPropertyProtoRecords: number,
+ public bindingTargets: BindingTarget[], public directiveIndices: DirectiveIndex[],
+ public strategy: ChangeDetectionStrategy) {
this.ref = new ChangeDetectorRef_(this);
}
@@ -65,10 +70,24 @@ export class AbstractChangeDetector implements ChangeDetector {
remove(): void { this.parent.removeContentChild(this); }
- handleEvent(eventName: string, elIndex: number, locals: Locals): boolean {
- var res = this.handleEventInternal(eventName, elIndex, locals);
- this.markPathToRootAsCheckOnce();
- return res;
+ handleEvent(eventName: string, elIndex: number, event: any): boolean {
+ if (!this.hydrated()) {
+ return true;
+ }
+ try {
+ var locals = new Map();
+ locals.set('$event', event);
+ var res = !this.handleEventInternal(eventName, elIndex, new Locals(this.locals, locals));
+ this.markPathToRootAsCheckOnce();
+ return res;
+ } catch (e) {
+ var c = this.dispatcher.getDebugContext(null, elIndex, null);
+ var context = isPresent(c) ?
+ new EventEvaluationErrorContext(c.element, c.componentElement, c.context,
+ c.locals, c.injector) :
+ null;
+ throw new EventEvaluationError(eventName, e, e.stack, context);
+ }
}
handleEventInternal(eventName: string, elIndex: number, locals: Locals): boolean { return false; }
@@ -133,7 +152,8 @@ export class AbstractChangeDetector implements ChangeDetector {
// This method is not intended to be overridden. Subclasses should instead provide an
// implementation of `hydrateDirectives`.
- hydrate(context: T, locals: Locals, directives: any, pipes: Pipes): void {
+ hydrate(context: T, locals: Locals, dispatcher: ChangeDispatcher, pipes: Pipes): void {
+ this.dispatcher = dispatcher;
this.mode = ChangeDetectionUtil.changeDetectionMode(this.strategy);
this.context = context;
@@ -143,12 +163,12 @@ export class AbstractChangeDetector implements ChangeDetector {
this.locals = locals;
this.pipes = pipes;
- this.hydrateDirectives(directives);
+ this.hydrateDirectives(dispatcher);
this.state = ChangeDetectorState.NeverChecked;
}
// Subclasses should override this method to hydrate any directives.
- hydrateDirectives(directives: any): void {}
+ hydrateDirectives(dispatcher: ChangeDispatcher): void {}
// This method is not intended to be overridden. Subclasses should instead provide an
// implementation of `dehydrateDirectives`.
@@ -160,6 +180,7 @@ export class AbstractChangeDetector implements ChangeDetector {
this._unsubsribeFromObservables();
}
+ this.dispatcher = null;
this.context = null;
this.locals = null;
this.pipes = null;
@@ -171,6 +192,19 @@ export class AbstractChangeDetector implements ChangeDetector {
hydrated(): boolean { return isPresent(this.context); }
+ destroyRecursive(): void {
+ this.dispatcher.notifyOnDestroy();
+ this.dehydrate();
+ var children = this.contentChildren;
+ for (var i = 0; i < children.length; i++) {
+ children[i].destroyRecursive();
+ }
+ children = this.viewChildren;
+ for (var i = 0; i < children.length; i++) {
+ children[i].destroyRecursive();
+ }
+ }
+
afterContentLifecycleCallbacks(): void {
this.dispatcher.notifyAfterContentChecked();
this.afterContentLifecycleCallbacksInternal();
@@ -298,7 +332,7 @@ export class AbstractChangeDetector implements ChangeDetector {
private _throwError(exception: any, stack: any): void {
var error;
try {
- var c = this.dispatcher.getDebugContext(this._currentBinding().elementIndex, null);
+ var c = this.dispatcher.getDebugContext(null, this._currentBinding().elementIndex, null);
var context = isPresent(c) ? new _Context(c.element, c.componentElement, c.context, c.locals,
c.injector, this._currentBinding().debug) :
null;
diff --git a/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts b/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts
index 14c9cafc7e21c..98615d94ae3ae 100644
--- a/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts
+++ b/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts
@@ -66,8 +66,8 @@ export class ChangeDetectorJITGenerator {
generate(): Function {
var factorySource = `
${this.generateSource()}
- return function(dispatcher) {
- return new ${this.typeName}(dispatcher);
+ return function() {
+ return new ${this.typeName}();
}
`;
return new Function(this.abstractChangeDetectorVarName, this.changeDetectionUtilVarName,
@@ -77,9 +77,9 @@ export class ChangeDetectorJITGenerator {
generateSource(): string {
return `
- var ${this.typeName} = function ${this.typeName}(dispatcher) {
+ var ${this.typeName} = function ${this.typeName}() {
${this.abstractChangeDetectorVarName}.call(
- this, ${JSON.stringify(this.id)}, dispatcher, ${this.records.length},
+ this, ${JSON.stringify(this.id)}, ${this.records.length},
${this.typeName}.gen_propertyBindingTargets, ${this.typeName}.gen_directiveIndices,
${codify(this.changeDetectionStrategy)});
this.dehydrateDirectives(false);
@@ -199,13 +199,14 @@ export class ChangeDetectorJITGenerator {
/** @internal */
_maybeGenDehydrateDirectives(): string {
var destroyPipesCode = this._names.genPipeOnDestroy();
- if (destroyPipesCode) {
- destroyPipesCode = `if (destroyPipes) { ${destroyPipesCode} }`;
- }
+ var destroyDirectivesCode = this._logic.genDirectivesOnDestroy(this.directiveRecords);
var dehydrateFieldsCode = this._names.genDehydrateFields();
- if (!destroyPipesCode && !dehydrateFieldsCode) return '';
+ if (!destroyPipesCode && !destroyDirectivesCode && !dehydrateFieldsCode) return '';
return `${this.typeName}.prototype.dehydrateDirectives = function(destroyPipes) {
- ${destroyPipesCode}
+ if (destroyPipes) {
+ ${destroyPipesCode}
+ ${destroyDirectivesCode}
+ }
${dehydrateFieldsCode}
}`;
}
diff --git a/modules/angular2/src/core/change_detection/change_detector_ref.ts b/modules/angular2/src/core/change_detection/change_detector_ref.ts
index e128dcaac2bcd..e34fe448571b9 100644
--- a/modules/angular2/src/core/change_detection/change_detector_ref.ts
+++ b/modules/angular2/src/core/change_detection/change_detector_ref.ts
@@ -205,4 +205,4 @@ export class ChangeDetectorRef_ extends ChangeDetectorRef {
this._cd.mode = ChangeDetectionStrategy.CheckAlways;
this.markForCheck();
}
-}
+}
\ No newline at end of file
diff --git a/modules/angular2/src/core/change_detection/codegen_logic_util.ts b/modules/angular2/src/core/change_detection/codegen_logic_util.ts
index 2c2e2ab741a08..5da262e7b0720 100644
--- a/modules/angular2/src/core/change_detection/codegen_logic_util.ts
+++ b/modules/angular2/src/core/change_detection/codegen_logic_util.ts
@@ -103,7 +103,7 @@ export class CodegenLogicUtil {
break;
case RecordType.Chain:
- rhs = 'null';
+ rhs = `${getLocalName(protoRec.args[protoRec.args.length - 1])}`;
break;
default:
@@ -155,17 +155,49 @@ export class CodegenLogicUtil {
var res = [];
for (var i = 0; i < directiveRecords.length; ++i) {
var r = directiveRecords[i];
- res.push(`${this._names.getDirectiveName(r.directiveIndex)} = ${this._genReadDirective(i)};`);
+ var dirVarName = this._names.getDirectiveName(r.directiveIndex);
+ res.push(`${dirVarName} = ${this._genReadDirective(i)};`);
+ if (isPresent(r.outputs)) {
+ r.outputs.forEach(output => {
+ var eventHandlerExpr = this._genEventHandler(r.directiveIndex.elementIndex, output[1]);
+ if (IS_DART) {
+ res.push(`${dirVarName}.${output[0]}.listen(${eventHandlerExpr});`);
+ } else {
+ res.push(`${dirVarName}.${output[0]}.subscribe({next: ${eventHandlerExpr}});`);
+ }
+ });
+ }
}
return res.join("\n");
}
+ genDirectivesOnDestroy(directiveRecords: DirectiveRecord[]): string {
+ var res = [];
+ for (var i = 0; i < directiveRecords.length; ++i) {
+ var r = directiveRecords[i];
+ if (r.callOnDestroy) {
+ var dirVarName = this._names.getDirectiveName(r.directiveIndex);
+ res.push(`${dirVarName}.ngOnDestroy();`);
+ }
+ }
+ return res.join("\n");
+ }
+
+ private _genEventHandler(boundElementIndex: number, eventName: string): string {
+ if (IS_DART) {
+ return `(event) => this.handleEvent('${eventName}', ${boundElementIndex}, event)`;
+ } else {
+ return `(function(event) { return this.handleEvent('${eventName}', ${boundElementIndex}, event); }).bind(this)`;
+ }
+ }
+
private _genReadDirective(index: number) {
+ var directiveExpr = `this.getDirectiveFor(directives, ${index})`;
// This is an experimental feature. Works only in Dart.
if (this._changeDetection === ChangeDetectionStrategy.OnPushObserve) {
- return `this.observeDirective(this.getDirectiveFor(directives, ${index}), ${index})`;
+ return `this.observeDirective(${directiveExpr}, ${index})`;
} else {
- return `this.getDirectiveFor(directives, ${index})`;
+ return directiveExpr;
}
}
diff --git a/modules/angular2/src/core/change_detection/directive_record.ts b/modules/angular2/src/core/change_detection/directive_record.ts
index 967034f07eff6..53c6f2e6cdca9 100644
--- a/modules/angular2/src/core/change_detection/directive_record.ts
+++ b/modules/angular2/src/core/change_detection/directive_record.ts
@@ -16,10 +16,14 @@ export class DirectiveRecord {
callOnChanges: boolean;
callDoCheck: boolean;
callOnInit: boolean;
+ callOnDestroy: boolean;
changeDetection: ChangeDetectionStrategy;
+ // array of [emitter property name, eventName]
+ outputs: string[][];
constructor({directiveIndex, callAfterContentInit, callAfterContentChecked, callAfterViewInit,
- callAfterViewChecked, callOnChanges, callDoCheck, callOnInit, changeDetection}: {
+ callAfterViewChecked, callOnChanges, callDoCheck, callOnInit, callOnDestroy,
+ changeDetection, outputs}: {
directiveIndex?: DirectiveIndex,
callAfterContentInit?: boolean,
callAfterContentChecked?: boolean,
@@ -28,7 +32,9 @@ export class DirectiveRecord {
callOnChanges?: boolean,
callDoCheck?: boolean,
callOnInit?: boolean,
- changeDetection?: ChangeDetectionStrategy
+ callOnDestroy?: boolean,
+ changeDetection?: ChangeDetectionStrategy,
+ outputs?: string[][]
} = {}) {
this.directiveIndex = directiveIndex;
this.callAfterContentInit = normalizeBool(callAfterContentInit);
@@ -38,7 +44,9 @@ export class DirectiveRecord {
this.callAfterViewChecked = normalizeBool(callAfterViewChecked);
this.callDoCheck = normalizeBool(callDoCheck);
this.callOnInit = normalizeBool(callOnInit);
+ this.callOnDestroy = normalizeBool(callOnDestroy);
this.changeDetection = changeDetection;
+ this.outputs = outputs;
}
isDefaultChangeDetection(): boolean {
diff --git a/modules/angular2/src/core/change_detection/dynamic_change_detector.ts b/modules/angular2/src/core/change_detection/dynamic_change_detector.ts
index 344b71ff5a8b7..0b07abe62f0aa 100644
--- a/modules/angular2/src/core/change_detection/dynamic_change_detector.ts
+++ b/modules/angular2/src/core/change_detection/dynamic_change_detector.ts
@@ -11,21 +11,21 @@ import {ChangeDispatcher, ChangeDetectorGenConfig} from './interfaces';
import {ChangeDetectionUtil, SimpleChange} from './change_detection_util';
import {ChangeDetectionStrategy, ChangeDetectorState} from './constants';
import {ProtoRecord, RecordType} from './proto_record';
+import {reflector} from 'angular2/src/core/reflection/reflection';
+import {ObservableWrapper} from 'angular2/src/facade/async';
export class DynamicChangeDetector extends AbstractChangeDetector {
values: any[];
changes: any[];
localPipes: any[];
prevContexts: any[];
- directives: any = null;
- constructor(id: string, dispatcher: ChangeDispatcher, numberOfPropertyProtoRecords: number,
+ constructor(id: string, numberOfPropertyProtoRecords: number,
propertyBindingTargets: BindingTarget[], directiveIndices: DirectiveIndex[],
strategy: ChangeDetectionStrategy, private _records: ProtoRecord[],
private _eventBindings: EventBinding[], private _directiveRecords: DirectiveRecord[],
private _genConfig: ChangeDetectorGenConfig) {
- super(id, dispatcher, numberOfPropertyProtoRecords, propertyBindingTargets, directiveIndices,
- strategy);
+ super(id, numberOfPropertyProtoRecords, propertyBindingTargets, directiveIndices, strategy);
var len = _records.length + 1;
this.values = ListWrapper.createFixedSize(len);
this.localPipes = ListWrapper.createFixedSize(len);
@@ -104,24 +104,41 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
return this._eventBindings.filter(eb => eb.eventName == eventName && eb.elIndex === elIndex);
}
- hydrateDirectives(directives: any): void {
+ hydrateDirectives(dispatcher: ChangeDispatcher): void {
this.values[0] = this.context;
- this.directives = directives;
+ this.dispatcher = dispatcher;
if (this.strategy === ChangeDetectionStrategy.OnPushObserve) {
for (var i = 0; i < this.directiveIndices.length; ++i) {
var index = this.directiveIndices[i];
- super.observeDirective(directives.getDirectiveFor(index), i);
+ super.observeDirective(this._getDirectiveFor(index), i);
+ }
+ }
+ for (var i = 0; i < this._directiveRecords.length; ++i) {
+ var r = this._directiveRecords[i];
+ if (isPresent(r.outputs)) {
+ r.outputs.forEach(output => {
+ var eventHandler =
+ this._createEventHandler(r.directiveIndex.elementIndex, output[1]);
+ var directive = this._getDirectiveFor(r.directiveIndex);
+ var getter = reflector.getter(output[0]);
+ ObservableWrapper.subscribe(getter(directive), eventHandler);
+ });
}
}
}
+ private _createEventHandler(boundElementIndex: number, eventName: string): Function {
+ return (event) => this.handleEvent(eventName, boundElementIndex, event);
+ }
+
+
dehydrateDirectives(destroyPipes: boolean) {
if (destroyPipes) {
this._destroyPipes();
+ this._destroyDirectives();
}
this.values[0] = null;
- this.directives = null;
ListWrapper.fill(this.values, ChangeDetectionUtil.uninitialized, 1);
ListWrapper.fill(this.changes, false);
ListWrapper.fill(this.localPipes, null);
@@ -137,6 +154,16 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
}
+ /** @internal */
+ _destroyDirectives() {
+ for (var i = 0; i < this._directiveRecords.length; ++i) {
+ var record = this._directiveRecords[i];
+ if (record.callOnDestroy) {
+ this._getDirectiveFor(record.directiveIndex).ngOnDestroy();
+ }
+ }
+ }
+
checkNoChanges(): void { this.runDetectChanges(true); }
detectChangesInRecordsInternal(throwOnChange: boolean) {
@@ -241,12 +268,14 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
}
/** @internal */
- private _getDirectiveFor(directiveIndex) {
- return this.directives.getDirectiveFor(directiveIndex);
+ private _getDirectiveFor(directiveIndex: DirectiveIndex) {
+ return this.dispatcher.getDirectiveFor(directiveIndex);
}
/** @internal */
- private _getDetectorFor(directiveIndex) { return this.directives.getDetectorFor(directiveIndex); }
+ private _getDetectorFor(directiveIndex: DirectiveIndex) {
+ return this.dispatcher.getDetectorFor(directiveIndex);
+ }
/** @internal */
private _check(proto: ProtoRecord, throwOnChange: boolean, values: any[],
diff --git a/modules/angular2/src/core/change_detection/exceptions.ts b/modules/angular2/src/core/change_detection/exceptions.ts
index b8c7454447e08..11d04ee273373 100644
--- a/modules/angular2/src/core/change_detection/exceptions.ts
+++ b/modules/angular2/src/core/change_detection/exceptions.ts
@@ -93,3 +93,20 @@ export class ChangeDetectionError extends WrappedException {
export class DehydratedException extends BaseException {
constructor() { super('Attempt to detect changes on a dehydrated detector.'); }
}
+
+/**
+ * Wraps an exception thrown by an event handler.
+ */
+export class EventEvaluationError extends WrappedException {
+ constructor(eventName: string, originalException: any, originalStack: any, context: any) {
+ super(`Error during evaluation of "${eventName}"`, originalException, originalStack, context);
+ }
+}
+
+/**
+ * Error context included when an event handler throws an exception.
+ */
+export class EventEvaluationErrorContext {
+ constructor(public element: any, public componentElement: any, public context: any,
+ public locals: any, public injector: any) {}
+}
diff --git a/modules/angular2/src/core/change_detection/interfaces.ts b/modules/angular2/src/core/change_detection/interfaces.ts
index 803d962c563b6..0f3c165f56bee 100644
--- a/modules/angular2/src/core/change_detection/interfaces.ts
+++ b/modules/angular2/src/core/change_detection/interfaces.ts
@@ -1,6 +1,6 @@
import {Locals} from './parser/locals';
import {BindingTarget, BindingRecord} from './binding_record';
-import {DirectiveIndex, DirectiveRecord} from './directive_record';
+import {DirectiveRecord, DirectiveIndex} from './directive_record';
import {ChangeDetectionStrategy} from './constants';
import {ChangeDetectorRef} from './change_detector_ref';
@@ -10,11 +10,14 @@ export class DebugContext {
}
export interface ChangeDispatcher {
- getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext;
+ getDebugContext(appElement: any, elementIndex: number, directiveIndex: number): DebugContext;
notifyOnBinding(bindingTarget: BindingTarget, value: any): void;
logBindingUpdate(bindingTarget: BindingTarget, value: any): void;
notifyAfterContentChecked(): void;
notifyAfterViewChecked(): void;
+ notifyOnDestroy(): void;
+ getDetectorFor(directiveIndex: DirectiveIndex): ChangeDetector;
+ getDirectiveFor(directiveIndex: DirectiveIndex): any;
}
export interface ChangeDetector {
@@ -27,16 +30,18 @@ export interface ChangeDetector {
removeContentChild(cd: ChangeDetector): void;
removeViewChild(cd: ChangeDetector): void;
remove(): void;
- hydrate(context: any, locals: Locals, directives: any, pipes: any): void;
+ hydrate(context: any, locals: Locals, dispatcher: ChangeDispatcher, pipes: any): void;
dehydrate(): void;
markPathToRootAsCheckOnce(): void;
- handleEvent(eventName: string, elIndex: number, locals: Locals);
+ handleEvent(eventName: string, elIndex: number, event: any);
detectChanges(): void;
checkNoChanges(): void;
+ destroyRecursive(): void;
+ markAsCheckOnce(): void;
}
-export interface ProtoChangeDetector { instantiate(dispatcher: ChangeDispatcher): ChangeDetector; }
+export interface ProtoChangeDetector { instantiate(): ChangeDetector; }
export class ChangeDetectorGenConfig {
constructor(public genDebugInfo: boolean, public logBindingUpdate: boolean,
diff --git a/modules/angular2/src/core/change_detection/jit_proto_change_detector.dart b/modules/angular2/src/core/change_detection/jit_proto_change_detector.dart
index 46a3251a5bfc3..5fb02a8e4a7dc 100644
--- a/modules/angular2/src/core/change_detection/jit_proto_change_detector.dart
+++ b/modules/angular2/src/core/change_detection/jit_proto_change_detector.dart
@@ -3,11 +3,11 @@ library change_detection.jit_proto_change_detector;
import 'interfaces.dart' show ChangeDetector, ProtoChangeDetector;
class JitProtoChangeDetector implements ProtoChangeDetector {
- JitProtoChangeDetector(definition) : super();
+ JitProtoChangeDetector(definition);
static bool isSupported() => false;
- ChangeDetector instantiate(dispatcher) {
+ ChangeDetector instantiate() {
throw "Jit Change Detection not supported in Dart";
}
}
diff --git a/modules/angular2/src/core/change_detection/jit_proto_change_detector.ts b/modules/angular2/src/core/change_detection/jit_proto_change_detector.ts
index 3d4636e7e3a9b..bd747c493126d 100644
--- a/modules/angular2/src/core/change_detection/jit_proto_change_detector.ts
+++ b/modules/angular2/src/core/change_detection/jit_proto_change_detector.ts
@@ -14,7 +14,7 @@ export class JitProtoChangeDetector implements ProtoChangeDetector {
static isSupported(): boolean { return true; }
- instantiate(dispatcher: any): ChangeDetector { return this._factory(dispatcher); }
+ instantiate(): ChangeDetector { return this._factory(); }
/** @internal */
_createFactory(definition: ChangeDetectorDefinition) {
diff --git a/modules/angular2/src/core/change_detection/parser/locals.ts b/modules/angular2/src/core/change_detection/parser/locals.ts
index 92b1aaa86220a..fb7fbd2fbdcd2 100644
--- a/modules/angular2/src/core/change_detection/parser/locals.ts
+++ b/modules/angular2/src/core/change_detection/parser/locals.ts
@@ -41,5 +41,5 @@ export class Locals {
}
}
- clearValues(): void { MapWrapper.clearValues(this.current); }
+ clearLocalValues(): void { MapWrapper.clearValues(this.current); }
}
diff --git a/modules/angular2/src/core/change_detection/pregen_proto_change_detector.dart b/modules/angular2/src/core/change_detection/pregen_proto_change_detector.dart
index bf95c75e1d794..301801ddba088 100644
--- a/modules/angular2/src/core/change_detection/pregen_proto_change_detector.dart
+++ b/modules/angular2/src/core/change_detection/pregen_proto_change_detector.dart
@@ -1,8 +1,5 @@
library angular2.src.change_detection.pregen_proto_change_detector;
-import 'package:angular2/src/core/change_detection/interfaces.dart';
-import 'package:angular2/src/facade/lang.dart' show looseIdentical;
-
export 'dart:core' show List;
export 'package:angular2/src/core/change_detection/abstract_change_detector.dart'
show AbstractChangeDetector;
@@ -20,34 +17,3 @@ export 'package:angular2/src/core/change_detection/proto_record.dart'
export 'package:angular2/src/core/change_detection/change_detection_util.dart'
show ChangeDetectionUtil;
export 'package:angular2/src/facade/lang.dart' show assertionsEnabled, looseIdentical;
-
-typedef ProtoChangeDetector PregenProtoChangeDetectorFactory(
- ChangeDetectorDefinition definition);
-
-typedef ChangeDetector InstantiateMethod(dynamic dispatcher);
-
-/// Implementation of [ProtoChangeDetector] for use by pre-generated change
-/// detectors in Angular 2 Dart.
-/// Classes generated by the `TemplateCompiler` use this. The `export`s above
-/// allow the generated code to `import` a single library and get all
-/// dependencies.
-class PregenProtoChangeDetector extends ProtoChangeDetector {
- /// The [ChangeDetectorDefinition#id]. Strictly informational.
- final String id;
-
- /// Closure used to generate an actual [ChangeDetector].
- final InstantiateMethod _instantiateMethod;
-
- /// Internal ctor.
- PregenProtoChangeDetector._(this.id, this._instantiateMethod);
-
- static bool isSupported() => true;
-
- factory PregenProtoChangeDetector(
- InstantiateMethod instantiateMethod, ChangeDetectorDefinition def) {
- return new PregenProtoChangeDetector._(def.id, instantiateMethod);
- }
-
- @override
- instantiate(dynamic dispatcher) => _instantiateMethod(dispatcher);
-}
diff --git a/modules/angular2/src/core/change_detection/pregen_proto_change_detector.ts b/modules/angular2/src/core/change_detection/pregen_proto_change_detector.ts
index 5ef1eadb5bf0a..da60b225c91e6 100644
--- a/modules/angular2/src/core/change_detection/pregen_proto_change_detector.ts
+++ b/modules/angular2/src/core/change_detection/pregen_proto_change_detector.ts
@@ -1,14 +1 @@
-import {BaseException} from 'angular2/src/facade/exceptions';
-
-import {ProtoChangeDetector, ChangeDetector} from './interfaces';
-import {coalesce} from './coalesce';
-
-export {Function as PregenProtoChangeDetectorFactory};
-
-export class PregenProtoChangeDetector implements ProtoChangeDetector {
- static isSupported(): boolean { return false; }
-
- instantiate(dispatcher: any): ChangeDetector {
- throw new BaseException('Pregen change detection not supported in Js');
- }
-}
+// empty file as we only need the dart version
\ No newline at end of file
diff --git a/modules/angular2/src/core/change_detection/proto_change_detector.ts b/modules/angular2/src/core/change_detection/proto_change_detector.ts
index c25cc54867e35..ee0016a9df209 100644
--- a/modules/angular2/src/core/change_detection/proto_change_detector.ts
+++ b/modules/angular2/src/core/change_detection/proto_change_detector.ts
@@ -54,12 +54,11 @@ export class DynamicProtoChangeDetector implements ProtoChangeDetector {
this._directiveIndices = this._definition.directiveRecords.map(d => d.directiveIndex);
}
- instantiate(dispatcher: any): ChangeDetector {
+ instantiate(): ChangeDetector {
return new DynamicChangeDetector(
- this._definition.id, dispatcher, this._propertyBindingRecords.length,
- this._propertyBindingTargets, this._directiveIndices, this._definition.strategy,
- this._propertyBindingRecords, this._eventBindingRecords, this._definition.directiveRecords,
- this._definition.genConfig);
+ this._definition.id, this._propertyBindingRecords.length, this._propertyBindingTargets,
+ this._directiveIndices, this._definition.strategy, this._propertyBindingRecords,
+ this._eventBindingRecords, this._definition.directiveRecords, this._definition.genConfig);
}
}
diff --git a/modules/angular2/src/core/debug/debug_element.ts b/modules/angular2/src/core/debug/debug_element.ts
index c26acb8188e2a..88b196258e316 100644
--- a/modules/angular2/src/core/debug/debug_element.ts
+++ b/modules/angular2/src/core/debug/debug_element.ts
@@ -1,9 +1,9 @@
import {Type, isPresent, isBlank} from 'angular2/src/facade/lang';
import {ListWrapper, MapWrapper, Predicate} from 'angular2/src/facade/collection';
import {unimplemented} from 'angular2/src/facade/exceptions';
-import {ElementInjector} from 'angular2/src/core/linker/element_injector';
-import {AppView, ViewType} from 'angular2/src/core/linker/view';
-import {internalView} from 'angular2/src/core/linker/view_ref';
+
+import {AppElement} from 'angular2/src/core/linker/element';
+import {AppView} from 'angular2/src/core/linker/view';
import {ElementRef, ElementRef_} from 'angular2/src/core/linker/element_ref';
/**
@@ -103,79 +103,68 @@ export abstract class DebugElement {
}
export class DebugElement_ extends DebugElement {
- /** @internal */
- _elementInjector: ElementInjector;
-
- constructor(private _parentView: AppView, private _boundElementIndex: number) {
- super();
- this._elementInjector = this._parentView.elementInjectors[this._boundElementIndex];
- }
+ constructor(private _appElement: AppElement) { super(); }
get componentInstance(): any {
- if (!isPresent(this._elementInjector)) {
+ if (!isPresent(this._appElement)) {
return null;
}
- return this._elementInjector.getComponent();
+ return this._appElement.getComponent();
}
get nativeElement(): any { return this.elementRef.nativeElement; }
- get elementRef(): ElementRef { return this._parentView.elementRefs[this._boundElementIndex]; }
+ get elementRef(): ElementRef { return this._appElement.ref; }
getDirectiveInstance(directiveIndex: number): any {
- return this._elementInjector.getDirectiveAtIndex(directiveIndex);
+ return this._appElement.getDirectiveAtIndex(directiveIndex);
}
get children(): DebugElement[] {
- return this._getChildElements(this._parentView, this._boundElementIndex);
+ return this._getChildElements(this._appElement.parentView, this._appElement);
}
get componentViewChildren(): DebugElement[] {
- var shadowView = this._parentView.getNestedView(this._boundElementIndex);
-
- if (!isPresent(shadowView) || shadowView.proto.type !== ViewType.COMPONENT) {
+ if (!isPresent(this._appElement.componentView)) {
// The current element is not a component.
return [];
}
- return this._getChildElements(shadowView, null);
+ return this._getChildElements(this._appElement.componentView, null);
}
triggerEventHandler(eventName: string, eventObj: Event): void {
- this._parentView.triggerEventHandlers(eventName, eventObj, this._boundElementIndex);
+ this._appElement.parentView.triggerEventHandlers(eventName, eventObj,
+ this._appElement.proto.index);
}
hasDirective(type: Type): boolean {
- if (!isPresent(this._elementInjector)) {
+ if (!isPresent(this._appElement)) {
return false;
}
- return this._elementInjector.hasDirective(type);
+ return this._appElement.hasDirective(type);
}
inject(type: Type): any {
- if (!isPresent(this._elementInjector)) {
+ if (!isPresent(this._appElement)) {
return null;
}
- return this._elementInjector.get(type);
+ return this._appElement.get(type);
}
- getLocal(name: string): any { return this._parentView.locals.get(name); }
+ getLocal(name: string): any { return this._appElement.parentView.locals.get(name); }
/** @internal */
- _getChildElements(view: AppView, parentBoundElementIndex: number): DebugElement[] {
+ _getChildElements(view: AppView, parentAppElement: AppElement): DebugElement[] {
var els = [];
- var parentElementBinder = null;
- if (isPresent(parentBoundElementIndex)) {
- parentElementBinder = view.proto.elementBinders[parentBoundElementIndex - view.elementOffset];
- }
- for (var i = 0; i < view.proto.elementBinders.length; ++i) {
- var binder = view.proto.elementBinders[i];
- if (binder.parent == parentElementBinder) {
- els.push(new DebugElement_(view, view.elementOffset + i));
+ for (var i = 0; i < view.appElements.length; ++i) {
+ var appEl = view.appElements[i];
+ if (appEl.parent == parentAppElement) {
+ els.push(new DebugElement_(appEl));
- var views = view.viewContainers[view.elementOffset + i];
+ var views = appEl.nestedViews;
if (isPresent(views)) {
- views.views.forEach(
+ views.forEach(
(nextView) => { els = els.concat(this._getChildElements(nextView, null)); });
}
}
@@ -191,8 +180,7 @@ export class DebugElement_ extends DebugElement {
* @return {DebugElement}
*/
export function inspectElement(elementRef: ElementRef): DebugElement {
- return new DebugElement_(internalView((elementRef).parentView),
- (elementRef).boundElementIndex);
+ return new DebugElement_((elementRef).internalElement);
}
/**
diff --git a/modules/angular2/src/core/di/injector.ts b/modules/angular2/src/core/di/injector.ts
index 40c7e2049372e..4d499cc8a6f02 100644
--- a/modules/angular2/src/core/di/injector.ts
+++ b/modules/angular2/src/core/di/injector.ts
@@ -194,6 +194,11 @@ export class ProtoInjectorDynamicStrategy implements ProtoInjectorStrategy {
}
export class ProtoInjector {
+ static fromResolvedProviders(providers: ResolvedProvider[]): ProtoInjector {
+ var bd = providers.map(b => new ProviderWithVisibility(b, Visibility.Public));
+ return new ProtoInjector(bd);
+ }
+
/** @internal */
_strategy: ProtoInjectorStrategy;
numberOfProviders: number;
@@ -215,7 +220,6 @@ export interface InjectorStrategy {
getObjAtIndex(index: number): any;
getMaxNumberOfObjects(): number;
- attach(parent: Injector, isHost: boolean): void;
resetConstructionCounter(): void;
instantiateProvider(provider: ResolvedProvider, visibility: Visibility): any;
}
@@ -240,12 +244,6 @@ export class InjectorInlineStrategy implements InjectorStrategy {
return this.injector._new(provider, visibility);
}
- attach(parent: Injector, isHost: boolean): void {
- var inj = this.injector;
- inj._parent = parent;
- inj._isHost = isHost;
- }
-
getObjByKeyId(keyId: number, visibility: Visibility): any {
var p = this.protoStrategy;
var inj = this.injector;
@@ -346,12 +344,6 @@ export class InjectorDynamicStrategy implements InjectorStrategy {
return this.injector._new(provider, visibility);
}
- attach(parent: Injector, isHost: boolean): void {
- var inj = this.injector;
- inj._parent = parent;
- inj._isHost = isHost;
- }
-
getObjByKeyId(keyId: number, visibility: Visibility): any {
var p = this.protoStrategy;
@@ -516,9 +508,7 @@ export class Injector {
* ```
*/
static fromResolvedProviders(providers: ResolvedProvider[]): Injector {
- var bd = providers.map(b => new ProviderWithVisibility(b, Visibility.Public));
- var proto = new ProtoInjector(bd);
- return new Injector(proto, null, null);
+ return new Injector(ProtoInjector.fromResolvedProviders(providers));
}
/**
@@ -531,8 +521,6 @@ export class Injector {
/** @internal */
_strategy: InjectorStrategy;
/** @internal */
- _isHost: boolean = false;
- /** @internal */
_constructionCounter: number = 0;
/** @internal */
public _proto: any /* ProtoInjector */;
@@ -542,6 +530,7 @@ export class Injector {
* Private
*/
constructor(_proto: any /* ProtoInjector */, _parent: Injector = null,
+ private _isHostBoundary: boolean = false,
private _depProvider: any /* DependencyProvider */ = null,
private _debugContext: Function = null) {
this._proto = _proto;
@@ -549,6 +538,12 @@ export class Injector {
this._strategy = _proto._strategy.createInjectorStrategy(this);
}
+ /**
+ * Whether this injector is a boundary to a host.
+ * @internal
+ */
+ get hostBoundary() { return this._isHostBoundary; }
+
/**
* @internal
*/
@@ -692,7 +687,7 @@ export class Injector {
createChildFromResolved(providers: ResolvedProvider[]): Injector {
var bd = providers.map(b => new ProviderWithVisibility(b, Visibility.Public));
var proto = new ProtoInjector(bd);
- var inj = new Injector(proto, null, null);
+ var inj = new Injector(proto);
inj._parent = this;
return inj;
}
@@ -935,7 +930,7 @@ export class Injector {
var inj: Injector = this;
if (lowerBoundVisibility instanceof SkipSelfMetadata) {
- if (inj._isHost) {
+ if (inj._isHostBoundary) {
return this._getPrivateDependency(key, optional, inj);
} else {
inj = inj._parent;
@@ -946,7 +941,7 @@ export class Injector {
var obj = inj._strategy.getObjByKeyId(key.id, providerVisibility);
if (obj !== UNDEFINED) return obj;
- if (isPresent(inj._parent) && inj._isHost) {
+ if (isPresent(inj._parent) && inj._isHostBoundary) {
return this._getPrivateDependency(key, optional, inj);
} else {
inj = inj._parent;
@@ -968,7 +963,7 @@ export class Injector {
var inj: Injector = this;
if (lowerBoundVisibility instanceof SkipSelfMetadata) {
- providerVisibility = inj._isHost ? Visibility.PublicAndPrivate : Visibility.Public;
+ providerVisibility = inj._isHostBoundary ? Visibility.PublicAndPrivate : Visibility.Public;
inj = inj._parent;
}
@@ -976,7 +971,7 @@ export class Injector {
var obj = inj._strategy.getObjByKeyId(key.id, providerVisibility);
if (obj !== UNDEFINED) return obj;
- providerVisibility = inj._isHost ? Visibility.PublicAndPrivate : Visibility.Public;
+ providerVisibility = inj._isHostBoundary ? Visibility.PublicAndPrivate : Visibility.Public;
inj = inj._parent;
}
diff --git a/modules/angular2/src/core/di/provider.ts b/modules/angular2/src/core/di/provider.ts
index 267381244d988..753f0fd4d8d0c 100644
--- a/modules/angular2/src/core/di/provider.ts
+++ b/modules/angular2/src/core/di/provider.ts
@@ -538,50 +538,62 @@ export function resolveFactory(provider: Provider): ResolvedFactory {
* convenience provider syntax.
*/
export function resolveProvider(provider: Provider): ResolvedProvider {
- return new ResolvedProvider_(Key.get(provider.token), [resolveFactory(provider)], false);
+ return new ResolvedProvider_(Key.get(provider.token), [resolveFactory(provider)], provider.multi);
}
/**
* Resolve a list of Providers.
*/
export function resolveProviders(providers: Array): ResolvedProvider[] {
- var normalized = _createListOfProviders(_normalizeProviders(
- providers, new Map()));
- return normalized.map(b => {
- if (b instanceof _NormalizedProvider) {
- return new ResolvedProvider_(b.key, [b.resolvedFactory], false);
-
- } else {
- var arr = <_NormalizedProvider[]>b;
- return new ResolvedProvider_(arr[0].key, arr.map(_ => _.resolvedFactory), true);
- }
- });
+ var normalized = _normalizeProviders(providers, []);
+ var resolved = normalized.map(resolveProvider);
+ return MapWrapper.values(mergeResolvedProviders(resolved, new Map()));
}
/**
- * The algorithm works as follows:
- *
- * [Provider] -> [_NormalizedProvider|[_NormalizedProvider]] -> [ResolvedProvider]
- *
- * _NormalizedProvider is essentially a resolved provider before it was grouped by key.
+ * Merges a list of ResolvedProviders into a list where
+ * each key is contained exactly once and multi providers
+ * have been merged.
*/
-class _NormalizedProvider {
- constructor(public key: Key, public resolvedFactory: ResolvedFactory) {}
-}
-
-function _createListOfProviders(flattenedProviders: Map): any[] {
- return MapWrapper.values(flattenedProviders);
+export function mergeResolvedProviders(
+ providers: ResolvedProvider[],
+ normalizedProvidersMap: Map): Map {
+ for (var i = 0; i < providers.length; i++) {
+ var provider = providers[i];
+ var existing = normalizedProvidersMap.get(provider.key.id);
+ if (isPresent(existing)) {
+ if (provider.multiProvider !== existing.multiProvider) {
+ throw new MixingMultiProvidersWithRegularProvidersError(existing, provider);
+ }
+ if (provider.multiProvider) {
+ for (var j = 0; j < provider.resolvedFactories.length; j++) {
+ existing.resolvedFactories.push(provider.resolvedFactories[j]);
+ }
+ } else {
+ normalizedProvidersMap.set(provider.key.id, provider);
+ }
+ } else {
+ var resolvedProvider;
+ if (provider.multiProvider) {
+ resolvedProvider = new ResolvedProvider_(
+ provider.key, ListWrapper.clone(provider.resolvedFactories), provider.multiProvider);
+ } else {
+ resolvedProvider = provider;
+ }
+ normalizedProvidersMap.set(provider.key.id, resolvedProvider);
+ }
+ }
+ return normalizedProvidersMap;
}
function _normalizeProviders(providers: Array,
- res: Map):
- Map {
+ res: Provider[]): Provider[] {
providers.forEach(b => {
if (b instanceof Type) {
- _normalizeProvider(provide(b, {useClass: b}), res);
+ res.push(provide(b, {useClass: b}));
} else if (b instanceof Provider) {
- _normalizeProvider(b, res);
+ res.push(b);
} else if (b instanceof Array) {
_normalizeProviders(b, res);
@@ -597,36 +609,6 @@ function _normalizeProviders(providers: Array): void {
- var key = Key.get(b.token);
- var factory = resolveFactory(b);
- var normalized = new _NormalizedProvider(key, factory);
-
- if (b.multi) {
- var existingProvider = res.get(key.id);
-
- if (existingProvider instanceof Array) {
- existingProvider.push(normalized);
-
- } else if (isBlank(existingProvider)) {
- res.set(key.id, [normalized]);
-
- } else {
- throw new MixingMultiProvidersWithRegularProvidersError(existingProvider, b);
- }
-
- } else {
- var existingProvider = res.get(key.id);
-
- if (existingProvider instanceof Array) {
- throw new MixingMultiProvidersWithRegularProvidersError(existingProvider, b);
- }
-
- res.set(key.id, normalized);
- }
-}
-
function _constructDependencies(factoryFunction: Function, dependencies: any[]): Dependency[] {
if (isBlank(dependencies)) {
return _dependenciesFor(factoryFunction);
diff --git a/modules/angular2/src/core/linker.ts b/modules/angular2/src/core/linker.ts
index b43b69776f650..b04229c4a4794 100644
--- a/modules/angular2/src/core/linker.ts
+++ b/modules/angular2/src/core/linker.ts
@@ -17,6 +17,6 @@ export {QueryList} from './linker/query_list';
export {DynamicComponentLoader} from './linker/dynamic_component_loader';
export {ElementRef} from './linker/element_ref';
export {TemplateRef} from './linker/template_ref';
-export {ViewRef, HostViewRef, ProtoViewRef} from './linker/view_ref';
+export {EmbeddedViewRef, HostViewRef, ViewRef, HostViewFactoryRef} from './linker/view_ref';
export {ViewContainerRef} from './linker/view_container_ref';
export {ComponentRef} from './linker/dynamic_component_loader';
\ No newline at end of file
diff --git a/modules/angular2/src/core/linker/compiler.ts b/modules/angular2/src/core/linker/compiler.ts
index c4fdaea971f4b..9447952ffd631 100644
--- a/modules/angular2/src/core/linker/compiler.ts
+++ b/modules/angular2/src/core/linker/compiler.ts
@@ -1,12 +1,12 @@
-import {ProtoViewRef} from 'angular2/src/core/linker/view_ref';
-import {ProtoViewFactory} from 'angular2/src/core/linker/proto_view_factory';
+import {HostViewFactoryRef} from 'angular2/src/core/linker/view_ref';
import {Injectable} from 'angular2/src/core/di';
import {Type, isBlank, stringify} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
import {reflector} from 'angular2/src/core/reflection/reflection';
-import {CompiledHostTemplate} from 'angular2/src/core/linker/template_commands';
+import {HostViewFactory} from 'angular2/src/core/linker/view';
+import {HostViewFactoryRef_} from 'angular2/src/core/linker/view_ref';
/**
* Low-level service for compiling {@link Component}s into {@link ProtoViewRef ProtoViews}s, which
@@ -16,37 +16,25 @@ import {CompiledHostTemplate} from 'angular2/src/core/linker/template_commands';
* both compiles and instantiates a Component.
*/
export abstract class Compiler {
- abstract compileInHost(componentType: Type): Promise;
+ abstract compileInHost(componentType: Type): Promise;
abstract clearCache();
}
-function _isCompiledHostTemplate(type: any): boolean {
- return type instanceof CompiledHostTemplate;
+function isHostViewFactory(type: any): boolean {
+ return type instanceof HostViewFactory;
}
@Injectable()
export class Compiler_ extends Compiler {
- constructor(private _protoViewFactory: ProtoViewFactory) { super(); }
-
- compileInHost(componentType: Type): Promise {
+ compileInHost(componentType: Type): Promise {
var metadatas = reflector.annotations(componentType);
- var compiledHostTemplate = metadatas.find(_isCompiledHostTemplate);
+ var hostViewFactory = metadatas.find(isHostViewFactory);
- if (isBlank(compiledHostTemplate)) {
- throw new BaseException(
- `No precompiled template for component ${stringify(componentType)} found`);
+ if (isBlank(hostViewFactory)) {
+ throw new BaseException(`No precompiled component ${stringify(componentType)} found`);
}
- return PromiseWrapper.resolve(this._createProtoView(compiledHostTemplate));
- }
-
- private _createProtoView(compiledHostTemplate: CompiledHostTemplate): ProtoViewRef {
- return this._protoViewFactory.createHost(compiledHostTemplate).ref;
+ return PromiseWrapper.resolve(new HostViewFactoryRef_(hostViewFactory));
}
- clearCache() { this._protoViewFactory.clearCache(); }
-}
-
-export function internalCreateProtoView(compiler: Compiler,
- compiledHostTemplate: CompiledHostTemplate): ProtoViewRef {
- return (compiler)._createProtoView(compiledHostTemplate);
+ clearCache() {}
}
diff --git a/modules/angular2/src/core/linker/directive_resolver.ts b/modules/angular2/src/core/linker/directive_resolver.ts
index 1d19c4e9fe69e..63b34a46cc839 100644
--- a/modules/angular2/src/core/linker/directive_resolver.ts
+++ b/modules/angular2/src/core/linker/directive_resolver.ts
@@ -2,6 +2,7 @@ import {resolveForwardRef, Injectable} from 'angular2/src/core/di';
import {Type, isPresent, isBlank, stringify} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
+
import {
DirectiveMetadata,
ComponentMetadata,
@@ -38,7 +39,7 @@ export class DirectiveResolver {
var metadata = typeMetadata.find(_isDirectiveMetadata);
if (isPresent(metadata)) {
var propertyMetadata = reflector.propMetadata(type);
- return this._mergeWithPropertyMetadata(metadata, propertyMetadata);
+ return this._mergeWithPropertyMetadata(metadata, propertyMetadata, type);
}
}
@@ -46,7 +47,8 @@ export class DirectiveResolver {
}
private _mergeWithPropertyMetadata(dm: DirectiveMetadata,
- propertyMetadata: {[key: string]: any[]}): DirectiveMetadata {
+ propertyMetadata: {[key: string]: any[]},
+ directiveType: Type): DirectiveMetadata {
var inputs = [];
var outputs = [];
var host: {[key: string]: string} = {};
@@ -100,13 +102,27 @@ export class DirectiveResolver {
}
});
});
- return this._merge(dm, inputs, outputs, host, queries);
+ return this._merge(dm, inputs, outputs, host, queries, directiveType);
}
private _merge(dm: DirectiveMetadata, inputs: string[], outputs: string[],
- host: {[key: string]: string}, queries: {[key: string]: any}): DirectiveMetadata {
+ host: {[key: string]: string}, queries: {[key: string]: any},
+ directiveType: Type): DirectiveMetadata {
var mergedInputs = isPresent(dm.inputs) ? ListWrapper.concat(dm.inputs, inputs) : inputs;
- var mergedOutputs = isPresent(dm.outputs) ? ListWrapper.concat(dm.outputs, outputs) : outputs;
+
+ var mergedOutputs;
+ if (isPresent(dm.outputs)) {
+ dm.outputs.forEach((propName: string) => {
+ if (ListWrapper.contains(outputs, propName)) {
+ throw new BaseException(
+ `Output event '${propName}' defined multiple times in '${stringify(directiveType)}'`);
+ }
+ });
+ mergedOutputs = ListWrapper.concat(dm.outputs, outputs);
+ } else {
+ mergedOutputs = outputs;
+ }
+
var mergedHost = isPresent(dm.host) ? StringMapWrapper.merge(dm.host, host) : host;
var mergedQueries =
isPresent(dm.queries) ? StringMapWrapper.merge(dm.queries, queries) : queries;
@@ -138,3 +154,5 @@ export class DirectiveResolver {
}
}
}
+
+export var CODEGEN_DIRECTIVE_RESOLVER = new DirectiveResolver();
diff --git a/modules/angular2/src/core/linker/dynamic_component_loader.ts b/modules/angular2/src/core/linker/dynamic_component_loader.ts
index 76138359307a8..e885ab892fe21 100644
--- a/modules/angular2/src/core/linker/dynamic_component_loader.ts
+++ b/modules/angular2/src/core/linker/dynamic_component_loader.ts
@@ -3,8 +3,8 @@ import {Compiler} from './compiler';
import {isType, Type, stringify, isPresent} from 'angular2/src/facade/lang';
import {Promise} from 'angular2/src/facade/async';
import {AppViewManager} from 'angular2/src/core/linker/view_manager';
-import {ElementRef} from './element_ref';
-import {ViewRef, HostViewRef} from './view_ref';
+import {ElementRef, ElementRef_} from './element_ref';
+import {HostViewRef} from './view_ref';
/**
* Represents an instance of a Component created via {@link DynamicComponentLoader}.
@@ -42,7 +42,9 @@ export abstract class ComponentRef {
/**
* The {@link ViewRef} of the Host View of this Component instance.
*/
- get hostView(): HostViewRef { return this.location.parentView; }
+ get hostView(): HostViewRef {
+ return (this.location).internalElement.parentView.ref;
+ }
/**
* @internal
@@ -140,7 +142,7 @@ export abstract class DynamicComponentLoader {
* ```
*/
abstract loadAsRoot(type: Type, overrideSelector: string, injector: Injector,
- onDispose?: () => void): Promise;
+ onDispose?: () => void, projectableNodes?: any[][]): Promise;
/**
* Creates an instance of a Component and attaches it to a View Container located inside of the
@@ -190,7 +192,8 @@ export abstract class DynamicComponentLoader {
* ```
*/
abstract loadIntoLocation(type: Type, hostLocation: ElementRef, anchorName: string,
- providers?: ResolvedProvider[]): Promise;
+ providers?: ResolvedProvider[],
+ projectableNodes?: any[][]): Promise;
/**
* Creates an instance of a Component and attaches it to the View Container found at the
@@ -232,19 +235,19 @@ export abstract class DynamicComponentLoader {
* Child
* ```
*/
- abstract loadNextToLocation(type: Type, location: ElementRef,
- providers?: ResolvedProvider[]): Promise;
+ abstract loadNextToLocation(type: Type, location: ElementRef, providers?: ResolvedProvider[],
+ projectableNodes?: any[][]): Promise;
}
@Injectable()
export class DynamicComponentLoader_ extends DynamicComponentLoader {
constructor(private _compiler: Compiler, private _viewManager: AppViewManager) { super(); }
- loadAsRoot(type: Type, overrideSelector: string, injector: Injector,
- onDispose?: () => void): Promise {
+ loadAsRoot(type: Type, overrideSelector: string, injector: Injector, onDispose?: () => void,
+ projectableNodes?: any[][]): Promise {
return this._compiler.compileInHost(type).then(hostProtoViewRef => {
- var hostViewRef =
- this._viewManager.createRootHostView(hostProtoViewRef, overrideSelector, injector);
+ var hostViewRef = this._viewManager.createRootHostView(hostProtoViewRef, overrideSelector,
+ injector, projectableNodes);
var newLocation = this._viewManager.getHostElement(hostViewRef);
var component = this._viewManager.getComponent(newLocation);
@@ -259,24 +262,25 @@ export class DynamicComponentLoader_ extends DynamicComponentLoader {
}
loadIntoLocation(type: Type, hostLocation: ElementRef, anchorName: string,
- providers: ResolvedProvider[] = null): Promise {
+ providers: ResolvedProvider[] = null,
+ projectableNodes: any[][] = null): Promise {
return this.loadNextToLocation(
- type, this._viewManager.getNamedElementInComponentView(hostLocation, anchorName),
- providers);
+ type, this._viewManager.getNamedElementInComponentView(hostLocation, anchorName), providers,
+ projectableNodes);
}
- loadNextToLocation(type: Type, location: ElementRef,
- providers: ResolvedProvider[] = null): Promise {
+ loadNextToLocation(type: Type, location: ElementRef, providers: ResolvedProvider[] = null,
+ projectableNodes: any[][] = null): Promise {
return this._compiler.compileInHost(type).then(hostProtoViewRef => {
var viewContainer = this._viewManager.getViewContainer(location);
- var hostViewRef =
- viewContainer.createHostView(hostProtoViewRef, viewContainer.length, providers);
+ var hostViewRef = viewContainer.createHostView(hostProtoViewRef, viewContainer.length,
+ providers, projectableNodes);
var newLocation = this._viewManager.getHostElement(hostViewRef);
var component = this._viewManager.getComponent(newLocation);
var dispose = () => {
- var index = viewContainer.indexOf(hostViewRef);
- if (index !== -1) {
+ var index = viewContainer.indexOf(hostViewRef);
+ if (!hostViewRef.destroyed && index !== -1) {
viewContainer.remove(index);
}
};
diff --git a/modules/angular2/src/core/linker/element.ts b/modules/angular2/src/core/linker/element.ts
new file mode 100644
index 0000000000000..7911e35c60073
--- /dev/null
+++ b/modules/angular2/src/core/linker/element.ts
@@ -0,0 +1,867 @@
+import {
+ isPresent,
+ isBlank,
+ Type,
+ stringify,
+ CONST_EXPR,
+ StringWrapper
+} from 'angular2/src/facade/lang';
+import {BaseException} from 'angular2/src/facade/exceptions';
+import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
+import {
+ Injector,
+ Key,
+ Dependency,
+ provide,
+ Provider,
+ ResolvedProvider,
+ NoProviderError,
+ AbstractProviderError,
+ CyclicDependencyError,
+ resolveForwardRef,
+ Injectable
+} from 'angular2/src/core/di';
+import {mergeResolvedProviders} from 'angular2/src/core/di/provider';
+import {
+ UNDEFINED,
+ ProtoInjector,
+ Visibility,
+ InjectorInlineStrategy,
+ InjectorDynamicStrategy,
+ ProviderWithVisibility,
+ DependencyProvider
+} from 'angular2/src/core/di/injector';
+import {resolveProvider, ResolvedFactory, ResolvedProvider_} from 'angular2/src/core/di/provider';
+
+import {AttributeMetadata, QueryMetadata} from '../metadata/di';
+
+import {AppView} from './view';
+import {ViewType} from './view_type';
+import {ElementRef_} from './element_ref';
+
+import {ViewContainerRef} from './view_container_ref';
+import {ElementRef} from './element_ref';
+import {Renderer} from 'angular2/src/core/render/api';
+import {TemplateRef, TemplateRef_} from './template_ref';
+import {DirectiveMetadata, ComponentMetadata} from '../metadata/directives';
+import {
+ ChangeDetector,
+ ChangeDetectorRef
+} from 'angular2/src/core/change_detection/change_detection';
+import {QueryList} from './query_list';
+import {reflector} from 'angular2/src/core/reflection/reflection';
+import {SetterFn} from 'angular2/src/core/reflection/types';
+import {AfterViewChecked} from 'angular2/src/core/linker/interfaces';
+import {PipeProvider} from 'angular2/src/core/pipes/pipe_provider';
+
+import {ViewContainerRef_} from "./view_container_ref";
+import {ResolvedMetadataCache} from './resolved_metadata_cache';
+
+var _staticKeys;
+
+export class StaticKeys {
+ templateRefId: number;
+ viewContainerId: number;
+ changeDetectorRefId: number;
+ elementRefId: number;
+ rendererId: number;
+
+ constructor() {
+ this.templateRefId = Key.get(TemplateRef).id;
+ this.viewContainerId = Key.get(ViewContainerRef).id;
+ this.changeDetectorRefId = Key.get(ChangeDetectorRef).id;
+ this.elementRefId = Key.get(ElementRef).id;
+ this.rendererId = Key.get(Renderer).id;
+ }
+
+ static instance(): StaticKeys {
+ if (isBlank(_staticKeys)) _staticKeys = new StaticKeys();
+ return _staticKeys;
+ }
+}
+
+export class DirectiveDependency extends Dependency {
+ constructor(key: Key, optional: boolean, lowerBoundVisibility: Object,
+ upperBoundVisibility: Object, properties: any[], public attributeName: string,
+ public queryDecorator: QueryMetadata) {
+ super(key, optional, lowerBoundVisibility, upperBoundVisibility, properties);
+ this._verify();
+ }
+
+ /** @internal */
+ _verify(): void {
+ var count = 0;
+ if (isPresent(this.queryDecorator)) count++;
+ if (isPresent(this.attributeName)) count++;
+ if (count > 1)
+ throw new BaseException(
+ 'A directive injectable can contain only one of the following @Attribute or @Query.');
+ }
+
+ static createFrom(d: Dependency): DirectiveDependency {
+ return new DirectiveDependency(
+ d.key, d.optional, d.lowerBoundVisibility, d.upperBoundVisibility, d.properties,
+ DirectiveDependency._attributeName(d.properties), DirectiveDependency._query(d.properties));
+ }
+
+ /** @internal */
+ static _attributeName(properties: any[]): string {
+ var p = properties.find(p => p instanceof AttributeMetadata);
+ return isPresent(p) ? p.attributeName : null;
+ }
+
+ /** @internal */
+ static _query(properties: any[]): QueryMetadata {
+ return properties.find(p => p instanceof QueryMetadata);
+ }
+}
+
+export class DirectiveProvider extends ResolvedProvider_ {
+ constructor(key: Key, factory: Function, deps: Dependency[], public isComponent: boolean,
+ public providers: ResolvedProvider[], public viewProviders: ResolvedProvider[],
+ public queries: QueryMetadataWithSetter[]) {
+ super(key, [new ResolvedFactory(factory, deps)], false);
+ }
+
+ get displayName(): string { return this.key.displayName; }
+
+ static createFromType(type: Type, meta: DirectiveMetadata): DirectiveProvider {
+ var provider = new Provider(type, {useClass: type});
+ if (isBlank(meta)) {
+ meta = new DirectiveMetadata();
+ }
+ var rb = resolveProvider(provider);
+ var rf = rb.resolvedFactories[0];
+ var deps: DirectiveDependency[] = rf.dependencies.map(DirectiveDependency.createFrom);
+ var isComponent = meta instanceof ComponentMetadata;
+ var resolvedProviders = isPresent(meta.providers) ? Injector.resolve(meta.providers) : null;
+ var resolvedViewProviders = meta instanceof ComponentMetadata && isPresent(meta.viewProviders) ?
+ Injector.resolve(meta.viewProviders) :
+ null;
+ var queries = [];
+ if (isPresent(meta.queries)) {
+ StringMapWrapper.forEach(meta.queries, (meta, fieldName) => {
+ var setter = reflector.setter(fieldName);
+ queries.push(new QueryMetadataWithSetter(setter, meta));
+ });
+ }
+ // queries passed into the constructor.
+ // TODO: remove this after constructor queries are no longer supported
+ deps.forEach(d => {
+ if (isPresent(d.queryDecorator)) {
+ queries.push(new QueryMetadataWithSetter(null, d.queryDecorator));
+ }
+ });
+ return new DirectiveProvider(rb.key, rf.factory, deps, isComponent, resolvedProviders,
+ resolvedViewProviders, queries);
+ }
+}
+
+export class QueryMetadataWithSetter {
+ constructor(public setter: SetterFn, public metadata: QueryMetadata) {}
+}
+
+
+function setProvidersVisibility(providers: ResolvedProvider[], visibility: Visibility,
+ result: Map) {
+ for (var i = 0; i < providers.length; i++) {
+ result.set(providers[i].key.id, visibility);
+ }
+}
+
+export class AppProtoElement {
+ protoInjector: ProtoInjector;
+
+ static create(metadataCache: ResolvedMetadataCache, index: number,
+ attributes: {[key: string]: string}, directiveTypes: Type[],
+ directiveVariableBindings: {[key: string]: number}): AppProtoElement {
+ var componentDirProvider = null;
+ var mergedProvidersMap: Map = new Map();
+ var providerVisibilityMap: Map = new Map();
+ var providers = ListWrapper.createGrowableSize(directiveTypes.length);
+
+ var protoQueryRefs = [];
+ for (var i = 0; i < directiveTypes.length; i++) {
+ var dirProvider = metadataCache.getResolvedDirectiveMetadata(directiveTypes[i]);
+ providers[i] = new ProviderWithVisibility(
+ dirProvider, dirProvider.isComponent ? Visibility.PublicAndPrivate : Visibility.Public);
+
+ if (dirProvider.isComponent) {
+ componentDirProvider = dirProvider;
+ } else {
+ if (isPresent(dirProvider.providers)) {
+ mergeResolvedProviders(dirProvider.providers, mergedProvidersMap);
+ setProvidersVisibility(dirProvider.providers, Visibility.Public, providerVisibilityMap);
+ }
+ }
+ if (isPresent(dirProvider.viewProviders)) {
+ mergeResolvedProviders(dirProvider.viewProviders, mergedProvidersMap);
+ setProvidersVisibility(dirProvider.viewProviders, Visibility.Private,
+ providerVisibilityMap);
+ }
+ for (var queryIdx = 0; queryIdx < dirProvider.queries.length; queryIdx++) {
+ var q = dirProvider.queries[queryIdx];
+ protoQueryRefs.push(new ProtoQueryRef(i, q.setter, q.metadata));
+ }
+ }
+ if (isPresent(componentDirProvider) && isPresent(componentDirProvider.providers)) {
+ // directive providers need to be prioritized over component providers
+ mergeResolvedProviders(componentDirProvider.providers, mergedProvidersMap);
+ setProvidersVisibility(componentDirProvider.providers, Visibility.Public,
+ providerVisibilityMap);
+ }
+ mergedProvidersMap.forEach((provider, _) => {
+ providers.push(
+ new ProviderWithVisibility(provider, providerVisibilityMap.get(provider.key.id)));
+ });
+
+ return new AppProtoElement(isPresent(componentDirProvider), index, attributes, providers,
+ protoQueryRefs, directiveVariableBindings);
+ }
+
+ constructor(public firstProviderIsComponent: boolean, public index: number,
+ public attributes: {[key: string]: string}, pwvs: ProviderWithVisibility[],
+ public protoQueryRefs: ProtoQueryRef[],
+ public directiveVariableBindings: {[key: string]: number}) {
+ var length = pwvs.length;
+ if (length > 0) {
+ this.protoInjector = new ProtoInjector(pwvs);
+ } else {
+ this.protoInjector = null;
+ this.protoQueryRefs = [];
+ }
+ }
+
+ getProviderAtIndex(index: number): any { return this.protoInjector.getProviderAtIndex(index); }
+}
+
+class _Context {
+ constructor(public element: any, public componentElement: any, public injector: any) {}
+}
+
+export class InjectorWithHostBoundary {
+ constructor(public injector: Injector, public hostInjectorBoundary: boolean) {}
+}
+
+export class AppElement implements DependencyProvider, ElementRef, AfterViewChecked {
+ static getViewParentInjector(parentViewType: ViewType, containerAppElement: AppElement,
+ imperativelyCreatedProviders: ResolvedProvider[],
+ rootInjector: Injector): InjectorWithHostBoundary {
+ var parentInjector;
+ var hostInjectorBoundary;
+ switch (parentViewType) {
+ case ViewType.COMPONENT:
+ parentInjector = containerAppElement._injector;
+ hostInjectorBoundary = true;
+ break;
+ case ViewType.EMBEDDED:
+ parentInjector = isPresent(containerAppElement.proto.protoInjector) ?
+ containerAppElement._injector.parent :
+ containerAppElement._injector;
+ hostInjectorBoundary = containerAppElement._injector.hostBoundary;
+ break;
+ case ViewType.HOST:
+ if (isPresent(containerAppElement)) {
+ // host view is attached to a container
+ parentInjector = isPresent(containerAppElement.proto.protoInjector) ?
+ containerAppElement._injector.parent :
+ containerAppElement._injector;
+ if (isPresent(imperativelyCreatedProviders)) {
+ var imperativeProvidersWithVisibility = imperativelyCreatedProviders.map(
+ p => new ProviderWithVisibility(p, Visibility.Public));
+ // The imperative injector is similar to having an element between
+ // the dynamic-loaded component and its parent => no boundary between
+ // the component and imperativelyCreatedInjector.
+ parentInjector = new Injector(new ProtoInjector(imperativeProvidersWithVisibility),
+ parentInjector, true, null, null);
+ hostInjectorBoundary = false;
+ } else {
+ hostInjectorBoundary = containerAppElement._injector.hostBoundary;
+ }
+ } else {
+ // bootstrap
+ parentInjector = rootInjector;
+ hostInjectorBoundary = true;
+ }
+ break;
+ }
+ return new InjectorWithHostBoundary(parentInjector, hostInjectorBoundary);
+ }
+
+ public nestedViews: AppView[] = null;
+ public componentView: AppView = null;
+
+ private _queryStrategy: _QueryStrategy;
+ private _injector: Injector;
+ private _strategy: _ElementDirectiveStrategy;
+ public ref: ElementRef_;
+
+ constructor(public proto: AppProtoElement, public parentView: AppView, public parent: AppElement,
+ public nativeElement: any, public embeddedViewFactory: Function) {
+ this.ref = new ElementRef_(this);
+ var parentInjector = isPresent(parent) ? parent._injector : parentView.parentInjector;
+ if (isPresent(this.proto.protoInjector)) {
+ var isBoundary;
+ if (isPresent(parent) && isPresent(parent.proto.protoInjector)) {
+ isBoundary = false;
+ } else {
+ isBoundary = parentView.hostInjectorBoundary;
+ }
+ this._queryStrategy = this._buildQueryStrategy();
+ this._injector = new Injector(this.proto.protoInjector, parentInjector, isBoundary, this,
+ () => this._debugContext());
+
+ // we couple ourselves to the injector strategy to avoid polymorphic calls
+ var injectorStrategy = this._injector.internalStrategy;
+ this._strategy = injectorStrategy instanceof InjectorInlineStrategy ?
+ new ElementDirectiveInlineStrategy(injectorStrategy, this) :
+ new ElementDirectiveDynamicStrategy(injectorStrategy, this);
+ this._strategy.init();
+ } else {
+ this._queryStrategy = null;
+ this._injector = parentInjector;
+ this._strategy = null;
+ }
+ }
+
+ attachComponentView(componentView: AppView) { this.componentView = componentView; }
+
+ private _debugContext(): any {
+ var c = this.parentView.getDebugContext(this, null, null);
+ return isPresent(c) ? new _Context(c.element, c.componentElement, c.injector) : null;
+ }
+
+ hasVariableBinding(name: string): boolean {
+ var vb = this.proto.directiveVariableBindings;
+ return isPresent(vb) && StringMapWrapper.contains(vb, name);
+ }
+
+ getVariableBinding(name: string): any {
+ var index = this.proto.directiveVariableBindings[name];
+ return isPresent(index) ? this.getDirectiveAtIndex(index) : this.getElementRef();
+ }
+
+ get(token: any): any { return this._injector.get(token); }
+
+ hasDirective(type: Type): boolean { return isPresent(this._injector.getOptional(type)); }
+
+ getComponent(): any { return isPresent(this._strategy) ? this._strategy.getComponent() : null; }
+
+ getInjector(): Injector { return this._injector; }
+
+ getElementRef(): ElementRef { return this.ref; }
+
+ getViewContainerRef(): ViewContainerRef { return new ViewContainerRef_(this); }
+
+ getTemplateRef(): TemplateRef {
+ if (isPresent(this.embeddedViewFactory)) {
+ return new TemplateRef_(this.ref);
+ }
+ return null;
+ }
+
+ getDependency(injector: Injector, provider: ResolvedProvider, dep: Dependency): any {
+ if (provider instanceof DirectiveProvider) {
+ var dirDep = dep;
+
+ if (isPresent(dirDep.attributeName)) return this._buildAttribute(dirDep);
+
+ if (isPresent(dirDep.queryDecorator))
+ return this._queryStrategy.findQuery(dirDep.queryDecorator).list;
+
+ if (dirDep.key.id === StaticKeys.instance().changeDetectorRefId) {
+ // We provide the component's view change detector to components and
+ // the surrounding component's change detector to directives.
+ if (this.proto.firstProviderIsComponent) {
+ // Note: The component view is not yet created when
+ // this method is called!
+ return new _ComponentViewChangeDetectorRef(this);
+ } else {
+ return this.parentView.changeDetector.ref;
+ }
+ }
+
+ if (dirDep.key.id === StaticKeys.instance().elementRefId) {
+ return this.getElementRef();
+ }
+
+ if (dirDep.key.id === StaticKeys.instance().viewContainerId) {
+ return this.getViewContainerRef();
+ }
+
+ if (dirDep.key.id === StaticKeys.instance().templateRefId) {
+ var tr = this.getTemplateRef();
+ if (isBlank(tr) && !dirDep.optional) {
+ throw new NoProviderError(null, dirDep.key);
+ }
+ return tr;
+ }
+
+ if (dirDep.key.id === StaticKeys.instance().rendererId) {
+ return this.parentView.renderer;
+ }
+
+ } else if (provider instanceof PipeProvider) {
+ if (dep.key.id === StaticKeys.instance().changeDetectorRefId) {
+ // We provide the component's view change detector to components and
+ // the surrounding component's change detector to directives.
+ if (this.proto.firstProviderIsComponent) {
+ // Note: The component view is not yet created when
+ // this method is called!
+ return new _ComponentViewChangeDetectorRef(this);
+ } else {
+ return this.parentView.changeDetector;
+ }
+ }
+ }
+
+ return UNDEFINED;
+ }
+
+ private _buildAttribute(dep: DirectiveDependency): string {
+ var attributes = this.proto.attributes;
+ if (isPresent(attributes) && StringMapWrapper.contains(attributes, dep.attributeName)) {
+ return attributes[dep.attributeName];
+ } else {
+ return null;
+ }
+ }
+
+ addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
+ var templateRef = this.getTemplateRef();
+ if (query.selector === TemplateRef && isPresent(templateRef)) {
+ list.push(templateRef);
+ }
+ if (this._strategy != null) {
+ this._strategy.addDirectivesMatchingQuery(query, list);
+ }
+ }
+
+ private _buildQueryStrategy(): _QueryStrategy {
+ if (this.proto.protoQueryRefs.length === 0) {
+ return _emptyQueryStrategy;
+ } else if (this.proto.protoQueryRefs.length <=
+ InlineQueryStrategy.NUMBER_OF_SUPPORTED_QUERIES) {
+ return new InlineQueryStrategy(this);
+ } else {
+ return new DynamicQueryStrategy(this);
+ }
+ }
+
+
+ getDirectiveAtIndex(index: number): any { return this._injector.getAt(index); }
+
+ ngAfterViewChecked(): void {
+ if (isPresent(this._queryStrategy)) this._queryStrategy.updateViewQueries();
+ }
+
+ ngAfterContentChecked(): void {
+ if (isPresent(this._queryStrategy)) this._queryStrategy.updateContentQueries();
+ }
+
+ traverseAndSetQueriesAsDirty(): void {
+ var inj: AppElement = this;
+ while (isPresent(inj)) {
+ inj._setQueriesAsDirty();
+ inj = inj.parent;
+ }
+ }
+
+ private _setQueriesAsDirty(): void {
+ if (isPresent(this._queryStrategy)) {
+ this._queryStrategy.setContentQueriesAsDirty();
+ }
+ if (this.parentView.proto.type === ViewType.COMPONENT) {
+ this.parentView.containerAppElement._queryStrategy.setViewQueriesAsDirty();
+ }
+ }
+}
+
+interface _QueryStrategy {
+ setContentQueriesAsDirty(): void;
+ setViewQueriesAsDirty(): void;
+ updateContentQueries(): void;
+ updateViewQueries(): void;
+ findQuery(query: QueryMetadata): QueryRef;
+}
+
+class _EmptyQueryStrategy implements _QueryStrategy {
+ setContentQueriesAsDirty(): void {}
+ setViewQueriesAsDirty(): void {}
+ updateContentQueries(): void {}
+ updateViewQueries(): void {}
+ findQuery(query: QueryMetadata): QueryRef {
+ throw new BaseException(`Cannot find query for directive ${query}.`);
+ }
+}
+
+var _emptyQueryStrategy = new _EmptyQueryStrategy();
+
+class InlineQueryStrategy implements _QueryStrategy {
+ static NUMBER_OF_SUPPORTED_QUERIES = 3;
+
+ query0: QueryRef;
+ query1: QueryRef;
+ query2: QueryRef;
+
+ constructor(ei: AppElement) {
+ var protoRefs = ei.proto.protoQueryRefs;
+ if (protoRefs.length > 0) this.query0 = new QueryRef(protoRefs[0], ei);
+ if (protoRefs.length > 1) this.query1 = new QueryRef(protoRefs[1], ei);
+ if (protoRefs.length > 2) this.query2 = new QueryRef(protoRefs[2], ei);
+ }
+
+ setContentQueriesAsDirty(): void {
+ if (isPresent(this.query0) && !this.query0.isViewQuery) this.query0.dirty = true;
+ if (isPresent(this.query1) && !this.query1.isViewQuery) this.query1.dirty = true;
+ if (isPresent(this.query2) && !this.query2.isViewQuery) this.query2.dirty = true;
+ }
+
+ setViewQueriesAsDirty(): void {
+ if (isPresent(this.query0) && this.query0.isViewQuery) this.query0.dirty = true;
+ if (isPresent(this.query1) && this.query1.isViewQuery) this.query1.dirty = true;
+ if (isPresent(this.query2) && this.query2.isViewQuery) this.query2.dirty = true;
+ }
+
+ updateContentQueries() {
+ if (isPresent(this.query0) && !this.query0.isViewQuery) {
+ this.query0.update();
+ }
+ if (isPresent(this.query1) && !this.query1.isViewQuery) {
+ this.query1.update();
+ }
+ if (isPresent(this.query2) && !this.query2.isViewQuery) {
+ this.query2.update();
+ }
+ }
+
+ updateViewQueries() {
+ if (isPresent(this.query0) && this.query0.isViewQuery) {
+ this.query0.update();
+ }
+ if (isPresent(this.query1) && this.query1.isViewQuery) {
+ this.query1.update();
+ }
+ if (isPresent(this.query2) && this.query2.isViewQuery) {
+ this.query2.update();
+ }
+ }
+
+ findQuery(query: QueryMetadata): QueryRef {
+ if (isPresent(this.query0) && this.query0.protoQueryRef.query === query) {
+ return this.query0;
+ }
+ if (isPresent(this.query1) && this.query1.protoQueryRef.query === query) {
+ return this.query1;
+ }
+ if (isPresent(this.query2) && this.query2.protoQueryRef.query === query) {
+ return this.query2;
+ }
+ throw new BaseException(`Cannot find query for directive ${query}.`);
+ }
+}
+
+class DynamicQueryStrategy implements _QueryStrategy {
+ queries: QueryRef[];
+
+ constructor(ei: AppElement) {
+ this.queries = ei.proto.protoQueryRefs.map(p => new QueryRef(p, ei));
+ }
+
+ setContentQueriesAsDirty(): void {
+ for (var i = 0; i < this.queries.length; ++i) {
+ var q = this.queries[i];
+ if (!q.isViewQuery) q.dirty = true;
+ }
+ }
+
+ setViewQueriesAsDirty(): void {
+ for (var i = 0; i < this.queries.length; ++i) {
+ var q = this.queries[i];
+ if (q.isViewQuery) q.dirty = true;
+ }
+ }
+
+ updateContentQueries() {
+ for (var i = 0; i < this.queries.length; ++i) {
+ var q = this.queries[i];
+ if (!q.isViewQuery) {
+ q.update();
+ }
+ }
+ }
+
+ updateViewQueries() {
+ for (var i = 0; i < this.queries.length; ++i) {
+ var q = this.queries[i];
+ if (q.isViewQuery) {
+ q.update();
+ }
+ }
+ }
+
+ findQuery(query: QueryMetadata): QueryRef {
+ for (var i = 0; i < this.queries.length; ++i) {
+ var q = this.queries[i];
+ if (q.protoQueryRef.query === query) {
+ return q;
+ }
+ }
+ throw new BaseException(`Cannot find query for directive ${query}.`);
+ }
+}
+
+interface _ElementDirectiveStrategy {
+ getComponent(): any;
+ isComponentKey(key: Key): boolean;
+ addDirectivesMatchingQuery(q: QueryMetadata, res: any[]): void;
+ init(): void;
+}
+
+/**
+ * Strategy used by the `ElementInjector` when the number of providers is 10 or less.
+ * In such a case, inlining fields is beneficial for performances.
+ */
+class ElementDirectiveInlineStrategy implements _ElementDirectiveStrategy {
+ constructor(public injectorStrategy: InjectorInlineStrategy, public _ei: AppElement) {}
+
+ init(): void {
+ var i = this.injectorStrategy;
+ var p = i.protoStrategy;
+ i.resetConstructionCounter();
+
+ if (p.provider0 instanceof DirectiveProvider && isPresent(p.keyId0) && i.obj0 === UNDEFINED)
+ i.obj0 = i.instantiateProvider(p.provider0, p.visibility0);
+ if (p.provider1 instanceof DirectiveProvider && isPresent(p.keyId1) && i.obj1 === UNDEFINED)
+ i.obj1 = i.instantiateProvider(p.provider1, p.visibility1);
+ if (p.provider2 instanceof DirectiveProvider && isPresent(p.keyId2) && i.obj2 === UNDEFINED)
+ i.obj2 = i.instantiateProvider(p.provider2, p.visibility2);
+ if (p.provider3 instanceof DirectiveProvider && isPresent(p.keyId3) && i.obj3 === UNDEFINED)
+ i.obj3 = i.instantiateProvider(p.provider3, p.visibility3);
+ if (p.provider4 instanceof DirectiveProvider && isPresent(p.keyId4) && i.obj4 === UNDEFINED)
+ i.obj4 = i.instantiateProvider(p.provider4, p.visibility4);
+ if (p.provider5 instanceof DirectiveProvider && isPresent(p.keyId5) && i.obj5 === UNDEFINED)
+ i.obj5 = i.instantiateProvider(p.provider5, p.visibility5);
+ if (p.provider6 instanceof DirectiveProvider && isPresent(p.keyId6) && i.obj6 === UNDEFINED)
+ i.obj6 = i.instantiateProvider(p.provider6, p.visibility6);
+ if (p.provider7 instanceof DirectiveProvider && isPresent(p.keyId7) && i.obj7 === UNDEFINED)
+ i.obj7 = i.instantiateProvider(p.provider7, p.visibility7);
+ if (p.provider8 instanceof DirectiveProvider && isPresent(p.keyId8) && i.obj8 === UNDEFINED)
+ i.obj8 = i.instantiateProvider(p.provider8, p.visibility8);
+ if (p.provider9 instanceof DirectiveProvider && isPresent(p.keyId9) && i.obj9 === UNDEFINED)
+ i.obj9 = i.instantiateProvider(p.provider9, p.visibility9);
+ }
+
+ getComponent(): any { return this.injectorStrategy.obj0; }
+
+ isComponentKey(key: Key): boolean {
+ return this._ei.proto.firstProviderIsComponent && isPresent(key) &&
+ key.id === this.injectorStrategy.protoStrategy.keyId0;
+ }
+
+ addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
+ var i = this.injectorStrategy;
+ var p = i.protoStrategy;
+ if (isPresent(p.provider0) && p.provider0.key.token === query.selector) {
+ if (i.obj0 === UNDEFINED) i.obj0 = i.instantiateProvider(p.provider0, p.visibility0);
+ list.push(i.obj0);
+ }
+ if (isPresent(p.provider1) && p.provider1.key.token === query.selector) {
+ if (i.obj1 === UNDEFINED) i.obj1 = i.instantiateProvider(p.provider1, p.visibility1);
+ list.push(i.obj1);
+ }
+ if (isPresent(p.provider2) && p.provider2.key.token === query.selector) {
+ if (i.obj2 === UNDEFINED) i.obj2 = i.instantiateProvider(p.provider2, p.visibility2);
+ list.push(i.obj2);
+ }
+ if (isPresent(p.provider3) && p.provider3.key.token === query.selector) {
+ if (i.obj3 === UNDEFINED) i.obj3 = i.instantiateProvider(p.provider3, p.visibility3);
+ list.push(i.obj3);
+ }
+ if (isPresent(p.provider4) && p.provider4.key.token === query.selector) {
+ if (i.obj4 === UNDEFINED) i.obj4 = i.instantiateProvider(p.provider4, p.visibility4);
+ list.push(i.obj4);
+ }
+ if (isPresent(p.provider5) && p.provider5.key.token === query.selector) {
+ if (i.obj5 === UNDEFINED) i.obj5 = i.instantiateProvider(p.provider5, p.visibility5);
+ list.push(i.obj5);
+ }
+ if (isPresent(p.provider6) && p.provider6.key.token === query.selector) {
+ if (i.obj6 === UNDEFINED) i.obj6 = i.instantiateProvider(p.provider6, p.visibility6);
+ list.push(i.obj6);
+ }
+ if (isPresent(p.provider7) && p.provider7.key.token === query.selector) {
+ if (i.obj7 === UNDEFINED) i.obj7 = i.instantiateProvider(p.provider7, p.visibility7);
+ list.push(i.obj7);
+ }
+ if (isPresent(p.provider8) && p.provider8.key.token === query.selector) {
+ if (i.obj8 === UNDEFINED) i.obj8 = i.instantiateProvider(p.provider8, p.visibility8);
+ list.push(i.obj8);
+ }
+ if (isPresent(p.provider9) && p.provider9.key.token === query.selector) {
+ if (i.obj9 === UNDEFINED) i.obj9 = i.instantiateProvider(p.provider9, p.visibility9);
+ list.push(i.obj9);
+ }
+ }
+}
+
+/**
+ * Strategy used by the `ElementInjector` when the number of bindings is 11 or more.
+ * In such a case, there are too many fields to inline (see ElementInjectorInlineStrategy).
+ */
+class ElementDirectiveDynamicStrategy implements _ElementDirectiveStrategy {
+ constructor(public injectorStrategy: InjectorDynamicStrategy, public _ei: AppElement) {}
+
+ init(): void {
+ var inj = this.injectorStrategy;
+ var p = inj.protoStrategy;
+ inj.resetConstructionCounter();
+
+ for (var i = 0; i < p.keyIds.length; i++) {
+ if (p.providers[i] instanceof DirectiveProvider && isPresent(p.keyIds[i]) &&
+ inj.objs[i] === UNDEFINED) {
+ inj.objs[i] = inj.instantiateProvider(p.providers[i], p.visibilities[i]);
+ }
+ }
+ }
+
+ getComponent(): any { return this.injectorStrategy.objs[0]; }
+
+ isComponentKey(key: Key): boolean {
+ var p = this.injectorStrategy.protoStrategy;
+ return this._ei.proto.firstProviderIsComponent && isPresent(key) && key.id === p.keyIds[0];
+ }
+
+ addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
+ var ist = this.injectorStrategy;
+ var p = ist.protoStrategy;
+
+ for (var i = 0; i < p.providers.length; i++) {
+ if (p.providers[i].key.token === query.selector) {
+ if (ist.objs[i] === UNDEFINED) {
+ ist.objs[i] = ist.instantiateProvider(p.providers[i], p.visibilities[i]);
+ }
+ list.push(ist.objs[i]);
+ }
+ }
+ }
+}
+
+export class ProtoQueryRef {
+ constructor(public dirIndex: number, public setter: SetterFn, public query: QueryMetadata) {}
+
+ get usesPropertySyntax(): boolean { return isPresent(this.setter); }
+}
+
+export class QueryRef {
+ public list: QueryList;
+ public dirty: boolean;
+
+ constructor(public protoQueryRef: ProtoQueryRef, private originator: AppElement) {
+ this.list = new QueryList();
+ this.dirty = true;
+ }
+
+ get isViewQuery(): boolean { return this.protoQueryRef.query.isViewQuery; }
+
+ update(): void {
+ if (!this.dirty) return;
+ this._update();
+ this.dirty = false;
+
+ // TODO delete the check once only field queries are supported
+ if (this.protoQueryRef.usesPropertySyntax) {
+ var dir = this.originator.getDirectiveAtIndex(this.protoQueryRef.dirIndex);
+ if (this.protoQueryRef.query.first) {
+ this.protoQueryRef.setter(dir, this.list.length > 0 ? this.list.first : null);
+ } else {
+ this.protoQueryRef.setter(dir, this.list);
+ }
+ }
+
+ this.list.notifyOnChanges();
+ }
+
+ private _update(): void {
+ var aggregator = [];
+ if (this.protoQueryRef.query.isViewQuery) {
+ // intentionally skipping originator for view queries.
+ var nestedView = this.originator.componentView;
+ if (isPresent(nestedView)) this._visitView(nestedView, aggregator);
+ } else {
+ this._visit(this.originator, aggregator);
+ }
+ this.list.reset(aggregator);
+ };
+
+ private _visit(inj: AppElement, aggregator: any[]): void {
+ var view = inj.parentView;
+ var startIdx = inj.proto.index;
+ for (var i = startIdx; i < view.appElements.length; i++) {
+ var curInj = view.appElements[i];
+ // The first injector after inj, that is outside the subtree rooted at
+ // inj has to have a null parent or a parent that is an ancestor of inj.
+ if (i > startIdx && (isBlank(curInj.parent) || curInj.parent.proto.index < startIdx)) {
+ break;
+ }
+
+ if (!this.protoQueryRef.query.descendants &&
+ !(curInj.parent == this.originator || curInj == this.originator))
+ continue;
+
+ // We visit the view container(VC) views right after the injector that contains
+ // the VC. Theoretically, that might not be the right order if there are
+ // child injectors of said injector. Not clear whether if such case can
+ // even be constructed with the current apis.
+ this._visitInjector(curInj, aggregator);
+ this._visitViewContainerViews(curInj.nestedViews, aggregator);
+ }
+ }
+
+ private _visitInjector(inj: AppElement, aggregator: any[]) {
+ if (this.protoQueryRef.query.isVarBindingQuery) {
+ this._aggregateVariableBinding(inj, aggregator);
+ } else {
+ this._aggregateDirective(inj, aggregator);
+ }
+ }
+
+ private _visitViewContainerViews(views: AppView[], aggregator: any[]) {
+ if (isPresent(views)) {
+ for (var j = 0; j < views.length; j++) {
+ this._visitView(views[j], aggregator);
+ }
+ }
+ }
+
+ private _visitView(view: AppView, aggregator: any[]) {
+ for (var i = 0; i < view.appElements.length; i++) {
+ var inj = view.appElements[i];
+ this._visitInjector(inj, aggregator);
+ this._visitViewContainerViews(inj.nestedViews, aggregator);
+ }
+ }
+
+ private _aggregateVariableBinding(inj: AppElement, aggregator: any[]): void {
+ var vb = this.protoQueryRef.query.varBindings;
+ for (var i = 0; i < vb.length; ++i) {
+ if (inj.hasVariableBinding(vb[i])) {
+ aggregator.push(inj.getVariableBinding(vb[i]));
+ }
+ }
+ }
+
+ private _aggregateDirective(inj: AppElement, aggregator: any[]): void {
+ inj.addDirectivesMatchingQuery(this.protoQueryRef.query, aggregator);
+ }
+}
+
+class _ComponentViewChangeDetectorRef extends ChangeDetectorRef {
+ constructor(private _appElement: AppElement) { super(); }
+
+ markForCheck(): void { this._appElement.componentView.changeDetector.ref.markForCheck(); }
+ detach(): void { this._appElement.componentView.changeDetector.ref.detach(); }
+ detectChanges(): void { this._appElement.componentView.changeDetector.ref.detectChanges(); }
+ checkNoChanges(): void { this._appElement.componentView.changeDetector.ref.checkNoChanges(); }
+ reattach(): void { this._appElement.componentView.changeDetector.ref.reattach(); }
+}
diff --git a/modules/angular2/src/core/linker/element_binder.ts b/modules/angular2/src/core/linker/element_binder.ts
deleted file mode 100644
index 00da679b672a9..0000000000000
--- a/modules/angular2/src/core/linker/element_binder.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import {isBlank} from 'angular2/src/facade/lang';
-import {BaseException} from 'angular2/src/facade/exceptions';
-import * as eiModule from './element_injector';
-import {DirectiveProvider} from './element_injector';
-import * as viewModule from './view';
-
-export class ElementBinder {
- constructor(public index: number, public parent: ElementBinder, public distanceToParent: number,
- public protoElementInjector: eiModule.ProtoElementInjector,
- public componentDirective: DirectiveProvider,
- public nestedProtoView: viewModule.AppProtoView) {
- if (isBlank(index)) {
- throw new BaseException('null index not allowed.');
- }
- }
-}
diff --git a/modules/angular2/src/core/linker/element_injector.ts b/modules/angular2/src/core/linker/element_injector.ts
deleted file mode 100644
index cbfa77717413e..0000000000000
--- a/modules/angular2/src/core/linker/element_injector.ts
+++ /dev/null
@@ -1,1086 +0,0 @@
-import {
- isPresent,
- isBlank,
- Type,
- stringify,
- CONST_EXPR,
- StringWrapper
-} from 'angular2/src/facade/lang';
-import {BaseException} from 'angular2/src/facade/exceptions';
-import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
-import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
-import {
- Injector,
- Key,
- Dependency,
- provide,
- Provider,
- ResolvedProvider,
- NoProviderError,
- AbstractProviderError,
- CyclicDependencyError,
- resolveForwardRef
-} from 'angular2/src/core/di';
-import {
- UNDEFINED,
- ProtoInjector,
- Visibility,
- InjectorInlineStrategy,
- InjectorDynamicStrategy,
- ProviderWithVisibility,
- DependencyProvider
-} from 'angular2/src/core/di/injector';
-import {resolveProvider, ResolvedFactory, ResolvedProvider_} from 'angular2/src/core/di/provider';
-
-import {AttributeMetadata, QueryMetadata} from '../metadata/di';
-
-import {AppViewContainer, AppView} from './view';
-/* circular */ import * as avmModule from './view_manager';
-import {ViewContainerRef} from './view_container_ref';
-import {ElementRef} from './element_ref';
-import {TemplateRef} from './template_ref';
-import {DirectiveMetadata, ComponentMetadata} from '../metadata/directives';
-import {hasLifecycleHook} from './directive_lifecycle_reflector';
-import {
- ChangeDetector,
- ChangeDetectorRef
-} from 'angular2/src/core/change_detection/change_detection';
-import {QueryList} from './query_list';
-import {reflector} from 'angular2/src/core/reflection/reflection';
-import {SetterFn} from 'angular2/src/core/reflection/types';
-import {EventConfig} from 'angular2/src/core/linker/event_config';
-import {AfterViewChecked} from 'angular2/src/core/linker/interfaces';
-import {PipeProvider} from 'angular2/src/core/pipes/pipe_provider';
-
-import {LifecycleHooks} from './interfaces';
-import {ViewContainerRef_} from "./view_container_ref";
-
-var _staticKeys;
-
-export class StaticKeys {
- viewManagerId: number;
- templateRefId: number;
- viewContainerId: number;
- changeDetectorRefId: number;
- elementRefId: number;
-
- constructor() {
- this.viewManagerId = Key.get(avmModule.AppViewManager).id;
- this.templateRefId = Key.get(TemplateRef).id;
- this.viewContainerId = Key.get(ViewContainerRef).id;
- this.changeDetectorRefId = Key.get(ChangeDetectorRef).id;
- this.elementRefId = Key.get(ElementRef).id;
- }
-
- static instance(): StaticKeys {
- if (isBlank(_staticKeys)) _staticKeys = new StaticKeys();
- return _staticKeys;
- }
-}
-
-export class TreeNode> {
- /** @internal */
- _parent: T;
- constructor(parent: T) {
- if (isPresent(parent)) {
- parent.addChild(this);
- } else {
- this._parent = null;
- }
- }
-
- addChild(child: T): void { child._parent = this; }
-
- remove(): void { this._parent = null; }
-
- get parent() { return this._parent; }
-}
-
-export class DirectiveDependency extends Dependency {
- constructor(key: Key, optional: boolean, lowerBoundVisibility: Object,
- upperBoundVisibility: Object, properties: any[], public attributeName: string,
- public queryDecorator: QueryMetadata) {
- super(key, optional, lowerBoundVisibility, upperBoundVisibility, properties);
- this._verify();
- }
-
- /** @internal */
- _verify(): void {
- var count = 0;
- if (isPresent(this.queryDecorator)) count++;
- if (isPresent(this.attributeName)) count++;
- if (count > 1)
- throw new BaseException(
- 'A directive injectable can contain only one of the following @Attribute or @Query.');
- }
-
- static createFrom(d: Dependency): Dependency {
- return new DirectiveDependency(
- d.key, d.optional, d.lowerBoundVisibility, d.upperBoundVisibility, d.properties,
- DirectiveDependency._attributeName(d.properties), DirectiveDependency._query(d.properties));
- }
-
- /** @internal */
- static _attributeName(properties: any[]): string {
- var p = properties.find(p => p instanceof AttributeMetadata);
- return isPresent(p) ? p.attributeName : null;
- }
-
- /** @internal */
- static _query(properties: any[]): QueryMetadata {
- return properties.find(p => p instanceof QueryMetadata);
- }
-}
-
-export class DirectiveProvider extends ResolvedProvider_ {
- public callOnDestroy: boolean;
-
- constructor(key: Key, factory: Function, deps: Dependency[], public metadata: DirectiveMetadata,
- public providers: Array,
- public viewProviders: Array) {
- super(key, [new ResolvedFactory(factory, deps)], false);
- this.callOnDestroy = hasLifecycleHook(LifecycleHooks.OnDestroy, key.token);
- }
-
- get displayName(): string { return this.key.displayName; }
-
- get queries(): QueryMetadataWithSetter[] {
- if (isBlank(this.metadata.queries)) return [];
-
- var res = [];
- StringMapWrapper.forEach(this.metadata.queries, (meta, fieldName) => {
- var setter = reflector.setter(fieldName);
- res.push(new QueryMetadataWithSetter(setter, meta));
- });
- return res;
- }
-
- get eventEmitters(): string[] {
- return isPresent(this.metadata) && isPresent(this.metadata.outputs) ? this.metadata.outputs :
- [];
- }
-
- static createFromProvider(provider: Provider, meta: DirectiveMetadata): DirectiveProvider {
- if (isBlank(meta)) {
- meta = new DirectiveMetadata();
- }
-
- var rb = resolveProvider(provider);
- var rf = rb.resolvedFactories[0];
- var deps = rf.dependencies.map(DirectiveDependency.createFrom);
-
- var providers = isPresent(meta.providers) ? meta.providers : [];
- var viewBindigs = meta instanceof ComponentMetadata && isPresent(meta.viewProviders) ?
- meta.viewProviders :
- [];
- return new DirectiveProvider(rb.key, rf.factory, deps, meta, providers, viewBindigs);
- }
-
- static createFromType(type: Type, annotation: DirectiveMetadata): DirectiveProvider {
- var provider = new Provider(type, {useClass: type});
- return DirectiveProvider.createFromProvider(provider, annotation);
- }
-}
-
-// TODO(rado): benchmark and consider rolling in as ElementInjector fields.
-export class PreBuiltObjects {
- nestedView: AppView = null;
- constructor(public viewManager: avmModule.AppViewManager, public view: AppView,
- public elementRef: ElementRef, public templateRef: TemplateRef) {}
-}
-
-export class QueryMetadataWithSetter {
- constructor(public setter: SetterFn, public metadata: QueryMetadata) {}
-}
-
-export class EventEmitterAccessor {
- constructor(public eventName: string, public getter: Function) {}
-
- subscribe(view: AppView, boundElementIndex: number, directive: Object): Object {
- var eventEmitter = this.getter(directive);
- return ObservableWrapper.subscribe(
- eventEmitter,
- eventObj => view.triggerEventHandlers(this.eventName, eventObj, boundElementIndex));
- }
-}
-
-function _createEventEmitterAccessors(bwv: ProviderWithVisibility): EventEmitterAccessor[] {
- var provider = bwv.provider;
- if (!(provider instanceof DirectiveProvider)) return [];
- var db = provider;
- return db.eventEmitters.map(eventConfig => {
- var parsedEvent = EventConfig.parse(eventConfig);
- return new EventEmitterAccessor(parsedEvent.eventName, reflector.getter(parsedEvent.fieldName));
- });
-}
-
-function _createProtoQueryRefs(providers: ProviderWithVisibility[]): ProtoQueryRef[] {
- var res = [];
- ListWrapper.forEachWithIndex(providers, (b, i) => {
- if (b.provider instanceof DirectiveProvider) {
- var directiveProvider = b.provider;
- // field queries
- var queries: QueryMetadataWithSetter[] = directiveProvider.queries;
- queries.forEach(q => res.push(new ProtoQueryRef(i, q.setter, q.metadata)));
-
- // queries passed into the constructor.
- // TODO: remove this after constructor queries are no longer supported
- var deps: DirectiveDependency[] =
- directiveProvider.resolvedFactory.dependencies;
- deps.forEach(d => {
- if (isPresent(d.queryDecorator)) res.push(new ProtoQueryRef(i, null, d.queryDecorator));
- });
- }
- });
- return res;
-}
-
-export class ProtoElementInjector {
- view: AppView;
- attributes: Map;
- eventEmitterAccessors: EventEmitterAccessor[][];
- protoQueryRefs: ProtoQueryRef[];
- protoInjector: ProtoInjector;
-
- static create(parent: ProtoElementInjector, index: number, providers: DirectiveProvider[],
- firstProviderIsComponent: boolean, distanceToParent: number,
- directiveVariableBindings: Map): ProtoElementInjector {
- var bd = [];
-
- ProtoElementInjector._createDirectiveProviderWithVisibility(providers, bd,
- firstProviderIsComponent);
- if (firstProviderIsComponent) {
- ProtoElementInjector._createViewProvidersWithVisibility(providers, bd);
- }
-
- ProtoElementInjector._createProvidersWithVisibility(providers, bd);
- return new ProtoElementInjector(parent, index, bd, distanceToParent, firstProviderIsComponent,
- directiveVariableBindings);
- }
-
- private static _createDirectiveProviderWithVisibility(dirProviders: DirectiveProvider[],
- bd: ProviderWithVisibility[],
- firstProviderIsComponent: boolean) {
- dirProviders.forEach(dirProvider => {
- bd.push(ProtoElementInjector._createProviderWithVisibility(
- firstProviderIsComponent, dirProvider, dirProviders, dirProvider));
- });
- }
-
- private static _createProvidersWithVisibility(dirProviders: DirectiveProvider[],
- bd: ProviderWithVisibility[]) {
- var providersFromAllDirectives = [];
- dirProviders.forEach(dirProvider => {
- providersFromAllDirectives =
- ListWrapper.concat(providersFromAllDirectives, dirProvider.providers);
- });
-
- var resolved = Injector.resolve(providersFromAllDirectives);
- resolved.forEach(b => bd.push(new ProviderWithVisibility(b, Visibility.Public)));
- }
-
- private static _createProviderWithVisibility(firstProviderIsComponent: boolean,
- dirProvider: DirectiveProvider,
- dirProviders: DirectiveProvider[],
- provider: ResolvedProvider) {
- var isComponent = firstProviderIsComponent && dirProviders[0] === dirProvider;
- return new ProviderWithVisibility(
- provider, isComponent ? Visibility.PublicAndPrivate : Visibility.Public);
- }
-
- private static _createViewProvidersWithVisibility(dirProviders: DirectiveProvider[],
- bd: ProviderWithVisibility[]) {
- var resolvedViewProviders = Injector.resolve(dirProviders[0].viewProviders);
- resolvedViewProviders.forEach(b => bd.push(new ProviderWithVisibility(b, Visibility.Private)));
- }
-
- /** @internal */
- public _firstProviderIsComponent: boolean;
-
-
- constructor(public parent: ProtoElementInjector, public index: number,
- bwv: ProviderWithVisibility[], public distanceToParent: number,
- _firstProviderIsComponent: boolean,
- public directiveVariableBindings: Map) {
- this._firstProviderIsComponent = _firstProviderIsComponent;
- var length = bwv.length;
- this.protoInjector = new ProtoInjector(bwv);
- this.eventEmitterAccessors = ListWrapper.createFixedSize(length);
- for (var i = 0; i < length; ++i) {
- this.eventEmitterAccessors[i] = _createEventEmitterAccessors(bwv[i]);
- }
- this.protoQueryRefs = _createProtoQueryRefs(bwv);
- }
-
- instantiate(parent: ElementInjector): ElementInjector {
- return new ElementInjector(this, parent);
- }
-
- directParent(): ProtoElementInjector { return this.distanceToParent < 2 ? this.parent : null; }
-
- get hasBindings(): boolean { return this.eventEmitterAccessors.length > 0; }
-
- getProviderAtIndex(index: number): any { return this.protoInjector.getProviderAtIndex(index); }
-}
-
-class _Context {
- constructor(public element: any, public componentElement: any, public injector: any) {}
-}
-
-export class ElementInjector extends TreeNode implements DependencyProvider,
- AfterViewChecked {
- private _host: ElementInjector;
- private _preBuiltObjects: PreBuiltObjects = null;
- private _queryStrategy: _QueryStrategy;
-
- hydrated: boolean;
-
- private _injector: Injector;
- private _strategy: _ElementInjectorStrategy;
- /** @internal */
- public _proto: ProtoElementInjector;
-
- constructor(_proto: ProtoElementInjector, parent: ElementInjector) {
- super(parent);
- this._proto = _proto;
- this._injector =
- new Injector(this._proto.protoInjector, null, this, () => this._debugContext());
-
- // we couple ourselves to the injector strategy to avoid polymoprhic calls
- var injectorStrategy = this._injector.internalStrategy;
- this._strategy = injectorStrategy instanceof InjectorInlineStrategy ?
- new ElementInjectorInlineStrategy(injectorStrategy, this) :
- new ElementInjectorDynamicStrategy(injectorStrategy, this);
-
- this.hydrated = false;
-
- this._queryStrategy = this._buildQueryStrategy();
- }
-
- dehydrate(): void {
- this.hydrated = false;
- this._host = null;
- this._preBuiltObjects = null;
- this._strategy.callOnDestroy();
- this._strategy.dehydrate();
- this._queryStrategy.dehydrate();
- }
-
- hydrate(imperativelyCreatedInjector: Injector, host: ElementInjector,
- preBuiltObjects: PreBuiltObjects): void {
- this._host = host;
- this._preBuiltObjects = preBuiltObjects;
-
- this._reattachInjectors(imperativelyCreatedInjector);
- this._queryStrategy.hydrate();
- this._strategy.hydrate();
-
- this.hydrated = true;
- }
-
- private _debugContext(): any {
- var p = this._preBuiltObjects;
- var index = p.elementRef.boundElementIndex - p.view.elementOffset;
- var c = this._preBuiltObjects.view.getDebugContext(index, null);
- return isPresent(c) ? new _Context(c.element, c.componentElement, c.injector) : null;
- }
-
- private _reattachInjectors(imperativelyCreatedInjector: Injector): void {
- // Dynamically-loaded component in the template. Not a root ElementInjector.
- if (isPresent(this._parent)) {
- if (isPresent(imperativelyCreatedInjector)) {
- // The imperative injector is similar to having an element between
- // the dynamic-loaded component and its parent => no boundaries.
- this._reattachInjector(this._injector, imperativelyCreatedInjector, false);
- this._reattachInjector(imperativelyCreatedInjector, this._parent._injector, false);
- } else {
- this._reattachInjector(this._injector, this._parent._injector, false);
- }
-
- // Dynamically-loaded component in the template. A root ElementInjector.
- } else if (isPresent(this._host)) {
- // The imperative injector is similar to having an element between
- // the dynamic-loaded component and its parent => no boundary between
- // the component and imperativelyCreatedInjector.
- // But since it is a root ElementInjector, we need to create a boundary
- // between imperativelyCreatedInjector and _host.
- if (isPresent(imperativelyCreatedInjector)) {
- this._reattachInjector(this._injector, imperativelyCreatedInjector, false);
- this._reattachInjector(imperativelyCreatedInjector, this._host._injector, true);
- } else {
- this._reattachInjector(this._injector, this._host._injector, true);
- }
-
- // Bootstrap
- } else {
- if (isPresent(imperativelyCreatedInjector)) {
- this._reattachInjector(this._injector, imperativelyCreatedInjector, true);
- }
- }
- }
-
- private _reattachInjector(injector: Injector, parentInjector: Injector, isBoundary: boolean) {
- injector.internalStrategy.attach(parentInjector, isBoundary);
- }
-
- hasVariableBinding(name: string): boolean {
- var vb = this._proto.directiveVariableBindings;
- return isPresent(vb) && vb.has(name);
- }
-
- getVariableBinding(name: string): any {
- var index = this._proto.directiveVariableBindings.get(name);
- return isPresent(index) ? this.getDirectiveAtIndex(index) : this.getElementRef();
- }
-
- get(token: any): any { return this._injector.get(token); }
-
- hasDirective(type: Type): boolean { return isPresent(this._injector.getOptional(type)); }
-
- getEventEmitterAccessors(): EventEmitterAccessor[][] { return this._proto.eventEmitterAccessors; }
-
- getDirectiveVariableBindings(): Map {
- return this._proto.directiveVariableBindings;
- }
-
- getComponent(): any { return this._strategy.getComponent(); }
-
- getInjector(): Injector { return this._injector; }
-
- getElementRef(): ElementRef { return this._preBuiltObjects.elementRef; }
-
- getViewContainerRef(): ViewContainerRef {
- return new ViewContainerRef_(this._preBuiltObjects.viewManager, this.getElementRef());
- }
-
- getNestedView(): AppView { return this._preBuiltObjects.nestedView; }
-
- getView(): AppView { return this._preBuiltObjects.view; }
-
- directParent(): ElementInjector { return this._proto.distanceToParent < 2 ? this.parent : null; }
-
- isComponentKey(key: Key): boolean { return this._strategy.isComponentKey(key); }
-
- getDependency(injector: Injector, provider: ResolvedProvider, dep: Dependency): any {
- var key: Key = dep.key;
-
- if (provider instanceof DirectiveProvider) {
- var dirDep = dep;
- var dirProvider = provider;
- var staticKeys = StaticKeys.instance();
-
-
- if (key.id === staticKeys.viewManagerId) return this._preBuiltObjects.viewManager;
-
- if (isPresent(dirDep.attributeName)) return this._buildAttribute(dirDep);
-
- if (isPresent(dirDep.queryDecorator))
- return this._queryStrategy.findQuery(dirDep.queryDecorator).list;
-
- if (dirDep.key.id === StaticKeys.instance().changeDetectorRefId) {
- // We provide the component's view change detector to components and
- // the surrounding component's change detector to directives.
- if (dirProvider.metadata instanceof ComponentMetadata) {
- var componentView = this._preBuiltObjects.view.getNestedView(
- this._preBuiltObjects.elementRef.boundElementIndex);
- return componentView.changeDetector.ref;
- } else {
- return this._preBuiltObjects.view.changeDetector.ref;
- }
- }
-
- if (dirDep.key.id === StaticKeys.instance().elementRefId) {
- return this.getElementRef();
- }
-
- if (dirDep.key.id === StaticKeys.instance().viewContainerId) {
- return this.getViewContainerRef();
- }
-
- if (dirDep.key.id === StaticKeys.instance().templateRefId) {
- if (isBlank(this._preBuiltObjects.templateRef)) {
- if (dirDep.optional) {
- return null;
- }
-
- throw new NoProviderError(null, dirDep.key);
- }
- return this._preBuiltObjects.templateRef;
- }
-
- } else if (provider instanceof PipeProvider) {
- if (dep.key.id === StaticKeys.instance().changeDetectorRefId) {
- var componentView = this._preBuiltObjects.view.getNestedView(
- this._preBuiltObjects.elementRef.boundElementIndex);
- return componentView.changeDetector.ref;
- }
- }
-
- return UNDEFINED;
- }
-
- private _buildAttribute(dep: DirectiveDependency): string {
- var attributes = this._proto.attributes;
- if (isPresent(attributes) && attributes.has(dep.attributeName)) {
- return attributes.get(dep.attributeName);
- } else {
- return null;
- }
- }
-
- addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
- var templateRef = isBlank(this._preBuiltObjects) ? null : this._preBuiltObjects.templateRef;
- if (query.selector === TemplateRef && isPresent(templateRef)) {
- list.push(templateRef);
- }
- this._strategy.addDirectivesMatchingQuery(query, list);
- }
-
- private _buildQueryStrategy(): _QueryStrategy {
- if (this._proto.protoQueryRefs.length === 0) {
- return _emptyQueryStrategy;
- } else if (this._proto.protoQueryRefs.length <=
- InlineQueryStrategy.NUMBER_OF_SUPPORTED_QUERIES) {
- return new InlineQueryStrategy(this);
- } else {
- return new DynamicQueryStrategy(this);
- }
- }
-
- link(parent: ElementInjector): void { parent.addChild(this); }
-
- unlink(): void { this.remove(); }
-
- getDirectiveAtIndex(index: number): any { return this._injector.getAt(index); }
-
- hasInstances(): boolean { return this._proto.hasBindings && this.hydrated; }
-
- getHost(): ElementInjector { return this._host; }
-
- getBoundElementIndex(): number { return this._proto.index; }
-
- getRootViewInjectors(): ElementInjector[] {
- if (!this.hydrated) return [];
- var view = this._preBuiltObjects.view;
- var nestedView = view.getNestedView(view.elementOffset + this.getBoundElementIndex());
- return isPresent(nestedView) ? nestedView.rootElementInjectors : [];
- }
-
- ngAfterViewChecked(): void { this._queryStrategy.updateViewQueries(); }
-
- ngAfterContentChecked(): void { this._queryStrategy.updateContentQueries(); }
-
- traverseAndSetQueriesAsDirty(): void {
- var inj: ElementInjector = this;
- while (isPresent(inj)) {
- inj._setQueriesAsDirty();
- inj = inj.parent;
- }
- }
-
- private _setQueriesAsDirty(): void {
- this._queryStrategy.setContentQueriesAsDirty();
- if (isPresent(this._host)) this._host._queryStrategy.setViewQueriesAsDirty();
- }
-}
-
-interface _QueryStrategy {
- setContentQueriesAsDirty(): void;
- setViewQueriesAsDirty(): void;
- hydrate(): void;
- dehydrate(): void;
- updateContentQueries(): void;
- updateViewQueries(): void;
- findQuery(query: QueryMetadata): QueryRef;
-}
-
-class _EmptyQueryStrategy implements _QueryStrategy {
- setContentQueriesAsDirty(): void {}
- setViewQueriesAsDirty(): void {}
- hydrate(): void {}
- dehydrate(): void {}
- updateContentQueries(): void {}
- updateViewQueries(): void {}
- findQuery(query: QueryMetadata): QueryRef {
- throw new BaseException(`Cannot find query for directive ${query}.`);
- }
-}
-
-var _emptyQueryStrategy = new _EmptyQueryStrategy();
-
-class InlineQueryStrategy implements _QueryStrategy {
- static NUMBER_OF_SUPPORTED_QUERIES = 3;
-
- query0: QueryRef;
- query1: QueryRef;
- query2: QueryRef;
-
- constructor(ei: ElementInjector) {
- var protoRefs = ei._proto.protoQueryRefs;
- if (protoRefs.length > 0) this.query0 = new QueryRef(protoRefs[0], ei);
- if (protoRefs.length > 1) this.query1 = new QueryRef(protoRefs[1], ei);
- if (protoRefs.length > 2) this.query2 = new QueryRef(protoRefs[2], ei);
- }
-
- setContentQueriesAsDirty(): void {
- if (isPresent(this.query0) && !this.query0.isViewQuery) this.query0.dirty = true;
- if (isPresent(this.query1) && !this.query1.isViewQuery) this.query1.dirty = true;
- if (isPresent(this.query2) && !this.query2.isViewQuery) this.query2.dirty = true;
- }
-
- setViewQueriesAsDirty(): void {
- if (isPresent(this.query0) && this.query0.isViewQuery) this.query0.dirty = true;
- if (isPresent(this.query1) && this.query1.isViewQuery) this.query1.dirty = true;
- if (isPresent(this.query2) && this.query2.isViewQuery) this.query2.dirty = true;
- }
-
- hydrate(): void {
- if (isPresent(this.query0)) this.query0.hydrate();
- if (isPresent(this.query1)) this.query1.hydrate();
- if (isPresent(this.query2)) this.query2.hydrate();
- }
-
- dehydrate(): void {
- if (isPresent(this.query0)) this.query0.dehydrate();
- if (isPresent(this.query1)) this.query1.dehydrate();
- if (isPresent(this.query2)) this.query2.dehydrate();
- }
-
- updateContentQueries() {
- if (isPresent(this.query0) && !this.query0.isViewQuery) {
- this.query0.update();
- }
- if (isPresent(this.query1) && !this.query1.isViewQuery) {
- this.query1.update();
- }
- if (isPresent(this.query2) && !this.query2.isViewQuery) {
- this.query2.update();
- }
- }
-
- updateViewQueries() {
- if (isPresent(this.query0) && this.query0.isViewQuery) {
- this.query0.update();
- }
- if (isPresent(this.query1) && this.query1.isViewQuery) {
- this.query1.update();
- }
- if (isPresent(this.query2) && this.query2.isViewQuery) {
- this.query2.update();
- }
- }
-
- findQuery(query: QueryMetadata): QueryRef {
- if (isPresent(this.query0) && this.query0.protoQueryRef.query === query) {
- return this.query0;
- }
- if (isPresent(this.query1) && this.query1.protoQueryRef.query === query) {
- return this.query1;
- }
- if (isPresent(this.query2) && this.query2.protoQueryRef.query === query) {
- return this.query2;
- }
- throw new BaseException(`Cannot find query for directive ${query}.`);
- }
-}
-
-class DynamicQueryStrategy implements _QueryStrategy {
- queries: QueryRef[];
-
- constructor(ei: ElementInjector) {
- this.queries = ei._proto.protoQueryRefs.map(p => new QueryRef(p, ei));
- }
-
- setContentQueriesAsDirty(): void {
- for (var i = 0; i < this.queries.length; ++i) {
- var q = this.queries[i];
- if (!q.isViewQuery) q.dirty = true;
- }
- }
-
- setViewQueriesAsDirty(): void {
- for (var i = 0; i < this.queries.length; ++i) {
- var q = this.queries[i];
- if (q.isViewQuery) q.dirty = true;
- }
- }
-
- hydrate(): void {
- for (var i = 0; i < this.queries.length; ++i) {
- var q = this.queries[i];
- q.hydrate();
- }
- }
-
- dehydrate(): void {
- for (var i = 0; i < this.queries.length; ++i) {
- var q = this.queries[i];
- q.dehydrate();
- }
- }
-
- updateContentQueries() {
- for (var i = 0; i < this.queries.length; ++i) {
- var q = this.queries[i];
- if (!q.isViewQuery) {
- q.update();
- }
- }
- }
-
- updateViewQueries() {
- for (var i = 0; i < this.queries.length; ++i) {
- var q = this.queries[i];
- if (q.isViewQuery) {
- q.update();
- }
- }
- }
-
- findQuery(query: QueryMetadata): QueryRef {
- for (var i = 0; i < this.queries.length; ++i) {
- var q = this.queries[i];
- if (q.protoQueryRef.query === query) {
- return q;
- }
- }
- throw new BaseException(`Cannot find query for directive ${query}.`);
- }
-}
-
-interface _ElementInjectorStrategy {
- callOnDestroy(): void;
- getComponent(): any;
- isComponentKey(key: Key): boolean;
- addDirectivesMatchingQuery(q: QueryMetadata, res: any[]): void;
- hydrate(): void;
- dehydrate(): void;
-}
-
-/**
- * Strategy used by the `ElementInjector` when the number of providers is 10 or less.
- * In such a case, inlining fields is beneficial for performances.
- */
-class ElementInjectorInlineStrategy implements _ElementInjectorStrategy {
- constructor(public injectorStrategy: InjectorInlineStrategy, public _ei: ElementInjector) {}
-
- hydrate(): void {
- var i = this.injectorStrategy;
- var p = i.protoStrategy;
- i.resetConstructionCounter();
-
- if (p.provider0 instanceof DirectiveProvider && isPresent(p.keyId0) && i.obj0 === UNDEFINED)
- i.obj0 = i.instantiateProvider(p.provider0, p.visibility0);
- if (p.provider1 instanceof DirectiveProvider && isPresent(p.keyId1) && i.obj1 === UNDEFINED)
- i.obj1 = i.instantiateProvider(p.provider1, p.visibility1);
- if (p.provider2 instanceof DirectiveProvider && isPresent(p.keyId2) && i.obj2 === UNDEFINED)
- i.obj2 = i.instantiateProvider(p.provider2, p.visibility2);
- if (p.provider3 instanceof DirectiveProvider && isPresent(p.keyId3) && i.obj3 === UNDEFINED)
- i.obj3 = i.instantiateProvider(p.provider3, p.visibility3);
- if (p.provider4 instanceof DirectiveProvider && isPresent(p.keyId4) && i.obj4 === UNDEFINED)
- i.obj4 = i.instantiateProvider(p.provider4, p.visibility4);
- if (p.provider5 instanceof DirectiveProvider && isPresent(p.keyId5) && i.obj5 === UNDEFINED)
- i.obj5 = i.instantiateProvider(p.provider5, p.visibility5);
- if (p.provider6 instanceof DirectiveProvider && isPresent(p.keyId6) && i.obj6 === UNDEFINED)
- i.obj6 = i.instantiateProvider(p.provider6, p.visibility6);
- if (p.provider7 instanceof DirectiveProvider && isPresent(p.keyId7) && i.obj7 === UNDEFINED)
- i.obj7 = i.instantiateProvider(p.provider7, p.visibility7);
- if (p.provider8 instanceof DirectiveProvider && isPresent(p.keyId8) && i.obj8 === UNDEFINED)
- i.obj8 = i.instantiateProvider(p.provider8, p.visibility8);
- if (p.provider9 instanceof DirectiveProvider && isPresent(p.keyId9) && i.obj9 === UNDEFINED)
- i.obj9 = i.instantiateProvider(p.provider9, p.visibility9);
- }
-
- dehydrate() {
- var i = this.injectorStrategy;
-
- i.obj0 = UNDEFINED;
- i.obj1 = UNDEFINED;
- i.obj2 = UNDEFINED;
- i.obj3 = UNDEFINED;
- i.obj4 = UNDEFINED;
- i.obj5 = UNDEFINED;
- i.obj6 = UNDEFINED;
- i.obj7 = UNDEFINED;
- i.obj8 = UNDEFINED;
- i.obj9 = UNDEFINED;
- }
-
- callOnDestroy(): void {
- var i = this.injectorStrategy;
- var p = i.protoStrategy;
-
- if (p.provider0 instanceof DirectiveProvider &&
- (p.provider0).callOnDestroy) {
- i.obj0.ngOnDestroy();
- }
- if (p.provider1 instanceof DirectiveProvider &&
- (p.provider1).callOnDestroy) {
- i.obj1.ngOnDestroy();
- }
- if (p.provider2 instanceof DirectiveProvider &&
- (p.provider2).callOnDestroy) {
- i.obj2.ngOnDestroy();
- }
- if (p.provider3 instanceof DirectiveProvider &&
- (p.provider3).callOnDestroy) {
- i.obj3.ngOnDestroy();
- }
- if (p.provider4 instanceof DirectiveProvider &&
- (p.provider4).callOnDestroy) {
- i.obj4.ngOnDestroy();
- }
- if (p.provider5 instanceof DirectiveProvider &&
- (p.provider5).callOnDestroy) {
- i.obj5.ngOnDestroy();
- }
- if (p.provider6 instanceof DirectiveProvider &&
- (p.provider6).callOnDestroy) {
- i.obj6.ngOnDestroy();
- }
- if (p.provider7 instanceof DirectiveProvider &&
- (p.provider7).callOnDestroy) {
- i.obj7.ngOnDestroy();
- }
- if (p.provider8 instanceof DirectiveProvider &&
- (p.provider8).callOnDestroy) {
- i.obj8.ngOnDestroy();
- }
- if (p.provider9 instanceof DirectiveProvider &&
- (p.provider9).callOnDestroy) {
- i.obj9.ngOnDestroy();
- }
- }
-
- getComponent(): any { return this.injectorStrategy.obj0; }
-
- isComponentKey(key: Key): boolean {
- return this._ei._proto._firstProviderIsComponent && isPresent(key) &&
- key.id === this.injectorStrategy.protoStrategy.keyId0;
- }
-
- addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
- var i = this.injectorStrategy;
- var p = i.protoStrategy;
-
- if (isPresent(p.provider0) && p.provider0.key.token === query.selector) {
- if (i.obj0 === UNDEFINED) i.obj0 = i.instantiateProvider(p.provider0, p.visibility0);
- list.push(i.obj0);
- }
- if (isPresent(p.provider1) && p.provider1.key.token === query.selector) {
- if (i.obj1 === UNDEFINED) i.obj1 = i.instantiateProvider(p.provider1, p.visibility1);
- list.push(i.obj1);
- }
- if (isPresent(p.provider2) && p.provider2.key.token === query.selector) {
- if (i.obj2 === UNDEFINED) i.obj2 = i.instantiateProvider(p.provider2, p.visibility2);
- list.push(i.obj2);
- }
- if (isPresent(p.provider3) && p.provider3.key.token === query.selector) {
- if (i.obj3 === UNDEFINED) i.obj3 = i.instantiateProvider(p.provider3, p.visibility3);
- list.push(i.obj3);
- }
- if (isPresent(p.provider4) && p.provider4.key.token === query.selector) {
- if (i.obj4 === UNDEFINED) i.obj4 = i.instantiateProvider(p.provider4, p.visibility4);
- list.push(i.obj4);
- }
- if (isPresent(p.provider5) && p.provider5.key.token === query.selector) {
- if (i.obj5 === UNDEFINED) i.obj5 = i.instantiateProvider(p.provider5, p.visibility5);
- list.push(i.obj5);
- }
- if (isPresent(p.provider6) && p.provider6.key.token === query.selector) {
- if (i.obj6 === UNDEFINED) i.obj6 = i.instantiateProvider(p.provider6, p.visibility6);
- list.push(i.obj6);
- }
- if (isPresent(p.provider7) && p.provider7.key.token === query.selector) {
- if (i.obj7 === UNDEFINED) i.obj7 = i.instantiateProvider(p.provider7, p.visibility7);
- list.push(i.obj7);
- }
- if (isPresent(p.provider8) && p.provider8.key.token === query.selector) {
- if (i.obj8 === UNDEFINED) i.obj8 = i.instantiateProvider(p.provider8, p.visibility8);
- list.push(i.obj8);
- }
- if (isPresent(p.provider9) && p.provider9.key.token === query.selector) {
- if (i.obj9 === UNDEFINED) i.obj9 = i.instantiateProvider(p.provider9, p.visibility9);
- list.push(i.obj9);
- }
- }
-}
-
-/**
- * Strategy used by the `ElementInjector` when the number of bindings is 11 or more.
- * In such a case, there are too many fields to inline (see ElementInjectorInlineStrategy).
- */
-class ElementInjectorDynamicStrategy implements _ElementInjectorStrategy {
- constructor(public injectorStrategy: InjectorDynamicStrategy, public _ei: ElementInjector) {}
-
- hydrate(): void {
- var inj = this.injectorStrategy;
- var p = inj.protoStrategy;
- inj.resetConstructionCounter();
-
- for (var i = 0; i < p.keyIds.length; i++) {
- if (p.providers[i] instanceof DirectiveProvider && isPresent(p.keyIds[i]) &&
- inj.objs[i] === UNDEFINED) {
- inj.objs[i] = inj.instantiateProvider(p.providers[i], p.visibilities[i]);
- }
- }
- }
-
- dehydrate(): void {
- var inj = this.injectorStrategy;
- ListWrapper.fill(inj.objs, UNDEFINED);
- }
-
- callOnDestroy(): void {
- var ist = this.injectorStrategy;
- var p = ist.protoStrategy;
-
- for (var i = 0; i < p.providers.length; i++) {
- if (p.providers[i] instanceof DirectiveProvider &&
- (p.providers[i]).callOnDestroy) {
- ist.objs[i].ngOnDestroy();
- }
- }
- }
-
- getComponent(): any { return this.injectorStrategy.objs[0]; }
-
- isComponentKey(key: Key): boolean {
- var p = this.injectorStrategy.protoStrategy;
- return this._ei._proto._firstProviderIsComponent && isPresent(key) && key.id === p.keyIds[0];
- }
-
- addDirectivesMatchingQuery(query: QueryMetadata, list: any[]): void {
- var ist = this.injectorStrategy;
- var p = ist.protoStrategy;
-
- for (var i = 0; i < p.providers.length; i++) {
- if (p.providers[i].key.token === query.selector) {
- if (ist.objs[i] === UNDEFINED) {
- ist.objs[i] = ist.instantiateProvider(p.providers[i], p.visibilities[i]);
- }
- list.push(ist.objs[i]);
- }
- }
- }
-}
-
-export class ProtoQueryRef {
- constructor(public dirIndex: number, public setter: SetterFn, public query: QueryMetadata) {}
-
- get usesPropertySyntax(): boolean { return isPresent(this.setter); }
-}
-
-export class QueryRef {
- public list: QueryList;
- public dirty: boolean;
-
- constructor(public protoQueryRef: ProtoQueryRef, private originator: ElementInjector) {}
-
- get isViewQuery(): boolean { return this.protoQueryRef.query.isViewQuery; }
-
- update(): void {
- if (!this.dirty) return;
- this._update();
- this.dirty = false;
-
- // TODO delete the check once only field queries are supported
- if (this.protoQueryRef.usesPropertySyntax) {
- var dir = this.originator.getDirectiveAtIndex(this.protoQueryRef.dirIndex);
- if (this.protoQueryRef.query.first) {
- this.protoQueryRef.setter(dir, this.list.length > 0 ? this.list.first : null);
- } else {
- this.protoQueryRef.setter(dir, this.list);
- }
- }
-
- this.list.notifyOnChanges();
- }
-
- private _update(): void {
- var aggregator = [];
- if (this.protoQueryRef.query.isViewQuery) {
- var view = this.originator.getView();
- // intentionally skipping originator for view queries.
- var nestedView =
- view.getNestedView(view.elementOffset + this.originator.getBoundElementIndex());
- if (isPresent(nestedView)) this._visitView(nestedView, aggregator);
- } else {
- this._visit(this.originator, aggregator);
- }
- this.list.reset(aggregator);
- };
-
- private _visit(inj: ElementInjector, aggregator: any[]): void {
- var view = inj.getView();
- var startIdx = view.elementOffset + inj._proto.index;
- for (var i = startIdx; i < view.elementOffset + view.ownBindersCount; i++) {
- var curInj = view.elementInjectors[i];
- if (isBlank(curInj)) continue;
- // The first injector after inj, that is outside the subtree rooted at
- // inj has to have a null parent or a parent that is an ancestor of inj.
- if (i > startIdx && (isBlank(curInj) || isBlank(curInj.parent) ||
- view.elementOffset + curInj.parent._proto.index < startIdx)) {
- break;
- }
-
- if (!this.protoQueryRef.query.descendants &&
- !(curInj.parent == this.originator || curInj == this.originator))
- continue;
-
- // We visit the view container(VC) views right after the injector that contains
- // the VC. Theoretically, that might not be the right order if there are
- // child injectors of said injector. Not clear whether if such case can
- // even be constructed with the current apis.
- this._visitInjector(curInj, aggregator);
- var vc = view.viewContainers[i];
- if (isPresent(vc)) this._visitViewContainer(vc, aggregator);
- }
- }
-
- private _visitInjector(inj: ElementInjector, aggregator: any[]) {
- if (this.protoQueryRef.query.isVarBindingQuery) {
- this._aggregateVariableBinding(inj, aggregator);
- } else {
- this._aggregateDirective(inj, aggregator);
- }
- }
-
- private _visitViewContainer(vc: AppViewContainer, aggregator: any[]) {
- for (var j = 0; j < vc.views.length; j++) {
- this._visitView(vc.views[j], aggregator);
- }
- }
-
- private _visitView(view: AppView, aggregator: any[]) {
- for (var i = view.elementOffset; i < view.elementOffset + view.ownBindersCount; i++) {
- var inj = view.elementInjectors[i];
- if (isBlank(inj)) continue;
-
- this._visitInjector(inj, aggregator);
-
- var vc = view.viewContainers[i];
- if (isPresent(vc)) this._visitViewContainer(vc, aggregator);
- }
- }
-
- private _aggregateVariableBinding(inj: ElementInjector, aggregator: any[]): void {
- var vb = this.protoQueryRef.query.varBindings;
- for (var i = 0; i < vb.length; ++i) {
- if (inj.hasVariableBinding(vb[i])) {
- aggregator.push(inj.getVariableBinding(vb[i]));
- }
- }
- }
-
- private _aggregateDirective(inj: ElementInjector, aggregator: any[]): void {
- inj.addDirectivesMatchingQuery(this.protoQueryRef.query, aggregator);
- }
-
- dehydrate(): void { this.list = null; }
-
- hydrate(): void {
- this.list = new QueryList();
- this.dirty = true;
- }
-}
diff --git a/modules/angular2/src/core/linker/element_ref.ts b/modules/angular2/src/core/linker/element_ref.ts
index 810fce84cb0d3..a052fb8fa04c3 100644
--- a/modules/angular2/src/core/linker/element_ref.ts
+++ b/modules/angular2/src/core/linker/element_ref.ts
@@ -1,6 +1,5 @@
-import {BaseException, unimplemented} from 'angular2/src/facade/exceptions';
-import {ViewRef, ViewRef_} from './view_ref';
-import {RenderViewRef, RenderElementRef, Renderer} from 'angular2/src/core/render/api';
+import {unimplemented} from 'angular2/src/facade/exceptions';
+import {AppElement} from './element';
/**
* Represents a location in a View that has an injection, change-detection and render context
@@ -12,23 +11,7 @@ import {RenderViewRef, RenderElementRef, Renderer} from 'angular2/src/core/rende
* An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM
* element.
*/
-export abstract class ElementRef implements RenderElementRef {
- /**
- * @internal
- *
- * Reference to the {@link ViewRef} that this `ElementRef` is part of.
- */
- parentView: ViewRef;
-
- /**
- * @internal
- *
- * Index of the element inside the {@link ViewRef}.
- *
- * This is used internally by the Angular framework to locate elements.
- */
- boundElementIndex: number;
-
+export abstract class ElementRef {
/**
* The underlying native element or `null` if direct access to native elements is not supported
* (e.g. when the application runs in a web worker).
@@ -48,24 +31,13 @@ export abstract class ElementRef implements RenderElementRef {
*
*
*/
- get nativeElement(): any { return unimplemented(); };
-
- get renderView(): RenderViewRef { return unimplemented(); }
+ get nativeElement(): any { return unimplemented(); }
}
-export class ElementRef_ extends ElementRef {
- constructor(public parentView: ViewRef,
+export class ElementRef_ implements ElementRef {
+ constructor(private _appElement: AppElement) {}
- /**
- * Index of the element inside the {@link ViewRef}.
- *
- * This is used internally by the Angular framework to locate elements.
- */
- public boundElementIndex: number, private _renderer: Renderer) {
- super();
- }
+ get internalElement(): AppElement { return this._appElement; }
- get renderView(): RenderViewRef { return (this.parentView).render; }
- set renderView(value) { unimplemented(); }
- get nativeElement(): any { return this._renderer.getNativeElementSync(this); }
+ get nativeElement() { return this._appElement.nativeElement; }
}
diff --git a/modules/angular2/src/core/linker/event_config.ts b/modules/angular2/src/core/linker/event_config.ts
deleted file mode 100644
index fdbcf2baa0598..0000000000000
--- a/modules/angular2/src/core/linker/event_config.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-export const EVENT_TARGET_SEPARATOR = ':';
-
-export class EventConfig {
- constructor(public fieldName: string, public eventName: string, public isLongForm: boolean) {}
-
- static parse(eventConfig: string): EventConfig {
- var fieldName = eventConfig, eventName = eventConfig, isLongForm = false;
- var separatorIdx = eventConfig.indexOf(EVENT_TARGET_SEPARATOR);
- if (separatorIdx > -1) {
- // long format: 'fieldName: eventName'
- fieldName = eventConfig.substring(0, separatorIdx).trim();
- eventName = eventConfig.substring(separatorIdx + 1).trim();
- isLongForm = true;
- }
- return new EventConfig(fieldName, eventName, isLongForm);
- }
-
- getFullName(): string {
- return this.isLongForm ? `${this.fieldName}${EVENT_TARGET_SEPARATOR}${this.eventName}` :
- this.eventName;
- }
-}
diff --git a/modules/angular2/src/core/linker/pipe_resolver.ts b/modules/angular2/src/core/linker/pipe_resolver.ts
index 67683978c791e..3de7a3f23c556 100644
--- a/modules/angular2/src/core/linker/pipe_resolver.ts
+++ b/modules/angular2/src/core/linker/pipe_resolver.ts
@@ -31,3 +31,5 @@ export class PipeResolver {
throw new BaseException(`No Pipe decorator found on ${stringify(type)}`);
}
}
+
+export var CODEGEN_PIPE_RESOLVER = new PipeResolver();
diff --git a/modules/angular2/src/core/linker/proto_view_factory.ts b/modules/angular2/src/core/linker/proto_view_factory.ts
deleted file mode 100644
index 30216a44b46d1..0000000000000
--- a/modules/angular2/src/core/linker/proto_view_factory.ts
+++ /dev/null
@@ -1,341 +0,0 @@
-import {isPresent, isBlank, Type, isArray, isNumber} from 'angular2/src/facade/lang';
-
-import {RenderProtoViewRef, RenderComponentTemplate} from 'angular2/src/core/render/api';
-
-import {Optional, Injectable, Provider, resolveForwardRef, Inject} from 'angular2/src/core/di';
-
-import {PipeProvider} from '../pipes/pipe_provider';
-import {ProtoPipes} from '../pipes/pipes';
-
-import {AppProtoView, AppProtoViewMergeInfo, ViewType} from './view';
-import {ElementBinder} from './element_binder';
-import {ProtoElementInjector, DirectiveProvider} from './element_injector';
-import {DirectiveResolver} from './directive_resolver';
-import {ViewResolver} from './view_resolver';
-import {PipeResolver} from './pipe_resolver';
-import {ViewMetadata, ViewEncapsulation} from '../metadata/view';
-import {PLATFORM_PIPES} from 'angular2/src/core/platform_directives_and_pipes';
-
-import {
- visitAllCommands,
- CompiledComponentTemplate,
- CompiledHostTemplate,
- TemplateCmd,
- CommandVisitor,
- EmbeddedTemplateCmd,
- BeginComponentCmd,
- BeginElementCmd,
- IBeginElementCmd,
- TextCmd,
- NgContentCmd
-} from './template_commands';
-
-import {Renderer} from 'angular2/src/core/render/api';
-import {APP_ID} from 'angular2/src/core/application_tokens';
-
-
-@Injectable()
-export class ProtoViewFactory {
- private _cache: Map = new Map();
- private _nextTemplateId: number = 0;
-
- constructor(private _renderer: Renderer,
- @Optional() @Inject(PLATFORM_PIPES) private _platformPipes: Array,
- private _directiveResolver: DirectiveResolver, private _viewResolver: ViewResolver,
- private _pipeResolver: PipeResolver, @Inject(APP_ID) private _appId: string) {}
-
- clearCache() { this._cache.clear(); }
-
- createHost(compiledHostTemplate: CompiledHostTemplate): AppProtoView {
- var compiledTemplate = compiledHostTemplate.template;
- var result = this._cache.get(compiledTemplate.id);
- if (isBlank(result)) {
- var emptyMap: {[key: string]: PipeProvider} = {};
- var shortId = `${this._appId}-${this._nextTemplateId++}`;
- this._renderer.registerComponentTemplate(new RenderComponentTemplate(
- compiledTemplate.id, shortId, ViewEncapsulation.None, compiledTemplate.commands, []));
- result =
- new AppProtoView(compiledTemplate.id, compiledTemplate.commands, ViewType.HOST, true,
- compiledTemplate.changeDetectorFactory, null, new ProtoPipes(emptyMap));
- this._cache.set(compiledTemplate.id, result);
- }
- return result;
- }
-
- private _createComponent(cmd: BeginComponentCmd): AppProtoView {
- var nestedProtoView = this._cache.get(cmd.templateId);
- if (isBlank(nestedProtoView)) {
- var component = cmd.directives[0];
- var view = this._viewResolver.resolve(component);
- var compiledTemplate = cmd.templateGetter();
- var styles = _flattenStyleArr(compiledTemplate.styles, []);
- var shortId = `${this._appId}-${this._nextTemplateId++}`;
- this._renderer.registerComponentTemplate(new RenderComponentTemplate(
- compiledTemplate.id, shortId, cmd.encapsulation, compiledTemplate.commands, styles));
- var boundPipes = this._flattenPipes(view).map(pipe => this._bindPipe(pipe));
-
- nestedProtoView = new AppProtoView(
- compiledTemplate.id, compiledTemplate.commands, ViewType.COMPONENT, true,
- compiledTemplate.changeDetectorFactory, null, ProtoPipes.fromProviders(boundPipes));
- // Note: The cache is updated before recursing
- // to be able to resolve cycles
- this._cache.set(compiledTemplate.id, nestedProtoView);
- this._initializeProtoView(nestedProtoView, null);
- }
- return nestedProtoView;
- }
-
- private _createEmbeddedTemplate(cmd: EmbeddedTemplateCmd, parent: AppProtoView): AppProtoView {
- var nestedProtoView = new AppProtoView(
- parent.templateId, cmd.children, ViewType.EMBEDDED, cmd.isMerged, cmd.changeDetectorFactory,
- arrayToMap(cmd.variableNameAndValues, true), new ProtoPipes(parent.pipes.config));
- if (cmd.isMerged) {
- this.initializeProtoViewIfNeeded(nestedProtoView);
- }
- return nestedProtoView;
- }
-
- initializeProtoViewIfNeeded(protoView: AppProtoView) {
- if (!protoView.isInitialized()) {
- var render = this._renderer.createProtoView(protoView.templateId, protoView.templateCmds);
- this._initializeProtoView(protoView, render);
- }
- }
-
- private _initializeProtoView(protoView: AppProtoView, render: RenderProtoViewRef) {
- var initializer = new _ProtoViewInitializer(protoView, this._directiveResolver, this);
- visitAllCommands(initializer, protoView.templateCmds);
- var mergeInfo =
- new AppProtoViewMergeInfo(initializer.mergeEmbeddedViewCount, initializer.mergeElementCount,
- initializer.mergeViewCount);
- protoView.init(render, initializer.elementBinders, initializer.boundTextCount, mergeInfo,
- initializer.variableLocations);
- }
-
- private _bindPipe(typeOrProvider): PipeProvider {
- let meta = this._pipeResolver.resolve(typeOrProvider);
- return PipeProvider.createFromType(typeOrProvider, meta);
- }
-
- private _flattenPipes(view: ViewMetadata): any[] {
- let pipes = [];
- if (isPresent(this._platformPipes)) {
- _flattenArray(this._platformPipes, pipes);
- }
- if (isPresent(view.pipes)) {
- _flattenArray(view.pipes, pipes);
- }
- return pipes;
- }
-}
-
-
-function createComponent(protoViewFactory: ProtoViewFactory, cmd: BeginComponentCmd): AppProtoView {
- return (protoViewFactory)._createComponent(cmd);
-}
-
-function createEmbeddedTemplate(protoViewFactory: ProtoViewFactory, cmd: EmbeddedTemplateCmd,
- parent: AppProtoView): AppProtoView {
- return (protoViewFactory)._createEmbeddedTemplate(cmd, parent);
-}
-
-class _ProtoViewInitializer implements CommandVisitor {
- variableLocations: Map = new Map();
- boundTextCount: number = 0;
- boundElementIndex: number = 0;
- elementBinderStack: ElementBinder[] = [];
- distanceToParentElementBinder: number = 0;
- distanceToParentProtoElementInjector: number = 0;
- elementBinders: ElementBinder[] = [];
- mergeEmbeddedViewCount: number = 0;
- mergeElementCount: number = 0;
- mergeViewCount: number = 1;
-
- constructor(private _protoView: AppProtoView, private _directiveResolver: DirectiveResolver,
- private _protoViewFactory: ProtoViewFactory) {}
-
- visitText(cmd: TextCmd, context: any): any {
- if (cmd.isBound) {
- this.boundTextCount++;
- }
- return null;
- }
- visitNgContent(cmd: NgContentCmd, context: any): any { return null; }
- visitBeginElement(cmd: BeginElementCmd, context: any): any {
- if (cmd.isBound) {
- this._visitBeginBoundElement(cmd, null);
- } else {
- this._visitBeginElement(cmd, null, null);
- }
- return null;
- }
- visitEndElement(context: any): any { return this._visitEndElement(); }
- visitBeginComponent(cmd: BeginComponentCmd, context: any): any {
- var nestedProtoView = createComponent(this._protoViewFactory, cmd);
- return this._visitBeginBoundElement(cmd, nestedProtoView);
- }
- visitEndComponent(context: any): any { return this._visitEndElement(); }
- visitEmbeddedTemplate(cmd: EmbeddedTemplateCmd, context: any): any {
- var nestedProtoView = createEmbeddedTemplate(this._protoViewFactory, cmd, this._protoView);
- if (cmd.isMerged) {
- this.mergeEmbeddedViewCount++;
- }
- this._visitBeginBoundElement(cmd, nestedProtoView);
- return this._visitEndElement();
- }
-
- private _visitBeginBoundElement(cmd: IBeginElementCmd, nestedProtoView: AppProtoView): any {
- if (isPresent(nestedProtoView) && nestedProtoView.isMergable) {
- this.mergeElementCount += nestedProtoView.mergeInfo.elementCount;
- this.mergeViewCount += nestedProtoView.mergeInfo.viewCount;
- this.mergeEmbeddedViewCount += nestedProtoView.mergeInfo.embeddedViewCount;
- }
- var elementBinder = _createElementBinder(
- this._directiveResolver, nestedProtoView, this.elementBinderStack, this.boundElementIndex,
- this.distanceToParentElementBinder, this.distanceToParentProtoElementInjector, cmd);
- this.elementBinders.push(elementBinder);
- var protoElementInjector = elementBinder.protoElementInjector;
- for (var i = 0; i < cmd.variableNameAndValues.length; i += 2) {
- this.variableLocations.set(cmd.variableNameAndValues[i], this.boundElementIndex);
- }
- this.boundElementIndex++;
- this.mergeElementCount++;
- return this._visitBeginElement(cmd, elementBinder, protoElementInjector);
- }
-
- private _visitBeginElement(cmd: IBeginElementCmd, elementBinder: ElementBinder,
- protoElementInjector: ProtoElementInjector): any {
- this.distanceToParentElementBinder =
- isPresent(elementBinder) ? 1 : this.distanceToParentElementBinder + 1;
- this.distanceToParentProtoElementInjector =
- isPresent(protoElementInjector) ? 1 : this.distanceToParentProtoElementInjector + 1;
- this.elementBinderStack.push(elementBinder);
- return null;
- }
-
- private _visitEndElement(): any {
- var parentElementBinder = this.elementBinderStack.pop();
- var parentProtoElementInjector =
- isPresent(parentElementBinder) ? parentElementBinder.protoElementInjector : null;
- this.distanceToParentElementBinder = isPresent(parentElementBinder) ?
- parentElementBinder.distanceToParent :
- this.distanceToParentElementBinder - 1;
- this.distanceToParentProtoElementInjector = isPresent(parentProtoElementInjector) ?
- parentProtoElementInjector.distanceToParent :
- this.distanceToParentProtoElementInjector - 1;
- return null;
- }
-}
-
-
-function _createElementBinder(directiveResolver: DirectiveResolver, nestedProtoView: AppProtoView,
- elementBinderStack: ElementBinder[], boundElementIndex: number,
- distanceToParentBinder: number, distanceToParentPei: number,
- beginElementCmd: IBeginElementCmd): ElementBinder {
- var parentElementBinder: ElementBinder = null;
- var parentProtoElementInjector: ProtoElementInjector = null;
- if (distanceToParentBinder > 0) {
- parentElementBinder = elementBinderStack[elementBinderStack.length - distanceToParentBinder];
- }
- if (isBlank(parentElementBinder)) {
- distanceToParentBinder = -1;
- }
- if (distanceToParentPei > 0) {
- var peiBinder = elementBinderStack[elementBinderStack.length - distanceToParentPei];
- if (isPresent(peiBinder)) {
- parentProtoElementInjector = peiBinder.protoElementInjector;
- }
- }
- if (isBlank(parentProtoElementInjector)) {
- distanceToParentPei = -1;
- }
- var componentDirectiveProvider: DirectiveProvider = null;
- var isEmbeddedTemplate = false;
- var directiveProviders: DirectiveProvider[] =
- beginElementCmd.directives.map(type => provideDirective(directiveResolver, type));
- if (beginElementCmd instanceof BeginComponentCmd) {
- componentDirectiveProvider = directiveProviders[0];
- } else if (beginElementCmd instanceof EmbeddedTemplateCmd) {
- isEmbeddedTemplate = true;
- }
-
- var protoElementInjector = null;
- // Create a protoElementInjector for any element that either has bindings *or* has one
- // or more var- defined *or* for elements:
- // - Elements with a var- defined need a their own element injector
- // so that, when hydrating, $implicit can be set to the element.
- // - elements need their own ElementInjector so that we can query their TemplateRef
- var hasVariables = beginElementCmd.variableNameAndValues.length > 0;
- if (directiveProviders.length > 0 || hasVariables || isEmbeddedTemplate) {
- var directiveVariableBindings = new Map();
- if (!isEmbeddedTemplate) {
- directiveVariableBindings = createDirectiveVariableBindings(
- beginElementCmd.variableNameAndValues, directiveProviders);
- }
- protoElementInjector = ProtoElementInjector.create(
- parentProtoElementInjector, boundElementIndex, directiveProviders,
- isPresent(componentDirectiveProvider), distanceToParentPei, directiveVariableBindings);
- protoElementInjector.attributes = arrayToMap(beginElementCmd.attrNameAndValues, false);
- }
-
- return new ElementBinder(boundElementIndex, parentElementBinder, distanceToParentBinder,
- protoElementInjector, componentDirectiveProvider, nestedProtoView);
-}
-
-function provideDirective(directiveResolver: DirectiveResolver, type: Type): DirectiveProvider {
- let annotation = directiveResolver.resolve(type);
- return DirectiveProvider.createFromType(type, annotation);
-}
-
-export function createDirectiveVariableBindings(
- variableNameAndValues: Array,
- directiveProviders: DirectiveProvider[]): Map {
- var directiveVariableBindings = new Map();
- for (var i = 0; i < variableNameAndValues.length; i += 2) {
- var templateName = variableNameAndValues[i];
- var dirIndex = variableNameAndValues[i + 1];
- if (isNumber(dirIndex)) {
- directiveVariableBindings.set(templateName, dirIndex);
- } else {
- // a variable without a directive index -> reference the element
- directiveVariableBindings.set(templateName, null);
- }
- }
- return directiveVariableBindings;
-}
-
-
-function arrayToMap(arr: string[], inverse: boolean): Map {
- var result = new Map();
- for (var i = 0; i < arr.length; i += 2) {
- if (inverse) {
- result.set(arr[i + 1], arr[i]);
- } else {
- result.set(arr[i], arr[i + 1]);
- }
- }
- return result;
-}
-
-function _flattenArray(tree: any[], out: Array): void {
- for (var i = 0; i < tree.length; i++) {
- var item = resolveForwardRef(tree[i]);
- if (isArray(item)) {
- _flattenArray(item, out);
- } else {
- out.push(item);
- }
- }
-}
-
-function _flattenStyleArr(arr: Array, out: string[]): string[] {
- for (var i = 0; i < arr.length; i++) {
- var entry = arr[i];
- if (isArray(entry)) {
- _flattenStyleArr(entry, out);
- } else {
- out.push(entry);
- }
- }
- return out;
-}
diff --git a/modules/angular2/src/core/linker/resolved_metadata_cache.ts b/modules/angular2/src/core/linker/resolved_metadata_cache.ts
new file mode 100644
index 0000000000000..370c2005e60ef
--- /dev/null
+++ b/modules/angular2/src/core/linker/resolved_metadata_cache.ts
@@ -0,0 +1,35 @@
+import {Injectable} from '../di';
+import {Type, isBlank} from 'angular2/src/facade/lang';
+import {DirectiveProvider} from './element';
+import {DirectiveResolver, CODEGEN_DIRECTIVE_RESOLVER} from './directive_resolver';
+import {PipeProvider} from '../pipes/pipe_provider';
+import {PipeResolver, CODEGEN_PIPE_RESOLVER} from './pipe_resolver';
+
+@Injectable()
+export class ResolvedMetadataCache {
+ private _directiveCache: Map = new Map();
+ private _pipeCache: Map = new Map();
+
+ constructor(private _directiveResolver: DirectiveResolver, private _pipeResolver: PipeResolver) {}
+
+ getResolvedDirectiveMetadata(type: Type): DirectiveProvider {
+ var result = this._directiveCache.get(type);
+ if (isBlank(result)) {
+ result = DirectiveProvider.createFromType(type, this._directiveResolver.resolve(type));
+ this._directiveCache.set(type, result);
+ }
+ return result;
+ }
+
+ getResolvedPipeMetadata(type: Type): PipeProvider {
+ var result = this._pipeCache.get(type);
+ if (isBlank(result)) {
+ result = PipeProvider.createFromType(type, this._pipeResolver.resolve(type));
+ this._pipeCache.set(type, result);
+ }
+ return result;
+ }
+}
+
+export var CODEGEN_RESOLVED_METADATA_CACHE =
+ new ResolvedMetadataCache(CODEGEN_DIRECTIVE_RESOLVER, CODEGEN_PIPE_RESOLVER);
diff --git a/modules/angular2/src/core/linker/template_commands.ts b/modules/angular2/src/core/linker/template_commands.ts
deleted file mode 100644
index 20d32cbfb4f3f..0000000000000
--- a/modules/angular2/src/core/linker/template_commands.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-import {Type, CONST_EXPR, CONST, isPresent, isBlank} from 'angular2/src/facade/lang';
-import {unimplemented} from 'angular2/src/facade/exceptions';
-import {
- RenderTemplateCmd,
- RenderCommandVisitor,
- RenderBeginElementCmd,
- RenderTextCmd,
- RenderNgContentCmd,
- RenderBeginComponentCmd,
- RenderEmbeddedTemplateCmd
-} from 'angular2/src/core/render/api';
-import {ViewEncapsulation} from 'angular2/src/core/metadata';
-// Export ViewEncapsulation so that compiled templates only need to depend
-// on template_commands.
-export {ViewEncapsulation} from 'angular2/src/core/metadata';
-
-/**
- * A compiled host template.
- *
- * This is const as we are storing it as annotation
- * for the compiled component type.
- */
-@CONST()
-export class CompiledHostTemplate {
- constructor(public template: CompiledComponentTemplate) {}
-}
-
-/**
- * A compiled template.
- */
-@CONST()
-export class CompiledComponentTemplate {
- constructor(public id: string, public changeDetectorFactory: Function,
- public commands: TemplateCmd[], public styles: string[]) {}
-}
-
-const EMPTY_ARR = CONST_EXPR([]);
-
-export interface TemplateCmd extends RenderTemplateCmd {
- visit(visitor: RenderCommandVisitor, context: any): any;
-}
-
-@CONST()
-export class TextCmd implements TemplateCmd, RenderTextCmd {
- constructor(public value: string, public isBound: boolean, public ngContentIndex: number) {}
- visit(visitor: RenderCommandVisitor, context: any): any {
- return visitor.visitText(this, context);
- }
-}
-
-@CONST()
-export class NgContentCmd implements TemplateCmd, RenderNgContentCmd {
- isBound: boolean = false;
- constructor(public index: number, public ngContentIndex: number) {}
- visit(visitor: RenderCommandVisitor, context: any): any {
- return visitor.visitNgContent(this, context);
- }
-}
-
-export abstract class IBeginElementCmd extends RenderBeginElementCmd implements TemplateCmd {
- get variableNameAndValues(): Array { return unimplemented(); }
- get eventTargetAndNames(): string[] { return unimplemented(); }
- get directives(): Type[] { return unimplemented(); }
- abstract visit(visitor: RenderCommandVisitor, context: any): any;
-}
-
-@CONST()
-export class BeginElementCmd implements TemplateCmd, IBeginElementCmd, RenderBeginElementCmd {
- constructor(public name: string, public attrNameAndValues: string[],
- public eventTargetAndNames: string[],
- public variableNameAndValues: Array, public directives: Type[],
- public isBound: boolean, public ngContentIndex: number) {}
- visit(visitor: RenderCommandVisitor, context: any): any {
- return visitor.visitBeginElement(this, context);
- }
-}
-
-
-@CONST()
-export class EndElementCmd implements TemplateCmd {
- visit(visitor: RenderCommandVisitor, context: any): any {
- return visitor.visitEndElement(context);
- }
-}
-
-@CONST()
-export class BeginComponentCmd implements TemplateCmd, IBeginElementCmd, RenderBeginComponentCmd {
- isBound: boolean = true;
- constructor(public name: string, public attrNameAndValues: string[],
- public eventTargetAndNames: string[],
- public variableNameAndValues: Array, public directives: Type[],
- public encapsulation: ViewEncapsulation, public ngContentIndex: number,
- // Note: the template needs to be stored as a function
- // so that we can resolve cycles
- public templateGetter: Function /*() => CompiledComponentTemplate*/) {}
-
- get templateId(): string { return this.templateGetter().id; }
-
- visit(visitor: RenderCommandVisitor, context: any): any {
- return visitor.visitBeginComponent(this, context);
- }
-}
-
-@CONST()
-export class EndComponentCmd implements TemplateCmd {
- visit(visitor: RenderCommandVisitor, context: any): any {
- return visitor.visitEndComponent(context);
- }
-}
-
-@CONST()
-export class EmbeddedTemplateCmd implements TemplateCmd, IBeginElementCmd,
- RenderEmbeddedTemplateCmd {
- isBound: boolean = true;
- name: string = null;
- eventTargetAndNames: string[] = EMPTY_ARR;
- constructor(public attrNameAndValues: string[], public variableNameAndValues: string[],
- public directives: Type[], public isMerged: boolean, public ngContentIndex: number,
- public changeDetectorFactory: Function, public children: TemplateCmd[]) {}
- visit(visitor: RenderCommandVisitor, context: any): any {
- return visitor.visitEmbeddedTemplate(this, context);
- }
-}
-
-
-export interface CommandVisitor extends RenderCommandVisitor {
- visitText(cmd: TextCmd, context: any): any;
- visitNgContent(cmd: NgContentCmd, context: any): any;
- visitBeginElement(cmd: BeginElementCmd, context: any): any;
- visitEndElement(context: any): any;
- visitBeginComponent(cmd: BeginComponentCmd, context: any): any;
- visitEndComponent(context: any): any;
- visitEmbeddedTemplate(cmd: EmbeddedTemplateCmd, context: any): any;
-}
-
-export function visitAllCommands(visitor: CommandVisitor, cmds: TemplateCmd[],
- context: any = null) {
- for (var i = 0; i < cmds.length; i++) {
- cmds[i].visit(visitor, context);
- }
-}
diff --git a/modules/angular2/src/core/linker/template_ref.ts b/modules/angular2/src/core/linker/template_ref.ts
index 4330f2ef64b23..ad934be9a1ed5 100644
--- a/modules/angular2/src/core/linker/template_ref.ts
+++ b/modules/angular2/src/core/linker/template_ref.ts
@@ -1,6 +1,4 @@
-import {internalView, ProtoViewRef} from './view_ref';
import {ElementRef, ElementRef_} from './element_ref';
-import * as viewModule from './view';
/**
* Represents an Embedded Template that can be used to instantiate Embedded Views.
@@ -27,34 +25,11 @@ export abstract class TemplateRef {
*
*/
// TODO(i): rename to anchor or location
- elementRef: ElementRef;
-
- /**
- * Allows you to check if this Embedded Template defines Local Variable with name matching `name`.
- */
- abstract hasLocal(name: string): boolean;
+ get elementRef(): ElementRef { return null; }
}
export class TemplateRef_ extends TemplateRef {
- constructor(elementRef: ElementRef) {
- super();
- this.elementRef = elementRef;
- }
-
- private _getProtoView(): viewModule.AppProtoView {
- let elementRef = this.elementRef;
- var parentView = internalView(elementRef.parentView);
- return parentView.proto.elementBinders[elementRef.boundElementIndex - parentView.elementOffset]
- .nestedProtoView;
- }
-
- /**
- * Reference to the ProtoView used for creating Embedded Views that are based on the compiled
- * Embedded Template.
- */
- get protoViewRef(): ProtoViewRef { return this._getProtoView().ref; }
+ constructor(private _elementRef: ElementRef_) { super(); }
- hasLocal(name: string): boolean {
- return this._getProtoView().templateVariableBindings.has(name);
- }
+ get elementRef(): ElementRef_ { return this._elementRef; }
}
diff --git a/modules/angular2/src/core/linker/view.ts b/modules/angular2/src/core/linker/view.ts
index 5eec1fcbe5c32..f91fb09b5ce2f 100644
--- a/modules/angular2/src/core/linker/view.ts
+++ b/modules/angular2/src/core/linker/view.ts
@@ -10,86 +10,53 @@ import {
DirectiveIndex,
BindingTarget,
Locals,
- ProtoChangeDetector
+ ProtoChangeDetector,
+ ChangeDetectorRef
} from 'angular2/src/core/change_detection/change_detection';
+import {ResolvedProvider, Injectable, Injector} from 'angular2/src/core/di';
import {DebugContext} from 'angular2/src/core/change_detection/interfaces';
+import {AppProtoElement, AppElement, DirectiveProvider} from './element';
import {
- ProtoElementInjector,
- ElementInjector,
- PreBuiltObjects,
- DirectiveProvider
-} from './element_injector';
-import {ElementBinder} from './element_binder';
-import {isPresent} from 'angular2/src/facade/lang';
+ isPresent,
+ isBlank,
+ Type,
+ isArray,
+ isNumber,
+ CONST,
+ CONST_EXPR
+} from 'angular2/src/facade/lang';
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
-import * as renderApi from 'angular2/src/core/render/api';
-import {RenderEventDispatcher} from 'angular2/src/core/render/api';
-import {ViewRef, ProtoViewRef, internalView} from './view_ref';
-import {ElementRef} from './element_ref';
+import {Renderer, RootRenderer} from 'angular2/src/core/render/api';
+import {ViewRef_, HostViewFactoryRef} from './view_ref';
import {ProtoPipes} from 'angular2/src/core/pipes/pipes';
import {camelCaseToDashCase} from 'angular2/src/core/render/util';
-import {TemplateCmd} from './template_commands';
-import {ViewRef_, ProtoViewRef_} from "./view_ref";
export {DebugContext} from 'angular2/src/core/change_detection/interfaces';
+import {Pipes} from 'angular2/src/core/pipes/pipes';
+import {AppViewManager_, AppViewManager} from './view_manager';
+import {ResolvedMetadataCache} from './resolved_metadata_cache';
+import {ViewType} from './view_type';
const REFLECT_PREFIX: string = 'ng-reflect-';
-export enum ViewType {
- // A view that contains the host element with bound component directive.
- // Contains a COMPONENT view
- HOST,
- // The view of the component
- // Can contain 0 to n EMBEDDED views
- COMPONENT,
- // A view that is embedded into another View via a element
- // inside of a COMPONENT view
- EMBEDDED
-}
-
-export class AppViewContainer {
- // The order in this list matches the DOM order.
- views: AppView[] = [];
-}
+const EMPTY_CONTEXT = CONST_EXPR(new Object());
/**
* Cost of making objects: http://jsperf.com/instantiate-size-of-object
*
*/
-export class AppView implements ChangeDispatcher, RenderEventDispatcher {
- // AppViews that have been merged in depth first order.
- // This list is shared between all merged views. Use this.elementOffset to get the local
- // entries.
- views: AppView[] = null;
- // root elementInjectors of this AppView
- // This list is local to this AppView and not shared with other Views.
- rootElementInjectors: ElementInjector[];
- // ElementInjectors of all AppViews in views grouped by view.
- // This list is shared between all merged views. Use this.elementOffset to get the local
- // entries.
- elementInjectors: ElementInjector[] = null;
- // ViewContainers of all AppViews in views grouped by view.
- // This list is shared between all merged views. Use this.elementOffset to get the local
- // entries.
- viewContainers: AppViewContainer[] = null;
- // PreBuiltObjects of all AppViews in views grouped by view.
- // This list is shared between all merged views. Use this.elementOffset to get the local
- // entries.
- preBuiltObjects: PreBuiltObjects[] = null;
- // ElementRef of all AppViews in views grouped by view.
- // This list is shared between all merged views. Use this.elementOffset to get the local
- // entries.
- elementRefs: ElementRef[];
-
- ref: ViewRef;
- changeDetector: ChangeDetector = null;
+export class AppView implements ChangeDispatcher {
+ ref: ViewRef_;
+ rootNodesOrAppElements: any[];
+ allNodes: any[];
+ disposables: Function[];
+ appElements: AppElement[];
/**
* The context against which data-binding expressions in this view are evaluated against.
* This is always a component instance.
*/
-
context: any = null;
/**
@@ -99,70 +66,133 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
*/
locals: Locals;
- constructor(public renderer: renderApi.Renderer, public proto: AppProtoView,
- public viewOffset: number, public elementOffset: number, public textOffset: number,
- protoLocals: Map, public render: renderApi.RenderViewRef,
- public renderFragment: renderApi.RenderFragmentRef,
- public containerElementInjector: ElementInjector) {
+ pipes: Pipes;
+
+ parentInjector: Injector;
+
+ /**
+ * Whether root injectors of this view
+ * have a hostBoundary.
+ */
+ hostInjectorBoundary: boolean;
+
+ destroyed: boolean = false;
+
+ constructor(public proto: AppProtoView, public renderer: Renderer,
+ public viewManager: AppViewManager_, public projectableNodes: Array,
+ public containerAppElement: AppElement,
+ imperativelyCreatedProviders: ResolvedProvider[], rootInjector: Injector,
+ public changeDetector: ChangeDetector) {
this.ref = new ViewRef_(this);
+ var injectorWithHostBoundary = AppElement.getViewParentInjector(
+ this.proto.type, containerAppElement, imperativelyCreatedProviders, rootInjector);
+ this.parentInjector = injectorWithHostBoundary.injector;
+ this.hostInjectorBoundary = injectorWithHostBoundary.hostInjectorBoundary;
+ var pipes;
+ var context;
+ switch (proto.type) {
+ case ViewType.COMPONENT:
+ pipes = new Pipes(proto.protoPipes, containerAppElement.getInjector());
+ context = containerAppElement.getComponent();
+ break;
+ case ViewType.EMBEDDED:
+ pipes = containerAppElement.parentView.pipes;
+ context = containerAppElement.parentView.context;
+ break;
+ case ViewType.HOST:
+ pipes = null;
+ context = EMPTY_CONTEXT;
+ break;
+ }
+ this.pipes = pipes;
+ this.context = context;
+ }
- this.locals = new Locals(null, MapWrapper.clone(protoLocals)); // TODO optimize this
+ init(rootNodesOrAppElements: any[], allNodes: any[], disposables: Function[],
+ appElements: AppElement[]) {
+ this.rootNodesOrAppElements = rootNodesOrAppElements;
+ this.allNodes = allNodes;
+ this.disposables = disposables;
+ this.appElements = appElements;
+ var localsMap = new Map();
+ StringMapWrapper.forEach(this.proto.templateVariableBindings,
+ (templateName, _) => { localsMap.set(templateName, null); });
+ for (var i = 0; i < appElements.length; i++) {
+ var appEl = appElements[i];
+ StringMapWrapper.forEach(appEl.proto.directiveVariableBindings, (directiveIndex, name) => {
+ if (isBlank(directiveIndex)) {
+ localsMap.set(name, appEl.nativeElement);
+ } else {
+ localsMap.set(name, appEl.getDirectiveAtIndex(directiveIndex));
+ }
+ });
+ }
+ var parentLocals = null;
+ if (this.proto.type !== ViewType.COMPONENT) {
+ parentLocals =
+ isPresent(this.containerAppElement) ? this.containerAppElement.parentView.locals : null;
+ }
+ if (this.proto.type === ViewType.COMPONENT) {
+ // Note: the render nodes have been attached to their host element
+ // in the ViewFactory already.
+ this.containerAppElement.attachComponentView(this);
+ this.containerAppElement.parentView.changeDetector.addViewChild(this.changeDetector);
+ }
+ this.locals = new Locals(parentLocals, localsMap);
+ this.changeDetector.hydrate(this.context, this.locals, this, this.pipes);
+ this.viewManager.onViewCreated(this);
}
- init(changeDetector: ChangeDetector, elementInjectors: ElementInjector[],
- rootElementInjectors: ElementInjector[], preBuiltObjects: PreBuiltObjects[],
- views: AppView[], elementRefs: ElementRef[], viewContainers: AppViewContainer[]) {
- this.changeDetector = changeDetector;
- this.elementInjectors = elementInjectors;
- this.rootElementInjectors = rootElementInjectors;
- this.preBuiltObjects = preBuiltObjects;
- this.views = views;
- this.elementRefs = elementRefs;
- this.viewContainers = viewContainers;
+ destroy() {
+ if (this.destroyed) {
+ throw new BaseException('This view has already been destroyed!');
+ }
+ this.changeDetector.destroyRecursive();
}
- setLocal(contextName: string, value: any): void {
- if (!this.hydrated()) throw new BaseException('Cannot set locals on dehydrated view.');
- if (!this.proto.templateVariableBindings.has(contextName)) {
- return;
+ notifyOnDestroy() {
+ this.destroyed = true;
+ var hostElement =
+ this.proto.type === ViewType.COMPONENT ? this.containerAppElement.nativeElement : null;
+ this.renderer.destroyView(hostElement, this.allNodes);
+ for (var i = 0; i < this.disposables.length; i++) {
+ this.disposables[i]();
}
- var templateName = this.proto.templateVariableBindings.get(contextName);
- this.locals.set(templateName, value);
+ this.viewManager.onViewDestroyed(this);
}
- hydrated(): boolean { return isPresent(this.context); }
+ get changeDetectorRef(): ChangeDetectorRef { return this.changeDetector.ref; }
- /**
- * Triggers the event handlers for the element and the directives.
- *
- * This method is intended to be called from directive EventEmitters.
- *
- * @param {string} eventName
- * @param {*} eventObj
- * @param {number} boundElementIndex
- */
- triggerEventHandlers(eventName: string, eventObj: Event, boundElementIndex: number): void {
- var locals = new Map();
- locals.set('$event', eventObj);
- this.dispatchEvent(boundElementIndex, eventName, locals);
+ get flatRootNodes(): any[] { return flattenNestedViewRenderNodes(this.rootNodesOrAppElements); }
+
+ hasLocal(contextName: string): boolean {
+ return StringMapWrapper.contains(this.proto.templateVariableBindings, contextName);
+ }
+
+ setLocal(contextName: string, value: any): void {
+ if (!this.hasLocal(contextName)) {
+ return;
+ }
+ var templateName = this.proto.templateVariableBindings[contextName];
+ this.locals.set(templateName, value);
}
// dispatch to element injector or text nodes based on context
notifyOnBinding(b: BindingTarget, currentValue: any): void {
if (b.isTextNode()) {
- this.renderer.setText(this.render, b.elementIndex + this.textOffset, currentValue);
+ this.renderer.setText(this.allNodes[b.elementIndex], currentValue);
} else {
- var elementRef = this.elementRefs[this.elementOffset + b.elementIndex];
+ var nativeElement = this.appElements[b.elementIndex].nativeElement;
if (b.isElementProperty()) {
- this.renderer.setElementProperty(elementRef, b.name, currentValue);
+ this.renderer.setElementProperty(nativeElement, b.name, currentValue);
} else if (b.isElementAttribute()) {
- this.renderer.setElementAttribute(elementRef, b.name,
+ this.renderer.setElementAttribute(nativeElement, b.name,
isPresent(currentValue) ? `${currentValue}` : null);
} else if (b.isElementClass()) {
- this.renderer.setElementClass(elementRef, b.name, currentValue);
+ this.renderer.setElementClass(nativeElement, b.name, currentValue);
} else if (b.isElementStyle()) {
var unit = isPresent(b.unit) ? b.unit : '';
- this.renderer.setElementStyle(elementRef, b.name,
+ this.renderer.setElementStyle(nativeElement, b.name,
isPresent(currentValue) ? `${currentValue}${unit}` : null);
} else {
throw new BaseException('Unsupported directive record');
@@ -172,57 +202,39 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
logBindingUpdate(b: BindingTarget, value: any): void {
if (b.isDirective() || b.isElementProperty()) {
- var elementRef = this.elementRefs[this.elementOffset + b.elementIndex];
+ var nativeElement = this.appElements[b.elementIndex].nativeElement;
this.renderer.setBindingDebugInfo(
- elementRef, `${REFLECT_PREFIX}${camelCaseToDashCase(b.name)}`, `${value}`);
+ nativeElement, `${REFLECT_PREFIX}${camelCaseToDashCase(b.name)}`, `${value}`);
}
}
notifyAfterContentChecked(): void {
- var eiCount = this.proto.elementBinders.length;
- var ei = this.elementInjectors;
- for (var i = eiCount - 1; i >= 0; i--) {
- if (isPresent(ei[i + this.elementOffset])) ei[i + this.elementOffset].ngAfterContentChecked();
+ var count = this.appElements.length;
+ for (var i = count - 1; i >= 0; i--) {
+ this.appElements[i].ngAfterContentChecked();
}
}
notifyAfterViewChecked(): void {
- var eiCount = this.proto.elementBinders.length;
- var ei = this.elementInjectors;
- for (var i = eiCount - 1; i >= 0; i--) {
- if (isPresent(ei[i + this.elementOffset])) ei[i + this.elementOffset].ngAfterViewChecked();
+ var count = this.appElements.length;
+ for (var i = count - 1; i >= 0; i--) {
+ this.appElements[i].ngAfterViewChecked();
}
}
- getDirectiveFor(directive: DirectiveIndex): any {
- var elementInjector = this.elementInjectors[this.elementOffset + directive.elementIndex];
- return elementInjector.getDirectiveAtIndex(directive.directiveIndex);
- }
-
- getNestedView(boundElementIndex: number): AppView {
- var eli = this.elementInjectors[boundElementIndex];
- return isPresent(eli) ? eli.getNestedView() : null;
- }
-
- getContainerElement(): ElementRef {
- return isPresent(this.containerElementInjector) ?
- this.containerElementInjector.getElementRef() :
- null;
- }
-
- getDebugContext(elementIndex: number, directiveIndex: DirectiveIndex): DebugContext {
+ getDebugContext(appElement: AppElement, elementIndex: number,
+ directiveIndex: number): DebugContext {
try {
- var offsettedIndex = this.elementOffset + elementIndex;
- var hasRefForIndex = offsettedIndex < this.elementRefs.length;
-
- var elementRef = hasRefForIndex ? this.elementRefs[this.elementOffset + elementIndex] : null;
- var container = this.getContainerElement();
- var ei = hasRefForIndex ? this.elementInjectors[this.elementOffset + elementIndex] : null;
+ if (isBlank(appElement) && elementIndex < this.appElements.length) {
+ appElement = this.appElements[elementIndex];
+ }
+ var container = this.containerAppElement;
- var element = isPresent(elementRef) ? elementRef.nativeElement : null;
+ var element = isPresent(appElement) ? appElement.nativeElement : null;
var componentElement = isPresent(container) ? container.nativeElement : null;
- var directive = isPresent(directiveIndex) ? this.getDirectiveFor(directiveIndex) : null;
- var injector = isPresent(ei) ? ei.getInjector() : null;
+ var directive =
+ isPresent(directiveIndex) ? appElement.getDirectiveAtIndex(directiveIndex) : null;
+ var injector = isPresent(appElement) ? appElement.getInjector() : null;
return new DebugContext(element, componentElement, directive, this.context,
_localsToStringMap(this.locals), injector);
@@ -234,43 +246,28 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
}
}
- getDetectorFor(directive: DirectiveIndex): any {
- var childView = this.getNestedView(this.elementOffset + directive.elementIndex);
- return isPresent(childView) ? childView.changeDetector : null;
- }
-
- invokeElementMethod(elementIndex: number, methodName: string, args: any[]) {
- this.renderer.invokeElementMethod(this.elementRefs[elementIndex], methodName, args);
+ getDirectiveFor(directive: DirectiveIndex): any {
+ return this.appElements[directive.elementIndex].getDirectiveAtIndex(directive.directiveIndex);
}
- // implementation of RenderEventDispatcher#dispatchRenderEvent
- dispatchRenderEvent(boundElementIndex: number, eventName: string,
- locals: Map): boolean {
- var elementRef = this.elementRefs[boundElementIndex];
- var view = internalView(elementRef.parentView);
- return view.dispatchEvent(elementRef.boundElementIndex, eventName, locals);
+ getDetectorFor(directive: DirectiveIndex): any {
+ var componentView = this.appElements[directive.elementIndex].componentView;
+ return isPresent(componentView) ? componentView.changeDetector : null;
}
-
- // returns false if preventDefault must be applied to the DOM event
- dispatchEvent(boundElementIndex: number, eventName: string, locals: Map): boolean {
- try {
- if (this.hydrated()) {
- return !this.changeDetector.handleEvent(eventName, boundElementIndex - this.elementOffset,
- new Locals(this.locals, locals));
- } else {
- return true;
- }
- } catch (e) {
- var c = this.getDebugContext(boundElementIndex - this.elementOffset, null);
- var context = isPresent(c) ? new _Context(c.element, c.componentElement, c.context, c.locals,
- c.injector) :
- null;
- throw new EventEvaluationError(eventName, e, e.stack, context);
- }
+ /**
+ * Triggers the event handlers for the element and the directives.
+ *
+ * This method is intended to be called from directive EventEmitters.
+ *
+ * @param {string} eventName
+ * @param {*} eventObj
+ * @param {number} boundElementIndex
+ * @return false if preventDefault must be applied to the DOM event
+ */
+ triggerEventHandlers(eventName: string, eventObj: Event, boundElementIndex: number): boolean {
+ return this.changeDetector.handleEvent(eventName, boundElementIndex, eventObj);
}
-
- get ownBindersCount(): number { return this.proto.elementBinders.length; }
}
function _localsToStringMap(locals: Locals): {[key: string]: any} {
@@ -284,68 +281,60 @@ function _localsToStringMap(locals: Locals): {[key: string]: any} {
}
/**
- * Error context included when an event handler throws an exception.
- */
-class _Context {
- constructor(public element: any, public componentElement: any, public context: any,
- public locals: any, public injector: any) {}
-}
-
-/**
- * Wraps an exception thrown by an event handler.
+ *
*/
-class EventEvaluationError extends WrappedException {
- constructor(eventName: string, originalException: any, originalStack: any, context: any) {
- super(`Error during evaluation of "${eventName}"`, originalException, originalStack, context);
+export class AppProtoView {
+ static create(metadataCache: ResolvedMetadataCache, type: ViewType, pipes: Type[],
+ templateVariableBindings: {[key: string]: string}): AppProtoView {
+ var protoPipes = null;
+ if (isPresent(pipes) && pipes.length > 0) {
+ var boundPipes = ListWrapper.createFixedSize(pipes.length);
+ for (var i = 0; i < pipes.length; i++) {
+ boundPipes[i] = metadataCache.getResolvedPipeMetadata(pipes[i]);
+ }
+ protoPipes = ProtoPipes.fromProviders(boundPipes);
+ }
+ return new AppProtoView(type, protoPipes, templateVariableBindings);
}
+
+ constructor(public type: ViewType, public protoPipes: ProtoPipes,
+ public templateVariableBindings: {[key: string]: string}) {}
}
-export class AppProtoViewMergeInfo {
- constructor(public embeddedViewCount: number, public elementCount: number,
- public viewCount: number) {}
+
+@CONST()
+export class HostViewFactory {
+ constructor(public selector: string, public viewFactory: Function) {}
}
-/**
- *
- */
-export class AppProtoView {
- ref: ProtoViewRef;
- protoLocals: Map;
-
- elementBinders: ElementBinder[] = null;
- mergeInfo: AppProtoViewMergeInfo = null;
- variableLocations: Map = null;
- textBindingCount = null;
- render: renderApi.RenderProtoViewRef = null;
-
- constructor(public templateId: string, public templateCmds: TemplateCmd[], public type: ViewType,
- public isMergable: boolean, public changeDetectorFactory: Function,
- public templateVariableBindings: Map, public pipes: ProtoPipes) {
- this.ref = new ProtoViewRef_(this);
- }
+export function flattenNestedViewRenderNodes(nodes: any[]): any[] {
+ return _flattenNestedViewRenderNodes(nodes, []);
+}
- init(render: renderApi.RenderProtoViewRef, elementBinders: ElementBinder[],
- textBindingCount: number, mergeInfo: AppProtoViewMergeInfo,
- variableLocations: Map) {
- this.render = render;
- this.elementBinders = elementBinders;
- this.textBindingCount = textBindingCount;
- this.mergeInfo = mergeInfo;
- this.variableLocations = variableLocations;
- this.protoLocals = new Map();
- if (isPresent(this.templateVariableBindings)) {
- this.templateVariableBindings.forEach(
- (templateName, _) => { this.protoLocals.set(templateName, null); });
- }
- if (isPresent(variableLocations)) {
- // The view's locals needs to have a full set of variable names at construction time
- // in order to prevent new variables from being set later in the lifecycle. Since we don't
- // want
- // to actually create variable bindings for the $implicit bindings, add to the
- // protoLocals manually.
- variableLocations.forEach((_, templateName) => { this.protoLocals.set(templateName, null); });
+function _flattenNestedViewRenderNodes(nodes: any[], renderNodes: any[]): any[] {
+ for (var i = 0; i < nodes.length; i++) {
+ var node = nodes[i];
+ if (node instanceof AppElement) {
+ var appEl = node;
+ renderNodes.push(appEl.nativeElement);
+ if (isPresent(appEl.nestedViews)) {
+ for (var k = 0; k < appEl.nestedViews.length; k++) {
+ _flattenNestedViewRenderNodes(appEl.nestedViews[k].rootNodesOrAppElements, renderNodes);
+ }
+ }
+ } else {
+ renderNodes.push(node);
}
}
+ return renderNodes;
+}
- isInitialized(): boolean { return isPresent(this.elementBinders); }
+export function checkSlotCount(componentName: string, expectedSlotCount: number,
+ projectableNodes: any[][]): void {
+ var givenSlotCount = isPresent(projectableNodes) ? projectableNodes.length : 0;
+ if (givenSlotCount < expectedSlotCount) {
+ throw new BaseException(
+ `The component ${componentName} has ${expectedSlotCount} elements,` +
+ ` but only ${givenSlotCount} slots were provided.`);
+ }
}
diff --git a/modules/angular2/src/core/linker/view_container_ref.ts b/modules/angular2/src/core/linker/view_container_ref.ts
index 45f2fd008af6f..b8561ed108414 100644
--- a/modules/angular2/src/core/linker/view_container_ref.ts
+++ b/modules/angular2/src/core/linker/view_container_ref.ts
@@ -3,12 +3,18 @@ import {unimplemented} from 'angular2/src/facade/exceptions';
import {ResolvedProvider} from 'angular2/src/core/di';
import {isPresent, isBlank} from 'angular2/src/facade/lang';
-import * as avmModule from './view_manager';
-import * as viewModule from './view';
+import {AppElement} from './element';
import {ElementRef, ElementRef_} from './element_ref';
-import {TemplateRef} from './template_ref';
-import {ViewRef, HostViewRef, ProtoViewRef, internalView} from './view_ref';
+import {TemplateRef, TemplateRef_} from './template_ref';
+import {
+ EmbeddedViewRef,
+ HostViewRef,
+ HostViewFactoryRef,
+ HostViewFactoryRef_,
+ ViewRef,
+ ViewRef_
+} from './view_ref';
/**
* Represents a container where one or more Views can be attached.
@@ -35,7 +41,7 @@ export abstract class ViewContainerRef {
* Anchor element that specifies the location of this container in the containing View.
*
*/
- public element: ElementRef;
+ get element(): ElementRef { return unimplemented(); }
/**
* Destroys all Views in this container.
@@ -64,7 +70,7 @@ export abstract class ViewContainerRef {
*
* Returns the {@link ViewRef} for the newly created View.
*/
- abstract createEmbeddedView(templateRef: TemplateRef, index?: number): ViewRef;
+ abstract createEmbeddedView(templateRef: TemplateRef, index?: number): EmbeddedViewRef;
/**
* Instantiates a single {@link Component} and inserts its Host View into this container at the
@@ -80,8 +86,9 @@ export abstract class ViewContainerRef {
*
* Returns the {@link HostViewRef} of the Host View created for the newly instantiated Component.
*/
- abstract createHostView(protoViewRef?: ProtoViewRef, index?: number,
- dynamicallyCreatedProviders?: ResolvedProvider[]): HostViewRef;
+ abstract createHostView(hostViewFactoryRef: HostViewFactoryRef, index?: number,
+ dynamicallyCreatedProviders?: ResolvedProvider[],
+ projectableNodes?: any[][]): HostViewRef;
/**
* Inserts a View identified by a {@link ViewRef} into the container at the specified `index`.
@@ -90,7 +97,7 @@ export abstract class ViewContainerRef {
*
* Returns the inserted {@link ViewRef}.
*/
- abstract insert(viewRef: ViewRef, index?: number): ViewRef;
+ abstract insert(viewRef: EmbeddedViewRef, index?: number): EmbeddedViewRef;
/**
* Returns the index of the View, specified via {@link ViewRef}, within the current container or
@@ -110,58 +117,60 @@ export abstract class ViewContainerRef {
*
* If the `index` param is omitted, the last {@link ViewRef} is detached.
*/
- abstract detach(index?: number): ViewRef;
+ abstract detach(index?: number): EmbeddedViewRef;
}
export class ViewContainerRef_ extends ViewContainerRef {
- constructor(public viewManager: avmModule.AppViewManager, element: ElementRef) {
- super();
- this.element = element;
- }
+ constructor(private _element: AppElement) { super(); }
- private _getViews(): Array {
- let element = this.element;
- var vc = internalView(element.parentView).viewContainers[element.boundElementIndex];
- return isPresent(vc) ? vc.views : [];
+ get(index: number): EmbeddedViewRef { return this._element.nestedViews[index].ref; }
+ get length(): number {
+ var views = this._element.nestedViews;
+ return isPresent(views) ? views.length : 0;
}
- get(index: number): ViewRef { return this._getViews()[index].ref; }
- get length(): number { return this._getViews().length; }
+ get element(): ElementRef_ { return this._element.ref; }
// TODO(rado): profile and decide whether bounds checks should be added
// to the methods below.
- createEmbeddedView(templateRef: TemplateRef, index: number = -1): ViewRef {
+ createEmbeddedView(templateRef: TemplateRef_, index: number = -1): EmbeddedViewRef {
if (index == -1) index = this.length;
- return this.viewManager.createEmbeddedViewInContainer(this.element, index, templateRef);
+ var vm = this._element.parentView.viewManager;
+ return vm.createEmbeddedViewInContainer(this._element.ref, index, templateRef);
}
- createHostView(protoViewRef: ProtoViewRef = null, index: number = -1,
- dynamicallyCreatedProviders: ResolvedProvider[] = null): HostViewRef {
+ createHostView(hostViewFactoryRef: HostViewFactoryRef_, index: number = -1,
+ dynamicallyCreatedProviders: ResolvedProvider[] = null,
+ projectableNodes: any[][] = null): HostViewRef {
if (index == -1) index = this.length;
- return this.viewManager.createHostViewInContainer(this.element, index, protoViewRef,
- dynamicallyCreatedProviders);
+ var vm = this._element.parentView.viewManager;
+ return vm.createHostViewInContainer(this._element.ref, index, hostViewFactoryRef,
+ dynamicallyCreatedProviders, projectableNodes);
}
// TODO(i): refactor insert+remove into move
- insert(viewRef: ViewRef, index: number = -1): ViewRef {
+ insert(viewRef: ViewRef_, index: number = -1): EmbeddedViewRef {
if (index == -1) index = this.length;
- return this.viewManager.attachViewInContainer(this.element, index, viewRef);
+ var vm = this._element.parentView.viewManager;
+ return vm.attachViewInContainer(this._element.ref, index, viewRef);
}
- indexOf(viewRef: ViewRef): number {
- return ListWrapper.indexOf(this._getViews(), internalView(viewRef));
+ indexOf(viewRef: ViewRef_): number {
+ return ListWrapper.indexOf(this._element.nestedViews, viewRef.internalView);
}
// TODO(i): rename to destroy
remove(index: number = -1): void {
if (index == -1) index = this.length - 1;
- this.viewManager.destroyViewInContainer(this.element, index);
+ var vm = this._element.parentView.viewManager;
+ return vm.destroyViewInContainer(this._element.ref, index);
// view is intentionally not returned to the client.
}
// TODO(i): refactor insert+remove into move
- detach(index: number = -1): ViewRef {
+ detach(index: number = -1): EmbeddedViewRef {
if (index == -1) index = this.length - 1;
- return this.viewManager.detachViewInContainer(this.element, index);
+ var vm = this._element.parentView.viewManager;
+ return vm.detachViewInContainer(this._element.ref, index);
}
}
diff --git a/modules/angular2/src/core/linker/view_manager.ts b/modules/angular2/src/core/linker/view_manager.ts
index 300608f41b021..57a0a82da848b 100644
--- a/modules/angular2/src/core/linker/view_manager.ts
+++ b/modules/angular2/src/core/linker/view_manager.ts
@@ -6,24 +6,27 @@ import {
ResolvedProvider,
forwardRef
} from 'angular2/src/core/di';
-import {isPresent, isBlank} from 'angular2/src/facade/lang';
+import {isPresent, isBlank, isArray} from 'angular2/src/facade/lang';
+import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {BaseException} from 'angular2/src/facade/exceptions';
-import * as viewModule from './view';
+import {AppView, HostViewFactory, flattenNestedViewRenderNodes} from './view';
+import {AppElement} from './element';
import {ElementRef, ElementRef_} from './element_ref';
-import {ProtoViewRef, ViewRef, HostViewRef, internalView, internalProtoView} from './view_ref';
+import {
+ HostViewFactoryRef,
+ HostViewFactoryRef_,
+ EmbeddedViewRef,
+ HostViewRef,
+ ViewRef_
+} from './view_ref';
import {ViewContainerRef} from './view_container_ref';
import {TemplateRef, TemplateRef_} from './template_ref';
-import {
- Renderer,
- RenderViewRef,
- RenderFragmentRef,
- RenderViewWithFragments
-} from 'angular2/src/core/render/api';
-import {AppViewManagerUtils} from './view_manager_utils';
-import {AppViewPool} from './view_pool';
import {AppViewListener} from './view_listener';
+import {RootRenderer, RenderComponentType} from 'angular2/src/core/render/api';
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
-import {ProtoViewFactory} from './proto_view_factory';
+import {APP_ID} from 'angular2/src/core/application_tokens';
+import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
+import {ViewType} from './view_type';
/**
* Service exposing low level API for creating, moving and destroying Views.
@@ -40,13 +43,7 @@ export abstract class AppViewManager {
/**
* Returns the {@link ElementRef} that makes up the specified Host View.
*/
- getHostElement(hostViewRef: HostViewRef): ElementRef {
- var hostView = internalView(hostViewRef);
- if (hostView.proto.type !== viewModule.ViewType.HOST) {
- throw new BaseException('This operation is only allowed on host views');
- }
- return hostView.elementRefs[hostView.elementOffset];
- }
+ abstract getHostElement(hostViewRef: HostViewRef): ElementRef;
/**
* Searches the Component View of the Component specified via `hostLocation` and returns the
@@ -70,7 +67,8 @@ export abstract class AppViewManager {
* This as a low-level way to bootstrap an application and upgrade an existing Element to a
* Host Element. Most applications should use {@link DynamicComponentLoader#loadAsRoot} instead.
*
- * The Component and its View are created based on the `hostProtoViewRef` which can be obtained
+ * The Component and its View are created based on the `hostProtoComponentRef` which can be
+ * obtained
* by compiling the component with {@link Compiler#compileInHost}.
*
* Use {@link AppViewManager#destroyRootHostView} to destroy the created Component and it's Host
@@ -101,7 +99,7 @@ export abstract class AppViewManager {
* viewRef: ng.ViewRef;
*
* constructor(public appViewManager: ng.AppViewManager, compiler: ng.Compiler) {
- * compiler.compileInHost(ChildComponent).then((protoView: ng.ProtoViewRef) => {
+ * compiler.compileInHost(ChildComponent).then((protoView: ng.ProtoComponentRef) => {
* this.viewRef = appViewManager.createRootHostView(protoView, 'some-component', null);
* })
* }
@@ -115,8 +113,8 @@ export abstract class AppViewManager {
* ng.bootstrap(MyApp);
* ```
*/
- abstract createRootHostView(hostProtoViewRef: ProtoViewRef, overrideSelector: string,
- injector: Injector): HostViewRef;
+ abstract createRootHostView(hostViewFactoryRef: HostViewFactoryRef, overrideSelector: string,
+ injector: Injector, projectableNodes?: any[][]): HostViewRef;
/**
* Destroys the Host View created via {@link AppViewManager#createRootHostView}.
@@ -140,7 +138,7 @@ export abstract class AppViewManager {
// TODO(i): this low-level version of ViewContainerRef#createEmbeddedView doesn't add anything new
// we should make it private, otherwise we have two apis to do the same thing.
abstract createEmbeddedViewInContainer(viewContainerLocation: ElementRef, index: number,
- templateRef: TemplateRef): ViewRef;
+ templateRef: TemplateRef): EmbeddedViewRef;
/**
* Instantiates a single {@link Component} and inserts its Host View into the View Container
@@ -150,16 +148,16 @@ export abstract class AppViewManager {
* The component is instantiated using its {@link ProtoViewRef `protoViewRef`} which can be
* obtained via {@link Compiler#compileInHost}.
*
- * You can optionally specify `imperativelyCreatedInjector`, which configure the {@link Injector}
+ * You can optionally specify `dynamicallyCreatedProviders`, which configure the {@link Injector}
* that will be created for the Host View.
*
* Returns the {@link HostViewRef} of the Host View created for the newly instantiated Component.
*
* Use {@link AppViewManager#destroyViewInContainer} to destroy the created Host View.
*/
- abstract createHostViewInContainer(viewContainerLocation: ElementRef, index: number,
- protoViewRef: ProtoViewRef,
- imperativelyCreatedInjector: ResolvedProvider[]): HostViewRef;
+ abstract createHostViewInContainer(
+ viewContainerLocation: ElementRef, index: number, hostViewFactoryRef: HostViewFactoryRef,
+ dynamicallyCreatedProviders: ResolvedProvider[], projectableNodes: any[][]): HostViewRef;
/**
* Destroys an Embedded or Host View attached to a View Container at the specified `index`.
@@ -174,85 +172,75 @@ export abstract class AppViewManager {
*/
// TODO(i): refactor detachViewInContainer+attachViewInContainer to moveViewInContainer
abstract attachViewInContainer(viewContainerLocation: ElementRef, index: number,
- viewRef: ViewRef): ViewRef;
+ viewRef: EmbeddedViewRef): EmbeddedViewRef;
/**
* See {@link AppViewManager#attachViewInContainer}.
*/
- abstract detachViewInContainer(viewContainerLocation: ElementRef, index: number): ViewRef;
+ abstract detachViewInContainer(viewContainerLocation: ElementRef, index: number): EmbeddedViewRef;
}
@Injectable()
export class AppViewManager_ extends AppViewManager {
- private _protoViewFactory: ProtoViewFactory;
+ private _nextCompTypeId: number = 0;
- constructor(private _viewPool: AppViewPool, private _viewListener: AppViewListener,
- private _utils: AppViewManagerUtils, private _renderer: Renderer,
- @Inject(forwardRef(() => ProtoViewFactory)) _protoViewFactory) {
+ constructor(private _renderer: RootRenderer, private _viewListener: AppViewListener,
+ @Inject(APP_ID) private _appId: string) {
super();
- this._protoViewFactory = _protoViewFactory;
}
- getViewContainer(location: ElementRef): ViewContainerRef {
- var hostView = internalView((location).parentView);
- return hostView.elementInjectors[(location).boundElementIndex]
- .getViewContainerRef();
+ getViewContainer(location: ElementRef_): ViewContainerRef {
+ return location.internalElement.getViewContainerRef();
+ }
+
+ getHostElement(hostViewRef: ViewRef_): ElementRef {
+ var hostView = hostViewRef.internalView;
+ if (hostView.proto.type !== ViewType.HOST) {
+ throw new BaseException('This operation is only allowed on host views');
+ }
+ return hostView.appElements[0].ref;
}
- getNamedElementInComponentView(hostLocation: ElementRef, variableName: string): ElementRef {
- var hostView = internalView((hostLocation).parentView);
- var boundElementIndex = (