4
4
5
5
import 'dart:async' ;
6
6
import 'dart:convert' show json;
7
- import 'dart:html' as html ;
7
+ import 'dart:js_interop' ;
8
8
import 'dart:math' as math;
9
9
10
+ import 'package:web/helpers.dart' ;
11
+
10
12
import 'src/common.dart' ;
11
13
import 'src/recorder.dart' ;
14
+
12
15
export 'src/recorder.dart' ;
13
16
14
17
/// Signature for a function that creates a [Recorder] .
@@ -47,7 +50,7 @@ Future<void> runBenchmarks(
47
50
48
51
await _runBenchmark (nextBenchmark);
49
52
50
- final Uri currentUri = Uri .parse (html. window.location.href);
53
+ final Uri currentUri = Uri .parse (window.location.href);
51
54
// Create a new URI with the current 'page' value set to [initialPage] to
52
55
// ensure the benchmark app is reloaded at the proper location.
53
56
final Uri newUri = Uri (
@@ -58,7 +61,7 @@ Future<void> runBenchmarks(
58
61
);
59
62
60
63
// Reloading the window will trigger the next benchmark to run.
61
- html. window.location.replace (newUri.toString ());
64
+ window.location.replace (newUri.toString ());
62
65
}
63
66
64
67
Future <void > _runBenchmark (String ? benchmarkName) async {
@@ -116,7 +119,7 @@ Future<void> _runBenchmark(String? benchmarkName) async {
116
119
}
117
120
118
121
void _fallbackToManual (String error) {
119
- html. document.body! .appendHtml ('''
122
+ document.body! .appendHtml ('''
120
123
<div id="manual-panel">
121
124
<h3>$error </h3>
122
125
@@ -127,33 +130,33 @@ void _fallbackToManual(String error) {
127
130
${_benchmarks .keys .map ((String name ) => '<li><button id="$name ">$name </button></li>' ).join ('\n ' )}
128
131
</ul>
129
132
</div>
130
- ''' ,
131
- validator: html.NodeValidatorBuilder ()
132
- ..allowHtml5 ()
133
- ..allowInlineStyles ());
133
+ ''' );
134
134
135
135
for (final String benchmarkName in _benchmarks.keys) {
136
136
// Find the button elements added above.
137
- final html.Element button = html.document.querySelector ('#$benchmarkName ' )! ;
138
- button.addEventListener ('click' , (_) {
139
- final html.Element ? manualPanel =
140
- html.document.querySelector ('#manual-panel' );
141
- manualPanel? .remove ();
142
- _runBenchmark (benchmarkName);
143
- });
137
+ final Element button = document.querySelector ('#$benchmarkName ' )! ;
138
+ button.addEventListener (
139
+ 'click' ,
140
+ (JSAny ? arg) {
141
+ final Element ? manualPanel = document.querySelector ('#manual-panel' );
142
+ manualPanel? .remove ();
143
+ _runBenchmark (benchmarkName);
144
+ }.toJS);
144
145
}
145
146
}
146
147
147
148
/// Visualizes results on the Web page for manual inspection.
148
149
void _printResultsToScreen (Profile profile) {
149
- final html. BodyElement body = html. document.body! ;
150
+ final HTMLBodyElement body = document.body! as HTMLBodyElement ;
150
151
151
- body.innerHtml = '<h2>${profile .name }</h2>' ;
152
+ body.innerHTML = '<h2>${profile .name }</h2>' ;
152
153
153
154
profile.scoreData.forEach ((String scoreKey, Timeseries timeseries) {
154
155
body.appendHtml ('<h2>$scoreKey </h2>' );
155
156
body.appendHtml ('<pre>${timeseries .computeStats ()}</pre>' );
156
- body.append (TimeseriesVisualization (timeseries).render ());
157
+ // TODO(kevmoo): remove `NodeGlue` cast when we no longer need to support
158
+ // pkg:web 0.3.0
159
+ NodeGlue (body).append (TimeseriesVisualization (timeseries).render ());
157
160
});
158
161
}
159
162
@@ -162,10 +165,10 @@ class TimeseriesVisualization {
162
165
/// Creates a visualization for a [Timeseries] .
163
166
TimeseriesVisualization (this ._timeseries) {
164
167
_stats = _timeseries.computeStats ();
165
- _canvas = html. CanvasElement ();
166
- _screenWidth = html. window.screen! .width! ;
168
+ _canvas = CanvasElement ();
169
+ _screenWidth = window.screen.width;
167
170
_canvas.width = _screenWidth;
168
- _canvas.height = (_kCanvasHeight * html. window.devicePixelRatio).round ();
171
+ _canvas.height = (_kCanvasHeight * window.devicePixelRatio).round ();
169
172
_canvas.style
170
173
..width = '100%'
171
174
..height = '${_kCanvasHeight }px'
@@ -186,8 +189,8 @@ class TimeseriesVisualization {
186
189
187
190
final Timeseries _timeseries;
188
191
late TimeseriesStats _stats;
189
- late html. CanvasElement _canvas;
190
- late html. CanvasRenderingContext2D _ctx;
192
+ late CanvasElement _canvas;
193
+ late CanvasRenderingContext2D _ctx;
191
194
late int _screenWidth;
192
195
193
196
// Used to normalize benchmark values to chart height.
@@ -209,9 +212,9 @@ class TimeseriesVisualization {
209
212
}
210
213
211
214
/// Renders the timeseries into a `<canvas>` and returns the canvas element.
212
- html. CanvasElement render () {
213
- _ctx.translate (0 , _kCanvasHeight * html. window.devicePixelRatio);
214
- _ctx.scale (1 , - html. window.devicePixelRatio);
215
+ CanvasElement render () {
216
+ _ctx.translate (0 , _kCanvasHeight * window.devicePixelRatio);
217
+ _ctx.scale (1 , - window.devicePixelRatio);
215
218
216
219
final double barWidth = _screenWidth / _stats.samples.length;
217
220
double xOffset = 0 ;
@@ -220,19 +223,19 @@ class TimeseriesVisualization {
220
223
221
224
if (sample.isWarmUpValue) {
222
225
// Put gray background behind warm-up samples.
223
- _ctx.fillStyle = 'rgba(200,200,200,1)' ;
226
+ _ctx.fillStyle = 'rgba(200,200,200,1)' .toJS ;
224
227
_ctx.fillRect (xOffset, 0 , barWidth, _normalized (_maxValueChartRange));
225
228
}
226
229
227
230
if (sample.magnitude > _maxValueChartRange) {
228
231
// The sample value is so big it doesn't fit on the chart. Paint it purple.
229
- _ctx.fillStyle = 'rgba(100,50,100,0.8)' ;
232
+ _ctx.fillStyle = 'rgba(100,50,100,0.8)' .toJS ;
230
233
} else if (sample.isOutlier) {
231
234
// The sample is an outlier, color it light red.
232
- _ctx.fillStyle = 'rgba(255,50,50,0.6)' ;
235
+ _ctx.fillStyle = 'rgba(255,50,50,0.6)' .toJS ;
233
236
} else {
234
237
// A non-outlier sample, color it light blue.
235
- _ctx.fillStyle = 'rgba(50,50,255,0.6)' ;
238
+ _ctx.fillStyle = 'rgba(50,50,255,0.6)' .toJS ;
236
239
}
237
240
238
241
_ctx.fillRect (xOffset, 0 , barWidth - 1 , _normalized (sample.magnitude));
@@ -245,12 +248,12 @@ class TimeseriesVisualization {
245
248
_normalized (_stats.average));
246
249
247
250
// Draw a horizontal dashed line corresponding to the outlier cut off.
248
- _ctx.setLineDash (< num > [5 , 5 ] );
251
+ _ctx.setLineDash (< JSNumber > [5. toJS , 5. toJS].toJS );
249
252
drawLine (0 , _normalized (_stats.outlierCutOff), _screenWidth,
250
253
_normalized (_stats.outlierCutOff));
251
254
252
255
// Draw a light red band that shows the noise (1 stddev in each direction).
253
- _ctx.fillStyle = 'rgba(255,50,50,0.3)' ;
256
+ _ctx.fillStyle = 'rgba(255,50,50,0.3)' .toJS ;
254
257
_ctx.fillRect (
255
258
0 ,
256
259
_normalized (_stats.average * (1 - _stats.noise)),
@@ -283,7 +286,7 @@ class LocalBenchmarkServerClient {
283
286
/// Returns [kManualFallback] if local server is not available (uses 404 as a
284
287
/// signal).
285
288
Future <String > requestNextBenchmark () async {
286
- final html. HttpRequest request = await _requestXhr (
289
+ final XMLHttpRequest request = await _requestXhr (
287
290
'/next-benchmark' ,
288
291
method: 'POST' ,
289
292
mimeType: 'application/json' ,
@@ -298,7 +301,7 @@ class LocalBenchmarkServerClient {
298
301
}
299
302
300
303
isInManualMode = false ;
301
- return request.responseText ?? kManualFallback ;
304
+ return request.responseText;
302
305
}
303
306
304
307
void _checkNotManualMode () {
@@ -314,7 +317,7 @@ class LocalBenchmarkServerClient {
314
317
/// DevTools Protocol.
315
318
Future <void > startPerformanceTracing (String ? benchmarkName) async {
316
319
_checkNotManualMode ();
317
- await html. HttpRequest .request (
320
+ await HttpRequest .request (
318
321
'/start-performance-tracing?label=$benchmarkName ' ,
319
322
method: 'POST' ,
320
323
mimeType: 'application/json' ,
@@ -324,7 +327,7 @@ class LocalBenchmarkServerClient {
324
327
/// Stops the performance tracing session started by [startPerformanceTracing] .
325
328
Future <void > stopPerformanceTracing () async {
326
329
_checkNotManualMode ();
327
- await html. HttpRequest .request (
330
+ await HttpRequest .request (
328
331
'/stop-performance-tracing' ,
329
332
method: 'POST' ,
330
333
mimeType: 'application/json' ,
@@ -335,7 +338,7 @@ class LocalBenchmarkServerClient {
335
338
/// server.
336
339
Future <void > sendProfileData (Profile profile) async {
337
340
_checkNotManualMode ();
338
- final html. HttpRequest request = await html. HttpRequest . request (
341
+ final XMLHttpRequest request = await _requestXhr (
339
342
'/profile-data' ,
340
343
method: 'POST' ,
341
344
mimeType: 'application/json' ,
@@ -352,7 +355,7 @@ class LocalBenchmarkServerClient {
352
355
/// The server will halt the devicelab task and log the error.
353
356
Future <void > reportError (dynamic error, StackTrace stackTrace) async {
354
357
_checkNotManualMode ();
355
- await html. HttpRequest .request (
358
+ await HttpRequest .request (
356
359
'/on-error' ,
357
360
method: 'POST' ,
358
361
mimeType: 'application/json' ,
@@ -366,31 +369,35 @@ class LocalBenchmarkServerClient {
366
369
/// Reports a message about the demo to the benchmark server.
367
370
Future <void > printToConsole (String report) async {
368
371
_checkNotManualMode ();
369
- await html. HttpRequest .request (
372
+ await HttpRequest .request (
370
373
'/print-to-console' ,
371
374
method: 'POST' ,
372
375
mimeType: 'text/plain' ,
373
376
sendData: report,
374
377
);
375
378
}
376
379
377
- /// This is the same as calling [html.HttpRequest .request] but it doesn't
380
+ /// This is the same as calling [XMLHttpRequest .request] but it doesn't
378
381
/// crash on 404, which we use to detect `flutter run` .
379
- Future <html. HttpRequest > _requestXhr (
382
+ Future <XMLHttpRequest > _requestXhr (
380
383
String url, {
381
384
required String method,
382
385
required String mimeType,
383
- required dynamic sendData,
386
+ required String sendData,
384
387
}) {
385
- final Completer <html. HttpRequest > completer = Completer <html. HttpRequest >();
386
- final html. HttpRequest xhr = html. HttpRequest ();
387
- xhr.open (method, url, async : true );
388
+ final Completer <XMLHttpRequest > completer = Completer <XMLHttpRequest >();
389
+ final XMLHttpRequest xhr = XMLHttpRequest ();
390
+ xhr.open (method, url, true );
388
391
xhr.overrideMimeType (mimeType);
389
- xhr.onLoad.listen ((html. ProgressEvent e) {
392
+ xhr.onLoad.listen ((ProgressEvent e) {
390
393
completer.complete (xhr);
391
394
});
392
395
xhr.onError.listen (completer.completeError);
393
- xhr.send (sendData);
396
+ xhr.send (sendData.toJS );
394
397
return completer.future;
395
398
}
396
399
}
400
+
401
+ extension on HTMLElement {
402
+ void appendHtml (String input) => insertAdjacentHTML ('beforeend' , input);
403
+ }
0 commit comments