简体   繁体   English

有没有办法检查脚本是否在 dart vm 或 dart2js 中运行?

[英]Is there a way to check if the script is running in the dart vm or dart2js?

Is there a way to check if the script is running in the dart vm or dart2js?有没有办法检查脚本是否在 dart vm 或 dart2js 中运行? Maybe using mirrors API?也许使用镜像 API?

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.目的是出于所有实际目的,您不必知道您是在运行本机还是编译为 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.最简单的方法可能是利用 Dart 有两种数字类型intdouble的事实,而 JavaScript 只有一种,相当于 Dart 的double ,而 dart2js 还没有int的特殊实现。 Therefore, identical(1, 1.0) is false in Dart, and the VM implements that correctly, but when compiled to JS, it is true .因此,Dart 中的 same identical(1, 1.0)false ,并且 VM 正确实现了它,但是当编译为 JS 时,它是true

Note that you should think pretty hard before using a hack like this.请注意,在使用这样的 hack 之前,您应该仔细考虑 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.在大多数情况下,您不必这样做,只需编写 Dart,不要尝试识别您是否正在运行 JS。 Also, noone can guarantee that it will work forever.此外,没有人可以保证它会永远有效。

Based on a code fragment found in path library (Dart v0.7.2) :基于在路径库(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());
}

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.另一种让脚本判断是在服务器端 VM 还是在客户端运行的非常笨拙的方法是使用Options类。

The following app (file called myapp.dart ) prints different output when run on the command line VM or in the browser:以下应用程序(名为myapp.dart文件)在命令行 VM 或浏览器中运行时会打印不同的输出:

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.但是,无论是在 Dart 浏览器 VM 中还是作为 JS 运行,浏览器内的输出都是相同的。

由于 dart.js 将脚本 .dart 转换为 .dart.js,这有效:

bool _isDart() => document.getElementsByTagName("script").where((s) => s.src.endsWith(".dart.js")).isEmpty;

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 .我一直在思考这个问题,实际上,有一种方法可以使用navigator.webkitStartDart来发现浏览器是否支持 Dart(几乎是一样的)。 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.这是引导 Dart 使用的 dart.js 文件,在确定浏览器是否原生支持 dart 时,我们可以使用 JavaScript 互操作来做同样的事情。

The following app returns true if running in Dartium , but false if running in Chrome or Firefox :如果在Dartium 中运行,以下应用程序返回true ,如果在ChromeFirefox 中运行,则返回false

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:您的 pubspec 将需要如下所示:

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

@Ladicek's caveat on another answer is still valid though: @Ladicek 对另一个答案的警告仍然有效:

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.在大多数情况下,您不必这样做,只需编写 Dart,不要尝试识别您是否正在运行 JS。

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.更新- 此解决方案实际上并没有说明脚本是否在基于浏览器的 dartvm 中运行,仅说明 dartvm 在浏览器中可用。 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.但是,如果您使用标准脚本标签(包括packages/browser/dart.js部署您的应用程序 - 那么这将确保如果浏览器具有dart-vm,它将在 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如果您仅显式链接应用程序的 .dart.js 版本并删除对 dart.js 脚本的引用,则您只会让应用程序在 javascript 中运行

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>

I would not recommend trying to figure out whether you are running "on the VM" or compiled to JavaScript.我不建议您尝试弄清楚您是在“在 VM 上”运行还是编译为 JavaScript。 In the future, there might be more ways to run Dart than that.将来,运行 Dart 的方法可能不止这些。

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.要检查 JavaScript集成是否可用,您可以检查const bool.fromEnvironment("dart.library.js")是否为真。 That means that the dart:js library is available.这意味着dart:js库可用。 You can use conditional imports to import a library which depends on dart:js only when it's available:您可以使用条件导入来导入依赖于dart:js的库,仅当它可用时:

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 .这将导入feature_js.dart只有当dart:js库是否可用,否则将导入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.有许多图书馆在浏览器中运行时这是目前唯一可用的: dart:jsdart:html和其他DOM库。 Similarly, only the VM currently has dart:cli and dart:ffi .同样,目前只有 VM 有dart:clidart:ffi The libraries dart:mirror is only available on some VMs (it's not in Flutter and not in ahead-of-time compiled code).dart:mirror仅在某些VM 上可用(它不在 Flutter 中,也不在提前编译的代码中)。

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.这可能是可以通过编译飞镖和虚拟机WASM,然后在浏览器中运行它使dart:js可供整合。 Or build a VM-based application which embeds a browser view and make dart:html available while still running on the VM.或者构建一个基于 VM 的应用程序,该应用程序嵌入浏览器视图并使dart:html可用,同时仍在 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.对于整数,您只需通过对它们进行运算来检查它们是 64 位整数还是浮点数。 For example bool integersAreFloats = (9007199254740992 == (9007199254740992 + 1));例如bool integersAreFloats = (9007199254740992 == (9007199254740992 + 1));

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 ).我认为现在最好的方法是: https : //dart.dev/guides/libraries/create-library-packages#conditionally-importing-and-exporting-library-files (以stackoverflow为例)。

Spec: https://github.com/munificent/dep-interface-libraries/blob/master/Proposal.md规范: 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 . dartpad 上的示例:此处

First part of the expression relies on the current implementation of dart2js (see #1 , #2 ).表达式的第一部分依赖于dart2js的当前实现(参见#1#2 )。

Second part of the expression relies on the JS spec: MDN .表达式的第二部分依赖于 JS 规范: MDN

 console.log(1 << 32); // 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM