-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjs-cpu-time.html
114 lines (97 loc) · 3.36 KB
/
js-cpu-time.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>JS CPU Time Canary</title>
</head>
<body>
<div id="app">Blocking the main thread before loading React app...</div>
<script>
const TASK_PAUSE_TIME = 50;
const APP_DELAY_TIME = 1000;
function createLongTask(duration) {
const startTime = performance.now();
while (performance.now() < startTime + duration) {
// Block the main thread for the specified time
}
}
requestAnimationFrame(() => {
createLongTask(APP_DELAY_TIME / 2);
document.getElementById("app").innerHTML = "Done blocking the main thread. Loading React app...";
});
</script>
<script src="react.production.min.js"></script>
<script src="react-dom.production.min.js"></script>
<script>
const e = React.createElement;
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
progress: 0,
};
}
render() {
return e("div", null,
e("h1", null, "JS CPU Time Canary"),
e("p", null, `Running long tasks... ${this.state.progress} / ${this.props.tasks}`),
e("pre", null, JSON.stringify({ props: this.props }, null, 4)),
e("div", {
style: {
display: "grid",
justifyContent: "center",
gridTemplateColumns: this.isDone() ? "repeat(12, 1fr)" : `repeat(${Math.round(Math.random() * 20)}, 1fr)`,
gap: "1rem",
}
}, ...this.progressImages()),
this.statusText(),
this.finalImage(),
);
}
isDone() {
return this.state.progress === this.props.tasks;
}
progressImages() {
return new Array(this.state.progress).fill().map((_, i) => {
return e("img", { src: i % 2 ? `eve.jpg?i=${i}` : `charlie.jpg?i=${i}`, style: { width: "40px" } });
});
}
finalImage() {
if (this.isDone()) {
return e("img", { src: "https://img.speedcurve.com/donut.png", style: { width: "400px" } });
}
}
statusText() {
if (this.isDone()) {
return e("h2", null, "Done!");
}
}
componentDidMount() {
const processNextTask = (taskNum) => {
if (taskNum <= this.props.tasks) {
return this.runTask(taskNum)
.then(() => this.setState({ progress: taskNum }))
.then(() => new Promise((resolve) => {
setTimeout(() => resolve(processNextTask(taskNum + 1)), TASK_PAUSE_TIME);
}));
} else {
return Promise.resolve(true);
}
};
requestAnimationFrame(() => processNextTask(1));
}
runTask() {
return new Promise((resolve) => {
resolve(createLongTask(this.props.taskTime));
});
}
}
const qs = new URLSearchParams(location.search);
const tasks = Number(qs.get("tasks")) || 40;
const taskTime = Number(qs.get("taskTime")) || 67;
setTimeout(() => {
ReactDOM.render(e(App, { tasks, taskTime }), document.getElementById("app"));
}, APP_DELAY_TIME / 2);
</script>
</body>
</html>