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

时间:2013-02-01 21:10:15

标签: dart dart2js

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

7 个答案:

答案 0 :(得分:8)

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

也就是说,你可以使用很少的黑客。最简单的可能是利用Dart具有两个数字类型intdouble的事实,而JavaScript只有一个,这相当于Dart' s double,而dart2js还没有int的特殊实现。因此,Dart中identical(1, 1.0)false,VM正确实现,但在编译为JS时,它为true

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

答案 1 :(得分:7)

基于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());
}

答案 2 :(得分: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中运行。

答案 3 :(得分:3)

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

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

答案 4 :(得分:2)

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

如果在 Dartium 中运行,则以下应用会返回true,但如果在 Chrome Firefox 中运行,则会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;
  }
});

您的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>

答案 5 :(得分:1)

我不建议您尝试弄清楚您是在“在VM上运行”还是在编译为JavaScript。将来,运行Dart的方式可能会更多。

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

要检查JavaScript 集成是否可用,可以检查const bool.fromEnvironment("dart.library.js")是否为true。这意味着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:jsdart: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));

答案 6 :(得分: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上的示例:here

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

表达式的第二部分取决于JS规范:MDN

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