|  | // 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. | 
|  |  | 
|  | /// Concurrent programming using _isolates_: | 
|  | /// independent workers that are similar to threads | 
|  | /// but don't share memory, | 
|  | /// communicating only via messages. | 
|  | /// | 
|  | /// To use this library in your code: | 
|  | /// ```dart | 
|  | /// import 'dart:isolate'; | 
|  | /// ``` | 
|  | /// {@category VM} | 
|  | library dart.isolate; | 
|  |  | 
|  | import "dart:async"; | 
|  | import "dart:_internal" show Since; | 
|  | import "dart:typed_data" show ByteBuffer, TypedData, Uint8List; | 
|  |  | 
|  | part "capability.dart"; | 
|  |  | 
|  | /// Thrown when an isolate cannot be created. | 
|  | class IsolateSpawnException implements Exception { | 
|  | /// Error message reported by the spawn operation. | 
|  | final String message; | 
|  | @pragma("vm:entry-point") | 
|  | IsolateSpawnException(this.message); | 
|  | String toString() => "IsolateSpawnException: $message"; | 
|  | } | 
|  |  | 
|  | /// An isolated Dart execution context. | 
|  | /// | 
|  | /// All Dart code runs in an isolate, and code can access classes and values | 
|  | /// only from the same isolate. Different isolates can communicate by sending | 
|  | /// values through ports (see [ReceivePort], [SendPort]). | 
|  | /// | 
|  | /// An `Isolate` object is a reference to an isolate, usually different from | 
|  | /// the current isolate. | 
|  | /// It represents, and can be used to control, the other isolate. | 
|  | /// | 
|  | /// When spawning a new isolate, the spawning isolate receives an `Isolate` | 
|  | /// object representing the new isolate when the spawn operation succeeds. | 
|  | /// | 
|  | /// Isolates run code in its own event loop, and each event may run smaller tasks | 
|  | /// in a nested microtask queue. | 
|  | /// | 
|  | /// An `Isolate` object allows other isolates to control the event loop | 
|  | /// of the isolate that it represents, and to inspect the isolate, | 
|  | /// for example by pausing the isolate or by getting events when the isolate | 
|  | /// has an uncaught error. | 
|  | /// | 
|  | /// The [controlPort] identifies and gives access to controlling the isolate, | 
|  | /// and the [pauseCapability] and [terminateCapability] guard access | 
|  | /// to some control operations. | 
|  | /// For example, calling [pause] on an `Isolate` object created without a | 
|  | /// [pauseCapability], has no effect. | 
|  | /// | 
|  | /// The `Isolate` object provided by a spawn operation will have the | 
|  | /// control port and capabilities needed to control the isolate. | 
|  | /// New isolate objects can be created without some of these capabilities | 
|  | /// if necessary, using the [Isolate.Isolate] constructor. | 
|  | /// | 
|  | /// An `Isolate` object cannot be sent over a `SendPort`, but the control port | 
|  | /// and capabilities can be sent, and can be used to create a new functioning | 
|  | /// `Isolate` object in the receiving port's isolate. | 
|  | class Isolate { | 
|  | /// Argument to `ping` and `kill`: Ask for immediate action. | 
|  | static const int immediate = 0; | 
|  |  | 
|  | /// Argument to `ping` and `kill`: Ask for action before the next event. | 
|  | static const int beforeNextEvent = 1; | 
|  |  | 
|  | /// Control port used to send control messages to the isolate. | 
|  | /// | 
|  | /// The control port identifies the isolate. | 
|  | /// | 
|  | /// An `Isolate` object allows sending control messages | 
|  | /// through the control port. | 
|  | /// | 
|  | /// Some control messages require a specific capability to be passed along | 
|  | /// with the message (see [pauseCapability] and [terminateCapability]), | 
|  | /// otherwise the message is ignored by the isolate. | 
|  | final SendPort controlPort; | 
|  |  | 
|  | /// Capability granting the ability to pause the isolate. | 
|  | /// | 
|  | /// This capability is required by [pause]. | 
|  | /// If the capability is `null`, or if it is not the correct pause capability | 
|  | /// of the isolate identified by [controlPort], | 
|  | /// then calls to [pause] will have no effect. | 
|  | /// | 
|  | /// If the isolate is spawned in a paused state, use this capability as | 
|  | /// argument to the [resume] method in order to resume the paused isolate. | 
|  | final Capability? pauseCapability; | 
|  |  | 
|  | /// Capability granting the ability to terminate the isolate. | 
|  | /// | 
|  | /// This capability is required by [kill] and [setErrorsFatal]. | 
|  | /// If the capability is `null`, or if it is not the correct termination | 
|  | /// capability of the isolate identified by [controlPort], | 
|  | /// then calls to those methods will have no effect. | 
|  | final Capability? terminateCapability; | 
|  |  | 
|  | /// The name of the [Isolate] displayed for debug purposes. | 
|  | /// | 
|  | /// This can be set using the `debugName` parameter in [spawn] and [spawnUri]. | 
|  | /// | 
|  | /// This name does not uniquely identify an isolate. Multiple isolates in the | 
|  | /// same process may have the same `debugName`. | 
|  | /// | 
|  | /// For a given isolate, this value will be the same as the values returned by | 
|  | /// `Dart_DebugName` in the C embedding API and the `debugName` property in | 
|  | /// [IsolateMirror]. | 
|  | @Since("2.3") | 
|  | external String? get debugName; | 
|  |  | 
|  | /// Creates a new [Isolate] object with a restricted set of capabilities. | 
|  | /// | 
|  | /// The port should be a control port for an isolate, as taken from | 
|  | /// another `Isolate` object. | 
|  | /// | 
|  | /// The capabilities should be the subset of the capabilities that are | 
|  | /// available to the original isolate. | 
|  | /// Capabilities of an isolate are locked to that isolate, and have no effect | 
|  | /// anywhere else, so the capabilities should come from the same isolate as | 
|  | /// the control port. | 
|  | /// | 
|  | /// Can also be used to create an [Isolate] object from a control port, and | 
|  | /// any available capabilities, that have been sent through a [SendPort]. | 
|  | /// | 
|  | /// Example: | 
|  | /// ```dart | 
|  | /// Isolate isolate = findSomeIsolate(); | 
|  | /// Isolate restrictedIsolate = Isolate(isolate.controlPort); | 
|  | /// untrustedCode(restrictedIsolate); | 
|  | /// ``` | 
|  | /// This example creates a new `Isolate` object that cannot be used to | 
|  | /// pause or terminate the isolate. All the untrusted code can do is to | 
|  | /// inspect the isolate and see uncaught errors or when it terminates. | 
|  | Isolate(this.controlPort, {this.pauseCapability, this.terminateCapability}); | 
|  |  | 
|  | /// An [Isolate] object representing the current isolate. | 
|  | /// | 
|  | /// The current isolate for code using [current] | 
|  | /// is the isolate running the code. | 
|  | /// | 
|  | /// The isolate object provides the capabilities required to inspect, | 
|  | /// pause or kill the isolate, and allows granting these capabilities | 
|  | /// to others. | 
|  | /// | 
|  | /// It is possible to pause the current isolate, but doing so *without* | 
|  | /// first passing the ability to resume it again to another isolate, | 
|  | /// is a sure way to hang your program. | 
|  | external static Isolate get current; | 
|  |  | 
|  | /// The package root of the current isolate, if any. | 
|  | /// | 
|  | /// This getter returns `null`, as the `packages/` directory is not supported | 
|  | /// in Dart 2. | 
|  | @Deprecated('packages/ directory resolution is not supported in Dart 2.') | 
|  | external static Future<Uri?> get packageRoot; | 
|  |  | 
|  | /// The location of the package configuration of the current isolate, if any. | 
|  | /// | 
|  | /// If the isolate has not been setup for package resolution, | 
|  | /// this location is `null`, | 
|  | /// otherwise it is a URI referencing the package config file. | 
|  | external static Future<Uri?> get packageConfig; | 
|  |  | 
|  | /// Maps a `package:` URI to a non-package Uri. | 
|  | /// | 
|  | /// If there is no valid mapping from the `package:` URI in the current | 
|  | /// isolate, then this call returns `null`. Non-`package:` URIs are | 
|  | /// returned unmodified. | 
|  | external static Future<Uri?> resolvePackageUri(Uri packageUri); | 
|  |  | 
|  | /// Creates and spawns an isolate that shares the same code as the current | 
|  | /// isolate. | 
|  | /// | 
|  | /// The argument [entryPoint] specifies the initial function to call | 
|  | /// in the spawned isolate. | 
|  | /// The entry-point function is invoked in the new isolate with [message] | 
|  | /// as the only argument. | 
|  | /// | 
|  | /// The function must be a top-level function or a static method | 
|  | /// that can be called with a single argument, | 
|  | /// that is, a compile-time constant function value | 
|  | /// which accepts at least one positional parameter | 
|  | /// and has at most one required positional parameter. | 
|  | /// The function may accept any number of optional parameters, | 
|  | /// as long as it *can* be called with just a single argument. | 
|  | /// The function must not be the value of a function expression | 
|  | /// or an instance method tear-off. | 
|  | /// | 
|  | /// Usually the initial [message] contains a [SendPort] so | 
|  | /// that the spawner and spawnee can communicate with each other. | 
|  | /// | 
|  | /// If the [paused] parameter is set to `true`, | 
|  | /// the isolate will start up in a paused state, | 
|  | /// just before calling the [entryPoint] function with the [message], | 
|  | /// as if by an initial call of `isolate.pause(isolate.pauseCapability)`. | 
|  | /// To resume the isolate, call `isolate.resume(isolate.pauseCapability)`. | 
|  | /// | 
|  | /// If the [errorsAreFatal], [onExit] and/or [onError] parameters are provided, | 
|  | /// the isolate will act as if, respectively, [setErrorsFatal], | 
|  | /// [addOnExitListener] and [addErrorListener] were called with the | 
|  | /// corresponding parameter and was processed before the isolate starts | 
|  | /// running. | 
|  | /// | 
|  | /// If [debugName] is provided, the spawned [Isolate] will be identifiable by | 
|  | /// this name in debuggers and logging. | 
|  | /// | 
|  | /// If [errorsAreFatal] is omitted, the platform may choose a default behavior | 
|  | /// or inherit the current isolate's behavior. | 
|  | /// | 
|  | /// You can also call the [setErrorsFatal], [addOnExitListener] and | 
|  | /// [addErrorListener] methods on the returned isolate, but unless the | 
|  | /// isolate was started as [paused], it may already have terminated | 
|  | /// before those methods can complete. | 
|  | /// | 
|  | /// Returns a future which will complete with an [Isolate] instance if the | 
|  | /// spawning succeeded. It will complete with an error otherwise. | 
|  | external static Future<Isolate> spawn<T>( | 
|  | void entryPoint(T message), T message, | 
|  | {bool paused = false, | 
|  | bool errorsAreFatal = true, | 
|  | SendPort? onExit, | 
|  | SendPort? onError, | 
|  | @Since("2.3") String? debugName}); | 
|  |  | 
|  | /// Creates and spawns an isolate that runs the code from the library with | 
|  | /// the specified URI. | 
|  | /// | 
|  | /// The isolate starts executing the top-level `main` function of the library | 
|  | /// with the given URI. | 
|  | /// | 
|  | /// The target `main` must be callable with zero, one or two arguments. | 
|  | /// Examples: | 
|  | /// | 
|  | /// * `main()` | 
|  | /// * `main(args)` | 
|  | /// * `main(args, message)` | 
|  | /// | 
|  | /// When present, the parameter `args` is set to the provided [args] list. | 
|  | /// When present, the parameter `message` is set to the initial [message]. | 
|  | /// | 
|  | /// If the [paused] parameter is set to `true`, | 
|  | /// the isolate will start up in a paused state, | 
|  | /// as if by an initial call of `isolate.pause(isolate.pauseCapability)`. | 
|  | /// To resume the isolate, call `isolate.resume(isolate.pauseCapability)`. | 
|  | /// | 
|  | /// If the [errorsAreFatal], [onExit] and/or [onError] parameters are provided, | 
|  | /// the isolate will act as if, respectively, [setErrorsFatal], | 
|  | /// [addOnExitListener] and [addErrorListener] were called with the | 
|  | /// corresponding parameter and was processed before the isolate starts | 
|  | /// running. | 
|  | /// | 
|  | /// You can also call the [setErrorsFatal], [addOnExitListener] and | 
|  | /// [addErrorListener] methods on the returned isolate, but unless the | 
|  | /// isolate was started as [paused], it may already have terminated | 
|  | /// before those methods can complete. | 
|  | /// | 
|  | /// If the [checked] parameter is set to `true` or `false`, | 
|  | /// the new isolate will run code in checked mode (enabling asserts and type | 
|  | /// checks), respectively in production mode (disabling asserts and type | 
|  | /// checks), if possible. If the parameter is omitted, the new isolate will | 
|  | /// inherit the value from the current isolate. | 
|  | /// | 
|  | /// In Dart2 strong mode, the `checked` parameter only controls asserts, but | 
|  | /// not type checks. | 
|  | /// | 
|  | /// It may not always be possible to honor the `checked` parameter. | 
|  | /// If the isolate code was pre-compiled, it may not be possible to change | 
|  | /// the checked mode setting dynamically. | 
|  | /// In that case, the `checked` parameter is ignored. | 
|  | /// | 
|  | /// WARNING: The [checked] parameter is not implemented on all platforms yet. | 
|  | /// | 
|  | /// If the [packageConfig] parameter is provided, then it is used to find the | 
|  | /// location of a package resolution configuration file for the spawned | 
|  | /// isolate. | 
|  | /// | 
|  | /// If the [automaticPackageResolution] parameter is provided, then the | 
|  | /// location of the package sources in the spawned isolate is automatically | 
|  | /// determined. | 
|  | /// | 
|  | /// The [environment] is a mapping from strings to strings which the | 
|  | /// spawned isolate uses when looking up [String.fromEnvironment] values. | 
|  | /// The system may add its own entries to environment as well. | 
|  | /// If `environment` is omitted, the spawned isolate has the same environment | 
|  | /// declarations as the spawning isolate. | 
|  | /// | 
|  | /// WARNING: The [environment] parameter is not implemented on all | 
|  | /// platforms yet. | 
|  | /// | 
|  | /// If [debugName] is provided, the spawned [Isolate] will be identifiable by | 
|  | /// this name in debuggers and logging. | 
|  | /// | 
|  | /// Returns a future that will complete with an [Isolate] instance if the | 
|  | /// spawning succeeded. It will complete with an error otherwise. | 
|  | external static Future<Isolate> spawnUri( | 
|  | Uri uri, | 
|  | List<String> args, | 
|  | var message, | 
|  | {bool paused = false, | 
|  | SendPort? onExit, | 
|  | SendPort? onError, | 
|  | bool errorsAreFatal = true, | 
|  | bool? checked, | 
|  | Map<String, String>? environment, | 
|  | @Deprecated('The packages/ dir is not supported in Dart 2') | 
|  | Uri? packageRoot, | 
|  | Uri? packageConfig, | 
|  | bool automaticPackageResolution = false, | 
|  | @Since("2.3") | 
|  | String? debugName}); | 
|  |  | 
|  | /// Requests the isolate to pause. | 
|  | /// | 
|  | /// When the isolate receives the pause command, it stops | 
|  | /// processing events from the event loop queue. | 
|  | /// It may still add new events to the queue in response to, e.g., timers | 
|  | /// or receive-port messages. When the isolate is resumed, | 
|  | /// it starts handling the already enqueued events. | 
|  | /// | 
|  | /// The pause request is sent through the isolate's command port, | 
|  | /// which bypasses the receiving isolate's event loop. | 
|  | /// The pause takes effect when it is received, pausing the event loop | 
|  | /// as it is at that time. | 
|  | /// | 
|  | /// The [resumeCapability] is used to identity the pause, | 
|  | /// and must be used again to end the pause using [resume]. | 
|  | /// If [resumeCapability] is omitted, a new capability object is created | 
|  | /// and used instead. | 
|  | /// | 
|  | /// If an isolate is paused more than once using the same capability, | 
|  | /// only one resume with that capability is needed to end the pause. | 
|  | /// | 
|  | /// If an isolate is paused using more than one capability, | 
|  | /// each pause must be individually ended before the isolate resumes. | 
|  | /// | 
|  | /// Returns the capability that must be used to end the pause. | 
|  | /// This is either [resumeCapability], or a new capability when | 
|  | /// [resumeCapability] is omitted. | 
|  | /// | 
|  | /// If [pauseCapability] is `null`, or it's not the pause capability | 
|  | /// of the isolate identified by [controlPort], | 
|  | /// the pause request is ignored by the receiving isolate. | 
|  | Capability pause([Capability? resumeCapability]) { | 
|  | resumeCapability ??= new Capability(); | 
|  | _pause(resumeCapability); | 
|  | return resumeCapability; | 
|  | } | 
|  |  | 
|  | /// Internal implementation of [pause]. | 
|  | external void _pause(Capability resumeCapability); | 
|  |  | 
|  | /// Resumes a paused isolate. | 
|  | /// | 
|  | /// Sends a message to an isolate requesting that it ends a pause | 
|  | /// that was previously requested. | 
|  | /// | 
|  | /// When all active pause requests have been cancelled, the isolate | 
|  | /// will continue processing events and handling normal messages. | 
|  | /// | 
|  | /// If the [resumeCapability] is not one that has previously been used | 
|  | /// to pause the isolate, or it has already been used to resume from | 
|  | /// that pause, the resume call has no effect. | 
|  | external void resume(Capability resumeCapability); | 
|  |  | 
|  | /// Requests an exit message on [responsePort] when the isolate terminates. | 
|  | /// | 
|  | /// The isolate will send [response] as a message on [responsePort] as the last | 
|  | /// thing before it terminates. It will run no further code after the message | 
|  | /// has been sent. | 
|  | /// | 
|  | /// Adding the same port more than once will only cause it to receive one exit | 
|  | /// message, using the last response value that was added, | 
|  | /// and it only needs to be removed once using [removeOnExitListener]. | 
|  | /// | 
|  | /// If the isolate has terminated before it can receive this request, | 
|  | /// no exit message will be sent. | 
|  | /// | 
|  | /// The [response] object must follow the same restrictions as enforced by | 
|  | /// [SendPort.send]. | 
|  | /// It is recommended to only use simple values that can be sent to all | 
|  | /// isolates, like `null`, booleans, numbers or strings. | 
|  | /// | 
|  | /// Since isolates run concurrently, it's possible for it to exit before the | 
|  | /// exit listener is established, and in that case no response will be | 
|  | /// sent on [responsePort]. | 
|  | /// To avoid this, either use the corresponding parameter to the spawn | 
|  | /// function, or start the isolate paused, add the listener and | 
|  | /// then resume the isolate. | 
|  | /* TODO(lrn): Can we do better? Can the system recognize this message and | 
|  | * send a reply if the receiving isolate is dead? | 
|  | */ | 
|  | external void addOnExitListener(SendPort responsePort, {Object? response}); | 
|  |  | 
|  | /// Stops listening for exit messages from the isolate. | 
|  | /// | 
|  | /// Requests for the isolate to not send exit messages on [responsePort]. | 
|  | /// If the isolate isn't expecting to send exit messages on [responsePort], | 
|  | /// because the port hasn't been added using [addOnExitListener], | 
|  | /// or because it has already been removed, the request is ignored. | 
|  | /// | 
|  | /// If the same port has been passed via [addOnExitListener] more than once, | 
|  | /// only one call to `removeOnExitListener` is needed to stop it from receiving | 
|  | /// exit messages. | 
|  | /// | 
|  | /// Closing the receive port that is associated with the [responsePort] does | 
|  | /// not stop the isolate from sending uncaught errors, they are just going to | 
|  | /// be lost. | 
|  | /// | 
|  | /// An exit message may still be sent if the isolate terminates | 
|  | /// before this request is received and processed. | 
|  | external void removeOnExitListener(SendPort responsePort); | 
|  |  | 
|  | /// Sets whether uncaught errors will terminate the isolate. | 
|  | /// | 
|  | /// If errors are fatal, any uncaught error will terminate the isolate | 
|  | /// event loop and shut down the isolate. | 
|  | /// | 
|  | /// This call requires the [terminateCapability] for the isolate. | 
|  | /// If the capability is absent or incorrect, no change is made. | 
|  | /// | 
|  | /// Since isolates run concurrently, it's possible for the receiving isolate | 
|  | /// to exit due to an error, before a request, using this method, has been | 
|  | /// received and processed. | 
|  | /// To avoid this, either use the corresponding parameter to the spawn | 
|  | /// function, or start the isolate paused, set errors non-fatal and | 
|  | /// then resume the isolate. | 
|  | external void setErrorsFatal(bool errorsAreFatal); | 
|  |  | 
|  | /// Requests the isolate to shut down. | 
|  | /// | 
|  | /// The isolate is requested to terminate itself. | 
|  | /// The [priority] argument specifies when this must happen. | 
|  | /// | 
|  | /// The [priority], when provided, must be one of [immediate] or | 
|  | /// [beforeNextEvent] (the default). | 
|  | /// The shutdown is performed at different times depending on the priority: | 
|  | /// | 
|  | /// * `immediate`: The isolate shuts down as soon as possible. | 
|  | ///     Control messages are handled in order, so all previously sent control | 
|  | ///     events from this isolate will all have been processed. | 
|  | ///     The shutdown should happen no later than if sent with | 
|  | ///     `beforeNextEvent`. | 
|  | ///     It may happen earlier if the system has a way to shut down cleanly | 
|  | ///     at an earlier time, even during the execution of another event. | 
|  | /// * `beforeNextEvent`: The shutdown is scheduled for the next time | 
|  | ///     control returns to the event loop of the receiving isolate, | 
|  | ///     after the current event, and any already scheduled control events, | 
|  | ///     are completed. | 
|  | /// | 
|  | /// If [terminateCapability] is `null`, or it's not the terminate capability | 
|  | /// of the isolate identified by [controlPort], | 
|  | /// the kill request is ignored by the receiving isolate. | 
|  | external void kill({int priority = beforeNextEvent}); | 
|  |  | 
|  | /// Requests that the isolate send [response] on the [responsePort]. | 
|  | /// | 
|  | /// The [response] object must follow the same restrictions as enforced by | 
|  | /// [SendPort.send]. | 
|  | /// It is recommended to only use simple values that can be sent to all | 
|  | /// isolates, like `null`, booleans, numbers or strings. | 
|  | /// | 
|  | /// If the isolate is alive, it will eventually send `response` | 
|  | /// (defaulting to `null`) on the response port. | 
|  | /// | 
|  | /// The [priority] must be one of [immediate] or [beforeNextEvent]. | 
|  | /// The response is sent at different times depending on the ping type: | 
|  | /// | 
|  | /// * `immediate`: The isolate responds as soon as it receives the | 
|  | ///     control message. This is after any previous control message | 
|  | ///     from the same isolate has been received and processed, | 
|  | ///     but may be during execution of another event. | 
|  | /// * `beforeNextEvent`: The response is scheduled for the next time | 
|  | ///     control returns to the event loop of the receiving isolate, | 
|  | ///     after the current event, and any already scheduled control events, | 
|  | ///     are completed. | 
|  | external void ping(SendPort responsePort, | 
|  | {Object? response, int priority = immediate}); | 
|  |  | 
|  | /// Requests that uncaught errors of the isolate are sent back to [port]. | 
|  | /// | 
|  | /// The errors are sent back as two-element lists. | 
|  | /// The first element is a `String` representation of the error, usually | 
|  | /// created by calling `toString` on the error. | 
|  | /// The second element is a `String` representation of an accompanying | 
|  | /// stack trace, or `null` if no stack trace was provided. | 
|  | /// To convert this back to a [StackTrace] object, use [StackTrace.fromString]. | 
|  | /// | 
|  | /// Listening using the same port more than once does nothing. | 
|  | /// A port will only receive each error once, | 
|  | /// and will only need to be removed once using [removeErrorListener]. | 
|  | /// | 
|  | /// Closing the receive port that is associated with the port does not stop | 
|  | /// the isolate from sending uncaught errors, they are just going to be lost. | 
|  | /// Instead use [removeErrorListener] to stop receiving errors on [port]. | 
|  | /// | 
|  | /// Since isolates run concurrently, it's possible for it to exit before the | 
|  | /// error listener is established. To avoid this, start the isolate paused, | 
|  | /// add the listener and then resume the isolate. | 
|  | external void addErrorListener(SendPort port); | 
|  |  | 
|  | /// Stops listening for uncaught errors from the isolate. | 
|  | /// | 
|  | /// Requests for the isolate to not send uncaught errors on [port]. | 
|  | /// If the isolate isn't expecting to send uncaught errors on [port], | 
|  | /// because the port hasn't been added using [addErrorListener], | 
|  | /// or because it has already been removed, the request is ignored. | 
|  | /// | 
|  | /// If the same port has been passed via [addErrorListener] more than once, | 
|  | /// only one call to `removeErrorListener` is needed to stop it from receiving | 
|  | /// uncaught errors. | 
|  | /// | 
|  | /// Uncaught errors message may still be sent by the isolate | 
|  | /// until this request is received and processed. | 
|  | external void removeErrorListener(SendPort port); | 
|  |  | 
|  | /// Returns a broadcast stream of uncaught errors from the isolate. | 
|  | /// | 
|  | /// Each error is provided as an error event on the stream. | 
|  | /// | 
|  | /// The actual error object and stackTraces will not necessarily | 
|  | /// be the same object types as in the actual isolate, but they will | 
|  | /// always have the same [Object.toString] result. | 
|  | /// | 
|  | /// This stream is based on [addErrorListener] and [removeErrorListener]. | 
|  | Stream get errors { | 
|  | StreamController controller = StreamController.broadcast(sync: true); | 
|  | RawReceivePort? port; | 
|  | void handleError(Object? message) { | 
|  | var listMessage = message as List<Object?>; | 
|  | var errorDescription = listMessage[0] as String; | 
|  | var stackDescription = listMessage[1] as String; | 
|  | var error = new RemoteError(errorDescription, stackDescription); | 
|  | controller.addError(error, error.stackTrace); | 
|  | } | 
|  |  | 
|  | controller.onListen = () { | 
|  | RawReceivePort receivePort = new RawReceivePort(handleError); | 
|  | port = receivePort; | 
|  | this.addErrorListener(receivePort.sendPort); | 
|  | }; | 
|  | controller.onCancel = () { | 
|  | var listenPort = port!; | 
|  | port = null; | 
|  | this.removeErrorListener(listenPort.sendPort); | 
|  | listenPort.close(); | 
|  | }; | 
|  | return controller.stream; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Sends messages to its [ReceivePort]s. | 
|  | /// | 
|  | /// [SendPort]s are created from [ReceivePort]s. Any message sent through | 
|  | /// a [SendPort] is delivered to its corresponding [ReceivePort]. There might be | 
|  | /// many [SendPort]s for the same [ReceivePort]. | 
|  | /// | 
|  | /// [SendPort]s can be transmitted to other isolates, and they preserve equality | 
|  | /// when sent. | 
|  | abstract class SendPort implements Capability { | 
|  | /// Sends an asynchronous [message] through this send port, to its | 
|  | /// corresponding `ReceivePort`. | 
|  | /// | 
|  | /// The content of [message] can be: primitive values | 
|  | /// (null, num, bool, double, String), instances of [SendPort], | 
|  | /// and lists and maps whose elements are any of these. | 
|  | /// List and maps are also allowed to contain cyclic references. | 
|  | /// | 
|  | /// In the special circumstances when two isolates share the same code and are | 
|  | /// running in the same process (e.g. isolates created via [Isolate.spawn]), | 
|  | /// it is also possible to send object instances (which would be copied in the | 
|  | /// process). This is currently only supported by the | 
|  | /// [Dart Native](https://dart.dev/platforms#dart-native-vm-jit-and-aot) | 
|  | /// platform. | 
|  | /// | 
|  | /// The send happens immediately and doesn't block.  The corresponding receive | 
|  | /// port can receive the message as soon as its isolate's event loop is ready | 
|  | /// to deliver it, independently of what the sending isolate is doing. | 
|  | void send(Object? message); | 
|  |  | 
|  | /// Tests whether [other] is a [SendPort] pointing to the same | 
|  | /// [ReceivePort] as this one. | 
|  | bool operator ==(var other); | 
|  |  | 
|  | /// A hash code for this send port that is consistent with the == operator. | 
|  | int get hashCode; | 
|  | } | 
|  |  | 
|  | /// Together with [SendPort], the only means of communication between isolates. | 
|  | /// | 
|  | /// [ReceivePort]s have a `sendPort` getter which returns a [SendPort]. | 
|  | /// Any message that is sent through this [SendPort] | 
|  | /// is delivered to the [ReceivePort] it has been created from. There, the | 
|  | /// message is dispatched to the `ReceivePort`'s listener. | 
|  | /// | 
|  | /// A [ReceivePort] is a non-broadcast stream. This means that it buffers | 
|  | /// incoming messages until a listener is registered. Only one listener can | 
|  | /// receive messages. See [Stream.asBroadcastStream] for transforming the port | 
|  | /// to a broadcast stream. | 
|  | /// | 
|  | /// A [ReceivePort] may have many [SendPort]s. | 
|  | abstract class ReceivePort implements Stream<dynamic> { | 
|  | /// Opens a long-lived port for receiving messages. | 
|  | /// | 
|  | /// A [ReceivePort] is a non-broadcast stream. This means that it buffers | 
|  | /// incoming messages until a listener is registered. Only one listener can | 
|  | /// receive messages. See [Stream.asBroadcastStream] for transforming the port | 
|  | /// to a broadcast stream. | 
|  | /// | 
|  | /// The optional `debugName` parameter can be set to associate a name with | 
|  | /// this port that can be displayed in tooling. | 
|  | /// | 
|  | /// A receive port is closed by canceling its subscription. | 
|  | external factory ReceivePort([String debugName = '']); | 
|  |  | 
|  | /// Creates a [ReceivePort] from a [RawReceivePort]. | 
|  | /// | 
|  | /// The handler of the given [rawPort] is overwritten during the construction | 
|  | /// of the result. | 
|  | external factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort); | 
|  |  | 
|  | /// Listen for events from [Stream]. | 
|  | /// | 
|  | /// See [Stream.listen]. | 
|  | /// | 
|  | /// Note that [onError] and [cancelOnError] are ignored since a [ReceivePort] | 
|  | /// will never receive an error. | 
|  | /// | 
|  | /// The [onDone] handler will be called when the stream closes. | 
|  | /// The stream closes when [close] is called. | 
|  | StreamSubscription<dynamic> listen(void onData(var message)?, | 
|  | {Function? onError, void onDone()?, bool? cancelOnError}); | 
|  |  | 
|  | /// Closes the receive port. | 
|  | /// | 
|  | /// No further events will be received by the receive port, | 
|  | /// or emitted as stream events. | 
|  | /// | 
|  | /// If [listen] has been called and the [StreamSubscription] has not | 
|  | /// been canceled yet, the subscription will be closed with a "done" | 
|  | /// event. | 
|  | /// | 
|  | /// If the stream has already been canceled this method has no effect. | 
|  | void close(); | 
|  |  | 
|  | /// A [SendPort] which sends messages to this receive port. | 
|  | SendPort get sendPort; | 
|  | } | 
|  |  | 
|  | /// A low-level asynchronous message receiver. | 
|  | /// | 
|  | /// A [RawReceivePort] is low level feature, and is not [Zone] aware. | 
|  | /// The [handler] will always be invoked  in the [Zone.root] zone. | 
|  | /// | 
|  | /// The port cannot be paused. The data-handler must be set before the first | 
|  | /// message is received, otherwise the message is lost. | 
|  | /// | 
|  | /// Messages can be sent to this port using [sendPort]. | 
|  | abstract class RawReceivePort { | 
|  | /// Opens a long-lived port for receiving messages. | 
|  | /// | 
|  | /// A [RawReceivePort] is low level and does not work with [Zone]s. It | 
|  | /// cannot be paused. The data-handler must be set before the first | 
|  | /// message is received, otherwise the message is lost. | 
|  | /// | 
|  | /// If [handler] is provided, it's set as the [RawReceivePort.handler]. | 
|  | /// | 
|  | /// The optional `debugName` parameter can be set to associate a name with | 
|  | /// this port that can be displayed in tooling. | 
|  | external factory RawReceivePort([Function? handler, String debugName = '']); | 
|  |  | 
|  | /// Sets the handler that is invoked for every incoming message. | 
|  | /// | 
|  | /// The handler is invoked in the [Zone.root] zone. | 
|  | /// If the handler should be invoked in the current zone, do: | 
|  | /// ```dart | 
|  | /// rawPort.handler = Zone.current.bind(actualHandler); | 
|  | /// ``` | 
|  | /// | 
|  | /// The handler must be a function which can accept one argument | 
|  | /// of the type of the messages sent to this port. | 
|  | /// This means that if it is known that messages will all be [String]s, | 
|  | /// a handler of type `void Function(String)` can be used. | 
|  | /// The function is invoked dynamically with the actual messages, | 
|  | /// and if this invocation fails, | 
|  | /// the error becomes a top-level uncaught error in the [Zone.root] zone. | 
|  | // TODO(44659): Change parameter type to `void Function(Never)` to only | 
|  | // accept functions which can be called with one argument. | 
|  | void set handler(Function? newHandler); | 
|  |  | 
|  | /// Closes the port. | 
|  | /// | 
|  | /// After a call to this method, any incoming message is silently dropped. | 
|  | /// The [handler] will never be called again. | 
|  | void close(); | 
|  |  | 
|  | /// Returns a [SendPort] that sends messages to this raw receive port. | 
|  | SendPort get sendPort; | 
|  | } | 
|  |  | 
|  | /// Description of an error from another isolate. | 
|  | /// | 
|  | /// This error has the same `toString()` and `stackTrace.toString()` behavior | 
|  | /// as the original error, but has no other features of the original error. | 
|  | class RemoteError implements Error { | 
|  | final String _description; | 
|  | final StackTrace stackTrace; | 
|  | RemoteError(String description, String stackDescription) | 
|  | : _description = description, | 
|  | stackTrace = new StackTrace.fromString(stackDescription); | 
|  | String toString() => _description; | 
|  | } | 
|  |  | 
|  | /// An efficiently transferable sequence of byte values. | 
|  | /// | 
|  | /// A [TransferableTypedData] is created from a number of bytes. | 
|  | /// This will take time proportional to the number of bytes. | 
|  | /// | 
|  | /// The [TransferableTypedData] can be moved between isolates, so | 
|  | /// sending it through a send port will only take constant time. | 
|  | /// | 
|  | /// When sent this way, the local transferable can no longer be materialized, | 
|  | /// and the received object is now the only way to materialize the data. | 
|  | @Since("2.3.2") | 
|  | abstract class TransferableTypedData { | 
|  | /// Creates a new [TransferableTypedData] containing the bytes of [list]. | 
|  | /// | 
|  | /// It must be possible to create a single [Uint8List] containing the | 
|  | /// bytes, so if there are more bytes than what the platform allows in | 
|  | /// a single [Uint8List], then creation fails. | 
|  | external factory TransferableTypedData.fromList(List<TypedData> list); | 
|  |  | 
|  | /// Creates a new [ByteBuffer] containing the bytes stored in this [TransferableTypedData]. | 
|  | /// | 
|  | /// The [TransferableTypedData] is a cross-isolate single-use resource. | 
|  | /// This method must not be called more than once on the same underlying | 
|  | /// transferable bytes, even if the calls occur in different isolates. | 
|  | ByteBuffer materialize(); | 
|  | } |