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/core/test/bundling/**',
|
||||
'dist/all/@angular/core/test/render3/ivy/**',
|
||||
'dist/all/@angular/core/test/render3/perf/**',
|
||||
'dist/all/@angular/elements/schematics/**',
|
||||
'dist/all/@angular/examples/**/e2e_test/*',
|
||||
'dist/all/@angular/language-service/**',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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(
|
||||
name = "perf_lib",
|
||||
|
@ -9,10 +9,18 @@ ts_library(
|
|||
),
|
||||
deps = [
|
||||
"//packages/core",
|
||||
"@npm//@types/jasmine",
|
||||
"@npm//@types/node",
|
||||
],
|
||||
)
|
||||
|
||||
jasmine_node_test(
|
||||
name = "perf",
|
||||
deps = [
|
||||
":perf_lib",
|
||||
],
|
||||
)
|
||||
|
||||
ng_rollup_bundle(
|
||||
name = "class_binding",
|
||||
entry_point = ":class_binding/index.ts",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
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;
|
||||
parentNode: RNode|null = null;
|
||||
parentElement: RElement|null = null;
|
||||
|
@ -15,15 +15,16 @@ export class WebWorkerRenderNode implements RNode, RComment, RText {
|
|||
removeChild(oldChild: RNode): RNode { return oldChild; }
|
||||
insertBefore(newChild: RNode, refChild: RNode|null, isViewRoot: boolean): void {}
|
||||
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.'); }
|
||||
createComment(value: string): RComment { return new WebWorkerRenderNode(); }
|
||||
createComment(value: string): RComment { return new MicroBenchmarkRenderNode(); }
|
||||
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;
|
||||
appendChild(parent: RElement, newChild: RNode): 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.'); }
|
||||
nextSibling(node: RNode): RNode|null { throw new Error('Method not implemented.'); }
|
||||
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 {}
|
||||
addClass(el: RElement, name: string): void {}
|
||||
removeClass(el: RElement, name: string): void {}
|
||||
addClass(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 {}
|
||||
removeStyle(el: RElement, style: string, flags?: RendererStyleFlags3|undefined): 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 {
|
||||
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 {insertView} from '../../../src/render3/node_manipulation';
|
||||
|
||||
import {NoopRendererFactory} from './noop_renderer';
|
||||
import {MicroBenchmarkRendererFactory} from './noop_renderer';
|
||||
|
||||
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);
|
||||
|
||||
export function createAndRenderLView(
|
||||
|
|
Loading…
Reference in New Issue