Ответ 1
Все ваши пулевые точки верны, за исключением:
современные интерпретаторы JS используют JIT для улучшения производительности кода и перевода его в байт-код
должен быть "... и перевести его в собственный код". SpiderMonkey (JS-движок в Firefox) долгое время работал в качестве интерпретатора байт-кода до текущей гонки гонок скорости JS.
На мостике Mozilla JS-to-DOM:
Объекты-хосты, как правило, реализуются на С++, хотя есть эксперимент по реализовать DOM в JS. Поэтому, когда веб-страница вызывает document.getElementById('foo')
, фактическая работа по извлечению элемента по его идентификатору выполняется в методе С++, как отметил hsivonen.
Конкретный способ вызова базовой реализации С++ зависит от API, а также изменяется со временем (обратите внимание, что я не участвую в разработке, поэтому может быть неправильно о некоторых деталях, здесь сообщение в блоге jst, которое фактически участвовало в создании большей части этого кода):
- На самом низком уровне каждый движок JS предоставляет API для определения объектов хоста. Например, браузер может вызывать JS_DefineFunctions (как показано в Руководство пользователя SpiderMonkey), чтобы сообщить движку, что всякий раз, когда script вызывает функцию с указанное имя, должен быть вызван обратный вызов C. То же самое для других аспектов объектов хоста (например, перечисление, свойство getters/seters и т.д.).
- Для основной функциональности ECMAScript и в некоторых сложных случаях DOM механизм JS/браузер использует эти API напрямую для определения объектов хоста и их поведения, но для этого требуется много общего шаблона кода, например. проверка типов параметров, преобразование их в соответствующие типы С++, обработку ошибок и т.д.
- По причинам, о которых я не буду говорить, скажем исторически, Mozilla сильно использовал XPCOM для многих своих объектов, включая большую часть DOM. Одной из особенностей XPCOM является ее привязка к JS под названием XPConnect. Помимо прочего, XPConnect может принимать определение интерфейса в IDL (например, nsIDOMDocument или, точнее, его скомпилированное представление), выставить объект с указанные свойства в script, а затем, когда script вызывает
getElementById
, выполните необходимые проверки/преобразования параметров и направьте вызов непосредственно на метод С++ (nsDocument::GetElementById(const nsAString& aId, nsIDOMElement** aReturn)
) - Работа XPConnect была довольно неэффективной: она регистрировала общие функции как обратные вызовы, которые должны выполняться, когда script обращается к объекту хоста, и эти общие функции выяснили, что им нужно делать в каждом конкретном случае динамически. Этот пост о быстрых файлах предлагает вам один пример.
- "Быстрые заглушки", упомянутые в предыдущей ссылке, - это способ оптимизации времени вызовов JS- > С++ путем торговли некоторым размером кода для него: вместо того, чтобы всегда использовать общие функции С++, которые знают, как совершать какие-либо вызовы, специализированные код автоматически генерируется во время сборки Firefox для предопределенного списка "горячих" вызовов.
- Позже JIT (tracemonkey в то время) учили генерировать код, вызывающий методы С++ как часть собственного кода, сгенерированного для "горячие" пути в JS. Я не уверен, как работают новые JIT (jaegermonkey) в этом отношении.
- С "paris bindings" объекты отображаются на веб-странице JS без какой-либо зависимости от XPConnect, вместо этого генерируя весь необходимый код АОкласса на основе WebIDL (вместо IDL XPCOM-эпохи). См. Также сообщения разработчиков, которые работали над этим: jst и khuey. Также см. Как реализуется веб-функция DOM?
Я неясен по деталям из трех последних точек, в частности, поэтому возьмите его с солью.
Самые последние улучшения перечислены в качестве зависимостей ошибка 622298, но я не следую им внимательно.