【问题标题】:Is there a way to check if the script is running in the dart vm or dart2js?有没有办法检查脚本是否在 dart vm 或 dart2js 中运行?
【发布时间】:2013-01-17 06:48:56
【问题描述】:

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

【问题讨论】:

  • 这是此功能的错误:code.google.com/p/dart/issues/detail?id=3357 不幸的是,现在没有标准的方法来执行此操作。这是一个已知问题。
  • 我认为 #3 对 Seth 发现的错误的评论是您问题 @Justin 的最佳答案。

标签: dart dart2js


【解决方案1】:

我不建议您尝试弄清楚您是在“虚拟机上”运行还是编译为 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";

仅当dart:js 库可用时才会导入feature_js.dart,否则将导入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));

【讨论】:

    【解决方案2】:

    我认为目前最好的方法是:https://dart.dev/guides/libraries/create-library-packages#conditionally-importing-and-exporting-library-filesstackoverflow 上的示例)。

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


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

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

    dartpad 上的示例:here

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

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

    console.log(1 &lt;&lt; 32); // 1

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        我一直在考虑这个问题,实际上,有一种方法可以使用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>
        

        【讨论】:

        • 太棒了!我没有想到这一点。我已更新您的答案以删除 Future,这是不必要的。可以直接返回js.scoped的结果。
        • 太棒了!我认为这需要未来,但我什至没有尝试过:)
        【解决方案6】:

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

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

        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 运行,浏览器内的输出都是相同的。

        【讨论】:

        • Options 类依赖于 dart:io 库,该库在 Dartium 和 Dart2js 中不可用。在 Dart 0.7.2 上导入失败。
        • 我猜这个项目在这个答案之后已经开始了。
        • 太糟糕了:(你的答案正是我想要的。有谁知道另一种方法来确定服务器端还是客户端?
        【解决方案7】:

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

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

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

        【讨论】:

        • 不确定我应该把它放在哪里,所以我写这个作为对我自己答案的评论。我们现在有 3 个答案,每个答案都回答一个不同的问题 :-) 我的答案是如何识别程序是在原生 Dart VM 中运行还是编译为 JS。首先,克里斯的回答说如何识别程序是在独立 Dart 中运行还是在浏览器中运行(可能是原生 Dart,可能编译为 JS)。第二个克里斯的回答说如何识别浏览器是否支持 Dart,但没有说明当前正在运行的程序(可以作为原生 Dart 运行,可以编译为 JS 运行)。有趣的是,这个 Dart 东西 :-)
        • 我认为最初的问题是模棱两可的:“脚本在 dart vm 或 dart2js 中运行” - OP 没有区分他的意思是 dart vm(服务器端)还是 dart vm(浏览器) , 与 dart2j2s。您的答案给出了浏览器 dart vm vs dart2js,我的第一个答案给出了服务器 dart vm vs dart2js(嗯,任何浏览器脚本)。为了完整起见,我添加了第二个答案(我添加了更新以进行澄清)。
        猜你喜欢
        • 2016-12-06
        • 2012-10-23
        • 2022-06-15
        • 2013-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-02
        相关资源
        最近更新 更多