Is there a way to check if the script is running in the dart vm or dart2js?
Asked Answered
J

7

8

Is there a way to check if the script is running in the dart vm or dart2js? Maybe using mirrors API?

Jumna answered 1/2, 2013 at 21:10 Comment(2)
Here's the bug for this feature: code.google.com/p/dart/issues/detail?id=3357 Unfortunately, there is no standard way to do this now. It's a known issue.Orthodontist
I think the comment #3 on the bug spoted by Seth is the best answer for your question @Justin.Jumna
O
8

There is no official way, as far as I know. The intent is that for all practical purposes, you shouldn't have to know if you are running native or compiled to JavaScript.

That said, there are few hacks you can use. The easiest one is probably to exploit the fact that Dart has two numeric types, int and double, while JavaScript has only one, which is equivalent to Dart's double, and dart2js doesn't have a special implementation of int just yet. Therefore, identical(1, 1.0) is false in Dart, and the VM implements that correctly, but when compiled to JS, it is true.

Note that you should think pretty hard before using a hack like this. In most cases, you don't have to do that, just write Dart and don't try to recognize if you are running JS or not. Also, noone can guarantee that it will work forever.

Oftentimes answered 2/2, 2013 at 10:4 Comment(2)
Not sure where I should put this, so I'm writing this as a comment to my own answer. We have 3 answers right now, and each one answers a different question :-) My answer says how to recognize if a program runs in native Dart VM or compiled to JS. First Chris's answer says how to recognize if a program runs in standalone Dart or in a browser (maybe native Dart, maybe compiled to JS). Second Chris's answer says how to recognize if the browser supports Dart or not, but nothing is said about currently running program (can run as native Dart, can run compiled to JS). Funny, this Dart thing :-)Oftentimes
I think that the original question is ambiguous: "script is running in the dart vm or dart2js" - the OP doesn't distinguish whether he meant dart vm (server side) or dart vm (browser), vs dart2j2s. Your answer gives browser dart vm vs dart2js, my first answer gives server dart vm vs dart2js (well, any browser script). My second answer was added for completeness (and I've added an update for clarification).Import
P
7

Based on a code fragment found in path library (Dart v0.7.2) :

import 'dart:mirrors';

/// Value indicating that the VM is Dart on server-side.
const int DART_SERVER=1;

/// Value indicating that the VM is Dart on client-side.
const int DART_CLIENT=2;

/// Value indicating that the VM is JavaScript on client-side (e.g. dart2js).
const int JS_CLIENT=3;

/// Returns the type of the current virtual machine.
int vmType() {
  Map<Uri, LibraryMirror> libraries=currentMirrorSystem().libraries;
  if(libraries[Uri.parse('dart:io')]!=null) return DART_SERVER;
  if(libraries[Uri.parse('dart:html')]!=null) return DART_CLIENT;
  return JS_CLIENT;
}

/// Application entry point.
void main() {
  print(vmType());
}
Punctual answered 18/9, 2013 at 0:4 Comment(1)
Update: a recent version of the path package provides another way. github.com/dart-lang/path/blob/master/lib/src/style.dart#L38 => bool isDartVM = Uri.base.scheme == 'file' && Uri.base.path.endsWith('/');Punctual
I
3

Another very hacky way to for a script to tell if is running in the server side VM vs the client side is to use the Options class.

The following app (file called myapp.dart) prints different output when run on the command line VM or in the browser:

void main() {
  var options = new Options();
  print(options.arguments);
  print(options.executable);
  print(options.script);
}

Command line output:

[]
C:\work\dart\editor\dart\dart-sdk\bin\dart.exe
myapp.dart

In-browser output:

[]
     <-- empty string
     <-- empty string

The in-browser output is the same, though, whether it's running in a Dart browser VM or as JS.

Import answered 2/2, 2013 at 11:12 Comment(3)
Options class depends on dart:io library which is NOT available in Dartium and Dart2js. Import fails on Dart 0.7.2.Punctual
I guess the project has moved on since this answer.Import
Too bad :( Your answer was exactly what I was looking for. Does anyone knows an alternative in order to determine server vs client-side?Punctual
P
3

Since dart.js transforms scripts .dart to .dart.js, this works :

bool _isDart() => document.getElementsByTagName("script").where((s) => s.src.endsWith(".dart.js")).isEmpty;
Peltz answered 12/11, 2013 at 21:25 Comment(0)
I
2

I've been thinking about this, and actually, there is a way to discover if the browser has support for Dart (which is almost the same thing) using navigator.webkitStartDart. This is what the dart.js file that bootstraps Dart uses, when determining if the browser supports dart natively, so we can use JavaScript interop to do the same thing.

The following app returns true if running in Dartium, but false if running in Chrome or Firefox:

import 'dart:html';
import 'package:js/js.dart' as js;

void main() {
  print("Is Dart? = ${isDart()}");
}

bool isDart() => js.scoped(() {
  try {
    // will throw exception if it doesn't exist
    var dartExists = js.context.navigator.webkitStartDart;
    return true;
  }
  on NoSuchMethodError {
    return false;
  }
});

Your pubspec will need to look something like this:

name: webkitstart
description: A sample web application
dependencies:
  browser: any
  js: any

@Ladicek's caveat on another answer is still valid though:

In most cases, you don't have to do that, just write Dart and don't try to recognize if you are running JS or not.

Update - This solution doesn't actually tell if the script is running in browser-based dartvm, only that the dartvm is available in the browser. However, if you deploy your app with the standard script tags including packages/browser/dart.js - then this will ensure that if the browser has the dart-vm, it will start the app in the dart-vm. You would only get the app running in javascript if you explicitly linked only the .dart.js version of your app and removed the reference to the dart.js script

ie, This:

<!-- will use dart-vm if available, fallback to JS if not -->
<script type="application/dart" src="example.dart"></script>
<script src="packages/browser/dart.js"></script>

versus this:

<!-- will only use JS, even if dart vm is available -->
<script type="application/dart" src="example.dart.js"></script>
Import answered 2/2, 2013 at 16:10 Comment(2)
Awesome ! I hadn't thought at this. I have updated your answer to remove Future which is not necessary. You can directly return the result of js.scoped.Dmz
Great! I assumed it would require the future, but I didn't even try it without :)Import
U
2

I would not recommend trying to figure out whether you are running "on the VM" or compiled to JavaScript. In the future, there might be more ways to run Dart than that.

You should be detecting the features that you actually want to use instead.

To check if JavaScript integration is available, you can check that const bool.fromEnvironment("dart.library.js") is true. That means that the dart:js library is available. You can use conditional imports to import a library which depends on dart:js only when it's available:

import "feature_default.dart"
  if (dart.library.js) import "feature_js.dart";

This will import feature_js.dart only if the dart:js library is available, otherwise it will import feature_default.dart. (The two libraries should be similar enough that the importing library is correct no matter which one is imported).

There are a number of libraries which are currently only available when run in a browser: dart:js and dart:html and the other DOM libraries. Similarly, only the VM currently has dart:cli and dart:ffi. The libraries dart:mirror is only available on some VMs (it's not in Flutter and not in ahead-of-time compiled code).

There is nothing inherent about the current combinations. It could be possible to compile Dart and the VM to WASM and then run it in a browser and make dart:js available for integration. Or build a VM-based application which embeds a browser view and make dart:html available while still running on the VM.

That's why you should test for the availability of the library that you need, not try to deduce a "platform" from it. Platforms are open ended, and your code will be future-proof (as much as such a thing is possible) if it doesn't assume that there are only two platforms.

For integers, you'll just have to check whether they are 64-bit integers or floating point numbers by doing operations on them. For example bool integersAreFloats = (9007199254740992 == (9007199254740992 + 1));

Unitarian answered 21/2, 2020 at 10:18 Comment(0)
T
0

I think the best way right now is: https://dart.dev/guides/libraries/create-library-packages#conditionally-importing-and-exporting-library-files (example on stackoverflow).

Spec: https://github.com/munificent/dep-interface-libraries/blob/master/Proposal.md


Something that I would consider it an implementation dependent hack:

const _isJs = (1 << 32) == 0 || (1 << 32) == 1;

Example on dartpad: here.

First part of the expression relies on the current implementation of dart2js (see #1, #2).

Second part of the expression relies on the JS spec: MDN.

console.log(1 << 32); // 1
Tailwind answered 21/2, 2020 at 7:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.