繁体   English   中英

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

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

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

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

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

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

基于在路径库(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());
}

另一种让脚本判断是在服务器端 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 运行,浏览器内的输出都是相同的。

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

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

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

如果在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;
  }
});

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

我不建议您尝试弄清楚您是在“在 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:jsdart:html和其他DOM库。 同样,目前只有 VM 有dart:clidart:ffi dart:mirror仅在某些VM 上可用(它不在 Flutter 中,也不在提前编译的代码中)。

目前的组合没有任何内在的东西。 这可能是可以通过编译飞镖和虚拟机WASM,然后在浏览器中运行它使dart:js可供整合。 或者构建一个基于 VM 的应用程序,该应用程序嵌入浏览器视图并使dart:html可用,同时仍在 VM 上运行。

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

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

我认为现在最好的方法是: 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

暂无
暂无

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

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