blob: 858f1f500317b0370ab08667a479c5251f4f8f81 [file] [log] [blame]
// Copyright (c) 2012, 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.
library dart._internal;
import 'dart:collection';
import 'dart:async'
show
Future,
Stream,
StreamSubscription,
StreamTransformer,
StreamTransformerBase,
Zone;
import 'dart:convert' show Converter;
import 'dart:core' hide Symbol;
import 'dart:core' as core show Symbol;
import 'dart:math' show Random;
import 'dart:typed_data' show Uint8List;
part 'async_cast.dart';
part 'bytes_builder.dart';
part 'cast.dart';
part 'errors.dart';
part 'iterable.dart';
part 'list.dart';
part 'linked_list.dart';
part 'print.dart';
part 'sort.dart';
part 'symbol.dart';
// Returns true iff `null as T` will succeed based on the
// execution mode.
external bool typeAcceptsNull<T>();
// Powers of 10 up to 10^22 are representable as doubles.
// Powers of 10 above that are only approximate due to lack of precission.
// Used by double-parsing.
const POWERS_OF_TEN = const [
1.0, // 0
10.0,
100.0,
1000.0,
10000.0,
100000.0, // 5
1000000.0,
10000000.0,
100000000.0,
1000000000.0,
10000000000.0, // 10
100000000000.0,
1000000000000.0,
10000000000000.0,
100000000000000.0,
1000000000000000.0, // 15
10000000000000000.0,
100000000000000000.0,
1000000000000000000.0,
10000000000000000000.0,
100000000000000000000.0, // 20
1000000000000000000000.0,
10000000000000000000000.0,
];
/**
* An [Iterable] of the UTF-16 code units of a [String] in index order.
*/
class CodeUnits extends UnmodifiableListBase<int> {
/** The string that this is the code units of. */
final String _string;
CodeUnits(this._string);
int get length => _string.length;
int operator [](int i) => _string.codeUnitAt(i);
static String stringOf(CodeUnits u) => u._string;
}
/// Marks a function or library as having an external implementation ("native"
/// in the Dart VM).
///
/// On a function, this provides a backend-specific String that can be used to
/// identify the function's implementation.
///
/// On a library, it provides a Uri that can be used to locate the native
/// library's implementation.
class ExternalName {
final String name;
const ExternalName(this.name);
}
// Shared hex-parsing utilities.
/// Parses a single hex-digit as code unit.
///
/// Returns a negative value if the character is not a valid hex-digit.
int hexDigitValue(int char) {
assert(char >= 0 && char <= 0xFFFF);
const int digit0 = 0x30;
const int a = 0x61;
const int f = 0x66;
int digit = char ^ digit0;
if (digit <= 9) return digit;
int letter = (char | 0x20);
if (a <= letter && letter <= f) return letter - (a - 10);
return -1;
}
/// Parses two hex digits in a string.
///
/// Returns a negative value if either digit isn't valid.
int parseHexByte(String source, int index) {
assert(index + 2 <= source.length);
int digit1 = hexDigitValue(source.codeUnitAt(index));
int digit2 = hexDigitValue(source.codeUnitAt(index + 1));
return digit1 * 16 + digit2 - (digit2 & 256);
}
/// A resusable `null`-valued future used by `dart:async`.
///
/// **DO NOT USE.**
///
/// This future is used in situations where a future is expected,
/// but no asynchronous computation actually happens,
/// like cancelling a stream from a controller with no `onCancel` callback.
/// *Some code depends on recognizing this future in order to react
/// synchronously.*
/// It does so to avoid changing event interleaving during the null safety
/// migration where, for example, the [StreamSubscription.cancel] method
/// stopped being able to return `null`.
/// The code that would be broken by such a timing change is fragile,
/// but we are not able to simply change it.
/// For better or worse, code depends on the precise timing that our libraries
/// have so far exhibited.
///
/// This future will be removed again if we can ever do so.
/// Do not use it for anything other than preserving timing
/// during the null safety migration.
final Future<Null> nullFuture = Zone.root.run(() => Future<Null>.value(null));
/// A default hash function used by the platform in various places.
///
/// This is currently the [Jenkins hash function][1] but using masking to keep
/// values in SMI range.
///
/// [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
///
/// Usage:
/// Hash each value with the hash of the previous value, then get the final
/// hash by calling finish.
/// ```
/// var hash = 0;
/// for (var value in values) {
/// hash = SystemHash.combine(hash, value.hashCode);
/// }
/// hash = SystemHash.finish(hash);
/// ```
// TODO(lrn): Consider specializing this code per platform,
// so the VM can use its 64-bit integers directly.
@Since("2.11")
class SystemHash {
static int combine(int hash, int value) {
hash = 0x1fffffff & (hash + value);
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
return hash ^ (hash >> 6);
}
static int finish(int hash) {
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
hash = hash ^ (hash >> 11);
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
}
static int hash2(int v1, int v2) {
int hash = 0;
hash = combine(hash, v1);
hash = combine(hash, v2);
return finish(hash);
}
static int hash3(int v1, int v2, int v3) {
int hash = 0;
hash = combine(hash, v1);
hash = combine(hash, v2);
hash = combine(hash, v3);
return finish(hash);
}
static int hash4(int v1, int v2, int v3, int v4) {
int hash = 0;
hash = combine(hash, v1);
hash = combine(hash, v2);
hash = combine(hash, v3);
hash = combine(hash, v4);
return finish(hash);
}
static int hash5(int v1, int v2, int v3, int v4, int v5) {
int hash = 0;
hash = combine(hash, v1);
hash = combine(hash, v2);
hash = combine(hash, v3);
hash = combine(hash, v4);
hash = combine(hash, v5);
return finish(hash);
}
static int hash6(int v1, int v2, int v3, int v4, int v5, int v6) {
int hash = 0;
hash = combine(hash, v1);
hash = combine(hash, v2);
hash = combine(hash, v3);
hash = combine(hash, v4);
hash = combine(hash, v5);
hash = combine(hash, v6);
return finish(hash);
}
static int hash7(int v1, int v2, int v3, int v4, int v5, int v6, int v7) {
int hash = 0;
hash = combine(hash, v1);
hash = combine(hash, v2);
hash = combine(hash, v3);
hash = combine(hash, v4);
hash = combine(hash, v5);
hash = combine(hash, v6);
hash = combine(hash, v7);
return finish(hash);
}
static int hash8(
int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) {
int hash = 0;
hash = combine(hash, v1);
hash = combine(hash, v2);
hash = combine(hash, v3);
hash = combine(hash, v4);
hash = combine(hash, v5);
hash = combine(hash, v6);
hash = combine(hash, v7);
hash = combine(hash, v8);
return finish(hash);
}
static int hash9(
int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9) {
int hash = 0;
hash = combine(hash, v1);
hash = combine(hash, v2);
hash = combine(hash, v3);
hash = combine(hash, v4);
hash = combine(hash, v5);
hash = combine(hash, v6);
hash = combine(hash, v7);
hash = combine(hash, v8);
hash = combine(hash, v9);
return finish(hash);
}
static int hash10(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
int v8, int v9, int v10) {
int hash = 0;
hash = combine(hash, v1);
hash = combine(hash, v2);
hash = combine(hash, v3);
hash = combine(hash, v4);
hash = combine(hash, v5);
hash = combine(hash, v6);
hash = combine(hash, v7);
hash = combine(hash, v8);
hash = combine(hash, v9);
hash = combine(hash, v10);
return finish(hash);
}
/// Bit shuffling operation to improve hash codes.
///
/// Dart integers have very simple hash codes (their value),
/// which is acceptable for the hash above because it smears the bits
/// as part of the combination.
/// However, for the unordered hash based on xor, we need to improve
/// the hash code of, e.g., integers, so a set containing the integers
/// from zero to 2^n won't always have a zero hashcode.
///
/// Assumes the input hash code is an unsigned 32-bit integer.
/// Found by Christopher Wellons [https://github.com/skeeto/hash-prospector].
static int smear(int x) {
// TODO: Use >>> instead of >> when available.
x ^= x >> 16;
x = (x * 0x7feb352d) & 0xFFFFFFFF;
x ^= x >> 15;
x = (x * 0x846ca68b) & 0xFFFFFFFF;
x ^= x >> 16;
return x;
}
}
/// Given an [instance] of some generic type [T], and [extract], a first-class
/// generic function that takes the same number of type parameters as [T],
/// invokes the function with the same type arguments that were passed to T
/// when [instance] was constructed.
///
/// Example:
///
/// ```dart
/// class Two<A, B> {}
///
/// print(extractTypeArguments<List>(<int>[], <T>() => new Set<T>()));
/// // Prints: Instance of 'Set<int>'.
///
/// print(extractTypeArguments<Map>(<String, bool>{},
/// <T, S>() => new Two<T, S>));
/// // Prints: Instance of 'Two<String, bool>'.
/// ```
///
/// The type argument T is important to choose which specific type parameter
/// list in [instance]'s type hierarchy is being extracted. Consider:
///
/// ```dart
/// class A<T> {}
/// class B<T> {}
///
/// class C implements A<int>, B<String> {}
///
/// main() {
/// var c = new C();
/// print(extractTypeArguments<A>(c, <T>() => <T>[]));
/// // Prints: Instance of 'List<int>'.
///
/// print(extractTypeArguments<B>(c, <T>() => <T>[]));
/// // Prints: Instance of 'List<String>'.
/// }
/// ```
///
/// A caller must not:
///
/// * Pass `null` for [instance].
/// * Use a non-class type (i.e. a function type) for [T].
/// * Use a non-generic type for [T].
/// * Pass an instance of a generic type and a function that don't both take
/// the same number of type arguments:
///
/// ```dart
/// extractTypeArguments<List>(<int>[], <T, S>() => null);
/// ```
///
/// See this issue for more context:
/// https://github.com/dart-lang/sdk/issues/31371
external Object? extractTypeArguments<T>(T instance, Function extract);
/// Annotation class marking the version where SDK API was added.
///
/// A `Since` annotation can be applied to a library declaration,
/// any public declaration in a library, or in a class, or to
/// an optional parameter.
///
/// It signifies that the export, member or parameter was *added* in
/// that version.
///
/// When applied to a library declaration, it also a applies to
/// all members declared or exported by that library.
/// If applied to a class, it also applies to all members and constructors
/// of that class.
/// If applied to a class method, or parameter of such,
/// any method implementing that interface method is also annotated.
/// If multiple `Since` annotations apply to the same declaration or
/// parameter, the latest version takes precendence.
///
/// Any use of a marked API may trigger a warning if the using code
/// does not require an SDK version guaranteeing that the API is available,
/// unless the API feature is also provided by something else.
/// It is only a problem if an annotated feature is used, and the annotated
/// API is the *only* thing providing the functionality.
/// For example, using `Future` exported by `dart:core` is not a problem
/// if the same library also imports `dart:async`, and using an optional
/// parameter on an interface is not a problem if the same type also
/// implements another interface providing the same parameter.
///
/// The version must be a semantic version (like `1.4.2` or `0.9.4-rec.4`),
/// or the first two numbers of a semantic version (like `1.0` or `2.2`),
/// representing a stable release, and equivalent to the semantic version
/// you get by appending a `.0`.
@Since("2.2")
class Since {
final String version;
const Since(this.version);
}
/// A null-check function for function parameters in Null Safety enabled code.
///
/// Because Dart does not have full null safety
/// until all legacy code has been removed from a program,
/// a non-nullable parameter can still end up with a `null` value.
/// This function can be used to guard those functions against null arguments.
/// It throws a [TypeError] because we are really seeing the failure to
/// assign `null` to a non-nullable type.
///
/// See http://dartbug.com/40614 for context.
T checkNotNullable<T extends Object>(T value, String name) {
if ((value as dynamic) == null) {
throw NotNullableError<T>(name);
}
return value;
}
/// A [TypeError] thrown by [checkNotNullable].
class NotNullableError<T> extends Error implements TypeError {
final String _name;
NotNullableError(this._name);
String toString() =>
"Null is not a valid value for the parameter '$_name' of type '$T'";
}
/// A function that returns the value or default value (if invoked with `null`
/// value) for non-nullable function parameters in Null safety enabled code.
///
/// Because Dart does not have full null safety
/// until all legacy code has been removed from a program,
/// a non-nullable parameter can still end up with a `null` value.
/// This function can be used to get a default value for a parameter
/// when a `null` value is passed in for a non-nullable parameter.
///
/// TODO(40810) - Remove uses of this function when Dart has full null safety.
T valueOfNonNullableParamWithDefault<T extends Object>(T value, T defaultVal) {
if ((value as dynamic) == null) {
return defaultVal;
} else {
return value;
}
}
/**
* HTTP status codes. Exported in dart:io and dart:html.
*/
abstract class HttpStatus {
static const int continue_ = 100;
static const int switchingProtocols = 101;
@Since("2.1")
static const int processing = 102;
static const int ok = 200;
static const int created = 201;
static const int accepted = 202;
static const int nonAuthoritativeInformation = 203;
static const int noContent = 204;
static const int resetContent = 205;
static const int partialContent = 206;
@Since("2.1")
static const int multiStatus = 207;
@Since("2.1")
static const int alreadyReported = 208;
@Since("2.1")
static const int imUsed = 226;
static const int multipleChoices = 300;
static const int movedPermanently = 301;
static const int found = 302;
static const int movedTemporarily = 302; // Common alias for found.
static const int seeOther = 303;
static const int notModified = 304;
static const int useProxy = 305;
static const int temporaryRedirect = 307;
@Since("2.1")
static const int permanentRedirect = 308;
static const int badRequest = 400;
static const int unauthorized = 401;
static const int paymentRequired = 402;
static const int forbidden = 403;
static const int notFound = 404;
static const int methodNotAllowed = 405;
static const int notAcceptable = 406;
static const int proxyAuthenticationRequired = 407;
static const int requestTimeout = 408;
static const int conflict = 409;
static const int gone = 410;
static const int lengthRequired = 411;
static const int preconditionFailed = 412;
static const int requestEntityTooLarge = 413;
static const int requestUriTooLong = 414;
static const int unsupportedMediaType = 415;
static const int requestedRangeNotSatisfiable = 416;
static const int expectationFailed = 417;
@Since("2.1")
static const int misdirectedRequest = 421;
@Since("2.1")
static const int unprocessableEntity = 422;
@Since("2.1")
static const int locked = 423;
@Since("2.1")
static const int failedDependency = 424;
static const int upgradeRequired = 426;
@Since("2.1")
static const int preconditionRequired = 428;
@Since("2.1")
static const int tooManyRequests = 429;
@Since("2.1")
static const int requestHeaderFieldsTooLarge = 431;
@Since("2.1")
static const int connectionClosedWithoutResponse = 444;
@Since("2.1")
static const int unavailableForLegalReasons = 451;
@Since("2.1")
static const int clientClosedRequest = 499;
static const int internalServerError = 500;
static const int notImplemented = 501;
static const int badGateway = 502;
static const int serviceUnavailable = 503;
static const int gatewayTimeout = 504;
static const int httpVersionNotSupported = 505;
@Since("2.1")
static const int variantAlsoNegotiates = 506;
@Since("2.1")
static const int insufficientStorage = 507;
@Since("2.1")
static const int loopDetected = 508;
@Since("2.1")
static const int notExtended = 510;
@Since("2.1")
static const int networkAuthenticationRequired = 511;
// Client generated status code.
static const int networkConnectTimeoutError = 599;
@Deprecated("Use continue_ instead")
static const int CONTINUE = continue_;
@Deprecated("Use switchingProtocols instead")
static const int SWITCHING_PROTOCOLS = switchingProtocols;
@Deprecated("Use ok instead")
static const int OK = ok;
@Deprecated("Use created instead")
static const int CREATED = created;
@Deprecated("Use accepted instead")
static const int ACCEPTED = accepted;
@Deprecated("Use nonAuthoritativeInformation instead")
static const int NON_AUTHORITATIVE_INFORMATION = nonAuthoritativeInformation;
@Deprecated("Use noContent instead")
static const int NO_CONTENT = noContent;
@Deprecated("Use resetContent instead")
static const int RESET_CONTENT = resetContent;
@Deprecated("Use partialContent instead")
static const int PARTIAL_CONTENT = partialContent;
@Deprecated("Use multipleChoices instead")
static const int MULTIPLE_CHOICES = multipleChoices;
@Deprecated("Use movedPermanently instead")
static const int MOVED_PERMANENTLY = movedPermanently;
@Deprecated("Use found instead")
static const int FOUND = found;
@Deprecated("Use movedTemporarily instead")
static const int MOVED_TEMPORARILY = movedTemporarily;
@Deprecated("Use seeOther instead")
static const int SEE_OTHER = seeOther;
@Deprecated("Use notModified instead")
static const int NOT_MODIFIED = notModified;
@Deprecated("Use useProxy instead")
static const int USE_PROXY = useProxy;
@Deprecated("Use temporaryRedirect instead")
static const int TEMPORARY_REDIRECT = temporaryRedirect;
@Deprecated("Use badRequest instead")
static const int BAD_REQUEST = badRequest;
@Deprecated("Use unauthorized instead")
static const int UNAUTHORIZED = unauthorized;
@Deprecated("Use paymentRequired instead")
static const int PAYMENT_REQUIRED = paymentRequired;
@Deprecated("Use forbidden instead")
static const int FORBIDDEN = forbidden;
@Deprecated("Use notFound instead")
static const int NOT_FOUND = notFound;
@Deprecated("Use methodNotAllowed instead")
static const int METHOD_NOT_ALLOWED = methodNotAllowed;
@Deprecated("Use notAcceptable instead")
static const int NOT_ACCEPTABLE = notAcceptable;
@Deprecated("Use proxyAuthenticationRequired instead")
static const int PROXY_AUTHENTICATION_REQUIRED = proxyAuthenticationRequired;
@Deprecated("Use requestTimeout instead")
static const int REQUEST_TIMEOUT = requestTimeout;
@Deprecated("Use conflict instead")
static const int CONFLICT = conflict;
@Deprecated("Use gone instead")
static const int GONE = gone;
@Deprecated("Use lengthRequired instead")
static const int LENGTH_REQUIRED = lengthRequired;
@Deprecated("Use preconditionFailed instead")
static const int PRECONDITION_FAILED = preconditionFailed;
@Deprecated("Use requestEntityTooLarge instead")
static const int REQUEST_ENTITY_TOO_LARGE = requestEntityTooLarge;
@Deprecated("Use requestUriTooLong instead")
static const int REQUEST_URI_TOO_LONG = requestUriTooLong;
@Deprecated("Use unsupportedMediaType instead")
static const int UNSUPPORTED_MEDIA_TYPE = unsupportedMediaType;
@Deprecated("Use requestedRangeNotSatisfiable instead")
static const int REQUESTED_RANGE_NOT_SATISFIABLE =
requestedRangeNotSatisfiable;
@Deprecated("Use expectationFailed instead")
static const int EXPECTATION_FAILED = expectationFailed;
@Deprecated("Use upgradeRequired instead")
static const int UPGRADE_REQUIRED = upgradeRequired;
@Deprecated("Use internalServerError instead")
static const int INTERNAL_SERVER_ERROR = internalServerError;
@Deprecated("Use notImplemented instead")
static const int NOT_IMPLEMENTED = notImplemented;
@Deprecated("Use badGateway instead")
static const int BAD_GATEWAY = badGateway;
@Deprecated("Use serviceUnavailable instead")
static const int SERVICE_UNAVAILABLE = serviceUnavailable;
@Deprecated("Use gatewayTimeout instead")
static const int GATEWAY_TIMEOUT = gatewayTimeout;
@Deprecated("Use httpVersionNotSupported instead")
static const int HTTP_VERSION_NOT_SUPPORTED = httpVersionNotSupported;
@Deprecated("Use networkConnectTimeoutError instead")
static const int NETWORK_CONNECT_TIMEOUT_ERROR = networkConnectTimeoutError;
}