1

If not - are there are any plans to make it so?

I know that dart itself has different backends that might have different implementation. I was curious if users can do the same, e.g. have a function that delegates to one @patch for js runtime and to another @patch in case of dart vm.

akhomchenko
  • 150
  • 1
  • 8

2 Answers2

3

If you're creating a package, you can export different implementations for different platforms, see here: https://dart.dev/guides/libraries/create-library-packages#conditionally-importing-and-exporting-library-files

Tidder
  • 1,126
  • 1
  • 7
  • 15
2

The way to make platform specific code (or rather platform library specific code) is to use conditional imports.

The syntax is:

import "helper_default.dart"
  if (dart.library.js) "helper_js.dart"
  if (dart.library.io) "helper_io.dart";

This import statement will import one of three libraries. If the dart:js library is available on the platform you are compiling for, you will import helper_js.dart. If not, and dart:io is available, then you will import helper_io.dart. If that's also not there, you will import helper_default.dart.

The trick is then to have the same library API implemented in all three libraries, but based only on the available platform library. The helper_js.dart library can implement something using dart:js and helper_io.dart can import dart:io. The default library will likely not be able to do anything useful, so it might just throw an UnsupportedError if you try to use it.

The code in the importing library must be valid for all three imports, which is why they must have "the same" API. That might include declaring a class, but you'd usually define the interface of that class in a non-platform dependent library that the three implementations can share, to ensure that they actually have the same interface.

Example:

library mypkg.shared_types;
import "helper_default.dart"
  if (dart.library.js) "helper_js.dart"
  if (dart.library.io) "helper_io.dart"
  as helper;

class SharedClass {
  factory SharedClass(int something) = helper.SharedClassImpl;
  int get value;
}

and

library mypkg.helper_io;
import "dart:io";
import "shared_types.dart";
class SharedClassImpl implements SharedClass {
  int _id;
  SharedClassImpl(this._id);
  int get value { // Something depending on dart:io.
    var bytes = File("pathToSomething-$id").readAsBytesSync();
    return bytes[0];
  }
}
lrn
  • 64,680
  • 7
  • 105
  • 121
  • Is `if (dart.library.js)` considered an officially blessed way to detect if runtime is js? I can link this answer to https://stackoverflow.com/questions/14655084/is-there-a-way-to-check-if-the-script-is-running-in-the-dart-vm-or-dart2js – akhomchenko Feb 21 '20 at 08:21
  • It is the official way to detect whether a `dart:js` library is available. That is *probably* correlated with being run on JavaScript, but you can't be absolutely sure that this will always be true. (It's *technically* possible to compile Dart to WASM and run it in the browser, with a `dart:js` integration library available, but Dart itself is not in JS). In code, you would use `const bool.fromEnvironment("dart.library.js")` to get a boolean which is true when the `dart:js` library is available. The configurable import syntax does an implicit Dart-environment lookup on its condition. – lrn Feb 21 '20 at 10:07