8

有没有办法检查脚本是否在 dart vm 或 dart2js 中运行?也许使用镜像 API?

4

7 回答 7

8

据我所知,没有官方的方法。其目的是出于所有实际目的,您不必知道您是在运行本机还是编译为 JavaScript。

也就是说,您可以使用的技巧很少。最简单的可能是利用了 Dart 有两种数字类型intdouble,而 JavaScript 只有一种,相当于 Dart 的double,而 dart2js 还没有特殊的实现int。因此,identical(1, 1.0)falseDart 中,VM 正确地实现了它,但是当编译为 JS 时,它是true.

请注意,在使用这样的 hack 之前,您应该好好思考一下。在大多数情况下,您不必这样做,只需编写 Dart 并且不要尝试识别您是否在运行 JS。此外,没有人能保证它会永远有效。

于 2013-02-02T10:04:31.070 回答
7

基于在路径库(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());
}
于 2013-09-18T00:04:12.257 回答
3

让脚本判断是在服务器端 VM 还是在客户端运行的另一种非常老套的方法是使用Options该类。

以下应用程序(名为 的文件myapp.dart)在命令行 VM 或浏览器中运行时会打印不同的输出:

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

命令行输出:

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

浏览器内输出:

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

不过,无论是在 Dart 浏览器 VM 中运行还是作为 JS 运行,浏览器内的输出都是相同的。

于 2013-02-02T11:12:03.580 回答
3

由于 dart.js 将脚本 .dart 转换为 .dart.js,因此可以:

bool _isDart() => document.getElementsByTagName("script").where((s) => s.src.endsWith(".dart.js")).isEmpty;
于 2013-11-12T21:25:17.683 回答
2

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

true如果在Dartium中运行,但false如果在ChromeFirefox中运行,则以下应用程序返回:

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;
  }
});

您的 pubspec 将需要如下所示:

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

@Ladicek 对另一个答案的警告仍然有效:

在大多数情况下,您不必这样做,只需编写 Dart 并且不要尝试识别您是否正在运行 JS。

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

即,这:

<!-- 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>

与此相比:

<!-- will only use JS, even if dart vm is available -->
<script type="application/dart" src="example.dart.js"></script>
于 2013-02-02T16:10:30.017 回答
2

我不建议您尝试弄清楚您是在“在 VM 上”运行还是编译为 JavaScript。未来,运行 Dart 的方法可能不止这些。

您应该检测您实际想要使用的功能。

要检查 JavaScript集成是否可用,您可以检查它是否可用const bool.fromEnvironment("dart.library.js")。这意味着该dart:js库可用。您可以使用条件导入来导入仅取决于dart:js可用时的库:

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

feature_js.dart仅当库可用时才会导入dart:js,否则将导入feature_default.dart. (这两个库应该足够相似,无论导入哪个库,导入库都是正确的)。

目前有许多库仅在浏览器中运行时可用:dart:js以及dart:html其他 DOM 库。同样,目前只有 VM 具有dart:clidart:ffi。这些库dart:mirror仅在某些VM 上可用(它不在 Flutter 中,也不在提前编译的代码中)。

当前的组合没有任何内在的东西。可以将 Dart 和 VM 编译为 WASM,然后在浏览器中运行它使其dart:js可用于集成。或者构建一个基于 VM 的应用程序,该应用程序嵌入浏览器视图并dart:html在 VM 上运行时仍可使用。

这就是为什么你应该测试你需要的库的可用性,而不是试图从中推断出一个“平台”。平台是开放式的,如果不假设只有两个平台,您的代码将是面向未来的(尽可能多的事情是可能的)。

对于整数,您只需通过对它们进行操作来检查它们是 64 位整数还是浮点数。例如bool integersAreFloats = (9007199254740992 == (9007199254740992 + 1));

于 2020-02-21T10:18:29.297 回答
0

我认为现在最好的方法是:https ://dart.dev/guides/libraries/create-library-packages#conditionally-importing-and-exporting-library-files (stackoverflow上的示例)。

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


我认为它是依赖于实现的黑客:

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

dartpad 上的示例:这里

表达式的第一部分依赖于dart2js(见#1#2)的当前实现。

表达式的第二部分依赖于 JS 规范:MDN

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

于 2020-02-21T07:54:23.407 回答