parent
5e80e7e216
commit
698b0288be
|
@ -13,7 +13,7 @@ import * as ts from 'typescript';
|
|||
import {getFileStatus} from './file_system';
|
||||
import {getModuleReferences} from './parser';
|
||||
|
||||
export type ModuleResolver = (specifier: string) => string | null;
|
||||
export type ModuleResolver = (specifier: string) => string|null;
|
||||
|
||||
/**
|
||||
* Reference chains describe a sequence of source files which are connected through imports.
|
||||
|
@ -69,7 +69,7 @@ export class Analyzer {
|
|||
getSourceFile(filePath: string): ts.SourceFile {
|
||||
const resolvedPath = resolve(filePath);
|
||||
if (this._sourceFileCache.has(resolvedPath)) {
|
||||
return this._sourceFileCache.get(resolvedPath) !;
|
||||
return this._sourceFileCache.get(resolvedPath)!;
|
||||
}
|
||||
const fileContent = readFileSync(resolvedPath, 'utf8');
|
||||
const sourceFile =
|
||||
|
@ -105,7 +105,7 @@ export class Analyzer {
|
|||
if (!this.unresolvedFiles.has(originFilePath)) {
|
||||
this.unresolvedFiles.set(originFilePath, [specifier]);
|
||||
}
|
||||
this.unresolvedFiles.get(originFilePath) !.push(specifier);
|
||||
this.unresolvedFiles.get(originFilePath)!.push(specifier);
|
||||
}
|
||||
|
||||
/** Resolves the given import specifier to the corresponding source file. */
|
||||
|
|
|
@ -44,4 +44,6 @@ export function getAngularDevConfig<K, T>(): DevInfraConfig<K, T> {
|
|||
* Interface exressing the expected structure of the DevInfraConfig.
|
||||
* Allows for providing a typing for a part of the config to read.
|
||||
*/
|
||||
export interface DevInfraConfig<K, T> { [K: string]: T; }
|
||||
export interface DevInfraConfig<K, T> {
|
||||
[K: string]: T;
|
||||
}
|
||||
|
|
|
@ -1064,7 +1064,7 @@ export declare function ɵɵstyleSanitizer(sanitizer: StyleSanitizeFn | null): v
|
|||
|
||||
export declare function ɵɵtemplate(index: number, templateFn: ComponentTemplate<any> | null, decls: number, vars: number, tagName?: string | null, attrsIndex?: number | null, localRefsIndex?: number | null, localRefExtractor?: LocalRefExtractor): void;
|
||||
|
||||
export declare function ɵɵtemplateRefExtractor(tNode: TNode, currentView: ɵangular_packages_core_core_bp): TemplateRef<unknown> | null;
|
||||
export declare function ɵɵtemplateRefExtractor(tNode: TNode, currentView: ɵangular_packages_core_core_bo): TemplateRef<unknown> | null;
|
||||
|
||||
export declare function ɵɵtext(index: number, value?: string): void;
|
||||
|
||||
|
|
|
@ -8,77 +8,79 @@
|
|||
|
||||
(function(global: any) {
|
||||
|
||||
writeScriptTag('/all/benchmarks/vendor/core.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/zone.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/long-stack-trace-zone.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/system.src.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/Reflect.js', 'benchmarksBootstrap()');
|
||||
writeScriptTag('/all/benchmarks/vendor/core.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/zone.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/long-stack-trace-zone.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/system.src.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/Reflect.js', 'benchmarksBootstrap()');
|
||||
|
||||
(<any>global).benchmarksBootstrap = benchmarksBootstrap;
|
||||
(<any>global).benchmarksBootstrap = benchmarksBootstrap;
|
||||
|
||||
function benchmarksBootstrap() {
|
||||
// check query param
|
||||
const useBundles = location.search.indexOf('bundles=false') == -1;
|
||||
if (useBundles) {
|
||||
System.config({
|
||||
defaultJSExtensions: true,
|
||||
map: {
|
||||
'@angular/core': '/packages-dist/core/bundles/core.umd.js',
|
||||
'@angular/animations': '/packages-dist/common/bundles/animations.umd.js',
|
||||
'@angular/platform-browser/animations':
|
||||
'/packages-dist/platform-browser/bundles/platform-browser-animations.umd.js',
|
||||
'@angular/common': '/packages-dist/common/bundles/common.umd.js',
|
||||
'@angular/forms': '/packages-dist/forms/bundles/forms.umd.js',
|
||||
'@angular/compiler': '/packages-dist/compiler/bundles/compiler.umd.js',
|
||||
'@angular/platform-browser':
|
||||
'/packages-dist/platform-browser/bundles/platform-browser.umd.js',
|
||||
'@angular/platform-browser-dynamic':
|
||||
'/packages-dist/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
||||
'@angular/http': '/packages-dist/http/bundles/http.umd.js',
|
||||
'@angular/upgrade': '/packages-dist/upgrade/bundles/upgrade.umd.js',
|
||||
'@angular/router': '/packages-dist/router/bundles/router.umd.js',
|
||||
'rxjs': '/all/benchmarks/vendor/rxjs',
|
||||
},
|
||||
packages: {
|
||||
'rxjs/ajax': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/operators': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/testing': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/websocket': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs': {main: 'index.js', defaultExtension: 'js'},
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(
|
||||
'Not using the Angular bundles. Don\'t use this configuration for e2e/performance tests!');
|
||||
function benchmarksBootstrap() {
|
||||
// check query param
|
||||
const useBundles = location.search.indexOf('bundles=false') == -1;
|
||||
if (useBundles) {
|
||||
System.config({
|
||||
defaultJSExtensions: true,
|
||||
map: {
|
||||
'@angular/core': '/packages-dist/core/bundles/core.umd.js',
|
||||
'@angular/animations': '/packages-dist/common/bundles/animations.umd.js',
|
||||
'@angular/platform-browser/animations':
|
||||
'/packages-dist/platform-browser/bundles/platform-browser-animations.umd.js',
|
||||
'@angular/common': '/packages-dist/common/bundles/common.umd.js',
|
||||
'@angular/forms': '/packages-dist/forms/bundles/forms.umd.js',
|
||||
'@angular/compiler': '/packages-dist/compiler/bundles/compiler.umd.js',
|
||||
'@angular/platform-browser':
|
||||
'/packages-dist/platform-browser/bundles/platform-browser.umd.js',
|
||||
'@angular/platform-browser-dynamic':
|
||||
'/packages-dist/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
||||
'@angular/http': '/packages-dist/http/bundles/http.umd.js',
|
||||
'@angular/upgrade': '/packages-dist/upgrade/bundles/upgrade.umd.js',
|
||||
'@angular/router': '/packages-dist/router/bundles/router.umd.js',
|
||||
'rxjs': '/all/benchmarks/vendor/rxjs',
|
||||
},
|
||||
packages: {
|
||||
'rxjs/ajax': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/operators': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/testing': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/websocket': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs': {main: 'index.js', defaultExtension: 'js'},
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(
|
||||
'Not using the Angular bundles. Don\'t use this configuration for e2e/performance tests!');
|
||||
|
||||
System.config({
|
||||
defaultJSExtensions: true,
|
||||
map: {'@angular': '/all/@angular', 'rxjs': '/all/benchmarks/vendor/rxjs'},
|
||||
packages: {
|
||||
'@angular/core': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/animations': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/platform-browser/animations': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/compiler': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/router': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/common': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/forms': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/platform-browser': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/platform-browser-dynamic': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/upgrade': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/ajax': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/operators': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/testing': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/websocket': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs': {main: 'index.js', defaultExtension: 'js'},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// BOOTSTRAP the app!
|
||||
System.import('index').then(function(m: any) { m.main(); }, console.error.bind(console));
|
||||
System.config({
|
||||
defaultJSExtensions: true,
|
||||
map: {'@angular': '/all/@angular', 'rxjs': '/all/benchmarks/vendor/rxjs'},
|
||||
packages: {
|
||||
'@angular/core': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/animations': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/platform-browser/animations': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/compiler': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/router': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/common': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/forms': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/platform-browser': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/platform-browser-dynamic': {main: 'index.js', defaultExtension: 'js'},
|
||||
'@angular/upgrade': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/ajax': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/operators': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/testing': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs/websocket': {main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs': {main: 'index.js', defaultExtension: 'js'},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function writeScriptTag(scriptUrl: string, onload?: string) {
|
||||
document.write(`<script src="${scriptUrl}" onload="${onload}"></script>`);
|
||||
}
|
||||
// BOOTSTRAP the app!
|
||||
System.import('index').then(function(m: any) {
|
||||
m.main();
|
||||
}, console.error.bind(console));
|
||||
}
|
||||
|
||||
function writeScriptTag(scriptUrl: string, onload?: string) {
|
||||
document.write(`<script src="${scriptUrl}" onload="${onload}"></script>`);
|
||||
}
|
||||
}(window));
|
||||
|
|
|
@ -8,24 +8,24 @@
|
|||
|
||||
(function(global: any) {
|
||||
|
||||
writeScriptTag('/all/benchmarks/vendor/core.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/system.src.js', 'benchmarksBootstrap()');
|
||||
writeScriptTag('/all/benchmarks/vendor/core.js');
|
||||
writeScriptTag('/all/benchmarks/vendor/system.src.js', 'benchmarksBootstrap()');
|
||||
|
||||
(<any>global).benchmarksBootstrap = benchmarksBootstrap;
|
||||
(<any>global).benchmarksBootstrap = benchmarksBootstrap;
|
||||
|
||||
function benchmarksBootstrap() {
|
||||
System.config({
|
||||
defaultJSExtensions: true,
|
||||
map: {'incremental-dom': '/all/benchmarks/vendor/incremental-dom-cjs.js'}
|
||||
});
|
||||
function benchmarksBootstrap() {
|
||||
System.config({
|
||||
defaultJSExtensions: true,
|
||||
map: {'incremental-dom': '/all/benchmarks/vendor/incremental-dom-cjs.js'}
|
||||
});
|
||||
|
||||
// BOOTSTRAP the app!
|
||||
System.import('index').then(function(m: any) {
|
||||
m.main && m.main();
|
||||
}, console.error.bind(console));
|
||||
}
|
||||
// BOOTSTRAP the app!
|
||||
System.import('index').then(function(m: any) {
|
||||
m.main && m.main();
|
||||
}, console.error.bind(console));
|
||||
}
|
||||
|
||||
function writeScriptTag(scriptUrl: string, onload?: string) {
|
||||
document.write(`<script src="${scriptUrl}" onload="${onload}"></script>`);
|
||||
}
|
||||
function writeScriptTag(scriptUrl: string, onload?: string) {
|
||||
document.write(`<script src="${scriptUrl}" onload="${onload}"></script>`);
|
||||
}
|
||||
}(window));
|
||||
|
|
|
@ -13,7 +13,7 @@ import {openBrowser, verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
|||
describe('change detection benchmark', () => {
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
it(`should render and update`, async() => {
|
||||
it(`should render and update`, async () => {
|
||||
openBrowser({
|
||||
url: '',
|
||||
ignoreBrowserSynchronization: true,
|
||||
|
|
|
@ -31,15 +31,14 @@ const UpdateWorker: Worker = {
|
|||
// name. We determine the name of the Bazel package where this test runs from the current test
|
||||
// target. The Bazel target
|
||||
// looks like: "//modules/benchmarks/src/change_detection/{pkg_name}:{target_name}".
|
||||
const testPackageName = process.env['BAZEL_TARGET'] !.split(':')[0].split('/').pop();
|
||||
const testPackageName = process.env['BAZEL_TARGET']!.split(':')[0].split('/').pop();
|
||||
|
||||
describe('change detection benchmark perf', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
[UpdateWorker].forEach((worker) => {
|
||||
describe(worker.id, () => {
|
||||
it(`should run benchmark for ${testPackageName}`, async() => {
|
||||
it(`should run benchmark for ${testPackageName}`, async () => {
|
||||
await runChangeDetectionBenchmark({
|
||||
id: `change_detection.${testPackageName}.${worker.id}`,
|
||||
url: '/',
|
||||
|
|
|
@ -35,7 +35,9 @@ export function init(moduleRef: NgModuleRef<TransplantedViewsModule>) {
|
|||
appRef.tick();
|
||||
}
|
||||
|
||||
function detectChanges() { appRef.tick(); }
|
||||
function detectChanges() {
|
||||
appRef.tick();
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
}
|
||||
|
|
|
@ -40,10 +40,14 @@ export class InsertionComponent {
|
|||
@Input() template !: TemplateRef<{}>;
|
||||
views: any[] = [];
|
||||
@Input()
|
||||
set viewCount(n: number) { this.views = n > 0 ? newArray<any>(n) : []; }
|
||||
set viewCount(n: number) {
|
||||
this.views = n > 0 ? newArray<any>(n) : [];
|
||||
}
|
||||
|
||||
// use trackBy to ensure profile isn't affected by the cost to refresh ngFor.
|
||||
trackByIndex(index: number, item: any) { return index; }
|
||||
trackByIndex(index: number, item: any) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -15,7 +15,7 @@ export function newArray<T>(size: number, value: T): T[];
|
|||
export function newArray<T>(size: number, value?: T): T[] {
|
||||
const list: T[] = [];
|
||||
for (let i = 0; i < size; i++) {
|
||||
list.push(value !);
|
||||
list.push(value!);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -27,12 +27,16 @@ export class AppComponent {
|
|||
}
|
||||
}
|
||||
|
||||
create() { this.show = true; }
|
||||
create() {
|
||||
this.show = true;
|
||||
}
|
||||
|
||||
update() {
|
||||
this.msg = this.msg === 'hello' ? 'bye' : 'hello';
|
||||
this.list[0].text = this.msg;
|
||||
}
|
||||
|
||||
destroy() { this.show = false; }
|
||||
destroy() {
|
||||
this.show = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,7 @@ import {$, browser} from 'protractor';
|
|||
import {runBenchmark} from '../../../e2e_util/perf_util';
|
||||
|
||||
describe('class bindings perf', () => {
|
||||
|
||||
it('should work for update', async() => {
|
||||
it('should work for update', async () => {
|
||||
browser.rootEl = '#root';
|
||||
await runBenchmark({
|
||||
id: 'create',
|
||||
|
@ -23,7 +22,7 @@ describe('class bindings perf', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should work for update', async() => {
|
||||
it('should work for update', async () => {
|
||||
browser.rootEl = '#root';
|
||||
await runBenchmark({
|
||||
id: 'update',
|
||||
|
@ -34,5 +33,4 @@ describe('class bindings perf', () => {
|
|||
work: () => $('#update').click()
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -31,23 +31,32 @@ import {BenchmarkableExpandingRowModule} from './benchmarkable_expanding_row_mod
|
|||
</benchmark-area>`,
|
||||
})
|
||||
export class InitializationRoot implements AfterViewInit {
|
||||
@ViewChild(BenchmarkableExpandingRow, {static: true})
|
||||
expandingRow !: BenchmarkableExpandingRow;
|
||||
@ViewChild(BenchmarkableExpandingRow, {static: true}) expandingRow!: BenchmarkableExpandingRow;
|
||||
|
||||
ngAfterViewInit() {}
|
||||
|
||||
reset() { this.expandingRow.reset(); }
|
||||
|
||||
init() { this.expandingRow.init(); }
|
||||
|
||||
async runAll() {
|
||||
await execTimed('initialization_benchmark', async() => { await this.doInit(); });
|
||||
reset() {
|
||||
this.expandingRow.reset();
|
||||
}
|
||||
|
||||
async handleInitClick() { await this.doInit(); }
|
||||
init() {
|
||||
this.expandingRow.init();
|
||||
}
|
||||
|
||||
async runAll() {
|
||||
await execTimed('initialization_benchmark', async () => {
|
||||
await this.doInit();
|
||||
});
|
||||
}
|
||||
|
||||
async handleInitClick() {
|
||||
await this.doInit();
|
||||
}
|
||||
|
||||
private async doInit() {
|
||||
await execTimed('initial_load', async() => { this.expandingRow.init(); });
|
||||
await execTimed('initial_load', async () => {
|
||||
this.expandingRow.init();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,5 +83,9 @@ export async function execTimed(description: string, func: () => Promise<void>)
|
|||
}
|
||||
|
||||
export async function nextTick(delay = 1) {
|
||||
return new Promise((res, rej) => { setTimeout(() => { res(); }, delay); });
|
||||
return new Promise((res, rej) => {
|
||||
setTimeout(() => {
|
||||
res();
|
||||
}, delay);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@ import {Component, ErrorHandler, Injectable, NgModule} from '@angular/core';
|
|||
export class BenchmarkArea {
|
||||
}
|
||||
|
||||
declare interface ExtendedWindow extends Window { benchmarkErrors?: string[]; }
|
||||
declare interface ExtendedWindow extends Window {
|
||||
benchmarkErrors?: string[];
|
||||
}
|
||||
const extendedWindow = window as ExtendedWindow;
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
|
|
|
@ -44,12 +44,12 @@ export interface MlbTeam {
|
|||
})
|
||||
export class BenchmarkableExpandingRow {
|
||||
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
|
||||
showExpandingRow !: boolean;
|
||||
showExpandingRow!: boolean;
|
||||
|
||||
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
|
||||
teams !: MlbTeam[];
|
||||
teams!: MlbTeam[];
|
||||
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
|
||||
private fakeTeams !: MlbTeam[];
|
||||
private fakeTeams!: MlbTeam[];
|
||||
|
||||
init(): void {
|
||||
this.teams = this.fakeTeams;
|
||||
|
|
|
@ -112,15 +112,14 @@ export class ExpandingRow {
|
|||
* The identifier for this node provided by the user code. We need this
|
||||
* while we are emitting onToggle event.
|
||||
*/
|
||||
@Input() rowId !: string;
|
||||
@Input() rowId!: string;
|
||||
|
||||
/**
|
||||
* An ElementRef to the main element in this component. We need a reference
|
||||
* to this element to compute the height. The height of cfc-expanding-row
|
||||
* is used in [cfcExpandingRowHost] directive for scroll adjustments.
|
||||
*/
|
||||
@ViewChild('expandingRowMainElement', {static: true})
|
||||
expandingRowMainElement !: ElementRef;
|
||||
@ViewChild('expandingRowMainElement', {static: true}) expandingRowMainElement!: ElementRef;
|
||||
|
||||
/**
|
||||
* This @Output event emitter will be triggered when the user expands or
|
||||
|
@ -145,7 +144,9 @@ export class ExpandingRow {
|
|||
}
|
||||
|
||||
/** TS getter for isExpanded property. */
|
||||
get isExpanded(): boolean { return this.isExpandedInternal; }
|
||||
get isExpanded(): boolean {
|
||||
return this.isExpandedInternal;
|
||||
}
|
||||
|
||||
/** Triggered when isExpanded property changes. */
|
||||
isExpandedChange = new EventEmitter<void>();
|
||||
|
@ -164,7 +165,9 @@ export class ExpandingRow {
|
|||
}
|
||||
|
||||
/** TS getter for isFocused property. */
|
||||
get isFocused(): boolean { return this.isFocusedInternal; }
|
||||
get isFocused(): boolean {
|
||||
return this.isFocusedInternal;
|
||||
}
|
||||
|
||||
/** The index of the row in the context of the entire collection. */
|
||||
set index(value: number) {
|
||||
|
@ -178,7 +181,9 @@ export class ExpandingRow {
|
|||
}
|
||||
|
||||
/** TS getter for index property. */
|
||||
get index(): number { return this.indexInternal; }
|
||||
get index(): number {
|
||||
return this.indexInternal;
|
||||
}
|
||||
|
||||
/**
|
||||
* We should probably rename this to summaryContentChild. Because technically
|
||||
|
@ -188,7 +193,7 @@ export class ExpandingRow {
|
|||
* component is not in the same file as ExpandingRow.
|
||||
*/
|
||||
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
|
||||
summaryViewChild !: ExpandingRowSummary;
|
||||
summaryViewChild!: ExpandingRowSummary;
|
||||
|
||||
/**
|
||||
* We compute the collapsed height (which is just height of
|
||||
|
@ -205,7 +210,7 @@ export class ExpandingRow {
|
|||
|
||||
/** Internal storage for index public property. */
|
||||
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
|
||||
private indexInternal !: number;
|
||||
private indexInternal!: number;
|
||||
|
||||
/**
|
||||
* This holds a reference to [cfcExpandingRowHost] directive. We need
|
||||
|
@ -233,7 +238,9 @@ export class ExpandingRow {
|
|||
* When user tabs into child cfc-expanding-row-summary component. This method
|
||||
* will make sure we focuse on this row, and blur on previously focused row.
|
||||
*/
|
||||
handleSummaryFocus(): void { this.focus(); }
|
||||
handleSummaryFocus(): void {
|
||||
this.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* cfc-expanding-row-details-caption component will call this function to
|
||||
|
@ -256,7 +263,9 @@ export class ExpandingRow {
|
|||
* Gets the height of this component. This height is used in parent
|
||||
* [cfcExpandingRowHost] directive to compute scroll adjustment.
|
||||
*/
|
||||
getHeight(): number { return this.expandingRowMainElement.nativeElement.offsetHeight; }
|
||||
getHeight(): number {
|
||||
return this.expandingRowMainElement.nativeElement.offsetHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands this row. This will notify the host so that it can collapse
|
||||
|
@ -268,7 +277,9 @@ export class ExpandingRow {
|
|||
this.expandingRowHost.handleRowExpand(this);
|
||||
|
||||
// setTimeout here makes sure we scroll this row into view after animation.
|
||||
setTimeout(() => { this.expandingRowMainElement.nativeElement.focus(); });
|
||||
setTimeout(() => {
|
||||
this.expandingRowMainElement.nativeElement.focus();
|
||||
});
|
||||
|
||||
this.onToggle.emit({rowId: this.rowId, isExpand: true});
|
||||
}
|
||||
|
@ -305,7 +316,9 @@ export class ExpandingRow {
|
|||
|
||||
// Summary child is not present currently. We need to NG2 to update the
|
||||
// template.
|
||||
setTimeout(() => { this.summaryViewChild.focus(); });
|
||||
setTimeout(() => {
|
||||
this.summaryViewChild.focus();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,5 +49,7 @@ export class ExpandingRowDetailsCaption implements OnDestroy {
|
|||
}
|
||||
|
||||
/** When component is destroyed, unlisten to isExpanded. */
|
||||
ngOnDestroy(): void { this.onDestroy.next(); }
|
||||
ngOnDestroy(): void {
|
||||
this.onDestroy.next();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,10 +35,13 @@ export class ExpandingRowDetailsContent implements OnDestroy {
|
|||
* hide this component if the row is collapsed.
|
||||
*/
|
||||
constructor(@Host() public expandingRow: ExpandingRow, changeDetectorRef: ChangeDetectorRef) {
|
||||
this.isExpandedChangeSubscription =
|
||||
this.expandingRow.isExpandedChange.subscribe(() => { changeDetectorRef.markForCheck(); });
|
||||
this.isExpandedChangeSubscription = this.expandingRow.isExpandedChange.subscribe(() => {
|
||||
changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/** Unsubscribe from changes in parent isExpanded property. */
|
||||
ngOnDestroy(): void { this.isExpandedChangeSubscription.unsubscribe(); }
|
||||
ngOnDestroy(): void {
|
||||
this.isExpandedChangeSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AfterContentInit, AfterViewInit, ChangeDetectionStrategy, Component, ContentChildren, ElementRef, EventEmitter, HostListener, Input, OnDestroy, Output, QueryList, ViewChild, forwardRef} from '@angular/core';
|
||||
import {AfterContentInit, AfterViewInit, ChangeDetectionStrategy, Component, ContentChildren, ElementRef, EventEmitter, forwardRef, HostListener, Input, OnDestroy, Output, QueryList, ViewChild} from '@angular/core';
|
||||
import {Subscription} from 'rxjs';
|
||||
|
||||
import {EXPANDING_ROW_HOST_INJECTION_TOKEN, ExpandingRow, ExpandingRowHostBase} from './expanding_row';
|
||||
|
@ -26,7 +26,7 @@ export const EXPANDING_ROW_KEYPRESS_THORTTLE_MS = 50;
|
|||
* This type union is created to make arguments of handleUpOrDownPress*
|
||||
* methods in ExpandingRowHost class more readable.
|
||||
*/
|
||||
type UpOrDown = 'up' | 'down';
|
||||
type UpOrDown = 'up'|'down';
|
||||
|
||||
/**
|
||||
* This is the wrapper directive for the cfc-expanding-row components. Note that
|
||||
|
@ -48,8 +48,7 @@ type UpOrDown = 'up' | 'down';
|
|||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [{provide: EXPANDING_ROW_HOST_INJECTION_TOKEN, useExisting: ExpandingRowHost}],
|
||||
})
|
||||
export class ExpandingRowHost implements AfterViewInit,
|
||||
OnDestroy, ExpandingRowHostBase {
|
||||
export class ExpandingRowHost implements AfterViewInit, OnDestroy, ExpandingRowHostBase {
|
||||
/**
|
||||
* An HTML selector (e.g. "body") for the scroll element. We need this to
|
||||
* make some scroll adjustments.
|
||||
|
@ -71,11 +70,10 @@ export class ExpandingRowHost implements AfterViewInit,
|
|||
@Output() onPrepend = new EventEmitter<void>();
|
||||
|
||||
/** A reference to the last focusable element in list of expanding rows. */
|
||||
@ViewChild('lastFocusable', {static: true}) lastFocusableElement !: ElementRef;
|
||||
@ViewChild('lastFocusable', {static: true}) lastFocusableElement!: ElementRef;
|
||||
|
||||
/** A reference to the first focusable element in list of expanding rows. */
|
||||
@ViewChild('firstFocusable', {static: true})
|
||||
firstFocusableElement !: ElementRef;
|
||||
@ViewChild('firstFocusable', {static: true}) firstFocusableElement!: ElementRef;
|
||||
|
||||
/**
|
||||
* A reference to all child cfc-expanding-row elements. We will need for
|
||||
|
@ -83,7 +81,7 @@ export class ExpandingRowHost implements AfterViewInit,
|
|||
* which row is previous row when user presses "left arrow" on a focused row.
|
||||
*/
|
||||
@ContentChildren(forwardRef(() => ExpandingRow), {descendants: true})
|
||||
contentRows !: QueryList<ExpandingRow>;
|
||||
contentRows!: QueryList<ExpandingRow>;
|
||||
|
||||
/**
|
||||
* Keeps track of the last row that had focus before focus left the list
|
||||
|
@ -122,7 +120,7 @@ export class ExpandingRowHost implements AfterViewInit,
|
|||
|
||||
/** Subscription to changes in the expanding rows. */
|
||||
// TODO(b/109816955): remove '!', see go/strict-prop-init-fix.
|
||||
private rowChangeSubscription !: Subscription;
|
||||
private rowChangeSubscription!: Subscription;
|
||||
|
||||
/**
|
||||
* When component initializes we need to attach click listener to the root
|
||||
|
@ -138,8 +136,9 @@ export class ExpandingRowHost implements AfterViewInit,
|
|||
|
||||
clickRootElement.addEventListener('mouseup', this.handleRootMouseUpBound);
|
||||
|
||||
this.rowChangeSubscription =
|
||||
this.contentRows.changes.subscribe(() => { this.recalcRowIndexes(); });
|
||||
this.rowChangeSubscription = this.contentRows.changes.subscribe(() => {
|
||||
this.recalcRowIndexes();
|
||||
});
|
||||
this.recalcRowIndexes();
|
||||
}
|
||||
|
||||
|
@ -256,13 +255,17 @@ export class ExpandingRowHost implements AfterViewInit,
|
|||
* Function that is called by expanding row summary to focus on the last
|
||||
* focusable element before the list of expanding rows.
|
||||
*/
|
||||
focusOnPreviousFocusableElement(): void { this.lastFocusedRow = this.focusedRow; }
|
||||
focusOnPreviousFocusableElement(): void {
|
||||
this.lastFocusedRow = this.focusedRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that is called by expanding row summary to focus on the next
|
||||
* focusable element after the list of expanding rows.
|
||||
*/
|
||||
focusOnNextFocusableElement(): void { this.lastFocusedRow = this.focusedRow; }
|
||||
focusOnNextFocusableElement(): void {
|
||||
this.lastFocusedRow = this.focusedRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles keydown event on the host. We are just concerned with up,
|
||||
|
@ -275,7 +278,8 @@ export class ExpandingRowHost implements AfterViewInit,
|
|||
* - Enter: Expands the focused row.
|
||||
*/
|
||||
@HostListener('keydown', ['$event'])
|
||||
handleKeyDown(event: KeyboardEvent) {}
|
||||
handleKeyDown(event: KeyboardEvent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively returns true if target HTMLElement is within a
|
||||
|
@ -491,7 +495,10 @@ export class ExpandingRowHost implements AfterViewInit,
|
|||
// Updates all of the rows with their new index.
|
||||
private recalcRowIndexes() {
|
||||
let index = 0;
|
||||
setTimeout(
|
||||
() => { this.contentRows.forEach((row: ExpandingRow) => { row.index = index++; }); });
|
||||
setTimeout(() => {
|
||||
this.contentRows.forEach((row: ExpandingRow) => {
|
||||
row.index = index++;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,8 +48,7 @@ export class ExpandingRowSummary implements OnDestroy {
|
|||
* reference to compute collapsed height of the row. We also use this
|
||||
* reference for focus and blur methods below.
|
||||
*/
|
||||
@ViewChild('expandingRowSummaryMainElement')
|
||||
mainElementRef !: ElementRef;
|
||||
@ViewChild('expandingRowSummaryMainElement') mainElementRef!: ElementRef;
|
||||
|
||||
/** Subscription for changes in parent isExpanded property. */
|
||||
private isExpandedSubscription: Subscription;
|
||||
|
@ -65,11 +64,13 @@ export class ExpandingRowSummary implements OnDestroy {
|
|||
*/
|
||||
constructor(@Host() public expandingRow: ExpandingRow, changeDetectorRef: ChangeDetectorRef) {
|
||||
this.expandingRow.summaryViewChild = this;
|
||||
this.isExpandedSubscription =
|
||||
this.expandingRow.isExpandedChange.subscribe(() => { changeDetectorRef.markForCheck(); });
|
||||
this.isExpandedSubscription = this.expandingRow.isExpandedChange.subscribe(() => {
|
||||
changeDetectorRef.markForCheck();
|
||||
});
|
||||
|
||||
this.indexSubscription =
|
||||
this.expandingRow.indexChange.subscribe(() => { changeDetectorRef.markForCheck(); });
|
||||
this.indexSubscription = this.expandingRow.indexChange.subscribe(() => {
|
||||
changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -203,5 +204,7 @@ export class ExpandingRowSummary implements OnDestroy {
|
|||
}
|
||||
|
||||
/** Returns array of focusable elements within this component. */
|
||||
private getFocusableChildren(): HTMLElement[] { return []; }
|
||||
private getFocusableChildren(): HTMLElement[] {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,7 @@ import {$, browser} from 'protractor';
|
|||
import {runBenchmark} from '../../../e2e_util/perf_util';
|
||||
|
||||
describe('benchmarks', () => {
|
||||
|
||||
it('should work for create', async() => {
|
||||
it('should work for create', async () => {
|
||||
browser.rootEl = '#root';
|
||||
await runBenchmark({
|
||||
id: 'create',
|
||||
|
@ -22,5 +21,4 @@ describe('benchmarks', () => {
|
|||
work: () => $('#init').click()
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -18,5 +18,5 @@ enableProdMode();
|
|||
platformBrowser().bootstrapModuleFactory(ExpandingRowBenchmarkModuleNgFactory);
|
||||
|
||||
function setMode(name: string): void {
|
||||
document.querySelector('#rendererMode') !.textContent = `Render Mode: ${name}`;
|
||||
document.querySelector('#rendererMode')!.textContent = `Render Mode: ${name}`;
|
||||
}
|
||||
|
|
|
@ -24,19 +24,25 @@ const Create1KWorker: Worker = {
|
|||
const Delete1KWorker: Worker = {
|
||||
id: 'delete1K',
|
||||
prepare: () => $('#create1KRows').click(),
|
||||
work: () => { $('#deleteAll').click(); }
|
||||
work: () => {
|
||||
$('#deleteAll').click();
|
||||
}
|
||||
};
|
||||
|
||||
const UpdateWorker: Worker = {
|
||||
id: 'update',
|
||||
prepare: () => $('#create1KRows').click(),
|
||||
work: () => { $('#update').click(); }
|
||||
work: () => {
|
||||
$('#update').click();
|
||||
}
|
||||
};
|
||||
|
||||
const SwapWorker: Worker = {
|
||||
id: 'swap',
|
||||
prepare: () => $('#create1KRows').click(),
|
||||
work: () => { $('#swap').click(); }
|
||||
work: () => {
|
||||
$('#swap').click();
|
||||
}
|
||||
};
|
||||
|
||||
// In order to make sure that we don't change the ids of the benchmarks, we need to
|
||||
|
@ -45,15 +51,14 @@ const SwapWorker: Worker = {
|
|||
// name. e.g. "largeTable.ng2_switch.createDestroy". We determine the name of the
|
||||
// Bazel package where this test runs from the current test target. The Bazel target
|
||||
// looks like: "//modules/benchmarks/src/largetable/{pkg_name}:{target_name}".
|
||||
const testPackageName = process.env['BAZEL_TARGET'] !.split(':')[0].split('/').pop();
|
||||
const testPackageName = process.env['BAZEL_TARGET']!.split(':')[0].split('/').pop();
|
||||
|
||||
describe('js-web-frameworks benchmark perf', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
[Create1KWorker, Delete1KWorker, UpdateWorker, SwapWorker].forEach((worker) => {
|
||||
describe(worker.id, () => {
|
||||
it(`should run benchmark for ${testPackageName}`, async() => {
|
||||
it(`should run benchmark for ${testPackageName}`, async () => {
|
||||
await runTableBenchmark({
|
||||
id: `js-web-frameworks.${testPackageName}.${worker.id}`,
|
||||
url: '/',
|
||||
|
|
|
@ -42,14 +42,16 @@ export class JsWebFrameworksComponent {
|
|||
|
||||
constructor(private _appRef: ApplicationRef) {}
|
||||
|
||||
itemById(index: number, item: RowData) { return item.id; }
|
||||
itemById(index: number, item: RowData) {
|
||||
return item.id;
|
||||
}
|
||||
|
||||
select(itemId: number) {
|
||||
this.selected = itemId;
|
||||
this._appRef.tick();
|
||||
}
|
||||
|
||||
delete (itemId: number) {
|
||||
delete(itemId: number) {
|
||||
const data = this.data;
|
||||
for (let i = 0, l = data.length; i < l; i++) {
|
||||
if (data[i].id === itemId) {
|
||||
|
|
|
@ -11,10 +11,9 @@ import {$, By, element} from 'protractor';
|
|||
import {openBrowser, verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
describe('largeform benchmark', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
it('should work for ng2', async() => {
|
||||
it('should work for ng2', async () => {
|
||||
openBrowser({
|
||||
url: '/',
|
||||
params: [{name: 'copies', value: 1}],
|
||||
|
|
|
@ -26,12 +26,11 @@ const CreateAndDestroyWorker = {
|
|||
};
|
||||
|
||||
describe('largeform benchmark spec', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
[CreateAndDestroyWorker].forEach((worker) => {
|
||||
describe(worker.id, () => {
|
||||
it('should run for ng2', async() => {
|
||||
it('should run for ng2', async () => {
|
||||
await runLargeFormBenchmark({url: '/', id: `largeform.ng2.${worker.id}`, worker: worker});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,9 @@ const {patch, elementOpen, elementClose, elementOpenStart, elementOpenEnd, attr,
|
|||
export class TableComponent {
|
||||
constructor(private _rootEl: any) {}
|
||||
|
||||
set data(data: TableCell[][]) { patch(this._rootEl, () => this._render(data)); }
|
||||
set data(data: TableCell[][]) {
|
||||
patch(this._rootEl, () => this._render(data));
|
||||
}
|
||||
|
||||
private _render(data: TableCell[][]) {
|
||||
elementOpen('table');
|
||||
|
|
|
@ -13,7 +13,7 @@ import {openBrowser, verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
|||
describe('largetable benchmark', () => {
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
it(`should render the table`, async() => {
|
||||
it(`should render the table`, async () => {
|
||||
openBrowser({
|
||||
url: '',
|
||||
ignoreBrowserSynchronization: true,
|
||||
|
|
|
@ -40,15 +40,14 @@ const UpdateWorker: Worker = {
|
|||
// name. e.g. "largeTable.ng2_switch.createDestroy". We determine the name of the
|
||||
// Bazel package where this test runs from the current test target. The Bazel target
|
||||
// looks like: "//modules/benchmarks/src/largetable/{pkg_name}:{target_name}".
|
||||
const testPackageName = process.env['BAZEL_TARGET'] !.split(':')[0].split('/').pop();
|
||||
const testPackageName = process.env['BAZEL_TARGET']!.split(':')[0].split('/').pop();
|
||||
|
||||
describe('largetable benchmark perf', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
[CreateOnlyWorker, CreateAndDestroyWorker, UpdateWorker].forEach((worker) => {
|
||||
describe(worker.id, () => {
|
||||
it(`should run benchmark for ${testPackageName}`, async() => {
|
||||
it(`should run benchmark for ${testPackageName}`, async () => {
|
||||
await runTableBenchmark({
|
||||
id: `largeTable.${testPackageName}.${worker.id}`,
|
||||
url: '/',
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {Component, Input, NgModule} from '@angular/core';
|
||||
import {BrowserModule, DomSanitizer, SafeStyle} from '@angular/platform-browser';
|
||||
|
||||
import {TableCell, emptyTable} from '../util';
|
||||
import {emptyTable, TableCell} from '../util';
|
||||
|
||||
let trustedEmptyColor: SafeStyle;
|
||||
let trustedGreyColor: SafeStyle;
|
||||
|
@ -25,12 +25,15 @@ let trustedGreyColor: SafeStyle;
|
|||
</tbody></table>`,
|
||||
})
|
||||
export class TableComponent {
|
||||
@Input()
|
||||
data: TableCell[][] = emptyTable;
|
||||
@Input() data: TableCell[][] = emptyTable;
|
||||
|
||||
trackByIndex(index: number, item: any) { return index; }
|
||||
trackByIndex(index: number, item: any) {
|
||||
return index;
|
||||
}
|
||||
|
||||
getColor(row: number) { return row % 2 ? trustedEmptyColor : trustedGreyColor; }
|
||||
getColor(row: number) {
|
||||
return row % 2 ? trustedEmptyColor : trustedGreyColor;
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({imports: [BrowserModule], bootstrap: [TableComponent], declarations: [TableComponent]})
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {Component, Input, NgModule} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
|
||||
import {TableCell, emptyTable} from '../util';
|
||||
import {emptyTable, TableCell} from '../util';
|
||||
|
||||
@Component({
|
||||
selector: 'largetable',
|
||||
|
@ -22,10 +22,11 @@ import {TableCell, emptyTable} from '../util';
|
|||
</tbody></table>`
|
||||
})
|
||||
export class TableComponent {
|
||||
@Input()
|
||||
data: TableCell[][] = emptyTable;
|
||||
@Input() data: TableCell[][] = emptyTable;
|
||||
|
||||
trackByIndex(index: number, item: any) { return index; }
|
||||
trackByIndex(index: number, item: any) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({imports: [BrowserModule], bootstrap: [TableComponent], declarations: [TableComponent]})
|
||||
|
|
|
@ -9,7 +9,7 @@ import {ɵrenderComponent as renderComponent} from '@angular/core';
|
|||
|
||||
import {bindAction, profile} from '../../util';
|
||||
|
||||
import {LargeTableComponent, createDom, destroyDom} from './table';
|
||||
import {createDom, destroyDom, LargeTableComponent} from './table';
|
||||
|
||||
function noop() {}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {CommonModule} from '@angular/common';
|
||||
import {Component, Input, NgModule, ɵdetectChanges} from '@angular/core';
|
||||
|
||||
import {TableCell, buildTable, emptyTable} from '../util';
|
||||
import {buildTable, emptyTable, TableCell} from '../util';
|
||||
|
||||
@Component({
|
||||
selector: 'largetable',
|
||||
|
@ -26,12 +26,15 @@ import {TableCell, buildTable, emptyTable} from '../util';
|
|||
`,
|
||||
})
|
||||
export class LargeTableComponent {
|
||||
@Input()
|
||||
data: TableCell[][] = emptyTable;
|
||||
@Input() data: TableCell[][] = emptyTable;
|
||||
|
||||
trackByIndex(index: number, item: any) { return index; }
|
||||
trackByIndex(index: number, item: any) {
|
||||
return index;
|
||||
}
|
||||
|
||||
getColor(row: number) { return row % 2 ? '' : 'grey'; }
|
||||
getColor(row: number) {
|
||||
return row % 2 ? '' : 'grey';
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({declarations: [LargeTableComponent], imports: [CommonModule]})
|
||||
|
|
|
@ -6,28 +6,23 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {CompilerConfig, DirectiveResolver} from '@angular/compiler';
|
||||
import {Component, ComponentResolver, Directive, ViewContainerRef,} from '@angular/core';
|
||||
import {ViewMetadata} from '@angular/core/src/metadata/view';
|
||||
import {PromiseWrapper} from '@angular/facade/src/async';
|
||||
import {Type, print} from '@angular/facade/src/lang';
|
||||
import {print, Type} from '@angular/facade/src/lang';
|
||||
import {bootstrap} from '@angular/platform-browser';
|
||||
import {BrowserDomAdapter} from '@angular/platform-browser/src/browser/browser_adapter';
|
||||
import {DOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
|
||||
import {ComponentResolver, Component, Directive, ViewContainerRef,} from '@angular/core';
|
||||
|
||||
import {ViewMetadata} from '@angular/core/src/metadata/view';
|
||||
|
||||
import {CompilerConfig, DirectiveResolver} from '@angular/compiler';
|
||||
|
||||
import {getIntParameter, bindAction} from '@angular/testing/src/benchmark_util';
|
||||
import {bindAction, getIntParameter} from '@angular/testing/src/benchmark_util';
|
||||
|
||||
function _createBindings(): any[] {
|
||||
const multiplyTemplatesBy = getIntParameter('elements');
|
||||
return [
|
||||
{
|
||||
provide: DirectiveResolver,
|
||||
useFactory:
|
||||
() => new MultiplyDirectiveResolver(
|
||||
multiplyTemplatesBy, [BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]),
|
||||
useFactory: () => new MultiplyDirectiveResolver(
|
||||
multiplyTemplatesBy, [BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]),
|
||||
deps: []
|
||||
},
|
||||
// Use interpretative mode as Dart does not support JIT and
|
||||
|
@ -57,7 +52,9 @@ function measureWrapper(func, desc) {
|
|||
const elapsedMs = new Date().getTime() - begin.getTime();
|
||||
print(`[${desc}] ...done, took ${elapsedMs} ms`);
|
||||
};
|
||||
const onError = function(e) { DOM.logError(e); };
|
||||
const onError = function(e) {
|
||||
DOM.logError(e);
|
||||
};
|
||||
PromiseWrapper.then(func(), onSuccess, onError);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -47,7 +47,9 @@ export function main() {
|
|||
function match() {
|
||||
let matchCount = 0;
|
||||
for (let i = 0; i < count; i++) {
|
||||
fixedMatcher.match(fixedSelectors[i][0], (selector, selected) => { matchCount += selected; });
|
||||
fixedMatcher.match(fixedSelectors[i][0], (selector, selected) => {
|
||||
matchCount += selected;
|
||||
});
|
||||
}
|
||||
return matchCount;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import {NgFor, NgIf} from '@angular/common';
|
|||
import {Component, Directive, DynamicComponentLoader, ViewContainerRef} from '@angular/core';
|
||||
import {ApplicationRef} from '@angular/core/src/application_ref';
|
||||
import {ListWrapper} from '@angular/facade/src/lang';
|
||||
import {BrowserModule, bootstrap} from '@angular/platform-browser';
|
||||
import {bootstrap, BrowserModule} from '@angular/platform-browser';
|
||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||
import {bindAction, getIntParameter} from '@angular/testing/src/benchmark_util';
|
||||
|
||||
|
@ -89,7 +89,9 @@ class AppComponent {
|
|||
testingWithDirectives: boolean;
|
||||
testingDynamicComponents: boolean;
|
||||
|
||||
constructor() { this.reset(); }
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.list = [];
|
||||
|
|
|
@ -98,30 +98,42 @@ export function main() {
|
|||
|
||||
@Injectable()
|
||||
class A {
|
||||
constructor() { count++; }
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class B {
|
||||
constructor(a: A) { count++; }
|
||||
constructor(a: A) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class C {
|
||||
constructor(b: B) { count++; }
|
||||
constructor(b: B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class D {
|
||||
constructor(c: C, b: B) { count++; }
|
||||
constructor(c: C, b: B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class E {
|
||||
constructor(d: D, c: C) { count++; }
|
||||
constructor(d: D, c: C) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class F {
|
||||
constructor(e: E, d: D) { count++; }
|
||||
constructor(e: E, d: D) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,9 @@ export class App {
|
|||
for (let i = 0; i < appSize; i++) {
|
||||
this.scrollAreas.push(i);
|
||||
}
|
||||
bindAction('#run-btn', () => { this.runBenchmark(); });
|
||||
bindAction('#run-btn', () => {
|
||||
this.runBenchmark();
|
||||
});
|
||||
bindAction('#reset-btn', () => {
|
||||
this._getScrollDiv().scrollTop = 0;
|
||||
const existingMarker = this._locateFinishedMarker();
|
||||
|
@ -88,7 +90,11 @@ export class App {
|
|||
}, 0);
|
||||
}
|
||||
|
||||
private _locateFinishedMarker() { return DOM.querySelector(document.body, '#done'); }
|
||||
private _locateFinishedMarker() {
|
||||
return DOM.querySelector(document.body, '#done');
|
||||
}
|
||||
|
||||
private _getScrollDiv() { return DOM.query('body /deep/ #scrollDiv'); }
|
||||
private _getScrollDiv() {
|
||||
return DOM.query('body /deep/ #scrollDiv');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,9 @@ export class HasStyle {
|
|||
|
||||
constructor() {}
|
||||
|
||||
set width(w: number) { this.cellWidth = w; }
|
||||
set width(w: number) {
|
||||
this.cellWidth = w;
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
@ -74,7 +76,9 @@ export class StageButtonsComponent extends HasStyle {
|
|||
private _offering: Offering;
|
||||
stages: Stage[];
|
||||
|
||||
get offering(): Offering { return this._offering; }
|
||||
get offering(): Offering {
|
||||
return this._offering;
|
||||
}
|
||||
|
||||
set offering(offering: Offering) {
|
||||
this._offering = offering;
|
||||
|
|
|
@ -56,13 +56,17 @@ export class CustomDate {
|
|||
return new CustomDate(newYear, newMonth, newDay);
|
||||
}
|
||||
|
||||
static now(): CustomDate { return new CustomDate(2014, 1, 28); }
|
||||
static now(): CustomDate {
|
||||
return new CustomDate(2014, 1, 28);
|
||||
}
|
||||
}
|
||||
|
||||
export class RawEntity {
|
||||
private _data: Map<any, any>;
|
||||
|
||||
constructor() { this._data = new Map(); }
|
||||
constructor() {
|
||||
this._data = new Map();
|
||||
}
|
||||
|
||||
get(key: string) {
|
||||
if (key.indexOf('.') == -1) {
|
||||
|
@ -114,51 +118,107 @@ export class RawEntity {
|
|||
}
|
||||
|
||||
export class Company extends RawEntity {
|
||||
get name(): string { return this.get('name'); }
|
||||
set name(val: string) { this.set('name', val); }
|
||||
get name(): string {
|
||||
return this.get('name');
|
||||
}
|
||||
set name(val: string) {
|
||||
this.set('name', val);
|
||||
}
|
||||
}
|
||||
|
||||
export class Offering extends RawEntity {
|
||||
get name(): string { return this.get('name'); }
|
||||
set name(val: string) { this.set('name', val); }
|
||||
get name(): string {
|
||||
return this.get('name');
|
||||
}
|
||||
set name(val: string) {
|
||||
this.set('name', val);
|
||||
}
|
||||
|
||||
get company(): Company { return this.get('company'); }
|
||||
set company(val: Company) { this.set('company', val); }
|
||||
get company(): Company {
|
||||
return this.get('company');
|
||||
}
|
||||
set company(val: Company) {
|
||||
this.set('company', val);
|
||||
}
|
||||
|
||||
get opportunity(): Opportunity { return this.get('opportunity'); }
|
||||
set opportunity(val: Opportunity) { this.set('opportunity', val); }
|
||||
get opportunity(): Opportunity {
|
||||
return this.get('opportunity');
|
||||
}
|
||||
set opportunity(val: Opportunity) {
|
||||
this.set('opportunity', val);
|
||||
}
|
||||
|
||||
get account(): Account { return this.get('account'); }
|
||||
set account(val: Account) { this.set('account', val); }
|
||||
get account(): Account {
|
||||
return this.get('account');
|
||||
}
|
||||
set account(val: Account) {
|
||||
this.set('account', val);
|
||||
}
|
||||
|
||||
get basePoints(): number { return this.get('basePoints'); }
|
||||
set basePoints(val: number) { this.set('basePoints', val); }
|
||||
get basePoints(): number {
|
||||
return this.get('basePoints');
|
||||
}
|
||||
set basePoints(val: number) {
|
||||
this.set('basePoints', val);
|
||||
}
|
||||
|
||||
get kickerPoints(): number { return this.get('kickerPoints'); }
|
||||
set kickerPoints(val: number) { this.set('kickerPoints', val); }
|
||||
get kickerPoints(): number {
|
||||
return this.get('kickerPoints');
|
||||
}
|
||||
set kickerPoints(val: number) {
|
||||
this.set('kickerPoints', val);
|
||||
}
|
||||
|
||||
get status(): string { return this.get('status'); }
|
||||
set status(val: string) { this.set('status', val); }
|
||||
get status(): string {
|
||||
return this.get('status');
|
||||
}
|
||||
set status(val: string) {
|
||||
this.set('status', val);
|
||||
}
|
||||
|
||||
get bundles(): string { return this.get('bundles'); }
|
||||
set bundles(val: string) { this.set('bundles', val); }
|
||||
get bundles(): string {
|
||||
return this.get('bundles');
|
||||
}
|
||||
set bundles(val: string) {
|
||||
this.set('bundles', val);
|
||||
}
|
||||
|
||||
get dueDate(): CustomDate { return this.get('dueDate'); }
|
||||
set dueDate(val: CustomDate) { this.set('dueDate', val); }
|
||||
get dueDate(): CustomDate {
|
||||
return this.get('dueDate');
|
||||
}
|
||||
set dueDate(val: CustomDate) {
|
||||
this.set('dueDate', val);
|
||||
}
|
||||
|
||||
get endDate(): CustomDate { return this.get('endDate'); }
|
||||
set endDate(val: CustomDate) { this.set('endDate', val); }
|
||||
get endDate(): CustomDate {
|
||||
return this.get('endDate');
|
||||
}
|
||||
set endDate(val: CustomDate) {
|
||||
this.set('endDate', val);
|
||||
}
|
||||
|
||||
get aatStatus(): string { return this.get('aatStatus'); }
|
||||
set aatStatus(val: string) { this.set('aatStatus', val); }
|
||||
get aatStatus(): string {
|
||||
return this.get('aatStatus');
|
||||
}
|
||||
set aatStatus(val: string) {
|
||||
this.set('aatStatus', val);
|
||||
}
|
||||
}
|
||||
|
||||
export class Opportunity extends RawEntity {
|
||||
get name(): string { return this.get('name'); }
|
||||
set name(val: string) { this.set('name', val); }
|
||||
get name(): string {
|
||||
return this.get('name');
|
||||
}
|
||||
set name(val: string) {
|
||||
this.set('name', val);
|
||||
}
|
||||
}
|
||||
|
||||
export class Account extends RawEntity {
|
||||
get accountId(): number { return this.get('accountId'); }
|
||||
set accountId(val: number) { this.set('accountId', val); }
|
||||
get accountId(): number {
|
||||
return this.get('accountId');
|
||||
}
|
||||
set accountId(val: number) {
|
||||
this.set('accountId', val);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {NgFor} from '@angular/common';
|
||||
import {Component, Directive} from '@angular/core';
|
||||
|
||||
import {HEIGHT, ITEMS, ITEM_HEIGHT, Offering, ROW_WIDTH, VIEW_PORT_HEIGHT, VISIBLE_ITEMS} from './common';
|
||||
import {HEIGHT, ITEM_HEIGHT, ITEMS, Offering, ROW_WIDTH, VIEW_PORT_HEIGHT, VISIBLE_ITEMS} from './common';
|
||||
import {generateOfferings} from './random_data';
|
||||
import {ScrollItemComponent} from './scroll_item';
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {Component, Directive} from '@angular/core';
|
||||
|
||||
import {AccountCellComponent, CompanyNameComponent, FormattedCellComponent, OfferingNameComponent, OpportunityNameComponent, StageButtonsComponent} from './cells';
|
||||
import {AAT_STATUS_WIDTH, ACCOUNT_CELL_WIDTH, BASE_POINTS_WIDTH, BUNDLES_WIDTH, COMPANY_NAME_WIDTH, DUE_DATE_WIDTH, END_DATE_WIDTH, ITEM_HEIGHT, KICKER_POINTS_WIDTH, OFFERING_NAME_WIDTH, OPPORTUNITY_NAME_WIDTH, Offering, STAGE_BUTTONS_WIDTH} from './common';
|
||||
import {AAT_STATUS_WIDTH, ACCOUNT_CELL_WIDTH, BASE_POINTS_WIDTH, BUNDLES_WIDTH, COMPANY_NAME_WIDTH, DUE_DATE_WIDTH, END_DATE_WIDTH, ITEM_HEIGHT, KICKER_POINTS_WIDTH, Offering, OFFERING_NAME_WIDTH, OPPORTUNITY_NAME_WIDTH, STAGE_BUTTONS_WIDTH} from './common';
|
||||
|
||||
@Component({
|
||||
selector: 'scroll-item',
|
||||
|
@ -63,17 +63,41 @@ export class ScrollItemComponent {
|
|||
|
||||
itemHeight: number;
|
||||
|
||||
constructor() { this.itemHeight = ITEM_HEIGHT; }
|
||||
constructor() {
|
||||
this.itemHeight = ITEM_HEIGHT;
|
||||
}
|
||||
|
||||
get companyNameWidth() { return COMPANY_NAME_WIDTH; }
|
||||
get opportunityNameWidth() { return OPPORTUNITY_NAME_WIDTH; }
|
||||
get offeringNameWidth() { return OFFERING_NAME_WIDTH; }
|
||||
get accountCellWidth() { return ACCOUNT_CELL_WIDTH; }
|
||||
get basePointsWidth() { return BASE_POINTS_WIDTH; }
|
||||
get kickerPointsWidth() { return KICKER_POINTS_WIDTH; }
|
||||
get stageButtonsWidth() { return STAGE_BUTTONS_WIDTH; }
|
||||
get bundlesWidth() { return BUNDLES_WIDTH; }
|
||||
get dueDateWidth() { return DUE_DATE_WIDTH; }
|
||||
get endDateWidth() { return END_DATE_WIDTH; }
|
||||
get aatStatusWidth() { return AAT_STATUS_WIDTH; }
|
||||
get companyNameWidth() {
|
||||
return COMPANY_NAME_WIDTH;
|
||||
}
|
||||
get opportunityNameWidth() {
|
||||
return OPPORTUNITY_NAME_WIDTH;
|
||||
}
|
||||
get offeringNameWidth() {
|
||||
return OFFERING_NAME_WIDTH;
|
||||
}
|
||||
get accountCellWidth() {
|
||||
return ACCOUNT_CELL_WIDTH;
|
||||
}
|
||||
get basePointsWidth() {
|
||||
return BASE_POINTS_WIDTH;
|
||||
}
|
||||
get kickerPointsWidth() {
|
||||
return KICKER_POINTS_WIDTH;
|
||||
}
|
||||
get stageButtonsWidth() {
|
||||
return STAGE_BUTTONS_WIDTH;
|
||||
}
|
||||
get bundlesWidth() {
|
||||
return BUNDLES_WIDTH;
|
||||
}
|
||||
get dueDateWidth() {
|
||||
return DUE_DATE_WIDTH;
|
||||
}
|
||||
get endDateWidth() {
|
||||
return END_DATE_WIDTH;
|
||||
}
|
||||
get aatStatusWidth() {
|
||||
return AAT_STATUS_WIDTH;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ export function init(moduleRef: NgModuleRef<StylingModule>) {
|
|||
const componentRef = appRef.components[0];
|
||||
const component = componentRef.instance;
|
||||
const componentHostEl = componentRef.location.nativeElement;
|
||||
const select = document.querySelector('#scenario-select') !as HTMLSelectElement;
|
||||
const select = document.querySelector('#scenario-select')! as HTMLSelectElement;
|
||||
|
||||
function create(tplRefIdx: number) {
|
||||
component.tplRefIdx = tplRefIdx;
|
||||
|
@ -41,7 +41,9 @@ export function init(moduleRef: NgModuleRef<StylingModule>) {
|
|||
appRef.tick();
|
||||
}
|
||||
|
||||
function detectChanges() { appRef.tick(); }
|
||||
function detectChanges() {
|
||||
appRef.tick();
|
||||
}
|
||||
|
||||
function modifyExternally() {
|
||||
const buttonEls = componentHostEl.querySelectorAll('button') as HTMLButtonElement[];
|
||||
|
|
|
@ -35,7 +35,9 @@ export class StylingComponent {
|
|||
tplRefIdx: number = 0;
|
||||
staticStyle = {width: '10px'};
|
||||
|
||||
getTplRef(...tplRefs): TemplateRef<any> { return tplRefs[this.tplRefIdx]; }
|
||||
getTplRef(...tplRefs): TemplateRef<any> {
|
||||
return tplRefs[this.tplRefIdx];
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -28,7 +28,7 @@ const SCENARIOS = [
|
|||
describe('styling benchmark spec', () => {
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
it('should render and interact to update and detect changes', async() => {
|
||||
it('should render and interact to update and detect changes', async () => {
|
||||
openBrowser({url: '/', ignoreBrowserSynchronization: true});
|
||||
create();
|
||||
const items = element.all(by.css('styling-bindings button'));
|
||||
|
@ -38,7 +38,7 @@ describe('styling benchmark spec', () => {
|
|||
expect(await items.first().getAttribute('title')).toBe('baz');
|
||||
});
|
||||
|
||||
it('should render and run noop change detection', async() => {
|
||||
it('should render and run noop change detection', async () => {
|
||||
openBrowser({url: '/', ignoreBrowserSynchronization: true});
|
||||
create();
|
||||
const items = element.all(by.css('styling-bindings button'));
|
||||
|
@ -51,7 +51,7 @@ describe('styling benchmark spec', () => {
|
|||
// Create benchmarks for each possible test scenario.
|
||||
SCENARIOS.forEach(({optionIndex, id}) => {
|
||||
describe(id, () => {
|
||||
it('should run create benchmark', async() => {
|
||||
it('should run create benchmark', async () => {
|
||||
await runStylingBenchmark(`styling.${id}.create`, {
|
||||
work: () => create(),
|
||||
prepare: () => {
|
||||
|
@ -61,7 +61,7 @@ describe('styling benchmark spec', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should run update benchmark', async() => {
|
||||
it('should run update benchmark', async () => {
|
||||
await runStylingBenchmark(`styling.${id}.update`, {
|
||||
work: () => update(),
|
||||
prepare: () => {
|
||||
|
@ -71,7 +71,7 @@ describe('styling benchmark spec', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should run detect changes benchmark', async() => {
|
||||
it('should run detect changes benchmark', async () => {
|
||||
await runStylingBenchmark(`styling.${id}.noop_cd`, {
|
||||
work: () => detectChanges(),
|
||||
prepare: () => {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {TreeNode, newArray} from '../util';
|
||||
import {newArray, TreeNode} from '../util';
|
||||
|
||||
export class TreeComponent {
|
||||
private _renderNodes: any[];
|
||||
|
|
|
@ -17,7 +17,9 @@ const {patch, elementOpen, elementClose, elementOpenStart, elementOpenEnd, text,
|
|||
export class TreeComponent {
|
||||
constructor(private _rootEl: any) {}
|
||||
|
||||
set data(data: TreeNode) { patch(this._rootEl, () => this._render(data)); }
|
||||
set data(data: TreeNode) {
|
||||
patch(this._rootEl, () => this._render(data));
|
||||
}
|
||||
|
||||
private _render(data: TreeNode) {
|
||||
elementOpenStart('span', '', null);
|
||||
|
|
|
@ -15,7 +15,7 @@ declare var angular: any;
|
|||
|
||||
function init() {
|
||||
let detectChangesRuns = 0;
|
||||
const numberOfChecksEl = document.getElementById('numberOfChecks') !;
|
||||
const numberOfChecksEl = document.getElementById('numberOfChecks')!;
|
||||
|
||||
addTreeToModule(angular.module('app', [])).run([
|
||||
'$rootScope',
|
||||
|
@ -31,11 +31,15 @@ function init() {
|
|||
function noop() {}
|
||||
|
||||
function destroyDom() {
|
||||
$rootScope.$apply(() => { $rootScope.initData = emptyTree; });
|
||||
$rootScope.$apply(() => {
|
||||
$rootScope.initData = emptyTree;
|
||||
});
|
||||
}
|
||||
|
||||
function createDom() {
|
||||
$rootScope.$apply(() => { $rootScope.initData = buildTree(); });
|
||||
$rootScope.$apply(() => {
|
||||
$rootScope.initData = buildTree();
|
||||
});
|
||||
}
|
||||
|
||||
bindAction('#destroyDom', destroyDom);
|
||||
|
|
|
@ -41,7 +41,6 @@ export function addTreeToModule(mod: any): any {
|
|||
}
|
||||
let childElement: any, childScope: any;
|
||||
$scope.$watch($attr.data, function ngIfWatchAction(value: any) {
|
||||
|
||||
if (value) {
|
||||
if (!childScope) {
|
||||
childScope = $scope.$new();
|
||||
|
@ -67,6 +66,8 @@ export function addTreeToModule(mod: any): any {
|
|||
])
|
||||
.config([
|
||||
'$compileProvider',
|
||||
function($compileProvider: any) { $compileProvider.debugInfoEnabled(false); }
|
||||
function($compileProvider: any) {
|
||||
$compileProvider.debugInfoEnabled(false);
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ export function init(moduleRef: NgModuleRef<AppModule>) {
|
|||
|
||||
const injector = moduleRef.injector;
|
||||
appRef = injector.get(ApplicationRef);
|
||||
const numberOfChecksEl = document.getElementById('numberOfChecks') !;
|
||||
const numberOfChecksEl = document.getElementById('numberOfChecks')!;
|
||||
|
||||
tree = appRef.components[0].instance;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {Component, NgModule} from '@angular/core';
|
||||
import {BrowserModule, DomSanitizer, SafeStyle} from '@angular/platform-browser';
|
||||
|
||||
import {TreeNode, emptyTree} from '../util';
|
||||
import {emptyTree, TreeNode} from '../util';
|
||||
|
||||
let trustedEmptyColor: SafeStyle;
|
||||
let trustedGreyColor: SafeStyle;
|
||||
|
@ -22,7 +22,9 @@ let trustedGreyColor: SafeStyle;
|
|||
})
|
||||
export class TreeComponent {
|
||||
data: TreeNode = emptyTree;
|
||||
get bgColor() { return this.data.depth % 2 ? trustedEmptyColor : trustedGreyColor; }
|
||||
get bgColor() {
|
||||
return this.data.depth % 2 ? trustedEmptyColor : trustedGreyColor;
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({imports: [BrowserModule], bootstrap: [TreeComponent], declarations: [TreeComponent]})
|
||||
|
|
|
@ -7,17 +7,19 @@
|
|||
*/
|
||||
|
||||
import {NgIf} from '@angular/common';
|
||||
import {ComponentFactory, ComponentFactoryResolver, ComponentRef, ErrorHandler, Injector, NgModuleRef, RendererFactory2, Sanitizer, TemplateRef, ViewContainerRef, ɵArgumentType as ArgumentType, ɵBindingFlags as BindingFlags, ɵNodeFlags as NodeFlags, ɵViewDefinition as ViewDefinition, ɵViewFlags as ViewFlags, ɵand as anchorDef, ɵccf as createComponentFactory, ɵdid as directiveDef, ɵeld as elementDef, ɵinitServicesIfNeeded as initServicesIfNeeded, ɵted as textDef, ɵvid as viewDef} from '@angular/core';
|
||||
import {ComponentFactory, ComponentFactoryResolver, ComponentRef, ErrorHandler, Injector, NgModuleRef, RendererFactory2, Sanitizer, TemplateRef, ViewContainerRef, ɵand as anchorDef, ɵArgumentType as ArgumentType, ɵBindingFlags as BindingFlags, ɵccf as createComponentFactory, ɵdid as directiveDef, ɵeld as elementDef, ɵinitServicesIfNeeded as initServicesIfNeeded, ɵNodeFlags as NodeFlags, ɵted as textDef, ɵvid as viewDef, ɵViewDefinition as ViewDefinition, ɵViewFlags as ViewFlags} from '@angular/core';
|
||||
import {SafeStyle, ɵDomRendererFactory2 as DomRendererFactory2, ɵDomSanitizerImpl as DomSanitizerImpl} from '@angular/platform-browser';
|
||||
|
||||
import {TreeNode, emptyTree} from '../util';
|
||||
import {emptyTree, TreeNode} from '../util';
|
||||
|
||||
let trustedEmptyColor: SafeStyle;
|
||||
let trustedGreyColor: SafeStyle;
|
||||
|
||||
export class TreeComponent {
|
||||
data: TreeNode = emptyTree;
|
||||
get bgColor() { return this.data.depth % 2 ? trustedEmptyColor : trustedGreyColor; }
|
||||
get bgColor() {
|
||||
return this.data.depth % 2 ? trustedEmptyColor : trustedGreyColor;
|
||||
}
|
||||
}
|
||||
|
||||
let viewFlags = ViewFlags.None;
|
||||
|
@ -120,11 +122,19 @@ export class AppModule implements Injector, NgModuleRef<any> {
|
|||
this.componentFactory.create(Injector.NULL, [], this.componentFactory.selector, this);
|
||||
}
|
||||
|
||||
tick() { this.componentRef.changeDetectorRef.detectChanges(); }
|
||||
tick() {
|
||||
this.componentRef.changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
get injector() { return this; }
|
||||
get componentFactoryResolver(): ComponentFactoryResolver { return null; }
|
||||
get instance() { return this; }
|
||||
get injector() {
|
||||
return this;
|
||||
}
|
||||
get componentFactoryResolver(): ComponentFactoryResolver {
|
||||
return null;
|
||||
}
|
||||
get instance() {
|
||||
return this;
|
||||
}
|
||||
destroy() {}
|
||||
onDestroy(callback: () => void) {}
|
||||
}
|
||||
|
|
|
@ -9,24 +9,25 @@
|
|||
import {Component, Input, NgModule} from '@angular/core';
|
||||
import {BrowserModule, DomSanitizer, SafeStyle} from '@angular/platform-browser';
|
||||
|
||||
import {TreeNode, emptyTree, getMaxDepth} from '../util';
|
||||
import {emptyTree, getMaxDepth, TreeNode} from '../util';
|
||||
|
||||
let trustedEmptyColor: SafeStyle;
|
||||
let trustedGreyColor: SafeStyle;
|
||||
|
||||
function createTreeComponent(level: number, isLeaf: boolean) {
|
||||
const nextTreeEl = `tree${level+1}`;
|
||||
const nextTreeEl = `tree${level + 1}`;
|
||||
let template = `<span [style.backgroundColor]="bgColor"> {{data.value}} </span>`;
|
||||
if (!isLeaf) {
|
||||
template +=
|
||||
`<${nextTreeEl} [data]='data.right'></${nextTreeEl}><${nextTreeEl} [data]='data.left'></${nextTreeEl}>`;
|
||||
template += `<${nextTreeEl} [data]='data.right'></${nextTreeEl}><${
|
||||
nextTreeEl} [data]='data.left'></${nextTreeEl}>`;
|
||||
}
|
||||
|
||||
@Component({selector: `tree${level}`, template: template})
|
||||
class TreeComponent {
|
||||
@Input()
|
||||
data: TreeNode;
|
||||
get bgColor() { return this.data.depth % 2 ? trustedEmptyColor : trustedGreyColor; }
|
||||
@Input() data: TreeNode;
|
||||
get bgColor() {
|
||||
return this.data.depth % 2 ? trustedEmptyColor : trustedGreyColor;
|
||||
}
|
||||
}
|
||||
|
||||
return TreeComponent;
|
||||
|
@ -34,8 +35,7 @@ function createTreeComponent(level: number, isLeaf: boolean) {
|
|||
|
||||
@Component({selector: 'tree', template: `<tree0 *ngIf="data.left != null" [data]='data'></tree0>`})
|
||||
export class RootTreeComponent {
|
||||
@Input()
|
||||
data: TreeNode = emptyTree;
|
||||
@Input() data: TreeNode = emptyTree;
|
||||
}
|
||||
|
||||
function createModule(): any {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {Component, Input, NgModule} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
|
||||
import {TreeNode, emptyTree} from '../util';
|
||||
import {emptyTree, TreeNode} from '../util';
|
||||
|
||||
@Component({
|
||||
selector: 'tree',
|
||||
|
@ -19,8 +19,7 @@ import {TreeNode, emptyTree} from '../util';
|
|||
<tree *ngIf='data.right != null' [data]='data.right'></tree><tree *ngIf='data.left != null' [data]='data.left'></tree>`
|
||||
})
|
||||
export class TreeComponent {
|
||||
@Input()
|
||||
data: TreeNode = emptyTree;
|
||||
@Input() data: TreeNode = emptyTree;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
*/
|
||||
|
||||
import {ɵrenderComponent as renderComponent} from '@angular/core';
|
||||
|
||||
import {bindAction, profile} from '../../util';
|
||||
import {TreeComponent, createDom, destroyDom, detectChanges} from './tree';
|
||||
|
||||
import {createDom, destroyDom, detectChanges, TreeComponent} from './tree';
|
||||
|
||||
function noop() {}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ export function createDom(component: TreeComponent) {
|
|||
ɵdetectChanges(component);
|
||||
}
|
||||
|
||||
const numberOfChecksEl = document.getElementById('numberOfChecks') !;
|
||||
const numberOfChecksEl = document.getElementById('numberOfChecks')!;
|
||||
let detectChangesRuns = 0;
|
||||
export function detectChanges(component: TreeComponent) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
|
@ -42,7 +42,9 @@ export function detectChanges(component: TreeComponent) {
|
|||
})
|
||||
export class TreeComponent {
|
||||
data: any = emptyTree;
|
||||
get bgColor() { return this.data.depth % 2 ? '' : 'grey'; }
|
||||
get bgColor() {
|
||||
return this.data.depth % 2 ? '' : 'grey';
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({declarations: [TreeComponent], imports: [CommonModule]})
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ɵRenderFlags, ɵrenderComponent as renderComponent, ɵɵadvance, ɵɵcontainer, ɵɵcontainerRefreshEnd, ɵɵcontainerRefreshStart, ɵɵdefineComponent, ɵɵelementEnd, ɵɵelementStart, ɵɵembeddedViewEnd, ɵɵembeddedViewStart, ɵɵstyleProp, ɵɵtext, ɵɵtextInterpolate1} from '@angular/core';
|
||||
import {ɵrenderComponent as renderComponent, ɵRenderFlags, ɵɵadvance, ɵɵcontainer, ɵɵcontainerRefreshEnd, ɵɵcontainerRefreshStart, ɵɵdefineComponent, ɵɵelementEnd, ɵɵelementStart, ɵɵembeddedViewEnd, ɵɵembeddedViewStart, ɵɵstyleProp, ɵɵtext, ɵɵtextInterpolate1} from '@angular/core';
|
||||
|
||||
import {bindAction, profile} from '../../util';
|
||||
import {createDom, destroyDom, detectChanges} from '../render3/tree';
|
||||
import {TreeNode, emptyTree} from '../util';
|
||||
import {emptyTree, TreeNode} from '../util';
|
||||
|
||||
function noop() {}
|
||||
|
||||
|
@ -26,15 +26,16 @@ export class TreeFunction {
|
|||
selectors: [['tree']],
|
||||
decls: 5,
|
||||
vars: 2,
|
||||
template: function(rf: ɵRenderFlags, ctx: TreeFunction) {
|
||||
// bit of a hack
|
||||
TreeTpl(rf, ctx.data);
|
||||
},
|
||||
template:
|
||||
function(rf: ɵRenderFlags, ctx: TreeFunction) {
|
||||
// bit of a hack
|
||||
TreeTpl(rf, ctx.data);
|
||||
},
|
||||
inputs: {data: 'data'}
|
||||
});
|
||||
}
|
||||
|
||||
const TreeFunctionCmpDef = TreeFunction.ɵcmp as{decls: number, vars: number};
|
||||
const TreeFunctionCmpDef = TreeFunction.ɵcmp as {decls: number, vars: number};
|
||||
export function TreeTpl(rf: ɵRenderFlags, ctx: TreeNode) {
|
||||
if (rf & ɵRenderFlags.Create) {
|
||||
ɵɵelementStart(0, 'tree');
|
||||
|
|
|
@ -11,7 +11,7 @@ import {$} from 'protractor';
|
|||
import {openTreeBenchmark} from './test_utils';
|
||||
|
||||
describe('tree benchmark', () => {
|
||||
it('should work for createDestroy', async() => {
|
||||
it('should work for createDestroy', async () => {
|
||||
openTreeBenchmark();
|
||||
await $('#createDom').click();
|
||||
expect($('#root').getText()).toContain('1');
|
||||
|
@ -19,7 +19,7 @@ describe('tree benchmark', () => {
|
|||
expect(await $('#root').getText()).toEqual('');
|
||||
});
|
||||
|
||||
it('should work for update', async() => {
|
||||
it('should work for update', async () => {
|
||||
openTreeBenchmark();
|
||||
await $('#createDom').click();
|
||||
await $('#createDom').click();
|
||||
|
|
|
@ -10,7 +10,7 @@ import {$} from 'protractor';
|
|||
import {runTreeBenchmark} from './test_utils';
|
||||
|
||||
describe('tree benchmark perf', () => {
|
||||
it('should work for createOnly', async() => {
|
||||
it('should work for createOnly', async () => {
|
||||
await runTreeBenchmark({
|
||||
// This cannot be called "createOnly" because the actual destroy benchmark
|
||||
// has the "createOnly" id already. See: https://github.com/angular/angular/pull/21503
|
||||
|
@ -20,7 +20,7 @@ describe('tree benchmark perf', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should work for destroy', async() => {
|
||||
it('should work for destroy', async () => {
|
||||
await runTreeBenchmark({
|
||||
// This is actually a benchmark for destroying the dom, but it has been accidentally
|
||||
// named "createOnly". See https://github.com/angular/angular/pull/21503.
|
||||
|
@ -30,7 +30,7 @@ describe('tree benchmark perf', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should work for createDestroy', async() => {
|
||||
it('should work for createDestroy', async () => {
|
||||
await runTreeBenchmark({
|
||||
id: 'createDestroy',
|
||||
work: () => {
|
||||
|
@ -40,7 +40,7 @@ describe('tree benchmark perf', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should work for update', async() => {
|
||||
it('should work for update', async () => {
|
||||
await runTreeBenchmark({
|
||||
id: 'update',
|
||||
work: () => $('#createDom').click(),
|
||||
|
|
|
@ -11,7 +11,7 @@ import {$} from 'protractor';
|
|||
import {openTreeBenchmark} from './test_utils';
|
||||
|
||||
describe('tree benchmark detect changes', () => {
|
||||
it('should work for detectChanges', async() => {
|
||||
it('should work for detectChanges', async () => {
|
||||
openTreeBenchmark();
|
||||
await $('#detectChanges').click();
|
||||
expect($('#numberOfChecks').getText()).toContain('10');
|
||||
|
|
|
@ -10,7 +10,7 @@ import {$} from 'protractor';
|
|||
import {runTreeBenchmark} from './test_utils';
|
||||
|
||||
describe('tree benchmark detect changes perf', () => {
|
||||
it('should work for detectChanges', async() => {
|
||||
it('should work for detectChanges', async () => {
|
||||
await runTreeBenchmark({
|
||||
id: 'detectChanges',
|
||||
work: () => $('#detectChanges').click(),
|
||||
|
|
|
@ -16,12 +16,14 @@ export class TreeNode {
|
|||
public value: string, public depth: number, public maxDepth: number,
|
||||
public left: TreeNode|null, public right: TreeNode|null) {
|
||||
this.transitiveChildCount = Math.pow(2, (this.maxDepth - this.depth + 1)) - 1;
|
||||
this.children = this.left ? [this.left, this.right !] : [];
|
||||
this.children = this.left ? [this.left, this.right!] : [];
|
||||
}
|
||||
|
||||
// Needed for Polymer as it does not support ternary nor modulo operator
|
||||
// in expressions
|
||||
get style(): string { return this.depth % 2 === 0 ? 'background-color: grey' : ''; }
|
||||
get style(): string {
|
||||
return this.depth % 2 === 0 ? 'background-color: grey' : '';
|
||||
}
|
||||
}
|
||||
|
||||
let treeCreateCount: number;
|
||||
|
@ -78,7 +80,7 @@ export function newArray<T>(size: number, value: T): T[];
|
|||
export function newArray<T>(size: number, value?: T): T[] {
|
||||
const list: T[] = [];
|
||||
for (let i = 0; i < size; i++) {
|
||||
list.push(value !);
|
||||
list.push(value!);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ export function getStringParameter(name: string) {
|
|||
}
|
||||
|
||||
export function bindAction(selector: string, callback: () => void) {
|
||||
document.querySelector(selector) !.addEventListener('click', callback);
|
||||
document.querySelector(selector)!.addEventListener('click', callback);
|
||||
}
|
||||
|
||||
|
||||
|
@ -66,7 +66,8 @@ function reportProfileResults(durations: number[], count: number) {
|
|||
Number.MAX_SAFE_INTEGER)
|
||||
.toFixed(2);
|
||||
window.console.log(
|
||||
`Iterations: ${count}; cold time: ${durations[0].toFixed(2)} ms; average time: ${avgDuration} ms / iteration; best time: ${minDuration} ms`);
|
||||
`Iterations: ${count}; cold time: ${durations[0].toFixed(2)} ms; average time: ${
|
||||
avgDuration} ms / iteration; best time: ${minDuration} ms`);
|
||||
}
|
||||
|
||||
// helper script that will read out the url parameters
|
||||
|
|
|
@ -20,7 +20,9 @@ export class ViewManipulationDirective {
|
|||
}
|
||||
}
|
||||
|
||||
clear() { this._vcRef.clear(); }
|
||||
clear() {
|
||||
this._vcRef.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
@ -44,9 +46,13 @@ export class ViewsBenchmark {
|
|||
|
||||
constructor(private _cdRef: ChangeDetectorRef) {}
|
||||
|
||||
create(vm: ViewManipulationDirective) { vm.create(1000); }
|
||||
create(vm: ViewManipulationDirective) {
|
||||
vm.create(1000);
|
||||
}
|
||||
|
||||
destroy(vm: ViewManipulationDirective) { vm.clear(); }
|
||||
destroy(vm: ViewManipulationDirective) {
|
||||
vm.clear();
|
||||
}
|
||||
|
||||
check() {
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
|
|
|
@ -11,7 +11,6 @@ import {browser} from 'protractor';
|
|||
import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
describe('hello world', function() {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
describe('hello world app', function() {
|
||||
|
@ -30,7 +29,6 @@ describe('hello world', function() {
|
|||
expect(getComponentText('hello-app', '.greeting')).toEqual('howdy world!');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function getComponentText(selector: string, innerSelector: string) {
|
||||
|
|
|
@ -11,7 +11,6 @@ import {browser} from 'protractor';
|
|||
import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
describe('http', function() {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
describe('fetching', function() {
|
||||
|
@ -25,6 +24,6 @@ describe('http', function() {
|
|||
});
|
||||
|
||||
function getComponentText(selector: string, innerSelector: string) {
|
||||
return browser.executeScript(
|
||||
`return document.querySelector("${selector}").querySelector("${innerSelector}").textContent.trim()`);
|
||||
return browser.executeScript(`return document.querySelector("${selector}").querySelector("${
|
||||
innerSelector}").textContent.trim()`);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import {browser} from 'protractor';
|
|||
import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
describe('jsonp', function() {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
describe('fetching', function() {
|
||||
|
@ -25,6 +24,6 @@ describe('jsonp', function() {
|
|||
});
|
||||
|
||||
function getComponentText(selector: string, innerSelector: string) {
|
||||
return browser.executeScript(
|
||||
`return document.querySelector("${selector}").querySelector("${innerSelector}").textContent.trim()`);
|
||||
return browser.executeScript(`return document.querySelector("${selector}").querySelector("${
|
||||
innerSelector}").textContent.trim()`);
|
||||
}
|
||||
|
|
|
@ -13,11 +13,12 @@ import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
|||
const Key = protractor.Key;
|
||||
|
||||
describe('key_events', function() {
|
||||
|
||||
const URL = '/';
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
beforeEach(() => { browser.get(URL); });
|
||||
beforeEach(() => {
|
||||
browser.get(URL);
|
||||
});
|
||||
|
||||
it('should display correct key names', function() {
|
||||
const firstArea = element.all(by.css('.sample-area')).get(0);
|
||||
|
@ -78,5 +79,4 @@ describe('key_events', function() {
|
|||
secondArea.sendKeys(Key.CONTROL, Key.SHIFT, Key.ENTER);
|
||||
expect(secondArea.getText()).toEqual('');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -11,7 +11,6 @@ import {browser, by, element} from 'protractor';
|
|||
import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
describe('Model-Driven Forms', function() {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
const URL = '/';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {$, ExpectedConditions, browser, by, element} from 'protractor';
|
||||
import {$, browser, by, element, ExpectedConditions} from 'protractor';
|
||||
|
||||
import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
|
@ -16,7 +16,6 @@ function waitForElement(selector: string) {
|
|||
}
|
||||
|
||||
describe('relative assets relative-app', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
const URL = '/';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {$, ExpectedConditions, browser, by, element} from 'protractor';
|
||||
import {$, browser, by, element, ExpectedConditions} from 'protractor';
|
||||
|
||||
import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
|
@ -16,7 +16,6 @@ function waitForElement(selector: string) {
|
|||
}
|
||||
|
||||
describe('routing inbox-app', () => {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
describe('index view', () => {
|
||||
|
|
|
@ -11,15 +11,15 @@ import {browser, by, element} from 'protractor';
|
|||
import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
describe('SVG', function() {
|
||||
|
||||
const URL = '/';
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
beforeEach(() => { browser.get(URL); });
|
||||
beforeEach(() => {
|
||||
browser.get(URL);
|
||||
});
|
||||
|
||||
it('should display SVG component contents', function() {
|
||||
const svgText = element.all(by.css('g text')).get(0);
|
||||
expect(svgText.getText()).toEqual('Hello');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -11,7 +11,6 @@ import {browser, by, element} from 'protractor';
|
|||
import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
describe('Template-Driven Forms', function() {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
const URL = '/';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ExpectedConditions, browser, by, element, protractor} from 'protractor';
|
||||
import {browser, by, element, ExpectedConditions, protractor} from 'protractor';
|
||||
|
||||
import {verifyNoBrowserErrors} from '../../../../e2e_util/e2e_util';
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ExpectedConditions, browser, by, element, protractor} from 'protractor';
|
||||
import {browser, by, element, ExpectedConditions, protractor} from 'protractor';
|
||||
|
||||
import {verifyNoBrowserErrors} from '../../../../e2e_util/e2e_util';
|
||||
|
||||
|
@ -27,7 +27,6 @@ describe('WebWorkers Kitchen Sink', function() {
|
|||
const elem = element(by.css(selector));
|
||||
browser.wait(ExpectedConditions.textToBePresentInElement(elem, 'hello world!'), 5000);
|
||||
expect(elem.getText()).toEqual('hello world!');
|
||||
|
||||
});
|
||||
|
||||
it('should change greeting', () => {
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ExpectedConditions, browser, by, element, protractor} from 'protractor';
|
||||
import {browser, by, element, ExpectedConditions, protractor} from 'protractor';
|
||||
|
||||
import {verifyNoBrowserErrors} from '../../../../e2e_util/e2e_util';
|
||||
|
||||
const URL = '/';
|
||||
|
||||
describe('MessageBroker', function() {
|
||||
|
||||
afterEach(() => {
|
||||
verifyNoBrowserErrors();
|
||||
browser.ignoreSynchronization = false;
|
||||
|
|
|
@ -69,7 +69,9 @@ describe('WebWorker Router', () => {
|
|||
browser.wait(() => {
|
||||
const deferred = protractor.promise.defer();
|
||||
const elem = element(by.css(contentSelector));
|
||||
elem.getText().then((text: string) => { return deferred.fulfill(text === expected); });
|
||||
elem.getText().then((text: string) => {
|
||||
return deferred.fulfill(text === expected);
|
||||
});
|
||||
return deferred.promise;
|
||||
}, 5000);
|
||||
}
|
||||
|
@ -77,8 +79,9 @@ describe('WebWorker Router', () => {
|
|||
function waitForUrl(regex: RegExp): void {
|
||||
browser.wait(() => {
|
||||
const deferred = protractor.promise.defer();
|
||||
browser.getCurrentUrl().then(
|
||||
(url: string) => { return deferred.fulfill(url.match(regex) !== null); });
|
||||
browser.getCurrentUrl().then((url: string) => {
|
||||
return deferred.fulfill(url.match(regex) !== null);
|
||||
});
|
||||
return deferred.promise;
|
||||
}, 5000);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ describe('WebWorkers Todo', function() {
|
|||
waitForBootstrap();
|
||||
expect(element(by.css('#todoapp header')).getText()).toEqual('todos');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function waitForBootstrap(): void {
|
||||
|
|
|
@ -11,13 +11,14 @@ import {browser, by, element} from 'protractor';
|
|||
import {verifyNoBrowserErrors} from '../../../e2e_util/e2e_util';
|
||||
|
||||
describe('Zippy Component', function() {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
describe('zippy', function() {
|
||||
const URL = '/';
|
||||
|
||||
beforeEach(function() { browser.get(URL); });
|
||||
beforeEach(function() {
|
||||
browser.get(URL);
|
||||
});
|
||||
|
||||
it('should change the zippy title depending on it\'s state', function() {
|
||||
const zippyTitle = element(by.css('.zippy__title'));
|
||||
|
|
|
@ -87,7 +87,9 @@ export class AnimateApp {
|
|||
alert(`backgroundAnimation has ${phase} from ${data['fromState']} to ${data['toState']}`);
|
||||
}
|
||||
|
||||
get state() { return this._state; }
|
||||
get state() {
|
||||
return this._state;
|
||||
}
|
||||
set state(s) {
|
||||
this._state = s;
|
||||
if (s == 'void') {
|
||||
|
|
|
@ -43,7 +43,9 @@ class AsyncApplication {
|
|||
multiTimeoutId: any = null;
|
||||
intervalId: any = null;
|
||||
|
||||
increment(): void { this.val1++; }
|
||||
increment(): void {
|
||||
this.val1++;
|
||||
}
|
||||
|
||||
delayedIncrement(): void {
|
||||
this.cancelDelayedIncrement();
|
||||
|
|
|
@ -16,11 +16,17 @@ class GesturesCmp {
|
|||
pinchScale: number = 1;
|
||||
rotateAngle: number = 0;
|
||||
|
||||
onSwipe(event: HammerInput): void { this.swipeDirection = event.deltaX > 0 ? 'right' : 'left'; }
|
||||
onSwipe(event: HammerInput): void {
|
||||
this.swipeDirection = event.deltaX > 0 ? 'right' : 'left';
|
||||
}
|
||||
|
||||
onPinch(event: HammerInput): void { this.pinchScale = event.scale; }
|
||||
onPinch(event: HammerInput): void {
|
||||
this.pinchScale = event.scale;
|
||||
}
|
||||
|
||||
onRotate(event: HammerInput): void { this.rotateAngle = event.rotation; }
|
||||
onRotate(event: HammerInput): void {
|
||||
this.rotateAngle = event.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({declarations: [GesturesCmp], bootstrap: [GesturesCmp], imports: [BrowserModule]})
|
||||
|
|
|
@ -48,9 +48,13 @@ export class RedDec {
|
|||
export class HelloCmp {
|
||||
greeting: string;
|
||||
|
||||
constructor(service: GreetingService) { this.greeting = service.greeting; }
|
||||
constructor(service: GreetingService) {
|
||||
this.greeting = service.greeting;
|
||||
}
|
||||
|
||||
changeGreeting(): void { this.greeting = 'howdy'; }
|
||||
changeGreeting(): void {
|
||||
this.greeting = 'howdy';
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({declarations: [HelloCmp, RedDec], bootstrap: [HelloCmp], imports: [BrowserModule]})
|
||||
|
|
|
@ -36,7 +36,9 @@ export class KeyEventsApp {
|
|||
event.preventDefault();
|
||||
}
|
||||
|
||||
resetShiftEnter(): void { this.shiftEnter = false; }
|
||||
resetShiftEnter(): void {
|
||||
this.shiftEnter = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a more readable version of current pressed keys.
|
||||
|
|
|
@ -52,7 +52,9 @@ export class ShowError {
|
|||
controlPath: string;
|
||||
errorTypes: string[];
|
||||
|
||||
constructor(@Host() formDir: FormGroupDirective) { this.formDir = formDir; }
|
||||
constructor(@Host() formDir: FormGroupDirective) {
|
||||
this.formDir = formDir;
|
||||
}
|
||||
|
||||
get errorMessage(): string {
|
||||
const form: FormGroup = this.formDir.form;
|
||||
|
|
|
@ -23,7 +23,9 @@ class OrderItem {
|
|||
public orderItemId: number, public orderId: number, public productName: string,
|
||||
public qty: number, public unitPrice: number) {}
|
||||
|
||||
get total(): number { return this.qty * this.unitPrice; }
|
||||
get total(): number {
|
||||
return this.qty * this.unitPrice;
|
||||
}
|
||||
}
|
||||
|
||||
class Order {
|
||||
|
@ -31,8 +33,12 @@ class Order {
|
|||
public orderId: number, public customerName: string, public limit: number,
|
||||
private _dataService: DataService) {}
|
||||
|
||||
get items(): OrderItem[] { return this._dataService.itemsFor(this); }
|
||||
get total(): number { return this.items.map(i => i.total).reduce((a, b) => a + b, 0); }
|
||||
get items(): OrderItem[] {
|
||||
return this._dataService.itemsFor(this);
|
||||
}
|
||||
get total(): number {
|
||||
return this.items.map(i => i.total).reduce((a, b) => a + b, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,7 +75,9 @@ export class DataService {
|
|||
this.orderItems.push(new OrderItem(_nextId++, order.orderId, '', 0, 0));
|
||||
}
|
||||
|
||||
deleteItem(item: OrderItem): void { this.orderItems.splice(this.orderItems.indexOf(item), 1); }
|
||||
deleteItem(item: OrderItem): void {
|
||||
this.orderItems.splice(this.orderItems.indexOf(item), 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -107,8 +115,12 @@ export class DataService {
|
|||
export class OrderListComponent {
|
||||
orders: Order[];
|
||||
|
||||
constructor(private _service: DataService) { this.orders = _service.orders; }
|
||||
select(order: Order): void { this._service.currentOrder = order; }
|
||||
constructor(private _service: DataService) {
|
||||
this.orders = _service.orders;
|
||||
}
|
||||
select(order: Order): void {
|
||||
this._service.currentOrder = order;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -141,7 +153,9 @@ export class OrderItemComponent {
|
|||
@Input() item: OrderItem;
|
||||
@Output() delete = new EventEmitter();
|
||||
|
||||
onDelete(): void { this.delete.emit(this.item); }
|
||||
onDelete(): void {
|
||||
this.delete.emit(this.item);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
@ -176,11 +190,17 @@ export class OrderItemComponent {
|
|||
export class OrderDetailsComponent {
|
||||
constructor(private _service: DataService) {}
|
||||
|
||||
get order(): Order { return this._service.currentOrder; }
|
||||
get order(): Order {
|
||||
return this._service.currentOrder;
|
||||
}
|
||||
|
||||
deleteItem(item: OrderItem): void { this._service.deleteItem(item); }
|
||||
deleteItem(item: OrderItem): void {
|
||||
this._service.deleteItem(item);
|
||||
}
|
||||
|
||||
addItem(): void { this._service.addItemForOrder(this.order); }
|
||||
addItem(): void {
|
||||
this._service.addItemForOrder(this.order);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
|
|
@ -35,9 +35,15 @@ class Person {
|
|||
this.personId = _nextId++;
|
||||
}
|
||||
|
||||
get age(): number { return 2015 - this.yearOfBirth; }
|
||||
get fullName(): string { return `${this.firstName} ${this.lastName}`; }
|
||||
get friendNames(): string { return this.friends.map(f => f.fullName).join(', '); }
|
||||
get age(): number {
|
||||
return 2015 - this.yearOfBirth;
|
||||
}
|
||||
get fullName(): string {
|
||||
return `${this.firstName} ${this.lastName}`;
|
||||
}
|
||||
get friendNames(): string {
|
||||
return this.friends.map(f => f.fullName).join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,7 +112,9 @@ export class DataService {
|
|||
})
|
||||
export class FullNameComponent {
|
||||
constructor(private _service: DataService) {}
|
||||
get person(): Person { return this._service.currentPerson; }
|
||||
get person(): Person {
|
||||
return this._service.currentPerson;
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
@ -158,7 +166,9 @@ export class FullNameComponent {
|
|||
})
|
||||
export class PersonsDetailComponent {
|
||||
constructor(private _service: DataService) {}
|
||||
get person(): Person { return this._service.currentPerson; }
|
||||
get person(): Person {
|
||||
return this._service.currentPerson;
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
@ -179,9 +189,13 @@ export class PersonsDetailComponent {
|
|||
export class PersonsComponent {
|
||||
persons: Person[];
|
||||
|
||||
constructor(private _service: DataService) { this.persons = _service.persons; }
|
||||
constructor(private _service: DataService) {
|
||||
this.persons = _service.persons;
|
||||
}
|
||||
|
||||
select(person: Person): void { this._service.currentPerson = person; }
|
||||
select(person: Person): void {
|
||||
this._service.currentPerson = person;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -199,8 +213,12 @@ export class PersonsComponent {
|
|||
export class PersonManagementApplication {
|
||||
mode: string;
|
||||
|
||||
switchToEditName(): void { this.mode = 'editName'; }
|
||||
switchToPersonList(): void { this.mode = 'personList'; }
|
||||
switchToEditName(): void {
|
||||
this.mode = 'editName';
|
||||
}
|
||||
switchToPersonList(): void {
|
||||
this.mode = 'personList';
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -29,7 +29,8 @@ export class InboxRecord {
|
|||
email: string,
|
||||
firstName: string,
|
||||
lastName: string,
|
||||
date: string, draft?: boolean
|
||||
date: string,
|
||||
draft?: boolean
|
||||
} = null) {
|
||||
if (data) {
|
||||
this.setData(data);
|
||||
|
@ -43,7 +44,8 @@ export class InboxRecord {
|
|||
email: string,
|
||||
firstName: string,
|
||||
lastName: string,
|
||||
date: string, draft?: boolean
|
||||
date: string,
|
||||
draft?: boolean
|
||||
}) {
|
||||
this.id = record.id;
|
||||
this.subject = record.subject;
|
||||
|
|
|
@ -17,8 +17,11 @@ export class InboxDetailCmp {
|
|||
private ready: boolean = false;
|
||||
|
||||
constructor(db: DbService, route: ActivatedRoute) {
|
||||
route.paramMap.forEach(
|
||||
p => { db.email(p.get('id')).then((data) => { this.record.setData(data); }); });
|
||||
route.paramMap.forEach(p => {
|
||||
db.email(p.get('id')).then((data) => {
|
||||
this.record.setData(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,9 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
|||
<button class="errorButton" (click)="createError()">create error</button>`
|
||||
})
|
||||
export class ErrorComponent {
|
||||
createError(): void { throw new Error('Sourcemap test'); }
|
||||
createError(): void {
|
||||
throw new Error('Sourcemap test');
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({declarations: [ErrorComponent], bootstrap: [ErrorComponent], imports: [BrowserModule]})
|
||||
|
|
|
@ -78,7 +78,9 @@ export class ShowError {
|
|||
controlPath: string;
|
||||
errorTypes: string[];
|
||||
|
||||
constructor(@Host() formDir: NgForm) { this.formDir = formDir; }
|
||||
constructor(@Host() formDir: NgForm) {
|
||||
this.formDir = formDir;
|
||||
}
|
||||
|
||||
get errorMessage(): string {
|
||||
const form: FormGroup = this.formDir.form;
|
||||
|
|
|
@ -14,14 +14,18 @@ export abstract class KeyModel {
|
|||
}
|
||||
|
||||
export class Todo extends KeyModel {
|
||||
constructor(key: number, public title: string, public completed: boolean) { super(key); }
|
||||
constructor(key: number, public title: string, public completed: boolean) {
|
||||
super(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class TodoFactory {
|
||||
private _uid: number = 0;
|
||||
|
||||
nextUid(): number { return ++this._uid; }
|
||||
nextUid(): number {
|
||||
return ++this._uid;
|
||||
}
|
||||
|
||||
create(title: string, isCompleted: boolean): Todo {
|
||||
return new Todo(this.nextUid(), title, isCompleted);
|
||||
|
@ -33,9 +37,13 @@ export class TodoFactory {
|
|||
export class Store<T extends KeyModel> {
|
||||
list: T[] = [];
|
||||
|
||||
add(record: T): void { this.list.push(record); }
|
||||
add(record: T): void {
|
||||
this.list.push(record);
|
||||
}
|
||||
|
||||
remove(record: T): void { this.removeBy((item) => item === record); }
|
||||
remove(record: T): void {
|
||||
this.removeBy((item) => item === record);
|
||||
}
|
||||
|
||||
removeBy(callback: (record: T) => boolean): void {
|
||||
this.list = this.list.filter((record) => !callback(record));
|
||||
|
|
|
@ -23,7 +23,9 @@ export class TodoApp {
|
|||
inputElement.value = '';
|
||||
}
|
||||
|
||||
editTodo(todo: Todo): void { this.todoEdit = todo; }
|
||||
editTodo(todo: Todo): void {
|
||||
this.todoEdit = todo;
|
||||
}
|
||||
|
||||
doneEditing($event: KeyboardEvent, todo: Todo): void {
|
||||
const which = $event.which;
|
||||
|
@ -37,18 +39,28 @@ export class TodoApp {
|
|||
}
|
||||
}
|
||||
|
||||
addTodo(newTitle: string): void { this.todoStore.add(this.factory.create(newTitle, false)); }
|
||||
addTodo(newTitle: string): void {
|
||||
this.todoStore.add(this.factory.create(newTitle, false));
|
||||
}
|
||||
|
||||
completeMe(todo: Todo): void { todo.completed = !todo.completed; }
|
||||
completeMe(todo: Todo): void {
|
||||
todo.completed = !todo.completed;
|
||||
}
|
||||
|
||||
deleteMe(todo: Todo): void { this.todoStore.remove(todo); }
|
||||
deleteMe(todo: Todo): void {
|
||||
this.todoStore.remove(todo);
|
||||
}
|
||||
|
||||
toggleAll($event: MouseEvent): void {
|
||||
const isComplete = ($event.target as HTMLInputElement).checked;
|
||||
this.todoStore.list.forEach((todo: Todo) => { todo.completed = isComplete; });
|
||||
this.todoStore.list.forEach((todo: Todo) => {
|
||||
todo.completed = isComplete;
|
||||
});
|
||||
}
|
||||
|
||||
clearCompleted(): void { this.todoStore.removeBy((todo: Todo) => todo.completed); }
|
||||
clearCompleted(): void {
|
||||
this.todoStore.removeBy((todo: Todo) => todo.completed);
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({declarations: [TodoApp], bootstrap: [TodoApp], imports: [BrowserModule]})
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component, EventEmitter, Input, NgModule, Output, forwardRef} from '@angular/core';
|
||||
import {Component, EventEmitter, forwardRef, Input, NgModule, Output} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {UpgradeAdapter} from '@angular/upgrade';
|
||||
|
||||
|
@ -30,7 +30,9 @@ const styles = [`
|
|||
const adapter = new UpgradeAdapter(forwardRef(() => Ng2AppModule));
|
||||
const ng1module = angular.module('myExample', []);
|
||||
|
||||
ng1module.controller('Index', function($scope: any) { $scope.name = 'World'; });
|
||||
ng1module.controller('Index', function($scope: any) {
|
||||
$scope.name = 'World';
|
||||
});
|
||||
|
||||
ng1module.directive('ng1User', function() {
|
||||
return {
|
||||
|
|
|
@ -26,7 +26,11 @@ export class InputCmp {
|
|||
inputVal = '';
|
||||
textareaVal = '';
|
||||
|
||||
inputChanged(e: Event) { this.inputVal = (e.target as HTMLInputElement).value; }
|
||||
inputChanged(e: Event) {
|
||||
this.inputVal = (e.target as HTMLInputElement).value;
|
||||
}
|
||||
|
||||
textAreaChanged(e: Event) { this.textareaVal = (e.target as HTMLTextAreaElement).value; }
|
||||
textAreaChanged(e: Event) {
|
||||
this.textareaVal = (e.target as HTMLTextAreaElement).value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,9 +49,15 @@ export class HelloCmp {
|
|||
greeting: string;
|
||||
lastKey: string = '(none)';
|
||||
|
||||
constructor(service: GreetingService) { this.greeting = service.greeting; }
|
||||
constructor(service: GreetingService) {
|
||||
this.greeting = service.greeting;
|
||||
}
|
||||
|
||||
changeGreeting(): void { this.greeting = 'howdy'; }
|
||||
changeGreeting(): void {
|
||||
this.greeting = 'howdy';
|
||||
}
|
||||
|
||||
onKeyDown(event: KeyboardEvent): void { this.lastKey = String.fromCharCode(event.keyCode); }
|
||||
onKeyDown(event: KeyboardEvent): void {
|
||||
this.lastKey = String.fromCharCode(event.keyCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import {PlatformRef} from '@angular/core';
|
||||
import {ClientMessageBrokerFactory, FnArg, SerializerTypes, UiArguments, bootstrapWorkerUi} from '@angular/platform-webworker';
|
||||
import {bootstrapWorkerUi, ClientMessageBrokerFactory, FnArg, SerializerTypes, UiArguments} from '@angular/platform-webworker';
|
||||
|
||||
const ECHO_CHANNEL = 'ECHO';
|
||||
|
||||
|
|
|
@ -19,5 +19,7 @@ export class App {
|
|||
'echo', [SerializerTypes.PRIMITIVE], this._echo, SerializerTypes.PRIMITIVE);
|
||||
}
|
||||
|
||||
private _echo(val: string) { return new Promise((res) => res(val)); }
|
||||
private _echo(val: string) {
|
||||
return new Promise((res) => res(val));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {WORKER_UI_LOCATION_PROVIDERS, bootstrapWorkerUi} from '@angular/platform-webworker';
|
||||
import {bootstrapWorkerUi, WORKER_UI_LOCATION_PROVIDERS} from '@angular/platform-webworker';
|
||||
|
||||
bootstrapWorkerUi('loader.js', WORKER_UI_LOCATION_PROVIDERS);
|
||||
|
|
|
@ -36,11 +36,17 @@ export class TodoApp {
|
|||
}
|
||||
}
|
||||
|
||||
editTodo(todo: Todo): void { this.todoEdit = todo; }
|
||||
editTodo(todo: Todo): void {
|
||||
this.todoEdit = todo;
|
||||
}
|
||||
|
||||
addTodo(newTitle: string): void { this.todoStore.add(this.factory.create(newTitle, false)); }
|
||||
addTodo(newTitle: string): void {
|
||||
this.todoStore.add(this.factory.create(newTitle, false));
|
||||
}
|
||||
|
||||
completeMe(todo: Todo): void { todo.completed = !todo.completed; }
|
||||
completeMe(todo: Todo): void {
|
||||
todo.completed = !todo.completed;
|
||||
}
|
||||
|
||||
toggleCompleted(): void {
|
||||
this.hideActive = !this.hideActive;
|
||||
|
@ -57,12 +63,18 @@ export class TodoApp {
|
|||
this.hideActive = false;
|
||||
}
|
||||
|
||||
deleteMe(todo: Todo): void { this.todoStore.remove(todo); }
|
||||
deleteMe(todo: Todo): void {
|
||||
this.todoStore.remove(todo);
|
||||
}
|
||||
|
||||
toggleAll($event: MouseEvent): void {
|
||||
this.isComplete = !this.isComplete;
|
||||
this.todoStore.list.forEach((todo: Todo) => { todo.completed = this.isComplete; });
|
||||
this.todoStore.list.forEach((todo: Todo) => {
|
||||
todo.completed = this.isComplete;
|
||||
});
|
||||
}
|
||||
|
||||
clearCompleted(): void { this.todoStore.removeBy((todo: Todo) => todo.completed); }
|
||||
clearCompleted(): void {
|
||||
this.todoStore.removeBy((todo: Todo) => todo.completed);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue