From 5256afd0fffe6d23c4c0b364381a62ddaf7f1aaf Mon Sep 17 00:00:00 2001
From: Parker Lougheed <parlough@gmail.com>
Date: Thu, 30 Jan 2025 15:34:55 -0600
Subject: [PATCH] Clean up and fixes for dart:html usages in code excerpts

---
 .../create_libraries/lib/src/hw_html.dart     |  7 ------
 examples/create_libraries/lib/src/hw_web.dart |  7 ++++++
 examples/create_libraries/pubspec.yaml        |  3 +++
 examples/html/README.md                       |  7 ++++--
 examples/html/lib/html.dart                   |  2 +-
 examples/html/pubspec.yaml                    |  4 +--
 examples/html/test/html_test.dart             |  2 ++
 examples/misc/bin/cheatsheet/cascades.dart    | 18 ++++++-------
 .../lib/effective_dart/style_lib_good.dart    |  2 +-
 examples/misc/pubspec.yaml                    |  1 +
 .../misc/test/language_tour/browser_test.dart | 24 ++++++++----------
 .../lib/common_fixes_analysis.dart            |  5 ++--
 src/content/effective-dart/style.md           |  2 +-
 src/content/interop/js-interop/package-web.md | 25 ++++++++++---------
 src/content/language/operators.md             | 16 +++++-------
 src/content/libraries/async/zones.md          |  2 +-
 src/content/libraries/index.md                |  2 +-
 src/content/resources/dart-cheatsheet.md      | 16 ++++++------
 src/content/tutorials/server/cmdline.md       |  3 ++-
 src/content/tutorials/server/fetch-data.md    |  6 ++---
 20 files changed, 78 insertions(+), 76 deletions(-)
 delete mode 100644 examples/create_libraries/lib/src/hw_html.dart
 create mode 100644 examples/create_libraries/lib/src/hw_web.dart

diff --git a/examples/create_libraries/lib/src/hw_html.dart b/examples/create_libraries/lib/src/hw_html.dart
deleted file mode 100644
index e3eca24351..0000000000
--- a/examples/create_libraries/lib/src/hw_html.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-import 'dart:html';
-
-void alarm([String? text]) {
-  window.alert(text ?? message);
-}
-
-String get message => 'Hello World from JavaScript!';
diff --git a/examples/create_libraries/lib/src/hw_web.dart b/examples/create_libraries/lib/src/hw_web.dart
new file mode 100644
index 0000000000..49708c6430
--- /dev/null
+++ b/examples/create_libraries/lib/src/hw_web.dart
@@ -0,0 +1,7 @@
+import 'package:web/web.dart' as web;
+
+void alarm([String? text]) {
+  web.window.alert(text ?? message);
+}
+
+String get message => 'Hello world from the web!';
diff --git a/examples/create_libraries/pubspec.yaml b/examples/create_libraries/pubspec.yaml
index be4f5d01ca..37451e8b11 100644
--- a/examples/create_libraries/pubspec.yaml
+++ b/examples/create_libraries/pubspec.yaml
@@ -6,5 +6,8 @@ resolution: workspace
 environment:
   sdk: ^3.6.0
 
+dependencies:
+  web: ^1.1.0
+
 dev_dependencies:
   test: ^1.25.8
diff --git a/examples/html/README.md b/examples/html/README.md
index 9a6c8f55d7..e75f9438d5 100644
--- a/examples/html/README.md
+++ b/examples/html/README.md
@@ -1,2 +1,5 @@
-This package is not an app, it is a collection of code excerpts and associated
-tests used in the `dart:html` library tour.
+**Deprecated** collection of code excerpts used
+in the now-historical `dart:html` library tour.
+
+All usages of `dart:html` should migrate to `dart:js_interop` and `package:web`.
+To learn more, check out [Dart JS interop](https://dart.dev/interop/js-interop).
diff --git a/examples/html/lib/html.dart b/examples/html/lib/html.dart
index 3cd1cb1e98..a956bc9154 100644
--- a/examples/html/lib/html.dart
+++ b/examples/html/lib/html.dart
@@ -1,4 +1,4 @@
-// ignore_for_file: unused_element, unused_local_variable
+// ignore_for_file: unused_element, unused_local_variable, deprecated_member_use
 // #docregion import
 import 'dart:html';
 // #enddocregion import
diff --git a/examples/html/pubspec.yaml b/examples/html/pubspec.yaml
index 1f665528c8..b05879fe71 100644
--- a/examples/html/pubspec.yaml
+++ b/examples/html/pubspec.yaml
@@ -1,5 +1,5 @@
-name: html_library_examples
-description: dart.dev example code.
+name: deprecated_html_library_examples
+description: Deprecated dart.dev example code.
 version: 0.0.1
 
 resolution: workspace
diff --git a/examples/html/test/html_test.dart b/examples/html/test/html_test.dart
index bbc1ccbe00..f9f6f110f3 100644
--- a/examples/html/test/html_test.dart
+++ b/examples/html/test/html_test.dart
@@ -1,3 +1,5 @@
+// ignore_for_file: deprecated_member_use
+
 @Tags(['browser'])
 @TestOn('browser')
 library;
diff --git a/examples/misc/bin/cheatsheet/cascades.dart b/examples/misc/bin/cheatsheet/cascades.dart
index 409c04df29..250388f6e7 100644
--- a/examples/misc/bin/cheatsheet/cascades.dart
+++ b/examples/misc/bin/cheatsheet/cascades.dart
@@ -1,6 +1,6 @@
 // ignore_for_file: avoid_single_cascade_in_expression_statements
 
-import 'dart:html';
+import 'package:web/web.dart' as web;
 
 void main() {
   final myObject = SomeObject();
@@ -14,18 +14,18 @@ void main() {
   // #enddocregion uses-cascade
 
   // #docregion query-without-cascades
-  var button = querySelector('#confirm');
-  button?.text = 'Confirm';
-  button?.classes.add('important');
-  button?.onClick.listen((e) => window.alert('Confirmed!'));
+  final button = web.document.querySelector('#confirm');
+  button?.textContent = 'Confirm';
+  button?.classList.add('important');
+  button?.onClick.listen((e) => web.window.alert('Confirmed!'));
   button?.scrollIntoView();
   // #enddocregion query-without-cascades
 
   // #docregion query-with-cascades
-  querySelector('#confirm')
-    ?..text = 'Confirm'
-    ..classes.add('important')
-    ..onClick.listen((e) => window.alert('Confirmed!'))
+  web.document.querySelector('#confirm')
+    ?..textContent = 'Confirm'
+    ..classList.add('important')
+    ..onClick.listen((e) => web.window.alert('Confirmed!'))
     ..scrollIntoView();
   // #enddocregion query-with-cascades
 }
diff --git a/examples/misc/lib/effective_dart/style_lib_good.dart b/examples/misc/lib/effective_dart/style_lib_good.dart
index 60d7b23004..4e159df5cc 100644
--- a/examples/misc/lib/effective_dart/style_lib_good.dart
+++ b/examples/misc/lib/effective_dart/style_lib_good.dart
@@ -14,7 +14,7 @@ import 'package:examples/effective_dart/bar.dart' as js;
 
 // #docregion dart-import-first
 import 'dart:async';
-import 'dart:html';
+import 'dart:collection';
 
 // #docregion pkg-import-before-local, sorted
 import 'package:examples/effective_dart/bar/bar.dart';
diff --git a/examples/misc/pubspec.yaml b/examples/misc/pubspec.yaml
index c27ffea177..29c2597eca 100644
--- a/examples/misc/pubspec.yaml
+++ b/examples/misc/pubspec.yaml
@@ -10,6 +10,7 @@ dependencies:
   characters: ^1.3.0
   examples_util: { path: ../util }
   http: ^1.2.2
+  web: ^1.1.0
 
 dev_dependencies:
   test: ^1.25.8
diff --git a/examples/misc/test/language_tour/browser_test.dart b/examples/misc/test/language_tour/browser_test.dart
index e2f07cb54e..9216b56377 100644
--- a/examples/misc/test/language_tour/browser_test.dart
+++ b/examples/misc/test/language_tour/browser_test.dart
@@ -1,5 +1,3 @@
-// ignore_for_file: unused_import
-
 @Tags(['browser'])
 @TestOn('browser')
 library;
@@ -7,39 +5,39 @@ library;
 // #docregion dart-js-interop-import
 import 'dart:js_interop';
 // #enddocregion dart-js-interop-import
-import 'dart:html';
 // #docregion package-import
 import 'package:test/test.dart';
 // #enddocregion package-import
+import 'package:web/web.dart';
 
 void main() {
   test('cascade-operator', () {
     final div = '<button id="confirm"></button>';
-    document.body?.appendHtml(div);
+    document.body?.insertAdjacentHTML('beforeend', div.toJS);
 
     // #docregion cascade-operator
-    querySelector('#confirm') // Get an object.
-      ?..text = 'Confirm' // Use its members.
-      ..classes.add('important')
+    document.querySelector('#confirm') // Get an object.
+      ?..textContent = 'Confirm' // Use its members.
+      ..classList.add('important')
       ..onClick.listen((e) => window.alert('Confirmed!'))
       ..scrollIntoView();
     // #enddocregion cascade-operator
 
-    expect(document.querySelector('#confirm')?.text, 'Confirm');
+    expect(document.querySelector('#confirm')?.textContent, 'Confirm');
   });
 
   test('cascade-operator-example-expanded', () {
     final div = '<button id="confirm"></button>';
-    document.body?.appendHtml(div);
+    document.body?.insertAdjacentHTML('beforeend', div.toJS);
 
     // #docregion cascade-operator-example-expanded
-    var button = querySelector('#confirm');
-    button?.text = 'Confirm';
-    button?.classes.add('important');
+    final button = document.querySelector('#confirm');
+    button?.textContent = 'Confirm';
+    button?.classList.add('important');
     button?.onClick.listen((e) => window.alert('Confirmed!'));
     button?.scrollIntoView();
     // #enddocregion cascade-operator-example-expanded
 
-    expect(document.querySelector('#confirm')?.text, 'Confirm');
+    expect(document.querySelector('#confirm')?.textContent, 'Confirm');
   });
 }
diff --git a/examples/type_system/lib/common_fixes_analysis.dart b/examples/type_system/lib/common_fixes_analysis.dart
index 68d168a0d3..0c7d2cb035 100644
--- a/examples/type_system/lib/common_fixes_analysis.dart
+++ b/examples/type_system/lib/common_fixes_analysis.dart
@@ -1,6 +1,6 @@
 // NOTE: Declarations in this file are analyzed but not tested.
 // ignore_for_file: unused_element, unused_local_variable, one_member_abstracts, use_super_parameters
-// ignore_for_file: prefer_function_declarations_over_variables, unused_field, strict_raw_type
+// ignore_for_file: prefer_function_declarations_over_variables, unused_field, strict_raw_type, deprecated_member_use
 
 import 'dart:html';
 
@@ -157,7 +157,6 @@ abstract class C implements List<int> {}
 // #enddocregion compatible-generics
 
 // #docregion conflicting-generics
-// ignore: inconsistent_inheritance, conflicting_generic_interfaces,
-// ignore: duplicate_definition
+// ignore: duplicate_definition, inconsistent_inheritance, conflicting_generic_interfaces
 abstract class C implements List<int>, Iterable<num> {}
 // #enddocregion conflicting-generics
diff --git a/src/content/effective-dart/style.md b/src/content/effective-dart/style.md
index ef4154d94d..4414f8acd5 100644
--- a/src/content/effective-dart/style.md
+++ b/src/content/effective-dart/style.md
@@ -355,7 +355,7 @@ A single linter rule handles all the ordering guidelines:
 <?code-excerpt "style_lib_good.dart (dart-import-first)" replace="/\w+\/effective_dart\///g"?>
 ```dart tag=good
 import 'dart:async';
-import 'dart:html';
+import 'dart:collection';
 
 import 'package:bar/bar.dart';
 import 'package:foo/foo.dart';
diff --git a/src/content/interop/js-interop/package-web.md b/src/content/interop/js-interop/package-web.md
index 23c9d6238c..40ddf16935 100644
--- a/src/content/interop/js-interop/package-web.md
+++ b/src/content/interop/js-interop/package-web.md
@@ -205,7 +205,7 @@ A value of type '...' can't be assigned to a variable of type 'JSFunction?'
 
 ### Conditional imports
 
-It is common for code to use a conditional import based on whether `dart:html`
+It's common for code to use a conditional import based on whether `dart:html`
 is supported to differentiate between native and web:
 
 ```dart
@@ -214,14 +214,15 @@ export 'src/hw_none.dart'
     if (dart.library.html) 'src/hw_html.dart';
 ```
 
-However, since `dart:html` is not supported when compiling to Wasm, the correct
-alternative now is to use `dart.library.js_interop` to differentiate between
-native and web:
+However, since `dart:html` is deprecated and not supported when
+compiling to Wasm, the correct alternative now is to
+use `dart.library.js_interop` to differentiate between native and web:
 
+<?code-excerpt "create_libraries/lib/hw_mp.dart (export)"?>
 ```dart
-export 'src/hw_none.dart'
-    if (dart.library.io) 'src/hw_io.dart'
-    if (dart.library.js_interop) 'src/hw_web.dart';
+export 'src/hw_none.dart' // Stub implementation
+    if (dart.library.io) 'src/hw_io.dart' // dart:io implementation
+    if (dart.library.js_interop) 'src/hw_web.dart'; // package:web implementation
 ```
 
 ### Virtual dispatch and mocking
@@ -263,7 +264,7 @@ automatically do this.
 ## Helpers
 
 The core of `package:web` contains `external` interop members,
-but does not provide other functionality that `dart:html` provided by default.
+but doesn't provide other functionality that `dart:html` provided by default.
 To mitigate these differences, `package:web` contains [`helpers`][helpers]
 for additional support in handling a number of use cases
 that aren't directly available through the core interop.
@@ -275,12 +276,12 @@ event listeners. Instead, you can use [stream helpers][] that makes it easy to
 subscribe to events with Dart `Stream`s without writing that code yourself.
 
 ```dart
-// dart:html version
-InputElement htmlInput = InputElement();
+// Original dart:html version:
+final htmlInput = InputElement();
 await htmlInput.onBlur.first;
 
-// package:web version
-HTMLInputElement webInput = document.createElement('input') as HTMLInputElement;
+// Migrated package:web version:
+final webInput = HTMLInputElement();
 await webInput.onBlur.first;
 ```
 
diff --git a/src/content/language/operators.md b/src/content/language/operators.md
index c21dda735a..b9b6bd87cd 100644
--- a/src/content/language/operators.md
+++ b/src/content/language/operators.md
@@ -448,24 +448,20 @@ are attempted on that null object.
 
 <?code-excerpt "misc/test/language_tour/browser_test.dart (cascade-operator)"?>
 ```dart
-querySelector('#confirm') // Get an object.
-  ?..text = 'Confirm' // Use its members.
-  ..classes.add('important')
+document.querySelector('#confirm') // Get an object.
+  ?..textContent = 'Confirm' // Use its members.
+  ..classList.add('important')
   ..onClick.listen((e) => window.alert('Confirmed!'))
   ..scrollIntoView();
 ```
 
-:::version-note
-The `?..` syntax requires a [language version][] of at least 2.12.
-:::
-
 The previous code is equivalent to the following:
 
 <?code-excerpt "misc/test/language_tour/browser_test.dart (cascade-operator-example-expanded)"?>
 ```dart
-var button = querySelector('#confirm');
-button?.text = 'Confirm';
-button?.classes.add('important');
+final button = document.querySelector('#confirm');
+button?.textContent = 'Confirm';
+button?.classList.add('important');
 button?.onClick.listen((e) => window.alert('Confirmed!'));
 button?.scrollIntoView();
 ```
diff --git a/src/content/libraries/async/zones.md b/src/content/libraries/async/zones.md
index 75507ddccb..173e67327f 100644
--- a/src/content/libraries/async/zones.md
+++ b/src/content/libraries/async/zones.md
@@ -792,7 +792,7 @@ The source code for the stack_trace package
   You can find the stack_trace source code in the
   [stack_trace GitHub project]({{site.repo.dart.org}}/stack_trace).
 
-The source code for dart:html and dart:async
+The source code for dart:async
 : These two SDK libraries implement APIs featuring asynchronous callbacks,
   and thus they deal with zones.
   You can browse or download their source code under the
diff --git a/src/content/libraries/index.md b/src/content/libraries/index.md
index a268bf7aa7..39534e2a97 100644
--- a/src/content/libraries/index.md
+++ b/src/content/libraries/index.md
@@ -48,7 +48,7 @@ consult the [Dart API reference.][Dart API]
 
 [dart:js_interop](/interop/js-interop)
 : APIs for interop with the web platform.
-  Along with `package:web`,`dart:js_interop` replaces `dart:html`.
+  Along with `package:web`, `dart:js_interop` replaces `dart:html`.
 
 
 As mentioned, these pages are just an overview;
diff --git a/src/content/resources/dart-cheatsheet.md b/src/content/resources/dart-cheatsheet.md
index 498d19ee8d..5ab989b54d 100644
--- a/src/content/resources/dart-cheatsheet.md
+++ b/src/content/resources/dart-cheatsheet.md
@@ -619,10 +619,10 @@ to read properties of `button` if it isn't `null`:
 
 <?code-excerpt "misc/bin/cheatsheet/cascades.dart (query-without-cascades)"?>
 ```dart
-var button = querySelector('#confirm');
-button?.text = 'Confirm';
-button?.classes.add('important');
-button?.onClick.listen((e) => window.alert('Confirmed!'));
+final button = web.document.querySelector('#confirm');
+button?.textContent = 'Confirm';
+button?.classList.add('important');
+button?.onClick.listen((e) => web.window.alert('Confirmed!'));
 button?.scrollIntoView();
 ```
 
@@ -635,10 +635,10 @@ and makes the `button` variable unnecessary:
 
 <?code-excerpt "misc/bin/cheatsheet/cascades.dart (query-with-cascades)"?>
 ```dart
-querySelector('#confirm')
-  ?..text = 'Confirm'
-  ..classes.add('important')
-  ..onClick.listen((e) => window.alert('Confirmed!'))
+web.document.querySelector('#confirm')
+  ?..textContent = 'Confirm'
+  ..classList.add('important')
+  ..onClick.listen((e) => web.window.alert('Confirmed!'))
   ..scrollIntoView();
 ```
 
diff --git a/src/content/tutorials/server/cmdline.md b/src/content/tutorials/server/cmdline.md
index 6ce6cca8cd..74c4ac8c5a 100644
--- a/src/content/tutorials/server/cmdline.md
+++ b/src/content/tutorials/server/cmdline.md
@@ -285,7 +285,8 @@ import 'dart:io';
 ```
 
 :::note
-Web apps (apps that depend on `dart:html`) can't use the `dart:io` library.
+Apps that run on the [web platform](/overview#platform)
+can't use the `dart:io` library.
 :::
 
 ### stdout
diff --git a/src/content/tutorials/server/fetch-data.md b/src/content/tutorials/server/fetch-data.md
index c1300316bb..a2f5ac2ac0 100644
--- a/src/content/tutorials/server/fetch-data.md
+++ b/src/content/tutorials/server/fetch-data.md
@@ -148,10 +148,8 @@ for making composable HTTP requests,
 with optional fine-grained control.
 
 :::note
-You should avoid directly using `dart:io` or `dart:html`
-to make HTTP requests.
-Those libraries are platform-dependent
-and tied to a single implementation.
+Avoid directly using `dart:io` or `dart:html` to make HTTP requests.
+Those libraries are platform-dependent and tied to a single implementation.
 :::
 
 To add a dependency on `package:http`,