有没有办法检查脚本是在dart vm还是dart2js中运行?也许使用镜像API?
答案 0 :(得分:8)
据我所知,没有官方方式。目的是,出于所有实际目的,您不必知道您是在运行本机还是编译为JavaScript。
也就是说,你可以使用很少的黑客。最简单的可能是利用Dart具有两个数字类型int
和double
的事实,而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:js
和dart:html
以及其他DOM库。
同样,当前只有VM具有dart:cli
和dart: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