Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Illegal argument in isolate message: object is unsendable - Library:'dart:async' Class: _Future #1099

Open
8symbols opened this issue Sep 2, 2024 · 0 comments

Comments

@8symbols
Copy link

8symbols commented Sep 2, 2024

If you provide a bundle argument to SvgPicture.asset and use Image.asset(...), then in profile and release modes the following exception will be thrown and svg won't be displayed:

Exception
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): Illegal argument in isolate message: object is unsendable - Library:'dart:async' Class: _Future@4048458 (see restrictions listed at `SendPort.send()` documentation for more information)
 <- _List len:8 (from dart:core)
 <- _Map len:1 (from dart:collection)
 <- Instance of 'PlatformAssetBundle' (from package:flutter/src/services/asset_bundle.dart)
 <- Instance of 'SvgAssetLoader' (from package:flutter_svg/src/loaders.dart)
 <- Context num_variables: 2 <- SvgLoader._load.<anonymous closure>.<anonymous closure> (from package:flutter_svg/src/loaders.dart)
 <- Context num_variables: 2 <- compute.<anonymous closure> (from package:flutter/src/foundation/_isolates_io.dart)
 <- resultPort in Instance of '_RemoteRunner<ByteData>' (from dart:isolate)

#0      Isolate._spawnFunction (dart:isolate-patch/isolate_patch.dart:398)
#1      Isolate.spawn (dart:isolate-patch/isolate_patch.dart:378)
#2      Isolate.run (dart:isolate:285)
#3      compute (package:flutter/src/foundation/_isolates_io.dart:18)
#4      compute (package:flutter/src/foundation/isolates.dart:82)
#5      SvgLoader._load.<anonymous closure> (package:flutter_svg/src/loaders.dart:154)
<asynchronous suspension>
#6      _VectorGraphicWidgetState._loadPicture.<anonymous closure> (package:vector_graphics/src/vector_graphics.dart:355)
<asynchronous suspension>
#7      _VectorGraphicWidgetState._loadPicture.<anonymous closure> (package:vector_graphics/src/vector_graphics.dart:369)
<asynchronous suspension>
#8      _VectorGraphicWidgetState._loadAssetBytes.<anonymous closure> (package:vector_graphics/src/vector_graphics.dart:402)
<asynchronous suspension>

That's because CachingAssetBundle stores futures in its fields, SvgAssetLoader stores bundle (if you provided one) and SvgLoader somehow sends it to other isolate in compute.

Debug build doesn't have this problem because it doesn't use other isolate.

Reproducible with Flutter 3.24.1 and flutter_svg: 2.0.10+1.

Sample app

assets/any_svg.svg and assets/any_png.png are literally any svg and png files respectively.

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Screen(),
    ),
  );
}

class Screen extends StatelessWidget {
  const Screen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          SvgPicture.asset(
            'assets/any_svg.svg',
            bundle: DefaultAssetBundle.of(context),
          ),
          Image.asset(
            'assets/any_png.png',
            width: 100.0,
            height: 100.0,
          ),
        ],
      ),
    );
  }
}

Problem can be fixed with the following change, but I don't sure how adequate it is.

Change that fixes problem
  Future<ByteData> _load(BuildContext? context) {
    final SvgTheme theme = getTheme(context);
    return prepareMessage(context).then((T? message) {
      return _compute<T>(
        message: message,
        xml: provideSvg(message),
        theme: theme,
        colorMapper: colorMapper,
      );
    });
  }

  static Future<ByteData> _compute<T>({
    required T? message,
    required String xml,
    required SvgTheme theme,
    required ColorMapper? colorMapper,
  }) {
    return compute((T? message) {
      return vg
          .encodeSvg(
            xml: xml,
            theme: theme.toVgTheme(),
            colorMapper: colorMapper == null
                ? null
                : _DelegateVgColorMapper(colorMapper),
            debugName: 'Svg loader',
            enableClippingOptimizer: false,
            enableMaskingOptimizer: false,
            enableOverdrawOptimizer: false,
          )
          .buffer
          .asByteData();
    }, message, debugLabel: 'Load Bytes');
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant