mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 17:56:11 +00:00
[js_runtime] Use URLSearchParams to escape query parameters
Use URLSearchParams to escape query parameters. - For large query parameters (>100KB), where escaping the parameters causes jank, this can be 2x-5x faster, reducing ~100ms pauses to nearer frame rate. - For small query parameters (<100B) it can be slightly (10-20%) slower, but still well below 1 millisecond. TEST=ci Issue: #53712 Change-Id: I045bac7a067a658a58aaac4266409d526ccda774 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/329822 Commit-Queue: Stephen Adams <sra@google.com> Reviewed-by: Siva Annamalai <asiva@google.com> Reviewed-by: Ömer Ağacan <omersa@google.com> Reviewed-by: Nicholas Shahan <nshahan@google.com> Reviewed-by: Lasse Nielsen <lrn@google.com>
This commit is contained in:
parent
54b588a373
commit
8ea74c0f2e
|
@ -2448,6 +2448,7 @@ const Set<String> reservedCapitalizedGlobalSymbols = {
|
|||
|
||||
// Some additional names
|
||||
"Isolate",
|
||||
"URLSearchParams",
|
||||
};
|
||||
|
||||
/// Symbols that we might be using in our JS snippets. Some of the symbols in
|
||||
|
|
|
@ -932,6 +932,12 @@ class _Uri {
|
|||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@patch
|
||||
static String _makeQueryFromParameters(
|
||||
Map<String, dynamic /*String?|Iterable<String>*/ > queryParameters) {
|
||||
return _makeQueryFromParametersDefault(queryParameters);
|
||||
}
|
||||
}
|
||||
|
||||
@patch
|
||||
|
|
|
@ -826,6 +826,67 @@ class _Uri {
|
|||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@patch
|
||||
static String _makeQueryFromParameters(
|
||||
Map<String, dynamic /*String?|Iterable<String>*/ > queryParameters) {
|
||||
if (!_useURLSearchParams) {
|
||||
return _makeQueryFromParametersDefault(queryParameters);
|
||||
}
|
||||
|
||||
// Copy the values from [queryParameters] into a browser URLSearchParams
|
||||
// object.
|
||||
final params = JS('', 'new URLSearchParams()');
|
||||
queryParameters.forEach((key, value) {
|
||||
if (value is String) {
|
||||
JS('', '#.set(#, #)', params, key, value);
|
||||
} else if (value == null) {
|
||||
JS('', '#.set(#, #)', params, key, '');
|
||||
} else {
|
||||
Iterable values = value;
|
||||
|
||||
// This could be written as `for (final String? value in values)` but in
|
||||
// some optimized modes the type check is 'trusted' (ignored). So we
|
||||
// check [value] explicitly to avoid JavaScript implicit ToString
|
||||
// conversions.
|
||||
for (final value in values) {
|
||||
if (value is String) {
|
||||
JS('', '#.append(#, #)', params, key, value);
|
||||
} else if (value == null) {
|
||||
JS('', '#.append(#, #)', params, key, '');
|
||||
} else {
|
||||
// Signal the error we would have for the typed for-in loop.
|
||||
value as String?;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
String encoded = JS('String', '#.toString()', params);
|
||||
|
||||
// Fix differences between the URLSearchParams encoding and the desired
|
||||
// encoding.
|
||||
//
|
||||
// 1. URLSearchParams encodes empty values as `foo=` rather than just `foo`.
|
||||
// 2. URLSearchParams does not escape `*`.
|
||||
// 3. URLSearchParams escapes `~`.
|
||||
|
||||
// Handle `foo=` at end of encoded query.
|
||||
final length = encoded.length;
|
||||
if (length > 0 && encoded[length - 1] == '=') {
|
||||
encoded = encoded.substring(0, length - 1);
|
||||
}
|
||||
|
||||
// Handle other cases with one RegExp.
|
||||
encoded = JS(
|
||||
'',
|
||||
r'#.replace(/=&|\*|%7E/g, (m) => m === "=&" ? "&" : m === "*" ? "%2A" : "~")',
|
||||
encoded);
|
||||
|
||||
return encoded;
|
||||
}
|
||||
|
||||
static final bool _useURLSearchParams =
|
||||
JS('bool', 'typeof URLSearchParams == "function"');
|
||||
}
|
||||
|
||||
@patch
|
||||
|
|
|
@ -78,4 +78,10 @@ class _Uri {
|
|||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@patch
|
||||
static String _makeQueryFromParameters(
|
||||
Map<String, dynamic /*String?|Iterable<String>*/ > queryParameters) {
|
||||
return _makeQueryFromParametersDefault(queryParameters);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,4 +70,10 @@ class _Uri {
|
|||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@patch
|
||||
static String _makeQueryFromParameters(
|
||||
Map<String, dynamic /*String?|Iterable<String>*/ > queryParameters) {
|
||||
return _makeQueryFromParametersDefault(queryParameters);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2350,7 +2350,18 @@ class _Uri implements Uri {
|
|||
escapeDelimiters: true);
|
||||
}
|
||||
if (queryParameters == null) return null;
|
||||
return _makeQueryFromParameters(queryParameters);
|
||||
}
|
||||
|
||||
external static String _makeQueryFromParameters(
|
||||
Map<String, dynamic /*String?|Iterable<String>*/ > queryParameters);
|
||||
|
||||
/// Default implementation of [_makeQueryFromParameters].
|
||||
///
|
||||
/// This implementation is used from the patch for [_makeQueryFromParameters]
|
||||
/// where there is not a more efficient native implementation available.
|
||||
static String _makeQueryFromParametersDefault(
|
||||
Map<String, dynamic /*String?|Iterable<String>*/ > queryParameters) {
|
||||
var result = StringBuffer();
|
||||
var separator = "";
|
||||
|
||||
|
|
Loading…
Reference in a new issue