[dart2wasm] Implement unimplemented Uri methods.

Change-Id: I54b8633d39df64d1760a7face5dda38c3aa95d5c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/251592
Commit-Queue: Joshua Litt <joshualitt@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/pkg/dart2wasm/bin/run_wasm.js b/pkg/dart2wasm/bin/run_wasm.js
index 8d376f8..abe9cc7 100644
--- a/pkg/dart2wasm/bin/run_wasm.js
+++ b/pkg/dart2wasm/bin/run_wasm.js
@@ -258,6 +258,18 @@
     toLowerCase: function(string) {
         return stringToDartString(stringFromDartString(string).toLowerCase());
     },
+    isWindows: function() {
+        return typeof process != undefined &&
+            Object.prototype.toString.call(process) == "[object process]" &&
+            process.platform == "win32";
+    },
+    getCurrentUri: function() {
+        // On browsers return `globalThis.location.href`
+        if (globalThis.location != null) {
+          return stringToDartString(globalThis.location.href);
+        }
+        return null;
+    },
 };
 
 function instantiate(filename, imports) {
diff --git a/sdk/lib/_internal/wasm/lib/core_patch.dart b/sdk/lib/_internal/wasm/lib/core_patch.dart
index e8756c9..68f6517 100644
--- a/sdk/lib/_internal/wasm/lib/core_patch.dart
+++ b/sdk/lib/_internal/wasm/lib/core_patch.dart
@@ -45,6 +45,8 @@
         UnmodifiableMapBase,
         UnmodifiableMapView;
 
+import 'dart:convert' show Encoding, utf8;
+
 import 'dart:math' show Random;
 
 import "dart:typed_data"
diff --git a/sdk/lib/_internal/wasm/lib/uri_patch.dart b/sdk/lib/_internal/wasm/lib/uri_patch.dart
new file mode 100644
index 0000000..85fe951
--- /dev/null
+++ b/sdk/lib/_internal/wasm/lib/uri_patch.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// part of "core_patch.dart";
+
+@pragma("wasm:import", "dart2wasm.isWindows")
+external bool _isWindowsRaw();
+
+@pragma("wasm:import", "dart2wasm.getCurrentUri")
+external String? _currentUriRaw();
+
+@patch
+class Uri {
+  @patch
+  static Uri get base {
+    String? currentUri = _currentUriRaw();
+    if (currentUri != null) {
+      return Uri.parse(currentUri);
+    }
+    throw UnsupportedError("'Uri.base' is not supported");
+  }
+}
+
+@patch
+class _Uri {
+  @patch
+  static bool get _isWindows => _isWindowsCached;
+
+  static final bool _isWindowsCached = _isWindowsRaw();
+
+  // Matches a String that _uriEncodes to itself regardless of the kind of
+  // component.  This corresponds to [_unreservedTable], i.e. characters that
+  // are not encoded by any encoding table.
+  static final RegExp _needsNoEncoding = RegExp(r'^[\-\.0-9A-Z_a-z~]*$');
+
+  /**
+   * This is the internal implementation of JavaScript's encodeURI function.
+   * It encodes all characters in the string [text] except for those
+   * that appear in [canonicalTable], and returns the escaped string.
+   */
+  @patch
+  static String _uriEncode(List<int> canonicalTable, String text,
+      Encoding encoding, bool spaceToPlus) {
+    if (identical(encoding, utf8) && _needsNoEncoding.hasMatch(text)) {
+      return text;
+    }
+
+    // Encode the string into bytes then generate an ASCII only string
+    // by percent encoding selected bytes.
+    StringBuffer result = StringBuffer('');
+    var bytes = encoding.encode(text);
+    for (int i = 0; i < bytes.length; i++) {
+      int byte = bytes[i];
+      if (byte < 128 &&
+          ((canonicalTable[byte >> 4] & (1 << (byte & 0x0f))) != 0)) {
+        result.writeCharCode(byte);
+      } else if (spaceToPlus && byte == _SPACE) {
+        result.write('+');
+      } else {
+        const String hexDigits = '0123456789ABCDEF';
+        result.write('%');
+        result.write(hexDigits[(byte >> 4) & 0x0f]);
+        result.write(hexDigits[byte & 0x0f]);
+      }
+    }
+    return result.toString();
+  }
+}
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 4ab4f53..45bea43 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -218,7 +218,8 @@
           "_internal/wasm/lib/stopwatch_patch.dart",
           "_internal/wasm/lib/string_buffer_patch.dart",
           "_internal/wasm/lib/string_patch.dart",
-          "_internal/wasm/lib/type.dart"
+          "_internal/wasm/lib/type.dart",
+          "_internal/wasm/lib/uri_patch.dart"
         ]
       },
       "developer": {
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index da112be..04d1f2d 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -208,6 +208,7 @@
       - _internal/wasm/lib/string_buffer_patch.dart
       - _internal/wasm/lib/string_patch.dart
       - _internal/wasm/lib/type.dart
+      - _internal/wasm/lib/uri_patch.dart
     developer:
       uri: developer/developer.dart
       patches: