coerceStream<T> static method

Stream<T> coerceStream<T>(
  1. Object? arg,
  2. String paramName
)

Coerce a stream that came from d4rt into a typed Stream<T>.

Why a bare cast is not enough. The interpreter erases type arguments: Stream<String>.fromIterable(['a']) evaluates to a native Stream<Object?>, and a Stream<Object?> is not a Stream<String>. So both arg as Stream<T> and the arg is! Stream<T> guard that usually precedes it reject every stream a script can build. The guard failing first is what made this hard to spot — the adapter reports "wrong argument" rather than a cast error, so it reads like a script mistake.

Stream.cast<T>() would be the obvious repair and is also wrong for the nested case: it re-types the element, so cast<List<int>>() on a stream of List<Object?> chunks throws on the first chunk. Use coerceByteStream for chunked byte streams.

An element whose type genuinely does not match still fails — this widens nothing.

Implementation

static Stream<T> coerceStream<T>(Object? arg, String paramName) {
  final value = arg is BridgedInstance ? arg.nativeObject : arg;
  if (value is Stream<T>) return value;
  if (value is! Stream) {
    throw ArgumentD4rtException(
      'Invalid parameter "$paramName": expected Stream<$T>, '
      'got ${value.runtimeType}',
    );
  }
  return value.map<T>((element) {
    final unwrapped = element is BridgedInstance
        ? element.nativeObject
        : element;
    if (unwrapped is T) return unwrapped;
    throw ArgumentD4rtException(
      'Invalid parameter "$paramName": expected a Stream<$T>, but an '
      'element was ${unwrapped.runtimeType}',
    );
  });
}