perf: delete pre-view-engine core, compiler, platform-browser, etc code (#14788)
After the introduction of the view engine, we can drop a lot of code that is not used any more. This should reduce the size of the app bundles because a lot of this code was not being properly tree-shaken by today's tools even though it was dead code.
This commit is contained in:
@ -1,168 +0,0 @@
|
||||
# Ng2 Faster Than BaseLine (FTL) Benchmark
|
||||
|
||||
This benchmark was produced in a similar way as `ng2_static_ftl`,
|
||||
but starting from the `ng2` benchmark, i.e. the benchmark
|
||||
that only uses 1 component that contains itself via 2 `NgIf`s.
|
||||
|
||||
1. Run AoT over the `TreeComponent` and `AppModule`
|
||||
2. Move the `ComponentFactory` and the corresponding host view class
|
||||
from `tree.ngfactory.ts` into `tree_host.ngfactory.ts`
|
||||
3. Move the `NgModuleFactory` into the `app.ngfactory.ts`
|
||||
4. Optimize the `tree.ngfactory.ts` (see below)
|
||||
|
||||
The goal of this benchmark is to explore what kind of
|
||||
code the Ng2 compiler should generate in order to get faster.
|
||||
I.e. right now, the Ng2 compiler _does not_ produce this kind of code,
|
||||
but hopefully will in the future.
|
||||
|
||||
|
||||
## Optimizations and cleanups
|
||||
|
||||
See `tree.ngfactory.ts` and `tree_leaf.ngfactory.ts`.
|
||||
|
||||
Performance:
|
||||
|
||||
- remove view factory functions, call the constructor of the view class directly
|
||||
- remove `createInternal` and move the logic into the constructor
|
||||
- generate direct calls to `detectChangesInternal` / `destroyInternal` of nested components
|
||||
_and_ view containers, don't use `viewChildren` / `contentChildren`
|
||||
- remove `Renderer` and `SanitizationService` to update
|
||||
the dom directly via `document.createElement` / `element.appendChild` / setting
|
||||
`Text.nodeValue` / `Element.style....`
|
||||
- remove `AppElement` on component host elements
|
||||
- custom implementation of `ViewContainerRef` that uses
|
||||
the views as linked list, instead of an array (see `ftl_util`).
|
||||
- custom implementation of TemplateRef which not use a closure, only a view and an index,
|
||||
and the view has a factory method that switches over the index
|
||||
(see `ftl_util`).
|
||||
- Don't wrap Views into ViewRefs before passing to the user.
|
||||
- View does not use an array to store root nodes,
|
||||
but rather has a generated method `visitRootNodes` (see below)
|
||||
- ViewContainer, TemplateRef and views have minimal amount of fields
|
||||
- use `insertBefore` as primitive.
|
||||
|
||||
Code size:
|
||||
- inputs for `NgIf`, `TreeComponent` are wrapped into view class / directive wrapper method
|
||||
(see `ng_if.ngfactory.ts` and `tree.ngfactory.ts`).
|
||||
- helper methods `createElementAndAppend` / `createTextAndAppend` / `createAnchorAndAppend`
|
||||
- remove `injectorGetInternal` assuming we can detect that nobody is injecting an `Injector`
|
||||
|
||||
## Properties
|
||||
- no allocation of arrays nor closures
|
||||
|
||||
## Background: why `visitRootNodes`?
|
||||
|
||||
* An embedded view has root nodes that need to be attached / detached
|
||||
to the DOM when the view is inserted.
|
||||
* An embedded view can have view containers as root nodes. I.e. the root nodes
|
||||
of a view need to include the root nodes of all views in root view containers
|
||||
* An embedded view can have `<ng-content>` as root nodes. I.e. the root
|
||||
nodes of a view need to include the projects nodes, which can
|
||||
include a view container, in which case they need to include the root nodes
|
||||
of all included views as well.
|
||||
|
||||
Previous implementation:
|
||||
The generated view classes would store a (possible nested) array of root nodes
|
||||
that can contain regular DOM nodes as well as ViewContainers.
|
||||
The helper method `flattenNestedViewRootNodes` is used to convert this array
|
||||
into a flat array of node.
|
||||
However, this generates a new array and is probably hard to optimize for
|
||||
a vm.
|
||||
|
||||
### Solution
|
||||
Generate loop functions / methods.
|
||||
I.e. a method like:
|
||||
```
|
||||
loopRootNodes(cb: (obj: any, ctx: any), ctx: any) {
|
||||
cb(this.node0, ctx);
|
||||
...
|
||||
}
|
||||
```
|
||||
These methods can easily be nested, i.e. a view container
|
||||
can just loop over its views and call this method,
|
||||
forwarding the callback!
|
||||
|
||||
Same is true for projection!
|
||||
==> Tried it, no impact on the benchmark!
|
||||
|
||||
### Discarded Solution 1)
|
||||
Generate `attach` / `detach` method on EmbeddedView,
|
||||
which will `insertBefore` the root nodes. Also
|
||||
generate `project` and `unproject` methods in the caller
|
||||
of a component to add / remove nodes.
|
||||
|
||||
Problems:
|
||||
- generates a lot of code!
|
||||
- projected nodes can only be inserted into the DOM via
|
||||
`insertBefore`, but never via `appendChild` as
|
||||
the generated method `project` does it,
|
||||
and it can do only one of these two, but not both.
|
||||
|
||||
### Discarded Solution 2)
|
||||
Generate a method `rootNodes` on every view that will
|
||||
do produce a flattened array of nodes by generating the
|
||||
right `concat` statements.
|
||||
|
||||
Problems:
|
||||
- allocates arrays and `concat` calls that slows things down
|
||||
(an experiment showed about about 2-5%).
|
||||
|
||||
## Experiments tried
|
||||
- just the fact of having another base class in the prototype chain
|
||||
is not a problem!
|
||||
- Using a linked list over the views vs an array in ViewContainerRef
|
||||
has no impact on performance, given that we use `Array.prototype.push`
|
||||
for adding if possible (only tried with ngIf though...)
|
||||
* Using `Array.prototype.splice` to add made benchmark 2% slower though!
|
||||
- creating an array with root nodes does not make the benchmark much slower.
|
||||
* Using `flattenNestedViewRootNodes` made it 5-10% slower!
|
||||
* Note that this benchmark only includes `NgIf`, i.e. it only
|
||||
inserts 1 entry into the array.
|
||||
- creating an additional comment node for the view container,
|
||||
so it is safe to do `insertBefore`
|
||||
* this slows the benchmark down by 14% (added 2 comment nodes)!
|
||||
==> the number of comment nodes is important!
|
||||
|
||||
## Open experiments:
|
||||
- using ViewRef as a separate wrapper, compared to
|
||||
using the view itself as ref.
|
||||
- using AppElement with an injector, native node, ...,
|
||||
compared to not having all of these fields
|
||||
- using `insertAfter` instead of `insertBefore`?
|
||||
|
||||
## Initial resuls: size
|
||||
|
||||
File size for view class of the component + the 2 embedded view classes (without imports nor host view factory):
|
||||
* before: 140 LOC
|
||||
* after: 104 LOC
|
||||
|
||||
## Initial results: Deep Tree Benchmark
|
||||
|
||||
BENCHMARK deepTree....
|
||||
Description:
|
||||
- bundles: false
|
||||
- depth: 11
|
||||
- forceGc: false
|
||||
- regressionSlopeMetric: scriptTime
|
||||
- runId: f9ae32f0-8580-11e6-914d-9f4f8dbfb5e8
|
||||
- sampleSize: 20
|
||||
- userAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36
|
||||
|
||||
...createOnly | gcAmount | gcTime | majorGcTime | pureScriptTime | renderTime | scriptTime
|
||||
--------------- | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------
|
||||
ng2 | 5926.64+-11% | 17.46+-5% | 0.02+-44% | 96.74+-9% | 49.72+-5% | 114.19+-8%
|
||||
ng2.ftl | 584.50+-435% | 0.43+-435% | 0.00+-435% | 33.98+-7% | 50.27+-5% | 33.98+-7%
|
||||
baseline | 0.00 | 0.00 | 0.00 | 15.83+-7% | 45.75+-4% | 15.83+-7%
|
||||
incremental_dom | 100.82+-302% | 1.64+-321% | 0.00+-304% | 53.43+-9% | 43.96+-4% | 55.07+-13%
|
||||
|
||||
...update | gcAmount | gcTime | majorGcTime | pureScriptTime | renderTime | scriptTime
|
||||
--------------- | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------
|
||||
ng2 | 0.00 | 0.00+-435% | 0.00+-435% | 22.82+-9% | 29.52+-6% | 22.82+-9%
|
||||
ng2.ftl | 219.72+-301% | 0.97+-300% | 0.00+-302% | 17.37+-10% | 29.27+-5% | 17.37+-10%
|
||||
baseline | 530.73+-178% | 0.55+-281% | 0.35+-434% | 25.82+-8% | 31.67+-11% | 25.82+-8%
|
||||
incremental_dom | 1057.56+-200% | 0.28+-201% | 0.00+-204% | 22.50+-9% | 28.03+-4% | 22.50+-9%
|
||||
|
||||
Ratios (create, pureScriptTime):
|
||||
- 2.8x faster than current implementation
|
||||
- 1.5x faster than incremental DOM
|
||||
- 2.1x slower than baseline
|
@ -1,328 +0,0 @@
|
||||
/**
|
||||
* This file is generated by the Angular template compiler.
|
||||
* Do not edit.
|
||||
*/
|
||||
/* tslint:disable */
|
||||
|
||||
import * as import2 from '@angular/common/src/common_module';
|
||||
import * as import5 from '@angular/common/src/localization';
|
||||
import * as import34 from '@angular/core/src/animation/animation_queue';
|
||||
import * as import6 from '@angular/core/src/application_init';
|
||||
import * as import3 from '@angular/core/src/application_module';
|
||||
import * as import8 from '@angular/core/src/application_ref';
|
||||
import * as import19 from '@angular/core/src/application_tokens';
|
||||
import * as import31 from '@angular/core/src/change_detection/differs/iterable_differs';
|
||||
import * as import32 from '@angular/core/src/change_detection/differs/keyvalue_differs';
|
||||
import * as import24 from '@angular/core/src/console';
|
||||
import * as import17 from '@angular/core/src/di/injector';
|
||||
import * as import26 from '@angular/core/src/error_handler';
|
||||
import * as import33 from '@angular/core/src/i18n/tokens';
|
||||
import * as import25 from '@angular/core/src/i18n/tokens';
|
||||
import * as import9 from '@angular/core/src/linker/compiler';
|
||||
import * as import0 from '@angular/core/src/linker/ng_module_factory';
|
||||
import * as import15 from '@angular/core/src/linker/view_utils';
|
||||
import * as import29 from '@angular/core/src/render/api';
|
||||
import * as import30 from '@angular/core/src/security';
|
||||
import * as import7 from '@angular/core/src/testability/testability';
|
||||
import * as import22 from '@angular/core/src/zone/ng_zone';
|
||||
import * as import4 from '@angular/platform-browser/src/browser';
|
||||
import * as import16 from '@angular/platform-browser/src/browser/title';
|
||||
import * as import28 from '@angular/platform-browser/src/dom/animation_driver';
|
||||
import * as import23 from '@angular/platform-browser/src/dom/debug/ng_probe';
|
||||
import * as import13 from '@angular/platform-browser/src/dom/dom_renderer';
|
||||
import * as import27 from '@angular/platform-browser/src/dom/dom_tokens';
|
||||
import * as import20 from '@angular/platform-browser/src/dom/events/dom_events';
|
||||
import * as import11 from '@angular/platform-browser/src/dom/events/event_manager';
|
||||
import * as import10 from '@angular/platform-browser/src/dom/events/hammer_gestures';
|
||||
import * as import21 from '@angular/platform-browser/src/dom/events/key_events';
|
||||
import * as import12 from '@angular/platform-browser/src/dom/shared_styles_host';
|
||||
import * as import14 from '@angular/platform-browser/src/security/dom_sanitization_service';
|
||||
|
||||
import * as import1 from './tree';
|
||||
import * as import18 from './tree_host.ngfactory';
|
||||
|
||||
class AppModuleInjector extends import0.NgModuleInjector<import1.AppModule> {
|
||||
_CommonModule_0: import2.CommonModule;
|
||||
_ApplicationModule_1: import3.ApplicationModule;
|
||||
_BrowserModule_2: import4.BrowserModule;
|
||||
_AppModule_3: import1.AppModule;
|
||||
__LOCALE_ID_4: any;
|
||||
__NgLocalization_5: import5.NgLocaleLocalization;
|
||||
_ErrorHandler_6: any;
|
||||
_ApplicationInitStatus_7: import6.ApplicationInitStatus;
|
||||
_Testability_8: import7.Testability;
|
||||
_ApplicationRef__9: import8.ApplicationRef_;
|
||||
__ApplicationRef_10: any;
|
||||
__Compiler_11: import9.Compiler;
|
||||
__APP_ID_12: any;
|
||||
__DOCUMENT_13: any;
|
||||
__HAMMER_GESTURE_CONFIG_14: import10.HammerGestureConfig;
|
||||
__EVENT_MANAGER_PLUGINS_15: any[];
|
||||
__EventManager_16: import11.EventManager;
|
||||
__DomSharedStylesHost_17: import12.DomSharedStylesHost;
|
||||
__AnimationDriver_18: any;
|
||||
__DomRootRenderer_19: import13.DomRootRenderer_;
|
||||
__RootRenderer_20: any;
|
||||
__DomSanitizer_21: import14.DomSanitizerImpl;
|
||||
__Sanitizer_22: any;
|
||||
__ViewUtils_23: import15.ViewUtils;
|
||||
__IterableDiffers_24: any;
|
||||
__KeyValueDiffers_25: any;
|
||||
__SharedStylesHost_26: any;
|
||||
__Title_27: import16.Title;
|
||||
__TRANSLATIONS_FORMAT_28: any;
|
||||
__AnimationQueue_29: import34.AnimationQueue;
|
||||
constructor(parent: import17.Injector) {
|
||||
super(parent, [import18.TreeComponentNgFactory], [import18.TreeComponentNgFactory]);
|
||||
}
|
||||
get _LOCALE_ID_4(): any {
|
||||
if ((this.__LOCALE_ID_4 == (null as any))) {
|
||||
(this.__LOCALE_ID_4 = (null as any));
|
||||
}
|
||||
return this.__LOCALE_ID_4;
|
||||
}
|
||||
get _NgLocalization_5(): import5.NgLocaleLocalization {
|
||||
if ((this.__NgLocalization_5 == (null as any))) {
|
||||
(this.__NgLocalization_5 = new import5.NgLocaleLocalization(this._LOCALE_ID_4));
|
||||
}
|
||||
return this.__NgLocalization_5;
|
||||
}
|
||||
get _ApplicationRef_10(): any {
|
||||
if ((this.__ApplicationRef_10 == (null as any))) {
|
||||
(this.__ApplicationRef_10 = this._ApplicationRef__9);
|
||||
}
|
||||
return this.__ApplicationRef_10;
|
||||
}
|
||||
get _Compiler_11(): import9.Compiler {
|
||||
if ((this.__Compiler_11 == (null as any))) {
|
||||
(this.__Compiler_11 = new import9.Compiler());
|
||||
}
|
||||
return this.__Compiler_11;
|
||||
}
|
||||
get _APP_ID_12(): any {
|
||||
if ((this.__APP_ID_12 == (null as any))) {
|
||||
(this.__APP_ID_12 = import19._appIdRandomProviderFactory());
|
||||
}
|
||||
return this.__APP_ID_12;
|
||||
}
|
||||
get _DOCUMENT_13(): any {
|
||||
if ((this.__DOCUMENT_13 == (null as any))) {
|
||||
(this.__DOCUMENT_13 = import4._document());
|
||||
}
|
||||
return this.__DOCUMENT_13;
|
||||
}
|
||||
get _HAMMER_GESTURE_CONFIG_14(): import10.HammerGestureConfig {
|
||||
if ((this.__HAMMER_GESTURE_CONFIG_14 == (null as any))) {
|
||||
(this.__HAMMER_GESTURE_CONFIG_14 = new import10.HammerGestureConfig());
|
||||
}
|
||||
return this.__HAMMER_GESTURE_CONFIG_14;
|
||||
}
|
||||
get _EVENT_MANAGER_PLUGINS_15(): any[] {
|
||||
if ((this.__EVENT_MANAGER_PLUGINS_15 == (null as any))) {
|
||||
(this.__EVENT_MANAGER_PLUGINS_15 = [
|
||||
new import20.DomEventsPlugin(document), new import21.KeyEventsPlugin(document),
|
||||
new import10.HammerGesturesPlugin(document, this._HAMMER_GESTURE_CONFIG_14)
|
||||
]);
|
||||
}
|
||||
return this.__EVENT_MANAGER_PLUGINS_15;
|
||||
}
|
||||
get _EventManager_16(): import11.EventManager {
|
||||
if ((this.__EventManager_16 == (null as any))) {
|
||||
(this.__EventManager_16 = new import11.EventManager(
|
||||
this._EVENT_MANAGER_PLUGINS_15, this.parent.get(import22.NgZone)));
|
||||
}
|
||||
return this.__EventManager_16;
|
||||
}
|
||||
get _DomSharedStylesHost_17(): import12.DomSharedStylesHost {
|
||||
if ((this.__DomSharedStylesHost_17 == (null as any))) {
|
||||
(this.__DomSharedStylesHost_17 = new import12.DomSharedStylesHost(this._DOCUMENT_13));
|
||||
}
|
||||
return this.__DomSharedStylesHost_17;
|
||||
}
|
||||
get _AnimationDriver_18(): any {
|
||||
if ((this.__AnimationDriver_18 == (null as any))) {
|
||||
(this.__AnimationDriver_18 = import4._resolveDefaultAnimationDriver());
|
||||
}
|
||||
return this.__AnimationDriver_18;
|
||||
}
|
||||
get _DomRootRenderer_19(): import13.DomRootRenderer_ {
|
||||
if ((this.__DomRootRenderer_19 == (null as any))) {
|
||||
(this.__DomRootRenderer_19 = new import13.DomRootRenderer_(
|
||||
this._DOCUMENT_13, this._EventManager_16, this._DomSharedStylesHost_17,
|
||||
this._AnimationDriver_18, this._APP_ID_12));
|
||||
}
|
||||
return this.__DomRootRenderer_19;
|
||||
}
|
||||
get _RootRenderer_20(): any {
|
||||
if ((this.__RootRenderer_20 == (null as any))) {
|
||||
(this.__RootRenderer_20 = import23._createConditionalRootRenderer(
|
||||
this._DomRootRenderer_19, this.parent.get(import23.NgProbeToken, (null as any)),
|
||||
this.parent.get(import8.NgProbeToken, (null as any))));
|
||||
}
|
||||
return this.__RootRenderer_20;
|
||||
}
|
||||
get _DomSanitizer_21(): import14.DomSanitizerImpl {
|
||||
if ((this.__DomSanitizer_21 == (null as any))) {
|
||||
(this.__DomSanitizer_21 = new import14.DomSanitizerImpl(document));
|
||||
}
|
||||
return this.__DomSanitizer_21;
|
||||
}
|
||||
get _Sanitizer_22(): any {
|
||||
if ((this.__Sanitizer_22 == (null as any))) {
|
||||
(this.__Sanitizer_22 = this._DomSanitizer_21);
|
||||
}
|
||||
return this.__Sanitizer_22;
|
||||
}
|
||||
get _ViewUtils_23(): import15.ViewUtils {
|
||||
if ((this.__ViewUtils_23 == (null as any))) {
|
||||
(this.__ViewUtils_23 = new import15.ViewUtils(
|
||||
this._RootRenderer_20, this._Sanitizer_22, this._AnimationQueue_29));
|
||||
}
|
||||
return this.__ViewUtils_23;
|
||||
}
|
||||
get _AnimationQueue_29(): import34.AnimationQueue {
|
||||
if ((this.__AnimationQueue_29 == (null as any))) {
|
||||
(this.__AnimationQueue_29 = new import34.AnimationQueue(this.parent.get(import22.NgZone)));
|
||||
}
|
||||
return this.__AnimationQueue_29;
|
||||
}
|
||||
get _IterableDiffers_24(): any {
|
||||
if ((this.__IterableDiffers_24 == (null as any))) {
|
||||
(this.__IterableDiffers_24 = import3._iterableDiffersFactory());
|
||||
}
|
||||
return this.__IterableDiffers_24;
|
||||
}
|
||||
get _KeyValueDiffers_25(): any {
|
||||
if ((this.__KeyValueDiffers_25 == (null as any))) {
|
||||
(this.__KeyValueDiffers_25 = import3._keyValueDiffersFactory());
|
||||
}
|
||||
return this.__KeyValueDiffers_25;
|
||||
}
|
||||
get _SharedStylesHost_26(): any {
|
||||
if ((this.__SharedStylesHost_26 == (null as any))) {
|
||||
(this.__SharedStylesHost_26 = this._DomSharedStylesHost_17);
|
||||
}
|
||||
return this.__SharedStylesHost_26;
|
||||
}
|
||||
get _Title_27(): import16.Title {
|
||||
if ((this.__Title_27 == (null as any))) {
|
||||
(this.__Title_27 = new import16.Title(document));
|
||||
}
|
||||
return this.__Title_27;
|
||||
}
|
||||
get _TRANSLATIONS_FORMAT_28(): any {
|
||||
if ((this.__TRANSLATIONS_FORMAT_28 == (null as any))) {
|
||||
(this.__TRANSLATIONS_FORMAT_28 = (null as any));
|
||||
}
|
||||
return this.__TRANSLATIONS_FORMAT_28;
|
||||
}
|
||||
createInternal(): import1.AppModule {
|
||||
this._CommonModule_0 = new import2.CommonModule();
|
||||
this._ApplicationModule_1 = new import3.ApplicationModule();
|
||||
this._BrowserModule_2 =
|
||||
new import4.BrowserModule(this.parent.get(import4.BrowserModule, (null as any)));
|
||||
this._AppModule_3 = new import1.AppModule();
|
||||
this._ErrorHandler_6 = import4.errorHandler();
|
||||
this._ApplicationInitStatus_7 =
|
||||
new import6.ApplicationInitStatus(this.parent.get(import6.APP_INITIALIZER, (null as any)));
|
||||
this._Testability_8 = new import7.Testability(this.parent.get(import22.NgZone));
|
||||
this._ApplicationRef__9 = new import8.ApplicationRef_(
|
||||
this.parent.get(import22.NgZone), this.parent.get(import24.Console), this,
|
||||
this._ErrorHandler_6, this, this._ApplicationInitStatus_7,
|
||||
this.parent.get(import7.TestabilityRegistry, (null as any)), this._Testability_8);
|
||||
return this._AppModule_3;
|
||||
}
|
||||
getInternal(token: any, notFoundResult: any): any {
|
||||
if ((token === import2.CommonModule)) {
|
||||
return this._CommonModule_0;
|
||||
}
|
||||
if ((token === import3.ApplicationModule)) {
|
||||
return this._ApplicationModule_1;
|
||||
}
|
||||
if ((token === import4.BrowserModule)) {
|
||||
return this._BrowserModule_2;
|
||||
}
|
||||
if ((token === import1.AppModule)) {
|
||||
return this._AppModule_3;
|
||||
}
|
||||
if ((token === import25.LOCALE_ID)) {
|
||||
return this._LOCALE_ID_4;
|
||||
}
|
||||
if ((token === import5.NgLocalization)) {
|
||||
return this._NgLocalization_5;
|
||||
}
|
||||
if ((token === import26.ErrorHandler)) {
|
||||
return this._ErrorHandler_6;
|
||||
}
|
||||
if ((token === import6.ApplicationInitStatus)) {
|
||||
return this._ApplicationInitStatus_7;
|
||||
}
|
||||
if ((token === import7.Testability)) {
|
||||
return this._Testability_8;
|
||||
}
|
||||
if ((token === import8.ApplicationRef_)) {
|
||||
return this._ApplicationRef__9;
|
||||
}
|
||||
if ((token === import8.ApplicationRef)) {
|
||||
return this._ApplicationRef_10;
|
||||
}
|
||||
if ((token === import9.Compiler)) {
|
||||
return this._Compiler_11;
|
||||
}
|
||||
if ((token === import19.APP_ID)) {
|
||||
return this._APP_ID_12;
|
||||
}
|
||||
if ((token === import27.DOCUMENT)) {
|
||||
return this._DOCUMENT_13;
|
||||
}
|
||||
if ((token === import10.HAMMER_GESTURE_CONFIG)) {
|
||||
return this._HAMMER_GESTURE_CONFIG_14;
|
||||
}
|
||||
if ((token === import11.EVENT_MANAGER_PLUGINS)) {
|
||||
return this._EVENT_MANAGER_PLUGINS_15;
|
||||
}
|
||||
if ((token === import11.EventManager)) {
|
||||
return this._EventManager_16;
|
||||
}
|
||||
if ((token === import12.DomSharedStylesHost)) {
|
||||
return this._DomSharedStylesHost_17;
|
||||
}
|
||||
if ((token === import28.AnimationDriver)) {
|
||||
return this._AnimationDriver_18;
|
||||
}
|
||||
if ((token === import13.DomRootRenderer)) {
|
||||
return this._DomRootRenderer_19;
|
||||
}
|
||||
if ((token === import29.RootRenderer)) {
|
||||
return this._RootRenderer_20;
|
||||
}
|
||||
if ((token === import14.DomSanitizer)) {
|
||||
return this._DomSanitizer_21;
|
||||
}
|
||||
if ((token === import30.Sanitizer)) {
|
||||
return this._Sanitizer_22;
|
||||
}
|
||||
if ((token === import15.ViewUtils)) {
|
||||
return this._ViewUtils_23;
|
||||
}
|
||||
if ((token === import31.IterableDiffers)) {
|
||||
return this._IterableDiffers_24;
|
||||
}
|
||||
if ((token === import32.KeyValueDiffers)) {
|
||||
return this._KeyValueDiffers_25;
|
||||
}
|
||||
if ((token === import12.SharedStylesHost)) {
|
||||
return this._SharedStylesHost_26;
|
||||
}
|
||||
if ((token === import16.Title)) {
|
||||
return this._Title_27;
|
||||
}
|
||||
if ((token === import33.TRANSLATIONS_FORMAT)) {
|
||||
return this._TRANSLATIONS_FORMAT_28;
|
||||
}
|
||||
return notFoundResult;
|
||||
}
|
||||
destroyInternal(): void { this._ApplicationRef__9.ngOnDestroy(); }
|
||||
}
|
||||
export const AppModuleNgFactory: import0.NgModuleFactory<import1.AppModule> =
|
||||
new import0.NgModuleFactory(AppModuleInjector, import1.AppModule);
|
@ -1,221 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ComponentFactory, ComponentRef, ElementRef, Injector, TemplateRef, ViewContainerRef, ViewRef} from '@angular/core';
|
||||
import {devModeEqual, looseIdentical} from '@angular/core/src/change_detection/change_detection_util';
|
||||
import {expressionChangedAfterItHasBeenCheckedError} from '@angular/core/src/linker/errors';
|
||||
|
||||
|
||||
export function unimplemented(): any {
|
||||
throw new Error('unimplemented');
|
||||
}
|
||||
|
||||
export interface FtlView<C> {
|
||||
context: C;
|
||||
detectChangesInternal(throwOnChange: boolean): void;
|
||||
createEmbeddedView?<NC>(context: NC, nodeIndex: number): FtlEmbeddedView<NC>;
|
||||
destroyInternal(): void;
|
||||
}
|
||||
|
||||
export interface FtlEmbeddedView<C> extends FtlView<C> {
|
||||
// Note: if the view has a view container as first node,
|
||||
// create a comment node before it. This makes
|
||||
// inserting a view before this view simpler!
|
||||
_node0: any;
|
||||
prev: FtlEmbeddedView<any>;
|
||||
next: FtlEmbeddedView<any>;
|
||||
// Purpose of the `ctx` argument:
|
||||
// Allows to use top level functions, i.e. no need to create closures!
|
||||
visitRootNodes<CTX>(callback: (node: any, ctx: CTX) => void, ctx: CTX): void;
|
||||
}
|
||||
|
||||
// TODO(tbosch): FTL EmbeddedViewRefs should have no
|
||||
// methods / properties at all. Because of this we can just use the FtlView for it as well!
|
||||
// TODO(tbosch): We can't cast to EmbededViewRef as that also has the `rootNodes` filled
|
||||
// -> would need to generate code for that as well.
|
||||
// Rather: change API for FTL to allow to call View.attachBefore / View.detach
|
||||
// -> faster and we don't need to flatten the root nodes!
|
||||
export type FtlEmbeddedViewRef<C> = FtlView<C>;
|
||||
|
||||
export class FtlTemplateRef<C> implements TemplateRef<C> {
|
||||
constructor(private _index: number, private _view: FtlView<any>) {}
|
||||
get elementRef(): ElementRef { return unimplemented(); }
|
||||
createEmbeddedView(context: C): any {
|
||||
return this._view.createEmbeddedView(context, this._index);
|
||||
}
|
||||
}
|
||||
|
||||
export class FtlViewContainerRef implements ViewContainerRef {
|
||||
private _firstView: FtlEmbeddedView<any> = null;
|
||||
private _lastView: FtlEmbeddedView<any> = null;
|
||||
private _length = 0;
|
||||
|
||||
constructor(private _anchor: any) {}
|
||||
|
||||
detectChangesInternal(throwOnChange: boolean) {
|
||||
let view = this._firstView;
|
||||
while (view) {
|
||||
view.detectChangesInternal(throwOnChange);
|
||||
view = view.next;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(tbosch): don't allow this API in FTL mode!
|
||||
get element(): ElementRef { return <ElementRef>unimplemented(); }
|
||||
|
||||
// TODO(tbosch): don't allow this API in FTL mode!
|
||||
get injector(): Injector { return <Injector>unimplemented(); }
|
||||
|
||||
// TODO(tbosch): don't allow this API in FTL mode!
|
||||
get parentInjector(): Injector { return <Injector>unimplemented(); }
|
||||
|
||||
destroyInternal() {
|
||||
let view = this._firstView;
|
||||
while (view) {
|
||||
view.destroyInternal();
|
||||
view = view.next;
|
||||
}
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
let view = this._firstView;
|
||||
while (view) {
|
||||
detachView(view);
|
||||
view.destroyInternal();
|
||||
view = view.next;
|
||||
}
|
||||
this._firstView = null;
|
||||
this._lastView = null;
|
||||
this._length = 0;
|
||||
}
|
||||
|
||||
get(index: number): any {
|
||||
let result = this._firstView;
|
||||
while (index > 0 && result) {
|
||||
result = result.next;
|
||||
index--;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
get length(): number { return this._length; };
|
||||
|
||||
createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): any {
|
||||
const view = templateRef.createEmbeddedView(context);
|
||||
return this.insert(view, index);
|
||||
}
|
||||
|
||||
createComponent<C>(
|
||||
componentFactory: ComponentFactory<C>, index?: number, injector?: Injector,
|
||||
projectableNodes?: any[][]): ComponentRef<C> {
|
||||
// TODO(tbosch): implement this!
|
||||
return unimplemented();
|
||||
}
|
||||
|
||||
insert(viewRef: ViewRef, index?: number): any {
|
||||
const view: FtlEmbeddedView<any> = <any>viewRef;
|
||||
let insertBeforeNode: any;
|
||||
if (this._length === 0) {
|
||||
this._firstView = this._lastView = view;
|
||||
insertBeforeNode = this._anchor;
|
||||
view.prev = null;
|
||||
view.next = null;
|
||||
} else if (index >= this._length) {
|
||||
view.prev = this._lastView;
|
||||
view.next = null;
|
||||
this._lastView.next = view;
|
||||
this._lastView = view;
|
||||
insertBeforeNode = this._anchor;
|
||||
} else {
|
||||
// TODO(tbosch): implement this!
|
||||
unimplemented();
|
||||
}
|
||||
attachViewBefore(view, insertBeforeNode);
|
||||
this._length++;
|
||||
}
|
||||
|
||||
detach(index?: number): any {
|
||||
let view: FtlEmbeddedView<any>;
|
||||
if (this._length === 1) {
|
||||
view = this._firstView;
|
||||
this._firstView = this._lastView = null;
|
||||
} else if (index >= this._length) {
|
||||
view = this._lastView;
|
||||
this._lastView = view.prev;
|
||||
view.prev = null;
|
||||
this._lastView.next = null;
|
||||
} else {
|
||||
// TODO(tbosch): implement this!
|
||||
unimplemented();
|
||||
}
|
||||
this._length--;
|
||||
detachView(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
move(viewRef: ViewRef, currentIndex: number): ViewRef {
|
||||
// TODO(tbosch): implement this!
|
||||
return unimplemented();
|
||||
}
|
||||
|
||||
indexOf(viewRef: ViewRef): number {
|
||||
// TODO(tbosch): implement this!
|
||||
return unimplemented();
|
||||
}
|
||||
|
||||
remove(index?: number): void {
|
||||
const view: FtlView<any> = <any>this.detach(index);
|
||||
view.destroyInternal();
|
||||
}
|
||||
}
|
||||
|
||||
function attachViewBefore(view: FtlEmbeddedView<any>, node: any) {
|
||||
const parent = node.parentNode;
|
||||
view.visitRootNodes(insertBefore, {parent: parent, refNode: node});
|
||||
}
|
||||
|
||||
function insertBefore(node: any, ctx: {parent: any, refNode: any}) {
|
||||
ctx.parent.insertBefore(node, ctx.refNode);
|
||||
}
|
||||
|
||||
function detachView(view: FtlEmbeddedView<any>) {
|
||||
view.visitRootNodes(remove, null);
|
||||
}
|
||||
|
||||
function remove(node: any, ctx: any) {
|
||||
node.remove();
|
||||
}
|
||||
|
||||
export function createElementAndAppend(parent: any, name: string) {
|
||||
const el = document.createElement(name);
|
||||
parent.appendChild(el);
|
||||
return el;
|
||||
}
|
||||
|
||||
export function createTextAndAppend(parent: any) {
|
||||
const txt = document.createTextNode('');
|
||||
parent.appendChild(txt);
|
||||
return txt;
|
||||
}
|
||||
|
||||
export function createAnchorAndAppend(parent: any) {
|
||||
const txt = document.createComment('');
|
||||
parent.appendChild(txt);
|
||||
return txt;
|
||||
}
|
||||
|
||||
export function checkBinding(throwOnChange: boolean, oldValue: any, newValue: any): boolean {
|
||||
if (throwOnChange) {
|
||||
if (!devModeEqual(oldValue, newValue)) {
|
||||
throw expressionChangedAfterItHasBeenCheckedError(oldValue, newValue, false);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return !looseIdentical(oldValue, newValue);
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<h2>Params</h2>
|
||||
<form>
|
||||
Depth:
|
||||
<input type="number" name="depth" placeholder="depth" value="9">
|
||||
<br>
|
||||
<button>Apply</button>
|
||||
</form>
|
||||
|
||||
<h2>Ng2 FTL Tree Benchmark</h2>
|
||||
<p>
|
||||
<button id="destroyDom">destroyDom</button>
|
||||
<button id="createDom">createDom</button>
|
||||
<button id="updateDomProfile">profile updateDom</button>
|
||||
<button id="createDomProfile">profile createDom</button>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<tree id="root"></tree>
|
||||
</div>
|
||||
|
||||
<script src="../../bootstrap_ng2.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,49 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ApplicationRef, enableProdMode} from '@angular/core';
|
||||
import {platformBrowser} from '@angular/platform-browser';
|
||||
|
||||
import {bindAction, profile} from '../../util';
|
||||
import {buildTree, emptyTree} from '../util';
|
||||
|
||||
import {AppModuleNgFactory} from './app.ngfactory';
|
||||
import {TreeComponent} from './tree';
|
||||
|
||||
export function main() {
|
||||
let tree: TreeComponent;
|
||||
let appRef: ApplicationRef;
|
||||
|
||||
function destroyDom() {
|
||||
tree.data = emptyTree;
|
||||
appRef.tick();
|
||||
}
|
||||
|
||||
function createDom() {
|
||||
tree.data = buildTree();
|
||||
appRef.tick();
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
|
||||
function init() {
|
||||
enableProdMode();
|
||||
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory).then((ref) => {
|
||||
const injector = ref.injector;
|
||||
appRef = injector.get(ApplicationRef);
|
||||
|
||||
tree = appRef.components[0].instance;
|
||||
bindAction('#destroyDom', destroyDom);
|
||||
bindAction('#createDom', createDom);
|
||||
bindAction('#updateDomProfile', profile(createDom, noop, 'update'));
|
||||
bindAction('#createDomProfile', profile(createDom, destroyDom, 'create'));
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
import {NgIf} from '@angular/common';
|
||||
import {TemplateRef, ViewContainerRef} from '@angular/core';
|
||||
import * as import7 from '@angular/core/src/change_detection/change_detection';
|
||||
import * as import4 from '@angular/core/src/linker/view_utils';
|
||||
import {checkBinding} from './ftl_util';
|
||||
|
||||
export class NgIfWrapper {
|
||||
directive: NgIf;
|
||||
_expr_0: any;
|
||||
constructor(viewContainerRef: ViewContainerRef, templateRef: TemplateRef<any>) {
|
||||
this.directive = new NgIf(viewContainerRef, templateRef);
|
||||
}
|
||||
|
||||
updateNgIf(throwOnChange: boolean, currVal: any) {
|
||||
if (checkBinding(throwOnChange, this._expr_0, currVal)) {
|
||||
this.directive.ngIf = currVal;
|
||||
this._expr_0 = currVal;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
/**
|
||||
* This file is hand tweeked based on
|
||||
* the out put of the Angular template compiler
|
||||
* and then hand tweeked to show possible future output.
|
||||
*/
|
||||
/* tslint:disable */
|
||||
|
||||
import * as import10 from '@angular/common/src/directives/ng_if';
|
||||
import * as import7 from '@angular/core/src/change_detection/change_detection';
|
||||
import * as import5 from '@angular/core/src/di/injector';
|
||||
import * as import9 from '@angular/core/src/linker/component_factory';
|
||||
import * as import11 from '@angular/core/src/linker/template_ref';
|
||||
import * as import1 from '@angular/core/src/linker/view';
|
||||
import * as import2 from '@angular/core/src/linker/view_container';
|
||||
import * as import6 from '@angular/core/src/linker/view_type';
|
||||
import * as import4 from '@angular/core/src/linker/view_utils';
|
||||
import * as import8 from '@angular/core/src/metadata/view';
|
||||
import * as import0 from '@angular/core/src/render/api';
|
||||
import * as import12 from '@angular/core/src/security';
|
||||
|
||||
import {FtlEmbeddedView, FtlTemplateRef, FtlView, FtlViewContainerRef, checkBinding, createAnchorAndAppend, createElementAndAppend, createTextAndAppend} from './ftl_util';
|
||||
import {NgIfWrapper} from './ng_if.ngfactory';
|
||||
import * as import3 from './tree';
|
||||
|
||||
|
||||
export class _View_TreeComponent0 implements FtlView<import3.TreeComponent> {
|
||||
context: import3.TreeComponent;
|
||||
_el_0: any;
|
||||
_text_1: any;
|
||||
_anchor_2: any;
|
||||
_vc_2: FtlViewContainerRef;
|
||||
_TemplateRef_2_5: any;
|
||||
_NgIf_2_6: NgIfWrapper;
|
||||
_anchor_3: any;
|
||||
_vc_3: FtlViewContainerRef;
|
||||
_TemplateRef_3_5: any;
|
||||
_NgIf_3_6: NgIfWrapper;
|
||||
_expr_0: any;
|
||||
_expr_1: any;
|
||||
_expr_2: any;
|
||||
constructor(parentRenderNode: any) {
|
||||
this.context = new import3.TreeComponent();
|
||||
this._el_0 = createElementAndAppend(parentRenderNode, 'span');
|
||||
this._text_1 = createTextAndAppend(this._el_0);
|
||||
this._anchor_2 = createAnchorAndAppend(parentRenderNode);
|
||||
this._TemplateRef_2_5 = new FtlTemplateRef(2, this);
|
||||
this._vc_2 = new FtlViewContainerRef(this._anchor_2);
|
||||
this._NgIf_2_6 = new NgIfWrapper(this._vc_2, this._TemplateRef_2_5);
|
||||
this._anchor_3 = createAnchorAndAppend(parentRenderNode);
|
||||
this._TemplateRef_3_5 = new FtlTemplateRef(3, this);
|
||||
this._vc_3 = new FtlViewContainerRef(this._anchor_3);
|
||||
this._NgIf_3_6 = new NgIfWrapper(this._vc_3, this._TemplateRef_3_5);
|
||||
this._expr_0 = undefined;
|
||||
this._expr_1 = undefined;
|
||||
}
|
||||
detectChangesInternal(throwOnChange: boolean): void {
|
||||
this._NgIf_2_6.updateNgIf(throwOnChange, (this.context.data.right != (null as any)));
|
||||
this._NgIf_3_6.updateNgIf(throwOnChange, (this.context.data.left != (null as any)));
|
||||
this._vc_2.detectChangesInternal(throwOnChange);
|
||||
this._vc_3.detectChangesInternal(throwOnChange);
|
||||
const currVal_0: any = ((this.context.data.depth % 2) ? '' : 'grey');
|
||||
if (checkBinding(throwOnChange, this._expr_0, currVal_0)) {
|
||||
this._el_0.style.backgroundColor = currVal_0;
|
||||
this._expr_0 = currVal_0;
|
||||
}
|
||||
const currVal_1: any = import4.inlineInterpolate(1, ' ', this.context.data.value, ' ');
|
||||
if (checkBinding(throwOnChange, this._expr_1, currVal_1)) {
|
||||
this._text_1.nodeValue = currVal_1;
|
||||
this._expr_1 = currVal_1;
|
||||
}
|
||||
}
|
||||
destroyInternal() {
|
||||
this._vc_2.destroyInternal();
|
||||
this._vc_3.destroyInternal();
|
||||
}
|
||||
updateData(throwOnChange: boolean, currVal: any) {
|
||||
if (checkBinding(throwOnChange, this._expr_2, currVal)) {
|
||||
this.context.data = currVal;
|
||||
this._expr_2 = currVal;
|
||||
}
|
||||
}
|
||||
createEmbeddedView(context: any, nodeIndex: number): any {
|
||||
switch (nodeIndex) {
|
||||
case 2:
|
||||
return new _View_TreeComponent1(this, context);
|
||||
case 3:
|
||||
return new _View_TreeComponent2(this, context);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _View_TreeComponent1 implements FtlEmbeddedView<any> {
|
||||
_node0: any;
|
||||
_TreeComponent_0_4: _View_TreeComponent0;
|
||||
prev: FtlEmbeddedView<any>;
|
||||
next: FtlEmbeddedView<any>;
|
||||
constructor(private parent: _View_TreeComponent0, public context: any) {
|
||||
this._node0 = document.createElement('tree');
|
||||
this._TreeComponent_0_4 = new _View_TreeComponent0(this._node0);
|
||||
}
|
||||
detectChangesInternal(throwOnChange: boolean): void {
|
||||
this._TreeComponent_0_4.updateData(throwOnChange, this.parent.context.data.right);
|
||||
this._TreeComponent_0_4.detectChangesInternal(throwOnChange);
|
||||
}
|
||||
visitRootNodes(cb: (...args: any[]) => void, ctx: any) { cb(this._node0, ctx); }
|
||||
destroyInternal() { this._TreeComponent_0_4.destroyInternal(); }
|
||||
}
|
||||
|
||||
class _View_TreeComponent2 implements FtlEmbeddedView<any> {
|
||||
_node0: any;
|
||||
_TreeComponent_0_4: _View_TreeComponent0;
|
||||
prev: FtlEmbeddedView<any>;
|
||||
next: FtlEmbeddedView<any>;
|
||||
constructor(private parent: _View_TreeComponent0, public context: any) {
|
||||
this._node0 = document.createElement('tree');
|
||||
this._TreeComponent_0_4 = new _View_TreeComponent0(this._node0);
|
||||
}
|
||||
detectChangesInternal(throwOnChange: boolean): void {
|
||||
this._TreeComponent_0_4.updateData(throwOnChange, this.parent.context.data.left);
|
||||
this._TreeComponent_0_4.detectChangesInternal(throwOnChange);
|
||||
}
|
||||
visitRootNodes(cb: (...args: any[]) => void, ctx: any) { cb(this._node0, ctx); }
|
||||
destroyInternal() { this._TreeComponent_0_4.destroyInternal(); }
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {TreeNode, emptyTree} from '../util';
|
||||
|
||||
export class TreeComponent { data: TreeNode = emptyTree; }
|
||||
|
||||
export class AppModule {}
|
@ -1,57 +0,0 @@
|
||||
/**
|
||||
* This file is generated by the Angular template compiler.
|
||||
* Do not edit.
|
||||
*/
|
||||
/* tslint:disable */
|
||||
|
||||
import * as import10 from '@angular/common/src/directives/ng_if';
|
||||
import * as import7 from '@angular/core/src/change_detection/change_detection';
|
||||
import * as import5 from '@angular/core/src/di/injector';
|
||||
import * as import9 from '@angular/core/src/linker/component_factory';
|
||||
import * as import11 from '@angular/core/src/linker/template_ref';
|
||||
import * as import1 from '@angular/core/src/linker/view';
|
||||
import * as import2 from '@angular/core/src/linker/view_container';
|
||||
import * as import6 from '@angular/core/src/linker/view_type';
|
||||
import * as import4 from '@angular/core/src/linker/view_utils';
|
||||
import * as import8 from '@angular/core/src/metadata/view';
|
||||
import * as import0 from '@angular/core/src/render/api';
|
||||
import * as import12 from '@angular/core/src/security';
|
||||
|
||||
import * as import3 from './tree';
|
||||
import {_View_TreeComponent0} from './tree.ngfactory';
|
||||
|
||||
var renderType_TreeComponent_Host: import0.RenderComponentType =
|
||||
import4.createRenderComponentType('', 0, import8.ViewEncapsulation.None, [], {});
|
||||
class _View_TreeComponent_Host0 extends import1.AppView<any> {
|
||||
_el_0: any;
|
||||
_vc_0: import2.ViewContainer;
|
||||
_TreeComponent_0_4: _View_TreeComponent0;
|
||||
constructor(
|
||||
viewUtils: import4.ViewUtils, parentView: import1.AppView<any>, parentIndex: number,
|
||||
parentElement: any) {
|
||||
super(
|
||||
_View_TreeComponent_Host0, renderType_TreeComponent_Host, import6.ViewType.HOST, viewUtils,
|
||||
parentView, parentIndex, parentElement, import7.ChangeDetectorStatus.CheckAlways);
|
||||
}
|
||||
createInternal(rootSelector: string): import9.ComponentRef<any> {
|
||||
this._el_0 = import4.selectOrCreateRenderHostElement(
|
||||
this.renderer, 'tree', import4.EMPTY_INLINE_ARRAY, rootSelector, (null as any));
|
||||
this._vc_0 = new import2.ViewContainer(0, (null as any), this, this._el_0);
|
||||
this._TreeComponent_0_4 = new _View_TreeComponent0(this._el_0);
|
||||
this.init([].concat([this._el_0]), [this._el_0], []);
|
||||
return new import9.ComponentRef_(0, this, this._el_0, this._TreeComponent_0_4.context);
|
||||
}
|
||||
detectChangesInternal(): void {
|
||||
this._TreeComponent_0_4.detectChangesInternal(this.throwOnChange);
|
||||
}
|
||||
destroyInternal(): void { this._TreeComponent_0_4.destroyInternal(); }
|
||||
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
|
||||
if (((token === import3.TreeComponent) && (0 === requestNodeIndex))) {
|
||||
return this._TreeComponent_0_4;
|
||||
}
|
||||
return notFoundResult;
|
||||
}
|
||||
}
|
||||
export const TreeComponentNgFactory: import9.ComponentFactory<import3.TreeComponent> =
|
||||
new import9.ComponentFactory<import3.TreeComponent>(
|
||||
'tree', _View_TreeComponent_Host0, import3.TreeComponent);
|
@ -1,79 +0,0 @@
|
||||
# Ng2 Static Faster Than BaseLine (FTL) Benchmark
|
||||
|
||||
This benchmark was produced in the following way:
|
||||
|
||||
1. Run AoT over the root component, one branch component
|
||||
and the leaf component of the ng2_static benchmark
|
||||
2. Move all 3 component classes to `tree.ts`
|
||||
3. Add a `depth` property to the view factory constructor of
|
||||
the `TreeBranchComponent` and pass it down to nested view factory calls
|
||||
to be able to use the same view factory for all
|
||||
nesting levels. This is just to make the experiment simpler to not
|
||||
need to change so much code.
|
||||
4. Optimize the `tree_branch.ngfactory.ts` and `tree_leaf.ngfactory.ts`
|
||||
(see below)
|
||||
|
||||
The goal of this benchmark is to explore what kind of
|
||||
code the Ng2 compiler should generate in order to get faster.
|
||||
I.e. right now, the Ng2 compiler _does not_ produce this kind of code,
|
||||
but hopefully will in the future.
|
||||
|
||||
## Optimizations and cleanups
|
||||
|
||||
See `tree_branch.ngfactory.ts` and `tree_leaf.ngfactory.ts`.
|
||||
|
||||
Performance:
|
||||
|
||||
- remove view factory functions, call the constructor of the view class directly
|
||||
- remove `createInternal` and move the logic into the constructor
|
||||
- remove `AppView` parent class
|
||||
- generate direct calls to `detectChangesInternal` / `destroyInternal` of nested components
|
||||
- remove `Renderer` and `SanitizationService` to update
|
||||
the dom directly via `document.createElement` / `element.appendChild` / setting
|
||||
`Text.nodeValue` / `Element.style....`
|
||||
- remove `AppElement`
|
||||
- create component instance in view constructor
|
||||
|
||||
Code size:
|
||||
- helper methods `createElementAndAppend` / `createTextAndAppend` / `createAnchorAndAppend`
|
||||
- wrap dirty check for `TreeComponent.data` into the method `updateData`
|
||||
in the view class
|
||||
- remove `injectorGetInternal` assuming we can detect that nobody is injecting an `Injector`
|
||||
|
||||
|
||||
## Initial results: File size
|
||||
|
||||
File size for view class of the component (without imports nor host view factory):
|
||||
* before: 81 LOC
|
||||
* after: 53 LOC
|
||||
|
||||
## Initial results: Deep Tree Benchmark
|
||||
|
||||
BENCHMARK deepTree....
|
||||
Description:
|
||||
- bundles: false
|
||||
- depth: 11
|
||||
- forceGc: false
|
||||
- regressionSlopeMetric: scriptTime
|
||||
- runId: f9ae32f0-8580-11e6-914d-9f4f8dbfb5e8
|
||||
- sampleSize: 20
|
||||
- userAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36
|
||||
|
||||
...createOnly | gcAmount | gcTime | majorGcTime | pureScriptTime | renderTime | scriptTime
|
||||
--------------- | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------
|
||||
ng2.static | 10068.17+-33% | 9.50+-43% | 0.01+-84% | 83.01+-18% | 57.81+-19% | 92.33+-16%
|
||||
ng2.ftl | 493.36+-435% | 0.65+-435% | 0.00+-435% | 28.48+-16% | 53.97+-7% | 28.48+-16%
|
||||
baseline | 53.81+-435% | 0.10+-435% | 0.00+-435% | 19.79+-20% | 52.08+-19% | 19.89+-20%
|
||||
incremental_dom | 311.14+-254% | 2.43+-248% | 0.00+-207% | 68.30+-20% | 59.31+-19% | 70.73+-19%
|
||||
|
||||
.....update | gcAmount | gcTime | majorGcTime | pureScriptTime | renderTime | scriptTime
|
||||
--------------- | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------
|
||||
ng2.static | 0.00 | 0.00 | 0.00 | 24.65+-12% | 31.43+-22% | 24.65+-12%
|
||||
ng2.ftl | 0.00 | 0.00+-435% | 0.00+-435% | 16.02+-13% | 29.15+-9% | 16.02+-13%
|
||||
baseline | 509.97+-176% | 0.65+-269% | 0.40+-434% | 28.32+-16% | 35.80+-33% | 28.32+-16%
|
||||
incremental_dom | 961.48+-246% | 0.52+-311% | 0.31+-435% | 28.94+-19% | 36.13+-21% | 28.94+-19%
|
||||
|
||||
Ratios (create, pureScriptTime)
|
||||
- 2.9x faster than current implementation
|
||||
- 2.3x faster than incremental dom
|
||||
- 1.4x slower than baseline
|
@ -1,328 +0,0 @@
|
||||
/**
|
||||
* This file is generated by the Angular template compiler.
|
||||
* Do not edit.
|
||||
*/
|
||||
/* tslint:disable */
|
||||
|
||||
import * as import2 from '@angular/common/src/common_module';
|
||||
import * as import5 from '@angular/common/src/localization';
|
||||
import * as import34 from '@angular/core/src/animation/animation_queue';
|
||||
import * as import6 from '@angular/core/src/application_init';
|
||||
import * as import3 from '@angular/core/src/application_module';
|
||||
import * as import8 from '@angular/core/src/application_ref';
|
||||
import * as import19 from '@angular/core/src/application_tokens';
|
||||
import * as import31 from '@angular/core/src/change_detection/differs/iterable_differs';
|
||||
import * as import32 from '@angular/core/src/change_detection/differs/keyvalue_differs';
|
||||
import * as import24 from '@angular/core/src/console';
|
||||
import * as import17 from '@angular/core/src/di/injector';
|
||||
import * as import26 from '@angular/core/src/error_handler';
|
||||
import * as import33 from '@angular/core/src/i18n/tokens';
|
||||
import * as import25 from '@angular/core/src/i18n/tokens';
|
||||
import * as import9 from '@angular/core/src/linker/compiler';
|
||||
import * as import0 from '@angular/core/src/linker/ng_module_factory';
|
||||
import * as import15 from '@angular/core/src/linker/view_utils';
|
||||
import * as import29 from '@angular/core/src/render/api';
|
||||
import * as import30 from '@angular/core/src/security';
|
||||
import * as import7 from '@angular/core/src/testability/testability';
|
||||
import * as import22 from '@angular/core/src/zone/ng_zone';
|
||||
import * as import4 from '@angular/platform-browser/src/browser';
|
||||
import * as import16 from '@angular/platform-browser/src/browser/title';
|
||||
import * as import28 from '@angular/platform-browser/src/dom/animation_driver';
|
||||
import * as import23 from '@angular/platform-browser/src/dom/debug/ng_probe';
|
||||
import * as import13 from '@angular/platform-browser/src/dom/dom_renderer';
|
||||
import * as import27 from '@angular/platform-browser/src/dom/dom_tokens';
|
||||
import * as import20 from '@angular/platform-browser/src/dom/events/dom_events';
|
||||
import * as import11 from '@angular/platform-browser/src/dom/events/event_manager';
|
||||
import * as import10 from '@angular/platform-browser/src/dom/events/hammer_gestures';
|
||||
import * as import21 from '@angular/platform-browser/src/dom/events/key_events';
|
||||
import * as import12 from '@angular/platform-browser/src/dom/shared_styles_host';
|
||||
import * as import14 from '@angular/platform-browser/src/security/dom_sanitization_service';
|
||||
|
||||
import * as import1 from './app';
|
||||
import * as import18 from './tree_root.ngfactory';
|
||||
|
||||
class AppModuleInjector extends import0.NgModuleInjector<import1.AppModule> {
|
||||
_CommonModule_0: import2.CommonModule;
|
||||
_ApplicationModule_1: import3.ApplicationModule;
|
||||
_BrowserModule_2: import4.BrowserModule;
|
||||
_AppModule_3: import1.AppModule;
|
||||
__LOCALE_ID_4: any;
|
||||
__NgLocalization_5: import5.NgLocaleLocalization;
|
||||
_ErrorHandler_6: any;
|
||||
_ApplicationInitStatus_7: import6.ApplicationInitStatus;
|
||||
_Testability_8: import7.Testability;
|
||||
_ApplicationRef__9: import8.ApplicationRef_;
|
||||
__ApplicationRef_10: any;
|
||||
__Compiler_11: import9.Compiler;
|
||||
__APP_ID_12: any;
|
||||
__DOCUMENT_13: any;
|
||||
__HAMMER_GESTURE_CONFIG_14: import10.HammerGestureConfig;
|
||||
__EVENT_MANAGER_PLUGINS_15: any[];
|
||||
__EventManager_16: import11.EventManager;
|
||||
__DomSharedStylesHost_17: import12.DomSharedStylesHost;
|
||||
__AnimationDriver_18: any;
|
||||
__DomRootRenderer_19: import13.DomRootRenderer_;
|
||||
__RootRenderer_20: any;
|
||||
__DomSanitizer_21: import14.DomSanitizerImpl;
|
||||
__Sanitizer_22: any;
|
||||
__ViewUtils_23: import15.ViewUtils;
|
||||
__IterableDiffers_24: any;
|
||||
__KeyValueDiffers_25: any;
|
||||
__SharedStylesHost_26: any;
|
||||
__Title_27: import16.Title;
|
||||
__TRANSLATIONS_FORMAT_28: any;
|
||||
__AnimationQueue_29: import34.AnimationQueue;
|
||||
constructor(parent: import17.Injector) {
|
||||
super(parent, [import18.TreeRootComponentNgFactory], [import18.TreeRootComponentNgFactory]);
|
||||
}
|
||||
get _LOCALE_ID_4(): any {
|
||||
if ((this.__LOCALE_ID_4 == (null as any))) {
|
||||
(this.__LOCALE_ID_4 = (null as any));
|
||||
}
|
||||
return this.__LOCALE_ID_4;
|
||||
}
|
||||
get _NgLocalization_5(): import5.NgLocaleLocalization {
|
||||
if ((this.__NgLocalization_5 == (null as any))) {
|
||||
(this.__NgLocalization_5 = new import5.NgLocaleLocalization(this._LOCALE_ID_4));
|
||||
}
|
||||
return this.__NgLocalization_5;
|
||||
}
|
||||
get _ApplicationRef_10(): any {
|
||||
if ((this.__ApplicationRef_10 == (null as any))) {
|
||||
(this.__ApplicationRef_10 = this._ApplicationRef__9);
|
||||
}
|
||||
return this.__ApplicationRef_10;
|
||||
}
|
||||
get _Compiler_11(): import9.Compiler {
|
||||
if ((this.__Compiler_11 == (null as any))) {
|
||||
(this.__Compiler_11 = new import9.Compiler());
|
||||
}
|
||||
return this.__Compiler_11;
|
||||
}
|
||||
get _APP_ID_12(): any {
|
||||
if ((this.__APP_ID_12 == (null as any))) {
|
||||
(this.__APP_ID_12 = import19._appIdRandomProviderFactory());
|
||||
}
|
||||
return this.__APP_ID_12;
|
||||
}
|
||||
get _DOCUMENT_13(): any {
|
||||
if ((this.__DOCUMENT_13 == (null as any))) {
|
||||
(this.__DOCUMENT_13 = import4._document());
|
||||
}
|
||||
return this.__DOCUMENT_13;
|
||||
}
|
||||
get _HAMMER_GESTURE_CONFIG_14(): import10.HammerGestureConfig {
|
||||
if ((this.__HAMMER_GESTURE_CONFIG_14 == (null as any))) {
|
||||
(this.__HAMMER_GESTURE_CONFIG_14 = new import10.HammerGestureConfig());
|
||||
}
|
||||
return this.__HAMMER_GESTURE_CONFIG_14;
|
||||
}
|
||||
get _EVENT_MANAGER_PLUGINS_15(): any[] {
|
||||
if ((this.__EVENT_MANAGER_PLUGINS_15 == (null as any))) {
|
||||
(this.__EVENT_MANAGER_PLUGINS_15 = [
|
||||
new import20.DomEventsPlugin(document), new import21.KeyEventsPlugin(document),
|
||||
new import10.HammerGesturesPlugin(document, this._HAMMER_GESTURE_CONFIG_14)
|
||||
]);
|
||||
}
|
||||
return this.__EVENT_MANAGER_PLUGINS_15;
|
||||
}
|
||||
get _EventManager_16(): import11.EventManager {
|
||||
if ((this.__EventManager_16 == (null as any))) {
|
||||
(this.__EventManager_16 = new import11.EventManager(
|
||||
this._EVENT_MANAGER_PLUGINS_15, this.parent.get(import22.NgZone)));
|
||||
}
|
||||
return this.__EventManager_16;
|
||||
}
|
||||
get _DomSharedStylesHost_17(): import12.DomSharedStylesHost {
|
||||
if ((this.__DomSharedStylesHost_17 == (null as any))) {
|
||||
(this.__DomSharedStylesHost_17 = new import12.DomSharedStylesHost(this._DOCUMENT_13));
|
||||
}
|
||||
return this.__DomSharedStylesHost_17;
|
||||
}
|
||||
get _AnimationDriver_18(): any {
|
||||
if ((this.__AnimationDriver_18 == (null as any))) {
|
||||
(this.__AnimationDriver_18 = import4._resolveDefaultAnimationDriver());
|
||||
}
|
||||
return this.__AnimationDriver_18;
|
||||
}
|
||||
get _DomRootRenderer_19(): import13.DomRootRenderer_ {
|
||||
if ((this.__DomRootRenderer_19 == (null as any))) {
|
||||
(this.__DomRootRenderer_19 = new import13.DomRootRenderer_(
|
||||
this._DOCUMENT_13, this._EventManager_16, this._DomSharedStylesHost_17,
|
||||
this._AnimationDriver_18, this._APP_ID_12));
|
||||
}
|
||||
return this.__DomRootRenderer_19;
|
||||
}
|
||||
get _RootRenderer_20(): any {
|
||||
if ((this.__RootRenderer_20 == (null as any))) {
|
||||
(this.__RootRenderer_20 = import23._createConditionalRootRenderer(
|
||||
this._DomRootRenderer_19, this.parent.get(import23.NgProbeToken, (null as any)),
|
||||
this.parent.get(import8.NgProbeToken, (null as any))));
|
||||
}
|
||||
return this.__RootRenderer_20;
|
||||
}
|
||||
get _DomSanitizer_21(): import14.DomSanitizerImpl {
|
||||
if ((this.__DomSanitizer_21 == (null as any))) {
|
||||
(this.__DomSanitizer_21 = new import14.DomSanitizerImpl(document));
|
||||
}
|
||||
return this.__DomSanitizer_21;
|
||||
}
|
||||
get _Sanitizer_22(): any {
|
||||
if ((this.__Sanitizer_22 == (null as any))) {
|
||||
(this.__Sanitizer_22 = this._DomSanitizer_21);
|
||||
}
|
||||
return this.__Sanitizer_22;
|
||||
}
|
||||
get _ViewUtils_23(): import15.ViewUtils {
|
||||
if ((this.__ViewUtils_23 == (null as any))) {
|
||||
(this.__ViewUtils_23 = new import15.ViewUtils(
|
||||
this._RootRenderer_20, this._Sanitizer_22, this._AnimationQueue_29));
|
||||
}
|
||||
return this.__ViewUtils_23;
|
||||
}
|
||||
get _AnimationQueue_29(): import34.AnimationQueue {
|
||||
if ((this.__AnimationQueue_29 == (null as any))) {
|
||||
(this.__AnimationQueue_29 = new import34.AnimationQueue(this.parent.get(import22.NgZone)));
|
||||
}
|
||||
return this.__AnimationQueue_29;
|
||||
}
|
||||
get _IterableDiffers_24(): any {
|
||||
if ((this.__IterableDiffers_24 == (null as any))) {
|
||||
(this.__IterableDiffers_24 = import3._iterableDiffersFactory());
|
||||
}
|
||||
return this.__IterableDiffers_24;
|
||||
}
|
||||
get _KeyValueDiffers_25(): any {
|
||||
if ((this.__KeyValueDiffers_25 == (null as any))) {
|
||||
(this.__KeyValueDiffers_25 = import3._keyValueDiffersFactory());
|
||||
}
|
||||
return this.__KeyValueDiffers_25;
|
||||
}
|
||||
get _SharedStylesHost_26(): any {
|
||||
if ((this.__SharedStylesHost_26 == (null as any))) {
|
||||
(this.__SharedStylesHost_26 = this._DomSharedStylesHost_17);
|
||||
}
|
||||
return this.__SharedStylesHost_26;
|
||||
}
|
||||
get _Title_27(): import16.Title {
|
||||
if ((this.__Title_27 == (null as any))) {
|
||||
(this.__Title_27 = new import16.Title(document));
|
||||
}
|
||||
return this.__Title_27;
|
||||
}
|
||||
get _TRANSLATIONS_FORMAT_28(): any {
|
||||
if ((this.__TRANSLATIONS_FORMAT_28 == (null as any))) {
|
||||
(this.__TRANSLATIONS_FORMAT_28 = (null as any));
|
||||
}
|
||||
return this.__TRANSLATIONS_FORMAT_28;
|
||||
}
|
||||
createInternal(): import1.AppModule {
|
||||
this._CommonModule_0 = new import2.CommonModule();
|
||||
this._ApplicationModule_1 = new import3.ApplicationModule();
|
||||
this._BrowserModule_2 =
|
||||
new import4.BrowserModule(this.parent.get(import4.BrowserModule, (null as any)));
|
||||
this._AppModule_3 = new import1.AppModule();
|
||||
this._ErrorHandler_6 = import4.errorHandler();
|
||||
this._ApplicationInitStatus_7 =
|
||||
new import6.ApplicationInitStatus(this.parent.get(import6.APP_INITIALIZER, (null as any)));
|
||||
this._Testability_8 = new import7.Testability(this.parent.get(import22.NgZone));
|
||||
this._ApplicationRef__9 = new import8.ApplicationRef_(
|
||||
this.parent.get(import22.NgZone), this.parent.get(import24.Console), this,
|
||||
this._ErrorHandler_6, this, this._ApplicationInitStatus_7,
|
||||
this.parent.get(import7.TestabilityRegistry, (null as any)), this._Testability_8);
|
||||
return this._AppModule_3;
|
||||
}
|
||||
getInternal(token: any, notFoundResult: any): any {
|
||||
if ((token === import2.CommonModule)) {
|
||||
return this._CommonModule_0;
|
||||
}
|
||||
if ((token === import3.ApplicationModule)) {
|
||||
return this._ApplicationModule_1;
|
||||
}
|
||||
if ((token === import4.BrowserModule)) {
|
||||
return this._BrowserModule_2;
|
||||
}
|
||||
if ((token === import1.AppModule)) {
|
||||
return this._AppModule_3;
|
||||
}
|
||||
if ((token === import25.LOCALE_ID)) {
|
||||
return this._LOCALE_ID_4;
|
||||
}
|
||||
if ((token === import5.NgLocalization)) {
|
||||
return this._NgLocalization_5;
|
||||
}
|
||||
if ((token === import26.ErrorHandler)) {
|
||||
return this._ErrorHandler_6;
|
||||
}
|
||||
if ((token === import6.ApplicationInitStatus)) {
|
||||
return this._ApplicationInitStatus_7;
|
||||
}
|
||||
if ((token === import7.Testability)) {
|
||||
return this._Testability_8;
|
||||
}
|
||||
if ((token === import8.ApplicationRef_)) {
|
||||
return this._ApplicationRef__9;
|
||||
}
|
||||
if ((token === import8.ApplicationRef)) {
|
||||
return this._ApplicationRef_10;
|
||||
}
|
||||
if ((token === import9.Compiler)) {
|
||||
return this._Compiler_11;
|
||||
}
|
||||
if ((token === import19.APP_ID)) {
|
||||
return this._APP_ID_12;
|
||||
}
|
||||
if ((token === import27.DOCUMENT)) {
|
||||
return this._DOCUMENT_13;
|
||||
}
|
||||
if ((token === import10.HAMMER_GESTURE_CONFIG)) {
|
||||
return this._HAMMER_GESTURE_CONFIG_14;
|
||||
}
|
||||
if ((token === import11.EVENT_MANAGER_PLUGINS)) {
|
||||
return this._EVENT_MANAGER_PLUGINS_15;
|
||||
}
|
||||
if ((token === import11.EventManager)) {
|
||||
return this._EventManager_16;
|
||||
}
|
||||
if ((token === import12.DomSharedStylesHost)) {
|
||||
return this._DomSharedStylesHost_17;
|
||||
}
|
||||
if ((token === import28.AnimationDriver)) {
|
||||
return this._AnimationDriver_18;
|
||||
}
|
||||
if ((token === import13.DomRootRenderer)) {
|
||||
return this._DomRootRenderer_19;
|
||||
}
|
||||
if ((token === import29.RootRenderer)) {
|
||||
return this._RootRenderer_20;
|
||||
}
|
||||
if ((token === import14.DomSanitizer)) {
|
||||
return this._DomSanitizer_21;
|
||||
}
|
||||
if ((token === import30.Sanitizer)) {
|
||||
return this._Sanitizer_22;
|
||||
}
|
||||
if ((token === import15.ViewUtils)) {
|
||||
return this._ViewUtils_23;
|
||||
}
|
||||
if ((token === import31.IterableDiffers)) {
|
||||
return this._IterableDiffers_24;
|
||||
}
|
||||
if ((token === import32.KeyValueDiffers)) {
|
||||
return this._KeyValueDiffers_25;
|
||||
}
|
||||
if ((token === import12.SharedStylesHost)) {
|
||||
return this._SharedStylesHost_26;
|
||||
}
|
||||
if ((token === import16.Title)) {
|
||||
return this._Title_27;
|
||||
}
|
||||
if ((token === import33.TRANSLATIONS_FORMAT)) {
|
||||
return this._TRANSLATIONS_FORMAT_28;
|
||||
}
|
||||
return notFoundResult;
|
||||
}
|
||||
destroyInternal(): void { this._ApplicationRef__9.ngOnDestroy(); }
|
||||
}
|
||||
export const AppModuleNgFactory: import0.NgModuleFactory<import1.AppModule> =
|
||||
new import0.NgModuleFactory(AppModuleInjector, import1.AppModule);
|
@ -1,9 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
export class AppModule {}
|
@ -1,38 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {devModeEqual, looseIdentical} from '@angular/core/src/change_detection/change_detection_util';
|
||||
import {expressionChangedAfterItHasBeenCheckedError} from '@angular/core/src/linker/errors';
|
||||
|
||||
export function createElementAndAppend(parent: any, name: string) {
|
||||
const el = document.createElement(name);
|
||||
parent.appendChild(el);
|
||||
return el;
|
||||
}
|
||||
|
||||
export function createTextAndAppend(parent: any) {
|
||||
const txt = document.createTextNode('');
|
||||
parent.appendChild(txt);
|
||||
return txt;
|
||||
}
|
||||
|
||||
export function createAnchorAndAppend(parent: any) {
|
||||
const txt = document.createComment('');
|
||||
parent.appendChild(txt);
|
||||
return txt;
|
||||
}
|
||||
|
||||
export function checkBinding(throwOnChange: boolean, oldValue: any, newValue: any): boolean {
|
||||
if (throwOnChange) {
|
||||
if (!devModeEqual(oldValue, newValue)) {
|
||||
throw expressionChangedAfterItHasBeenCheckedError(oldValue, newValue, false);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return !looseIdentical(oldValue, newValue);
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<h2>Params</h2>
|
||||
<form>
|
||||
Depth:
|
||||
<input type="number" name="depth" placeholder="depth" value="9">
|
||||
<br>
|
||||
<button>Apply</button>
|
||||
</form>
|
||||
|
||||
<h2>Ng2 Static FTL Tree Benchmark</h2>
|
||||
<p>
|
||||
<button id="destroyDom">destroyDom</button>
|
||||
<button id="createDom">createDom</button>
|
||||
<button id="updateDomProfile">profile updateDom</button>
|
||||
<button id="createDomProfile">profile createDom</button>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<tree id="root"></tree>
|
||||
</div>
|
||||
|
||||
<script src="../../bootstrap_ng2.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,49 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ApplicationRef, enableProdMode} from '@angular/core';
|
||||
import {platformBrowser} from '@angular/platform-browser';
|
||||
|
||||
import {bindAction, profile} from '../../util';
|
||||
import {buildTree, emptyTree} from '../util';
|
||||
|
||||
import {AppModuleNgFactory} from './app.ngfactory';
|
||||
import {TreeRootComponent} from './tree';
|
||||
|
||||
export function main() {
|
||||
let tree: TreeRootComponent;
|
||||
let appRef: ApplicationRef;
|
||||
|
||||
function destroyDom() {
|
||||
tree.data = emptyTree;
|
||||
appRef.tick();
|
||||
}
|
||||
|
||||
function createDom() {
|
||||
tree.data = buildTree();
|
||||
appRef.tick();
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
|
||||
function init() {
|
||||
enableProdMode();
|
||||
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory).then((ref) => {
|
||||
const injector = ref.injector;
|
||||
appRef = injector.get(ApplicationRef);
|
||||
|
||||
tree = appRef.components[0].instance;
|
||||
bindAction('#destroyDom', destroyDom);
|
||||
bindAction('#createDom', createDom);
|
||||
bindAction('#updateDomProfile', profile(createDom, noop, 'update'));
|
||||
bindAction('#createDomProfile', profile(createDom, destroyDom, 'create'));
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {TreeNode, emptyTree} from '../util';
|
||||
|
||||
export class TreeRootComponent { data: TreeNode = emptyTree; }
|
||||
|
||||
export class TreeBranchComponent { data: TreeNode; }
|
||||
|
||||
export class TreeLeafComponent { data: TreeNode; }
|
@ -1,75 +0,0 @@
|
||||
/**
|
||||
* This file is hand tweeked based on
|
||||
* the out put of the Angular template compiler
|
||||
* and then hand tweeked to show possible future output.
|
||||
*/
|
||||
/* tslint:disable */
|
||||
|
||||
import * as import7 from '@angular/core/src/change_detection/change_detection';
|
||||
import * as import5 from '@angular/core/src/di/injector';
|
||||
import * as import9 from '@angular/core/src/linker/component_factory';
|
||||
import * as import1 from '@angular/core/src/linker/view';
|
||||
import * as import2 from '@angular/core/src/linker/view_container';
|
||||
import * as import6 from '@angular/core/src/linker/view_type';
|
||||
import * as import4 from '@angular/core/src/linker/view_utils';
|
||||
import * as import8 from '@angular/core/src/metadata/view';
|
||||
import * as import0 from '@angular/core/src/render/api';
|
||||
import * as import12 from '@angular/core/src/security';
|
||||
|
||||
import {checkBinding, createAnchorAndAppend, createElementAndAppend, createTextAndAppend} from './ftl_util';
|
||||
import * as import3 from './tree';
|
||||
import * as import11 from './tree_leaf.ngfactory';
|
||||
|
||||
export class View_TreeTreeComponent {
|
||||
context: import3.TreeBranchComponent;
|
||||
ref: any;
|
||||
_el_0: any;
|
||||
_text_1: any;
|
||||
_el_2: any;
|
||||
_TreeComponent20_2_4View: any;
|
||||
_el_3: any;
|
||||
_TreeComponent20_3_4View: any;
|
||||
/*private*/ _expr_0: any;
|
||||
/*private*/ _expr_1: any;
|
||||
/*private*/ _expr_2: any;
|
||||
constructor(depth: number, parentRenderNode: any) {
|
||||
this.context = new import3.TreeBranchComponent();
|
||||
this._el_0 = createElementAndAppend(parentRenderNode, 'span');
|
||||
this._text_1 = createTextAndAppend(this._el_0);
|
||||
this._el_2 = createElementAndAppend(parentRenderNode, 'tree');
|
||||
this._TreeComponent20_2_4View = depth > 0 ? new View_TreeTreeComponent(depth - 1, this._el_2) :
|
||||
new import11.View_TreeLeafComponent(this._el_2);
|
||||
this._el_3 = createElementAndAppend(parentRenderNode, 'tree');
|
||||
this._TreeComponent20_3_4View = depth > 0 ? new View_TreeTreeComponent(depth - 1, this._el_3) :
|
||||
new import11.View_TreeLeafComponent(this._el_3);
|
||||
this._expr_1 = undefined;
|
||||
this._expr_2 = undefined;
|
||||
}
|
||||
destroyInternal() {
|
||||
this._TreeComponent20_2_4View.destroyInternal();
|
||||
this._TreeComponent20_3_4View.destroyInternal();
|
||||
}
|
||||
updateData(currVal_2: any) {
|
||||
if (checkBinding(false, this._expr_2, currVal_2)) {
|
||||
this.context.data = currVal_2;
|
||||
this._expr_2 = currVal_2;
|
||||
}
|
||||
}
|
||||
detectChangesInternal(throwOnChange: boolean): void {
|
||||
this._TreeComponent20_2_4View.updateData(this.context.data.right);
|
||||
this._TreeComponent20_3_4View.updateData(this.context.data.left);
|
||||
|
||||
const currVal_0: any = ((this.context.data.depth % 2) ? '' : 'grey');
|
||||
if (checkBinding(throwOnChange, this._expr_0, currVal_0)) {
|
||||
this._el_0.style.backgroundColor = currVal_0;
|
||||
this._expr_0 = currVal_0;
|
||||
}
|
||||
const currVal_1: any = import4.inlineInterpolate(1, ' ', this.context.data.value, ' ');
|
||||
if (checkBinding(throwOnChange, this._expr_1, currVal_1)) {
|
||||
this._text_1.nodeValue = currVal_1;
|
||||
this._expr_1 = currVal_1;
|
||||
}
|
||||
this._TreeComponent20_2_4View.detectChangesInternal(throwOnChange);
|
||||
this._TreeComponent20_3_4View.detectChangesInternal(throwOnChange);
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/**
|
||||
* This file is hand tweeked based on
|
||||
* the out put of the Angular template compiler
|
||||
* and then hand tweeked to show possible future output.
|
||||
*/
|
||||
/* tslint:disable */
|
||||
|
||||
import * as import7 from '@angular/core/src/change_detection/change_detection';
|
||||
import * as import5 from '@angular/core/src/di/injector';
|
||||
import * as import9 from '@angular/core/src/linker/component_factory';
|
||||
import * as import1 from '@angular/core/src/linker/view';
|
||||
import * as import2 from '@angular/core/src/linker/view_container';
|
||||
import * as import6 from '@angular/core/src/linker/view_type';
|
||||
import * as import4 from '@angular/core/src/linker/view_utils';
|
||||
import * as import8 from '@angular/core/src/metadata/view';
|
||||
import * as import0 from '@angular/core/src/render/api';
|
||||
import * as import10 from '@angular/core/src/security';
|
||||
|
||||
import {checkBinding} from './ftl_util';
|
||||
import * as import3 from './tree';
|
||||
|
||||
export class View_TreeLeafComponent {
|
||||
context: import3.TreeLeafComponent;
|
||||
_el_0: any;
|
||||
_text_1: any;
|
||||
/*private*/ _expr_0: any;
|
||||
/*private*/ _expr_1: any;
|
||||
/*private*/ _expr_2: any;
|
||||
constructor(parentRenderNode: any) {
|
||||
this.context = new import3.TreeLeafComponent();
|
||||
this._el_0 = document.createElement('span');
|
||||
parentRenderNode.appendChild(this._el_0);
|
||||
this._text_1 = document.createTextNode('');
|
||||
this._el_0.appendChild(this._text_1);
|
||||
}
|
||||
updateData(currVal_2: any) {
|
||||
if (checkBinding(false, this._expr_2, currVal_2)) {
|
||||
this.context.data = currVal_2;
|
||||
this._expr_2 = currVal_2;
|
||||
}
|
||||
}
|
||||
destroyInternal() {}
|
||||
detectChangesInternal(throwOnChange: boolean): void {
|
||||
const currVal_0: any = ((this.context.data.depth % 2) ? '' : 'grey');
|
||||
if (checkBinding(throwOnChange, this._expr_0, currVal_0)) {
|
||||
this._el_0.style.backgroundColor = currVal_0;
|
||||
this._expr_0 = currVal_0;
|
||||
}
|
||||
const currVal_1: any = import4.inlineInterpolate(1, ' ', this.context.data.value, ' ');
|
||||
if (checkBinding(throwOnChange, this._expr_1, currVal_1)) {
|
||||
this._text_1.nodeValue = currVal_1;
|
||||
this._expr_1 = currVal_1;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/**
|
||||
* This file is generated by the Angular template compiler.
|
||||
* Do not edit.
|
||||
*/
|
||||
/* tslint:disable */
|
||||
|
||||
import * as import10 from '@angular/common/src/directives/ng_if';
|
||||
import * as import7 from '@angular/core/src/change_detection/change_detection';
|
||||
import * as import5 from '@angular/core/src/di/injector';
|
||||
import * as import9 from '@angular/core/src/linker/component_factory';
|
||||
import * as import11 from '@angular/core/src/linker/template_ref';
|
||||
import * as import1 from '@angular/core/src/linker/view';
|
||||
import * as import2 from '@angular/core/src/linker/view_container';
|
||||
import * as import6 from '@angular/core/src/linker/view_type';
|
||||
import * as import4 from '@angular/core/src/linker/view_utils';
|
||||
import * as import8 from '@angular/core/src/metadata/view';
|
||||
import * as import0 from '@angular/core/src/render/api';
|
||||
|
||||
import {maxDepth} from '../util';
|
||||
|
||||
import {checkBinding} from './ftl_util';
|
||||
import * as import3 from './tree';
|
||||
import * as import12 from './tree';
|
||||
import * as import13 from './tree_branch.ngfactory';
|
||||
|
||||
var renderType_TreeRootComponent_Host: import0.RenderComponentType =
|
||||
import4.createRenderComponentType('', 0, import8.ViewEncapsulation.None, [], {});
|
||||
class _View_TreeRootComponent_Host0 extends import1.AppView<any> {
|
||||
_el_0: any;
|
||||
/*private*/ _appEl_0: import2.ViewContainer;
|
||||
_TreeRootComponent_0_4: import3.TreeRootComponent;
|
||||
_TreeRootComponent_0_4_View: any;
|
||||
constructor(
|
||||
viewUtils: import4.ViewUtils, parentView: import1.AppView<any>, parentIndex: number,
|
||||
parentElement: any) {
|
||||
super(
|
||||
_View_TreeRootComponent_Host0, renderType_TreeRootComponent_Host, import6.ViewType.HOST,
|
||||
viewUtils, parentView, parentIndex, parentElement,
|
||||
import7.ChangeDetectorStatus.CheckAlways);
|
||||
}
|
||||
createInternal(rootSelector: string): import9.ComponentRef<any> {
|
||||
this._el_0 = import4.selectOrCreateRenderHostElement(
|
||||
this.renderer, 'tree', import4.EMPTY_INLINE_ARRAY, rootSelector, (null as any));
|
||||
this._appEl_0 = new import2.ViewContainer(0, (null as any), this, this._el_0);
|
||||
this._TreeRootComponent_0_4_View =
|
||||
new _View_TreeRootComponent0(this.viewUtils, this, 0, this._el_0);
|
||||
this._TreeRootComponent_0_4 = new import3.TreeRootComponent();
|
||||
this._TreeRootComponent_0_4_View.create(this._TreeRootComponent_0_4, (null as any));
|
||||
this.init([].concat([this._el_0]), [this._el_0], []);
|
||||
return new import9.ComponentRef_(0, this, this._el_0, this._TreeRootComponent_0_4);
|
||||
}
|
||||
detectChangesInternal(): void {
|
||||
this._TreeRootComponent_0_4_View.detectChangesInternal(this.throwOnChange);
|
||||
}
|
||||
destroyInternal(): void { this._TreeRootComponent_0_4_View.destroyInternal(); }
|
||||
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
|
||||
if (((token === import3.TreeRootComponent) && (0 === requestNodeIndex))) {
|
||||
return this._TreeRootComponent_0_4;
|
||||
}
|
||||
return notFoundResult;
|
||||
}
|
||||
}
|
||||
export const TreeRootComponentNgFactory: import9.ComponentFactory<import3.TreeRootComponent> =
|
||||
new import9.ComponentFactory<import3.TreeRootComponent>(
|
||||
'tree', _View_TreeRootComponent_Host0, import3.TreeRootComponent);
|
||||
const styles_TreeRootComponent: any[] = [];
|
||||
var renderType_TreeRootComponent: import0.RenderComponentType = import4.createRenderComponentType(
|
||||
'/Users/tbosch/projects/conf-demos/ngc-demo/src/ng2_static/root_tree.ts class TreeRootComponent - inline template',
|
||||
0, import8.ViewEncapsulation.None, styles_TreeRootComponent, {});
|
||||
class _View_TreeRootComponent0 extends import1.AppView<import3.TreeRootComponent> {
|
||||
_anchor_0: any;
|
||||
/*private*/ _appEl_0: import2.ViewContainer;
|
||||
_TemplateRef_0_5: any;
|
||||
_NgIf_0_6: import10.NgIf;
|
||||
/*private*/ _expr_0: any;
|
||||
constructor(
|
||||
viewUtils: import4.ViewUtils, parentView: import1.AppView<any>, parentIndex: number,
|
||||
parentElement: any) {
|
||||
super(
|
||||
_View_TreeRootComponent0, renderType_TreeRootComponent, import6.ViewType.COMPONENT,
|
||||
viewUtils, parentView, parentIndex, parentElement,
|
||||
import7.ChangeDetectorStatus.CheckAlways);
|
||||
}
|
||||
createInternal(rootSelector: string): import9.ComponentRef<any> {
|
||||
const parentRenderNode: any = this.renderer.createViewRoot(this.parentElement);
|
||||
this._anchor_0 = this.renderer.createTemplateAnchor(parentRenderNode, (null as any));
|
||||
this._appEl_0 = new import2.ViewContainer(0, (null as any), this, this._anchor_0);
|
||||
this._TemplateRef_0_5 = new import11.TemplateRef_(this, 0, this._anchor_0);
|
||||
this._NgIf_0_6 = new import10.NgIf(this._appEl_0.vcRef, this._TemplateRef_0_5);
|
||||
this.init([], [this._anchor_0], []);
|
||||
return (null as any);
|
||||
}
|
||||
|
||||
createEmbeddedViewInternal(nodeIndex: number): import1.AppView<any> {
|
||||
if (nodeIndex === 0) {
|
||||
return new _View_TreeRootComponent1(this.viewUtils, this, 0, this._anchor_0);
|
||||
}
|
||||
}
|
||||
|
||||
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
|
||||
if (((token === import11.TemplateRef) && (0 === requestNodeIndex))) {
|
||||
return this._TemplateRef_0_5;
|
||||
}
|
||||
if (((token === import10.NgIf) && (0 === requestNodeIndex))) {
|
||||
return this._NgIf_0_6;
|
||||
}
|
||||
return notFoundResult;
|
||||
}
|
||||
detectChangesInternal(): void {
|
||||
const currVal_0: any = (this.context.data.left != (null as any));
|
||||
if (checkBinding(this.throwOnChange, this._expr_0, currVal_0)) {
|
||||
this._NgIf_0_6.ngIf = currVal_0;
|
||||
this._expr_0 = currVal_0;
|
||||
}
|
||||
this._appEl_0.detectChangesInNestedViews(this.throwOnChange);
|
||||
}
|
||||
}
|
||||
class _View_TreeRootComponent1 extends import1.AppView<any> {
|
||||
_el_0: any;
|
||||
_TreeComponent0_0_4View: any;
|
||||
constructor(
|
||||
viewUtils: import4.ViewUtils, parentView: import1.AppView<any>, parentIndex: number,
|
||||
parentElement: any) {
|
||||
super(
|
||||
_View_TreeRootComponent1, renderType_TreeRootComponent, import6.ViewType.EMBEDDED,
|
||||
viewUtils, parentView, parentIndex, parentElement,
|
||||
import7.ChangeDetectorStatus.CheckAlways);
|
||||
}
|
||||
createInternal(rootSelector: string): import9.ComponentRef<any> {
|
||||
this._el_0 = this.renderer.createElement((null as any), 'tree0', (null as any));
|
||||
this._TreeComponent0_0_4View = new import13.View_TreeTreeComponent(maxDepth - 1, this._el_0);
|
||||
this.init([].concat([this._el_0]), [this._el_0], []);
|
||||
return (null as any);
|
||||
}
|
||||
destroyInternal() { this._TreeComponent0_0_4View.destroyInternal(); }
|
||||
detectChangesInternal(): void {
|
||||
this._TreeComponent0_0_4View.updateData(this.parentView.context.data);
|
||||
this._TreeComponent0_0_4View.detectChangesInternal(this.throwOnChange);
|
||||
}
|
||||
visitRootNodesInternal(cb: any, context: any) { cb(this._el_0, context); }
|
||||
}
|
Reference in New Issue
Block a user