Есть ли способ проверить, работает ли скрипт в dart vm или dart2js?
Есть ли способ проверить, работает ли скрипт в dart vm или dart2js? Может быть, с помощью зеркал API?
5 ответов
Официального пути, насколько я знаю, нет. Намерение состоит в том, что для всех практических целей вам не нужно знать, работаете ли вы на нативном языке или скомпилированы для JavaScript.
Тем не менее, есть несколько хаков, которые вы можете использовать. Самым простым, вероятно, является использование факта, что у Дарт есть два числовых типа: int
а также double
в то время как JavaScript имеет только один, что эквивалентно Dart's double
и dart2js не имеет специальной реализации int
только пока. Следовательно, identical(1, 1.0)
является false
в Dart, и виртуальная машина реализует это правильно, но при компиляции в JS, это true
,
Обратите внимание, что вы должны подумать, прежде чем использовать такой взлом. В большинстве случаев вам не нужно этого делать, просто напишите 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());
}
Другой очень хакерский способ для скрипта сказать, работает ли на виртуальной стороне сервера против клиентской стороны, это использовать 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 browser или как JS.
Поскольку dart.js преобразует сценарии.dart в.dart.js, это работает:
bool _isDart() => document.getElementsByTagName("script").where((s) => s.src.endsWith(".dart.js")).isEmpty;
Я думал об этом, и на самом деле, есть способ узнать, есть ли в браузере поддержка Dart (что почти то же самое), используя navigator.webkitStartDart
, Это то, что файл dart.js, который загружает Dart, использует при определении, поддерживает ли браузер dart изначально, поэтому мы можем использовать JavaScript-взаимодействие, чтобы сделать то же самое.
Следующее приложение возвращает true
если работает в Dartium, но false
если работает в Chrome или Firefox:
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. Вы могли бы запустить приложение только в javascript, если бы вы явно связали только версию вашего приложения.dart.js и удалили ссылку на скрипт dart.js.
т.е. это:
<!-- 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>
Я бы не рекомендовал пытаться выяснить, работаете ли вы "на виртуальной машине" или скомпилированы на 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. Точно так же только виртуальная машина в настоящее время имеетdart:cli
а также dart:ffi
. Библиотекиdart:mirror
доступен только на некоторых виртуальных машинах (его нет во Flutter и в заранее скомпилированном коде).
В нынешних комбинациях нет ничего присущего. Можно скомпилировать Dart и виртуальную машину в WASM, а затем запустить его в браузере и сделатьdart:js
доступны для интеграции. Или создайте приложение на основе виртуальной машины, в которое встроено представление браузера, и сделайтеdart:html
доступно при работе на виртуальной машине.
Вот почему вы должны проверять наличие необходимой библиотеки, а не пытаться вывести из нее "платформу". Платформы открыты, и ваш код будет ориентирован на будущее (насколько это возможно), если он не предполагает, что существует только две платформы.
Для целых чисел вам просто нужно будет проверить, являются ли они 64-битными целыми числами или числами с плавающей запятой, выполнив над ними операции. Напримерbool integersAreFloats = (9007199254740992 == (9007199254740992 + 1));
Я думаю, что сейчас лучший способ: https://dart.dev/guides/libraries/create-library-packages (пример в stackru).
Спецификация: https://github.com/munificent/dep-interface-libraries/blob/master/Proposal.md
То, что я бы назвал взломом, зависящим от реализации:
const _isJs = (1 << 32) == 0 || (1 << 32) == 1;
Пример на дартпаде: здесь.
Первая часть выражения основана на текущей реализации dart2js
(см. №1, №2).
Вторая часть выражения основана на спецификации JS: MDN.
console.log(1 << 32); // 1