test(ivy): support `className` in micro benchmarks (#33392)
The styling algorithm requires that the `RNode` has a `className` property in order to execute the fast-path. This changes adds the emulation of this property. PR Close #33392
This commit is contained in:
parent
b381497126
commit
6323a35468
|
@ -79,6 +79,7 @@ module.exports = function(config) {
|
||||||
'dist/all/@angular/compiler/test/render3/**',
|
'dist/all/@angular/compiler/test/render3/**',
|
||||||
'dist/all/@angular/core/test/bundling/**',
|
'dist/all/@angular/core/test/bundling/**',
|
||||||
'dist/all/@angular/core/test/render3/ivy/**',
|
'dist/all/@angular/core/test/render3/ivy/**',
|
||||||
|
'dist/all/@angular/core/test/render3/perf/**',
|
||||||
'dist/all/@angular/elements/schematics/**',
|
'dist/all/@angular/elements/schematics/**',
|
||||||
'dist/all/@angular/examples/**/e2e_test/*',
|
'dist/all/@angular/examples/**/e2e_test/*',
|
||||||
'dist/all/@angular/language-service/**',
|
'dist/all/@angular/language-service/**',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package(default_visibility = ["//visibility:private"])
|
package(default_visibility = ["//visibility:private"])
|
||||||
|
|
||||||
load("//tools:defaults.bzl", "ng_rollup_bundle", "ts_library")
|
load("//tools:defaults.bzl", "jasmine_node_test", "ng_rollup_bundle", "ts_library")
|
||||||
|
|
||||||
ts_library(
|
ts_library(
|
||||||
name = "perf_lib",
|
name = "perf_lib",
|
||||||
|
@ -9,10 +9,18 @@ ts_library(
|
||||||
),
|
),
|
||||||
deps = [
|
deps = [
|
||||||
"//packages/core",
|
"//packages/core",
|
||||||
|
"@npm//@types/jasmine",
|
||||||
"@npm//@types/node",
|
"@npm//@types/node",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
jasmine_node_test(
|
||||||
|
name = "perf",
|
||||||
|
deps = [
|
||||||
|
":perf_lib",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
ng_rollup_bundle(
|
ng_rollup_bundle(
|
||||||
name = "class_binding",
|
name = "class_binding",
|
||||||
entry_point = ":class_binding/index.ts",
|
entry_point = ":class_binding/index.ts",
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, RendererStyleFlags3} from '../../../src/render3/interfaces/renderer';
|
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, RendererStyleFlags3} from '../../../src/render3/interfaces/renderer';
|
||||||
|
|
||||||
export class WebWorkerRenderNode implements RNode, RComment, RText {
|
export class MicroBenchmarkRenderNode implements RNode, RComment, RText {
|
||||||
textContent: string|null = null;
|
textContent: string|null = null;
|
||||||
parentNode: RNode|null = null;
|
parentNode: RNode|null = null;
|
||||||
parentElement: RElement|null = null;
|
parentElement: RElement|null = null;
|
||||||
|
@ -15,15 +15,16 @@ export class WebWorkerRenderNode implements RNode, RComment, RText {
|
||||||
removeChild(oldChild: RNode): RNode { return oldChild; }
|
removeChild(oldChild: RNode): RNode { return oldChild; }
|
||||||
insertBefore(newChild: RNode, refChild: RNode|null, isViewRoot: boolean): void {}
|
insertBefore(newChild: RNode, refChild: RNode|null, isViewRoot: boolean): void {}
|
||||||
appendChild(newChild: RNode): RNode { return newChild; }
|
appendChild(newChild: RNode): RNode { return newChild; }
|
||||||
|
className: string = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NoopRenderer implements ProceduralRenderer3 {
|
export class MicroBenchmarkRenderer implements ProceduralRenderer3 {
|
||||||
destroy(): void { throw new Error('Method not implemented.'); }
|
destroy(): void { throw new Error('Method not implemented.'); }
|
||||||
createComment(value: string): RComment { return new WebWorkerRenderNode(); }
|
createComment(value: string): RComment { return new MicroBenchmarkRenderNode(); }
|
||||||
createElement(name: string, namespace?: string|null|undefined): RElement {
|
createElement(name: string, namespace?: string|null|undefined): RElement {
|
||||||
return new WebWorkerRenderNode() as any as RElement;
|
return new MicroBenchmarkRenderNode() as any as RElement;
|
||||||
}
|
}
|
||||||
createText(value: string): RText { return new WebWorkerRenderNode(); }
|
createText(value: string): RText { return new MicroBenchmarkRenderNode(); }
|
||||||
destroyNode?: ((node: RNode) => void)|null|undefined;
|
destroyNode?: ((node: RNode) => void)|null|undefined;
|
||||||
appendChild(parent: RElement, newChild: RNode): void {}
|
appendChild(parent: RElement, newChild: RNode): void {}
|
||||||
insertBefore(parent: RNode, newChild: RNode, refChild: RNode|null): void {}
|
insertBefore(parent: RNode, newChild: RNode, refChild: RNode|null): void {}
|
||||||
|
@ -32,10 +33,21 @@ export class NoopRenderer implements ProceduralRenderer3 {
|
||||||
parentNode(node: RNode): RElement|null { throw new Error('Method not implemented.'); }
|
parentNode(node: RNode): RElement|null { throw new Error('Method not implemented.'); }
|
||||||
nextSibling(node: RNode): RNode|null { throw new Error('Method not implemented.'); }
|
nextSibling(node: RNode): RNode|null { throw new Error('Method not implemented.'); }
|
||||||
setAttribute(el: RElement, name: string, value: string, namespace?: string|null|undefined): void {
|
setAttribute(el: RElement, name: string, value: string, namespace?: string|null|undefined): void {
|
||||||
|
if (name === 'class' && isOurNode(el)) {
|
||||||
|
el.className = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
removeAttribute(el: RElement, name: string, namespace?: string|null|undefined): void {}
|
removeAttribute(el: RElement, name: string, namespace?: string|null|undefined): void {}
|
||||||
addClass(el: RElement, name: string): void {}
|
addClass(el: RElement, name: string): void {
|
||||||
removeClass(el: RElement, name: string): void {}
|
if (isOurNode(el)) {
|
||||||
|
el.className = el.className === '' ? name : remove(el.className, name) + ' ' + name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeClass(el: RElement, name: string): void {
|
||||||
|
if (isOurNode(el)) {
|
||||||
|
el.className = remove(el.className, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
setStyle(el: RElement, style: string, value: any, flags?: RendererStyleFlags3|undefined): void {}
|
setStyle(el: RElement, style: string, value: any, flags?: RendererStyleFlags3|undefined): void {}
|
||||||
removeStyle(el: RElement, style: string, flags?: RendererStyleFlags3|undefined): void {}
|
removeStyle(el: RElement, style: string, flags?: RendererStyleFlags3|undefined): void {}
|
||||||
setProperty(el: RElement, name: string, value: any): void {}
|
setProperty(el: RElement, name: string, value: any): void {}
|
||||||
|
@ -47,11 +59,39 @@ export class NoopRenderer implements ProceduralRenderer3 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NoopRendererFactory implements RendererFactory3 {
|
export class MicroBenchmarkRendererFactory implements RendererFactory3 {
|
||||||
createRenderer(hostElement: RElement|null, rendererType: null): Renderer3 {
|
createRenderer(hostElement: RElement|null, rendererType: null): Renderer3 {
|
||||||
if (typeof global !== 'undefined') {
|
if (typeof global !== 'undefined') {
|
||||||
(global as any).Node = WebWorkerRenderNode;
|
(global as any).Node = MicroBenchmarkRenderNode;
|
||||||
}
|
}
|
||||||
return new NoopRenderer();
|
return new MicroBenchmarkRenderer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isOurNode(node: any): node is MicroBenchmarkRenderNode {
|
||||||
|
return node instanceof MicroBenchmarkRenderNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const enum Code {
|
||||||
|
SPACE = 32,
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove(text: string, key: string): string {
|
||||||
|
let wasLastWhitespace = true;
|
||||||
|
for (let i = 0; i < text.length; i++) {
|
||||||
|
if (wasLastWhitespace) {
|
||||||
|
const start = i;
|
||||||
|
let same = true;
|
||||||
|
let k = 0;
|
||||||
|
while (k < key.length && (same = text.charCodeAt(i) === key.charCodeAt(k))) {
|
||||||
|
k++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (same && text.charCodeAt(i) == Code.SPACE) {
|
||||||
|
return text.substring(0, start) + text.substring(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wasLastWhitespace = text.charCodeAt(i) <= Code.SPACE;
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {ProceduralRenderer3} from '@angular/core/src/render3/interfaces/renderer';
|
||||||
|
|
||||||
|
import {MicroBenchmarkRenderNode, MicroBenchmarkRendererFactory} from './noop_renderer';
|
||||||
|
|
||||||
|
describe('MicroBenchmarkRenderNode', () => {
|
||||||
|
const renderer =
|
||||||
|
new MicroBenchmarkRendererFactory().createRenderer(null, null) as ProceduralRenderer3;
|
||||||
|
describe('className', () => {
|
||||||
|
it('should be available in global space', () => {
|
||||||
|
expect(Node).toBeDefined();
|
||||||
|
const node: any = new MicroBenchmarkRenderNode();
|
||||||
|
expect(node instanceof Node).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emulate className', () => {
|
||||||
|
const node: any = new MicroBenchmarkRenderNode();
|
||||||
|
expect(node.className).toBe('');
|
||||||
|
renderer.setAttribute(node, 'foo', 'A AA BBB');
|
||||||
|
expect(node.className).toBe('');
|
||||||
|
renderer.setAttribute(node, 'class', 'A AA BBB');
|
||||||
|
expect(node.className).toBe('A AA BBB');
|
||||||
|
renderer.addClass(node, 'A');
|
||||||
|
expect(node.className).toBe('AA BBB A');
|
||||||
|
renderer.addClass(node, 'C');
|
||||||
|
expect(node.className).toBe('AA BBB A C');
|
||||||
|
renderer.removeClass(node, 'A');
|
||||||
|
expect(node.className).toBe('AA BBB C');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -12,10 +12,11 @@ import {RendererFactory3, domRendererFactory3} from '../../../src/render3/interf
|
||||||
import {LView, LViewFlags, TView} from '../../../src/render3/interfaces/view';
|
import {LView, LViewFlags, TView} from '../../../src/render3/interfaces/view';
|
||||||
import {insertView} from '../../../src/render3/node_manipulation';
|
import {insertView} from '../../../src/render3/node_manipulation';
|
||||||
|
|
||||||
import {NoopRendererFactory} from './noop_renderer';
|
import {MicroBenchmarkRendererFactory} from './noop_renderer';
|
||||||
|
|
||||||
const isBrowser = typeof process === 'undefined';
|
const isBrowser = typeof process === 'undefined';
|
||||||
const rendererFactory: RendererFactory3 = isBrowser ? domRendererFactory3 : new NoopRendererFactory;
|
const rendererFactory: RendererFactory3 =
|
||||||
|
isBrowser ? domRendererFactory3 : new MicroBenchmarkRendererFactory;
|
||||||
const renderer = rendererFactory.createRenderer(null, null);
|
const renderer = rendererFactory.createRenderer(null, null);
|
||||||
|
|
||||||
export function createAndRenderLView(
|
export function createAndRenderLView(
|
||||||
|
|
Loading…
Reference in New Issue