Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,13 @@
"tabWidth": 4,
"trailingComma": "es5",
"useTabs": false,
"plugins": ["prettier-plugin-tailwindcss"]
"plugins": ["prettier-plugin-tailwindcss"],
"overrides": [
{
"files": "suites-experimental/chat-room-angular/src/**/*.ts",
"options": {
"embeddedLanguageFormatting": "off"
}
}
]
}
20 changes: 20 additions & 0 deletions resources/benchmark-runner.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,26 @@ class PageElement {
};
}

/**
* Scroll geometry, for steps that drive a scroller to an explicit offset.
* Never animate a scroll inside a measured step: assign an offset instead.
*/
get scrollTop() {
return this.#node.scrollTop;
}

set scrollTop(offset) {
this.#node.scrollTop = offset;
}

get scrollHeight() {
return this.#node.scrollHeight;
}

get clientHeight() {
return this.#node.clientHeight;
}

dispatchEvent(eventName, options = NATIVE_OPTIONS, eventType = Event) {
if (eventName === "submit")
// FIXME FireFox doesn't like `new Event('submit')
Expand Down
20 changes: 20 additions & 0 deletions suites-experimental/chat-room-angular/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
node_modules

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
pnpm-debug.log*

# dist-ssr / local
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.sw?
.angular
53 changes: 53 additions & 0 deletions suites-experimental/chat-room-angular/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
## Description

An Angular port of the [ChatRoom-React](../chat-room/README.md) workload: the same
two-pane chat app, the same deterministic fixtures, the same windowed timeline,
and the same measured steps, so the three ports can be compared directly.

`src/data/`, `src/row-heights.js` and `src/styles.css` are copies of the React
workload's files and should be kept in sync with them. `src/types.ts` describes
the shapes `src/data/rooms.js` builds. The components are standalone, OnPush,
signal-based components that render the same DOM as the React version, row for
row and pixel for pixel. Every component uses an attribute selector
(`li[chat-message]`, `ol[chat-timeline]`, ...) so that its host element _is_ the
element the other ports render, rather than a wrapper around it.

## What are we testing

The same interactions as ChatRoom-React (see its README), through Angular's
change detection instead of React's reconciliation:

- Creating and destroying a large timeline view: a one-item `@for` tracked by
room id stands in for React's `key`
- `@for` diffing as the timeline window moves, with signal inputs on every row
- An `afterRenderEffect` that measures the mounted rows after each render and
corrects the scroll position, rerunning within the same tick until the
measurements settle, in place of React's `useLayoutEffect` loop

## How are we testing

The suite shares its steps (`ScrollTimeline`, `SwitchRooms`,
`LoadOlderMessages`) with ChatRoom-React, see `suites-experimental/suites.mjs`.

The app uses zone.js rather than zoneless change detection. The steps yield a
MessageChannel task between interactions and expect each update to have rendered
by then, which holds for React and Svelte. Zoneless Angular renders in a
setTimeout/requestAnimationFrame race instead, and in Firefox that regularly
lands after the yield, so consecutive interactions coalesce and the suite would
measure less work than the other ports. With zone.js, and without event
coalescing, Angular renders synchronously once the event handler returns.

## Developer Documentation

The app was created with the Angular CLI. It can be previewed during development
with `npm run dev`. To update the files run in the harness you have to run
`npm run build`, which regenerates the committed `dist/` directory and its
`resources.txt`.

The repository's Prettier predates Angular's control flow syntax and would
mangle the inline templates, so `.prettierrc` turns off embedded formatting for
this workload's TypeScript files.

The built workload can be loaded within the harness at e.g.
`http://localhost:8080/?developerMode&suites=ChatRoom-Angular`, or directly at
`http://localhost:8080/suites-experimental/chat-room-angular/dist/index.html`.
67 changes: 67 additions & 0 deletions suites-experimental/chat-room-angular/angular.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"cli": {
"analytics": false
},
"newProjectRoot": "projects",
"projects": {
"chat-room-angular": {
"projectType": "application",
"root": "",
"sourceRoot": "src",
"architect": {
"build": {
"builder": "@angular/build:application",
"options": {
"outputPath": {
"base": "dist",
"browser": ""
},
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.json",
"styles": ["src/styles.css"]
},
"configurations": {
"production": {
"outputHashing": "none",
"optimization": {
"scripts": true,
"styles": {
"minify": true,
"inlineCritical": false
},
"fonts": false
},
"sourceMap": {
"scripts": true,
"styles": false
},
"extractLicenses": false
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular/build:dev-server",
"configurations": {
"production": {
"buildTarget": "chat-room-angular:build:production"
},
"development": {
"buildTarget": "chat-room-angular:build:development"
}
},
"defaultConfiguration": "development"
}
}
}
}
}
20 changes: 20 additions & 0 deletions suites-experimental/chat-room-angular/dist/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>ChatRoom</title>
<script>
// This hack allows to capture the work normally happening in a rAF. We
// may be able to remove it if the runner improves.
window.requestAnimationFrame = (cb) => window.setTimeout(cb, 0);
window.cancelAnimationFrame = window.clearTimeout;
// Disable requestIdleCallback until WebKit / Safari supports it.
window.requestIdleCallback = undefined;
window.cancelIdleCallback = undefined;
</script>
<link rel="stylesheet" href="styles.css"></head>
<body>
<div id="root"><div chat-app=""></div></div>
<script src="polyfills.js" type="module"></script><script src="main.js" type="module"></script></body>
</html>
Loading
Loading