Как я могу определить, какой механизм javascript (v8 или JSC) используется во время выполнения в Android?

Более новые версии Android ( > 2.2) включают в себя механизм javascript v8, в то время как более старые версии имели только АО. Однако, согласно http://blogs.nitobi.com/joe/2011/01/14/android-your-js-engine-is-not-always-v8/, механизм javascript, используемый во время выполнения, по-видимому, зависит от переменной среды, присутствующей во время сборки (JS_ENGINE), а также аппаратные спецификации устройства:

# The default / alternative engine depends on the device class.
# On devices with a lot of memory (e.g. Passion/Sholes), the
# default is V8. On everything else, the only choice is JSC.

Мой вопрос заключается в следующем: есть ли способ определить, какой механизм javascript используется с веб-страницы, встроенного WebView или приложения?

Если ответ отрицательный, кто-нибудь знает, какой JS-движок используется эмулятором Android?


Причина, по которой я прошу об этом, связана с этой проблемой: http://code.google.com/p/android/issues/detail?id=12987

В принципе, может случиться, что модем javascript-to-java в АО нарушен на Android 2.3.X, и это влияет на приложение, которое я пытаюсь написать. Я вижу segfault где-то в глубине JNI на эмуляторе, но не на нескольких физических устройствах, которые я тестировал. Я пытаюсь определить, является ли это только эмулятор, только для АО или вообще что-то совсем другое.

Ответ 1

Я думаю, что лучший вопрос: почему тебя это волнует? Вы попадаете в ловушку "обнаружения браузеров", в которую многие попали в конце 90-х - начале 00-х годов. Однако с тех пор мы узнали, что это обнаружение функций, что является более полезным подходом, не в последнюю очередь потому, что функции, поддерживаемые в данном браузере, были (в основном) движущейся целью. Теперь есть код, работающий на IE9 с его значительно улучшенной поддержкой DOM и JavaScript, который не использует эти функции, потому что он выполняет обнаружение браузера и использует методы IE6.

Поэтому вместо того, чтобы беспокоиться о V8 vs. JSC, просто беспокойтесь о нужных вам функциях. Я ничего не знаю о JSC, но, например, предположим, что у него нет метода forEach для массивов, который есть в V8 (часть стандарта ECMAScript 5-е издание). Вместо того, чтобы бросать большой рычаг "V8 vs. JSC", вы должны сделать:

if (typeof Array.prototype.forEach === "function") {
    // Code that expects 'forEach'
}
else {
    // Code that falls back
}

(Ваш "резервный код" может добавить forEach к прототипу, или, возможно, этот тест находится в вашей собственной функции итератора, и вы хотите знать, следует ли отложить его до собственной реализации или предоставить свою собственную.)

И аналогично для других функций, которые вы хотите использовать, которые могут присутствовать или не присутствовать.


Но если вам действительно нужно обнаружить V8 против JSC (и из вашего комментария кажется, что вы можете), эта страница, кажется, демонстрирует способ сделать это, хотя и выглядит ужасно хрупким. Вот моя слегка отредактированная версия (не в последнюю очередь заменить window.devicePixelRatio тестом для WebkitAppearance - первый дает ложные срабатывания по крайней мере в некоторых других браузерах [например, Firefox, который использует Gecko, а не WebKit]):

var v8string = 'function%20javaEnabled%28%29%20%7B%20%5Bnative%20code%5D%20%7D';

if ('WebkitAppearance' in document.documentElement.style) { //If (probably) WebKit browser
    if (escape(navigator.javaEnabled.toString()) === v8string) {
        console.log('V8 detected');
    } else {
        console.log('JSC detected');
    }
} else {
    console.log("Not a WebKit browser");
}

Ответ 2

Хотя вышеприведенный ответ указывает на лучшие методы, я думал, что хочу указать другой способ сделать это изнутри собственной библиотеки.

void *dlWebCoreHandle = dlopen("libwebcore.so", RTLD_NOW);
void *v8GetVersion = dlsym(dlWebCoreHandle, "_ZN2v82V810GetVersionEv");
if (v8GetVersion == NULL) {
    /* does not appear to be V8 */
} ... etc.

Экспортированные символы, к сожалению, искалечены, поэтому нет гарантии 100%, что компилятор, используемый вашим производителем прошивки, искал символ таким же образом (используйте nm --defined-only libwebcore.so -g в библиотеке с символами). Можно было бы открыть эту функцию через JNI и проверить изнутри кода Java.

Библиотека libwebcore.so также перечисляет V8_Fatal как один из символов, который не поддается манипулированию.

АО будет иметь некоторые другие экспортированные символы, которые вы можете проверить изнутри собственной библиотеки. Если они не существуют, вы можете отказаться от других методов.

Ответ 3

var s = '';
for (x in {
    3: 3,
    1: 1
  }) {
  s += x
}
if (s === '31') {
  alert('JSC');
} else {
  alert('V8');
}