[Перевод] Раскрываем тему WebAssembly с Бренданом Айком
Представлено интервью Брендана Айка, сделанного 31 марта 2017 года Оно — на 1.5 часа, но 2-я половина — про проект Brave, не относится к компиляторам JS, поэтому опущена), создателя Javascript и журналистов из SE Daily (у них убедительно поясняется, почему полезно слушать такие подкасты — на сайте есть много интересного). Мы сами знаем, что рассказов о сложных идеях на уровне «слушания в автобусе» — очень мало. Текст — понятный, конечно, для программистов. Интервьюировал Caleb Meredith (CM), а редактор сайта Jeff Meyerson (JM) в основном, рекламу вставлял (её перевод опущен).
Айка всегда было крайне трудно переводить из-за некоторых оборотов речи, поэтому есть сложные места, например, высказывания про Python, к достаточно вольному переводу которых прошу отнестись с пониманием и предлагать в таких местах варианты. Но не взяться за него, за случай, когда он говорит для людей почти (часто путая их с программистами), а не для учёных, было бы непростительно:))
[0:02:53.9] CM: Я здесь [в чате?] — с Бренданом Айком, создателем языка программирования JavaScript и исполнительным директором Brave Software. Брендан, добро пожаловать в Software Engineering Daily!
[0:03:01.0] Brendan Eich (BE): Привет, спасибо, что пригласил меня.
[0:03:02.0] CM: Давайте начнём рзговор с WebAssembly. Самый низкоуровневый человекочитаемый формат команд, который мы предоставляем машине — это язык ассемблера, формат которого зависит от вычислительной машины. JavaScript — язык программирования гораздо более высокого уровня, но он временами описывается как язык ассемблера для Web. Недавно W3C Community Group, к которой вы, Брендан, подключились, работает над спецификацией WebAssembly. Почему полезен язык ассемблера для Web, и почему в качестве языка WebAssembly недостаточно просто JavaScript?
Как появился и чем стал Javascript?
[0:03:37.5] BE: Давайте, прежде всего, я начну с того, как JavaScript появился, чтобы начать играть современную роль. JavaScript я делал в спешке, в мае 1995 года в течение 10 дней, в Netscape, и он был частично ориентирован на сходство с Java, из-за внутренней политики компании. В результате, JavaScript, оттого что он загружается из HTML и может быть написан кем угодно, начиная с небольших скриптов и заканчивая большими программами, за последние 22 года занял место побежденной Java на стороне клиента в Интернете.
JavaScript был срочной работой. Конструкции скелета, заимствованные из других языков, спешно собирались мной в теле Франкенштейна. При этом, он вышел достаточно рано не только из-за политики Netscape, но и из-за привязки Microsoft Windows к Internet Explorer и связи его с Netscape; в итоге, это привело судебному иску в США к Microsoft за злоупотребление монополией… Мы знали, что нам нужно идти быстро. У нас были кое-какие технологии в Netscape 2, такие как JavaScript, ориентированный на Java, появились новшества в HTML того времени в Netscape. Мы понимали, что если сделаем их достаточно рано, они станут частью веб-стандартов.
В самом деле, JavaScript был одной из немногих вещей, которые выжили и пережили то время. Таким образом, эта среда выполнения, не требующая инсталляции, доступна почти везде, она находится на мобильных устройствах, встроена в приложения по технологии вебстраниц и, конечно, работает в браузерах, которые, по-прежнему, экономически важны как для мобильных устройств, так и для настольных компьютеров, там и там.
Представьте: будучи разработчиком ПО в 90-е годы вы могли, возможно, программировать для Windows PC. Вы должны были использовать Microsoft Visual C++. Если нужна была база данных, использовалась Rogue Wave [0:05:23.4] или что-то подобное. Потом вы смОтрите в Интернет, и с удивлением видите, что там никто этого не делает. Все делают веб-сайты, не требующие инсталляции.
Разработчики игр всё ещё использовали C++, потому что им нужно было добраться до «железа». Справедливости ради, я преувеличил, когда сказал, что никто этого не делает. Есть ещё другие «толстые» приложения, которых становилось всё меньше, потому что браузер поглотил большинство из них и превратил в серверные и базируемые на серверах модели бизнеса в ПО.
Тем не менее, игры и ваши другие хардкорные, привязанные к «железу» приложения, если они были вынуждены использовать JavaScript — то имели проблемы, потому что JavaScript, помимо того, что он ускоренно развивался, последние 20 лет улучшались стандарты. Стало лучше. Он стал больше. Возможности возросли и сгладили некоторые неудобные места, и всё пошло хорошо, кроме сборщика мусора. Он имеет неопределённость в производительности. Предсказуемость производительности — это один из способов сказать, где вы можете рассчитать что-то на 60 кадров в секунду для игры; и вдруг — у вас заканчивается реальное время из-за сбора мусора, который должен произойти, чтобы вернуть занятую память. Или вы сделали новейший движок, и ваша программа изменила представление о типах, которые она поддерживала в интерпретаторе Javascript.
Теперь весь код должен перекомпилироваться. Это может занять много реального времени, и вы не уложитесь в ваш 162-й кадр анимации, вас вытолкнет из этого условного предела в реальном времени. Затем игра становится медленнее, отстаёт, или анимация не обновляется должным образом. Это серёзный конкурентный недостаток для игр, поэтому разработчики предпочитают оставаться на C или C++, поэтому им нравится работать рядом с «железом».
Компилируемое подмножество Javascript asm.js
И вот что мы обнаружили в результате того, что JavaScript стал настолько повсеместным и быстрым, не считая этих непредсказуемых провалов производительности — мы обнаружили, что если вы используете подмножество JavaScript — это было в Mozilla, начиная с 2012 года — если вы сосредоточитесь только на частях JavaScript, которые выглядели как язык программирования C, наподобие функций редактирования для WebGL, и использовалась память в плоском большом непрерывном массиве под названием Typed Arrays — тогда, если используется подмножество JavaScript в этой модели памяти, можно работать почти так же быстро, как в C или C++. Можно выполнять программу так же, как при любом безопасном подходе к подобным низкоуровневым языкам. В этом деле были предшественники, начиная с 90-х годов; никто не слышал о них, особенно о мобильном нативном клиенте, работающем в Google, который был в то время, в 2012 году.
Мы разработали в Mozilla это подмножество JavaScript, назвали его asm.js в честь ассемблера, сделали для него систему типов — это сделал Дейв Герман. Люк Вагнер (Luke Wagner) из Mozilla, который всё ещё там, сделал потрясающий компилятор для подмножества JavaScript с проверкой типов, такой, что за время парсинга определялось, из подмножества ли asm.js этот код, и можно было очень быстро генерировать действительно хороший машинный код, с безопасным доступом к памяти. Это было важнейшим требованием.
Когда мы работали с Mozilla, то использовали в том числе компилятор, разработанный Алон Закай. Он написал свой Emscripten как компилятор C или C++ на основе LLVM, который генерирует JavaScript. Сказать по правде, asm.js был формализован с типизацией Дэйвом Херманом, в одиночку на самом деле — помнится, он это говорил в 2011 году на JSConf EU. Алон уже разработал интуитивное понимание подмножества в системе типов для ассемблерного JavaScript путём создания компилятора Emscripten и создания его JavaScript для быстрого перехода к JavaScript с типизированными массивами в плоской области памяти для обычных переменных в куче (heap) вместе с глобальными (куча — термин из теории компиляторов).
Стек JavaScript использовался для переменных стека в C. Трансляция была очень аккуратной для оптимизирующих компиляторов, и только он один помог нам понять, что такое asm.js. Опять же, были предшественники. В Adobe Labs был кто-то, кто создал систему — кажется, что она называлась Alchemy — которая использовала более раннюю версию прошивки компилятора LLVM, чтобы делать то же, что ActionScript 3 в Flash Player. Мы были в курсе этой работы, и именно в этой школе мы изучали безопасные методы выполнения собственного кода.
Тогда мы осознали, что asm.js может быть просто подмножеством JavaScript с расширением Typed Array. Он стал стандартизированным, поскольку WebGL, наконец, попал во все LSS, включая iOS. Мы поняли: «Это, вероятно, будет новая безопасная переносимая среда выполнения нативного кода. Это убьёт портативный Native Client (PNaCl) в Google». Планктон в Google (the pinochle people) не хотел признавать этого, но мы действительно это сделали. Люк Вагнер написал свой быстрый компилятор. Alon Zakai продолжал работать над своим внешним интерфейсом Emscripten, который сгенерировал код JavaScript. Дэйв Херман убедился, что система типов «задышала».
Хождение в игровой мир
К концу 2012 года мы связались с Epic Games, разработчиком Unreal Engine, посетили небольшую группу. Менее чем за неделю, в течение четырех дней, на пятый, когда они отдыхали, Unreal Engine 3 был перенесён в веб путем кросс-компиляции своей базы кода C++, многомиллионной базы строк кода в программы JavaScript и asm.js. Надо было сделать нечто похожее на их аудио API-интерфейсы для веб-аудиоинтерфейса, и у них были адаптеры для OpenAL и других аудио-библиотек, что было несложно.
Они уже использовали OpenGL для оптимизации графического интерфейса мобильного GPU. WebGL основан на OpenGL, так что это была быстрая адаптация. Они сделали правку бага Emscripten или две, они должны были исправить JIT-компиляцию на бекенде, которая работает на всём модуле asm.js, поэтому, в каком-то смысле, сделанное опередило время. В те выходные у них был Unreal Engine 3 с полной частотой кадров в прототипной версии Firefox. Тим Суини, основатель Epic, был ошеломлён. Он сказал: «Я думал, что на это уйдут годы. И вдруг — всё готово!».
С того времени мы в Mozilla продолжили работать над своим движком, убедившись, что он работает для других игр. Мы работали с Unity-разработчиками. Думаю, они объявили об этом в следующем году. Мы дали знать Microsoft — они заинтересовались, поэтому я предложил поговорить в Microsoft с инженерами. После этого я встретился с Андерсом Хейлсбергом, создателем .NET и C#, и Стивом Лукко, когда тот возглавлял группу разработчиков JavaScript, команду ChakraCore в Microsoft. Они очень заинтересовались асмом и подключились к проекту на той встрече, и довольно скоро объявили об этом.
Со временем, примерно последние три года, asm.js стали той средой, которую с неизбежностью можно было сделать сверхбыстрой. Среда выполнения, которая у вас уже есть — браузер, вместо того, чтобы пытаться добавить другую среду выполнения, — это не только переносимый собственный клиент. Хотели сделать на Dart, но это в значительной степени не удалось даже у Chrome. Очень сложно добавить вторую среду после JavaScript. Я могу понять, почему. Даже Flash, который был второй средой в качестве плагина, замедлял своё выполнение. Стив Джобс запретил его в iOS, и поэтому, я думаю, он был отозван и в Android примерно в 2011 году.
В распоряжении не было ничего другого, кроме браузера, если нужно было иметь быструю оптимизацию для языков. Единственная проблема была в том, что все говорили, что понимают только JavaScript. Теперь был ещё asm.js — подмножество, которое могло использоваться как целевой язык для компиляторов. За последние шесть лет люди уже строили сотни компиляторов из разных языков, таких как Python, Java или Ruby — в JavaScript. Это была расхожая тема на конференциях. Люди знали, что Emscripten является одним из многих среди большого набора компиляторов.
Над некоторыми из этих компиляторов не приходилось усиленно трудиться, чтобы оптимизировать, потому что они брали язык, который был не особо быстрым и переводили его на JavaScript. Они часто переводили языки, которые имели сходный с JavaScript семантический уровень и стиль, поэтому компилировать было легко. Это стало известно как transpiling (кросс-компиляция). Это сделано даже для наших будущих версий JavaScript и для предыдущих. Emscripten был тем, кто довёл эти вещи до машинного кода и стал использоваться разработчиками игр. Особенно, когда Unity 5 получила свою «цепочку инструментов» (tool chain), когда можно взять любую игру Unity, ткнуть кнопку, и рождалось то, что у них называется «WebGL-портом», что на самом деле означало asm.js, WebGL, веб-аудио, которые можно встроить В HTML. Просто подумайте, что у вас может быть игра для Xbox, вы ей делаете вторую жизнь в Интернете, помещаете в магазин, где её можно попробовать, прежде чем купить, просто загрузив в свой браузер. Это — большой успех.
Как сформировалась концепция WebAssembly?
Было ясно, что JavaScript может быть виртуальной машиной, или виртуальная машина для JavaScript может быть виртуальной машиной для мобильных языков. JavaScript по-прежнему загружается в виде исходного кода, даже в виде кода asm.js. Когда я разрабатывал JavaScript, я не выбирал кратчайшее ключевое слово для function, это восемь букв. Они — всего лишь затраты на разбор JavaScript. Даже если вы сжимаете его при транспортировке и передаете сжатие транспортного уровня, что экономит пропускную способность сети, экономит стоимость данных, а потом всё равно придётся распаковать её в памяти на целевом устройстве, а затем проанализировать.
Оказывается, именно поэтому есть портированная Unity-игра или даже игры, в которые можно играть уже сейчас. Например игра «Ski Safari» обрела вторую жизнь на Facebook в виде скомпилированной игры asm.js; можно пойти туда и поиграть. Это очень весело. Первоначально это была мобильная игра. По-моему, она использует Unity в варианте 2D. У неё есть третье измерение, она — забавная скоростная игра катания на лыжах. Она работает на полной частоте кадров, но во время загрузки немного тормозит.
Он работает лучше всего в Firefox из-за большой работы Люка Вагнера. Команда VA из Google не очень хотела делать ту же полную компиляцию программ, что и Люк. Люди Microsoft сделали. Они фактически взяли код Люка и изменили стиль, но сохранили авторское право за Mozilla, и его нужно было лицензировать; лицензию они использовать могли, поэтому вы, действительно, найдёте код в ChakraCore на GitHub. Этот движок теперь в Edge и в IE, вы найдете версию компилятора OdinMonkey от Люка для asm.js. Вот почему некоторые браузеры лучше других в «Ski Safari», но время загрузки — головная боль.
Если игры сменяют уровни — там такая же проблема [скорость загрузки]. Ещё до моего ухода из Mozilla в 2014 году, мы думали: «Как это исправить? Может быть, придумаем бинарный синтаксис, который имеет смысл для этого подмножества asm.js?». Это блестяще — WebAssembly появился на наших глазах. Как только к нам подключилась Microsoft, в какой-то момент казалось, что всё могло быть закончено в начале 2015 года. Я не уверен, когда точно были эти слухи. В Google была «схватка» между командой VA и командой Portable Native Client, «кровь лилась рекой». Затем, в результате, команда VA выиграла. Это было, как я сказал, ясно всем. Вы не займётесь вторым безопасным исполняемым кодом. Думали — скорее, давайте возьмём движок JavaScript и дадим ему второй язык ввода — WebAssembly.
Apple тоже — Apple никогда не объявляет свои ранние намерения, им всегда хочется контролировать свою историю на WWDC —, но Apple попала на борт. Я могу сказать это сейчас, задним числом. Тогда я не хотел этого раскрывать. Люди из Hacker News поторапливали: теперь, говорят, у вас есть все четыре производителя браузеров с общей идеей WebAssembly. Некоторые из них даже говорили: «Да, asm.js — это просто подмножество JavaScript. Мы быстро достигнем результатов. Нам даже не нужно распознавать его как таковой, чтобы он был быстрым. Вы дадите нам C-подобный низкоуровневый JavaScript, который использует большой типизированный массив памяти. Мы будем писать быстрый код. Не волнуйтесь об этом.»
Asm.js стал наподобие такого мальчика для битья на тему «почему у вас нет правильного двоичного синтаксиса?» И это — всего лишь один довод, убедительный аргумент в пользу WebAssembly. Как только все производители браузеров собрались в команду, WebAssembly стал продвигаться как проект сообщества W3C, как вы упомянули, и, конечно, на GitHub, где находятся код и проектные спецификации.
Что такое WebAssembly?
[0:19:52.7] CM: Объясните на пальцах — что такое WebAssembly? Как он выглядит? Вы открываете файл WebAssembly, что там?
[0:19:57.8] BE: Надеюсь, я смогу рассказать — почему это полезно и почему его стали делать. Полезно — потому что он загружается быстрее и даёт вам низкоуровневую модель памяти и инструкции ради производительности. Вы можете сделать 60-кадровый шутер (стрелялку) от первого лица.
Что это значит? Если вы думаете о JavaScript, на секунду, как о языке C, его грамматике выражений, то Си имеет все побитовые логические и сдвиговые операторы, у него есть несколько перепутанных приоритетов из-за истории языка C, и он имеет арифметические операторы. JavaScript не имеет целочисленных типов явно, но побитовыми операторами можно привести число к целочисленному 32-битовому значению, убрать знак у целых чисел со знаком во временных рядах, в оценке выражения. Это — ключ к asm.js. Так, asm.js может иметь целые числа, которые быстрее проходят через блок с плавающей запятой, не превращаясь в числа с двойной точностью IEEE 754, из-за которых все любят обвинять и JavaScript, и Java. Они были проблемой с типами JavaScript, поскольку у него только этот тип числа, поэтому люди иногда хотят использовать другой тип —, а его просто ещё нет. Мы работаем над исправлением ситуации.
В любом языке числа имеют двойную двоичную точность IEEE 754. Если вы добавите 0.1, плюс 0.2, и с полной точностью распечатаете результаты, обнаружится, что это не 0.3, а 0.300000000000000008. Это потому, что вы на самом деле делаете математику в двоично-десятичном значении, и вам нужна дополнительная точность, чтобы вычислить, как округлять, но округление выполняется с ошибкой из-за конечной точности, и в итоге получается 8 в конце после многих Нулей. Это IEEE 754.
JavaScript-операторы побитового логического сдвига дают возможность обрабатывать 32-битные знаковые и беззнаковые целые числа, если вы используете эти операторы, как если бы они были типизированными. Для компилятора Emscripten это легко сделать, поэтому это часть волшебства, созданного Алоном Закаи, которое привело к формализованному asm.js, чтобы сделать очень быструю целочисленную математику в подмножестве JavaScript.
WebAssembly просто даёт лучший синтаксис, чем написание инфиксных операторов в JavaScript. Я думаю, что они работают со своего рода небольшим машинным языком стека для части грамматики выражений, и они могут иметь синтаксис битов. Это очень эффективно для парсинга и пересылок.
Для более крупных структур программ есть управляющие структуры в программировании вида if-then-else, while-циклы и другие виды циклов. Очевидно, что JavaScript такие имеет. У WebAssembly они тоже есть в структурированной форме. Когда была разработана Java, она компилировалась в байт-код, а затем код отправлялся по сети. Проблема была в том, что можно было заставить какой-то ненадежный модуль послать вам плохие Java-байт-коды. Нужно было запускать так называемый верификатор.
После весьма долгого времени, когда отсутствовала информации о типе, они, наконец, сообщили, что проверка может иметь патологическое (разрушительное) поведение. Помню, мой друг Майкл Франц, профессор в UC Irvine, показал, что у них есть алгоритм порядка 4-й степени сложности, если вы отправите этот сложный тест, что-то наподобие байт-кода верификатора, это займёт неожиданно много времени. И на верификаторы можно совершать атаки типа отказа в обслуживании (DoS).
С WebAssembly мы узнали, что двоичный синтаксис WebAssembly, несмотря на то, что это — сочетание префикса и постфикса для части выражения, машинного кода SAC — это своего рода самопроверка в том смысле, что если вы его проанализируете, то это не сделает что-нибудь сумасшедшее [по затратам ресурсов]. Вы не проверяете код на предмет мошенничества. Поскольку верификатор пытался проверить, что это не вредоносный байт-код, который мог спутать тип в if-then-else-конструкции, вы отправляете значение через память, через переменную одного типа, и тут возможна атака, используя bad type pond или другой тип, а затем после if-then-else значения используются, но с неправильным предположением, что имеют только один тип.
Эта проверка важна для безопасности. С помощью WebAssembly у вас нет такой неприятной проблемы анализа потока управления, которую байт-код Java имел очень долгое время, где вы можете иметь путаницу типов, если не будете тщательно анализировать операции спагетти go-to, которые возможны в байт-коде Java.
Насколько я знаю, в WebAssembly нет никакого свободного go-to. Они немного изменили это, но я думаю, что это всё ещё структурированный код в старом смысле структурированного программирования 70-х годов. Не иметь go-to — считается вредным, т.к. с ним получается более сжатый код. Он загружается быстрее, разбирается быстрее, потребляет меньше энергии. И тогда игры, в которые вы играете, такие как Ski Safari, могут стать намного быстрее при компиляции в WebAssembly вместо asm.js.
Какие программы сейчас можно портировать на Javascript?
[0:24:37.8] CM: Это хорошо подходит к следующему вопросу. Вы много говорили о компьютерных играх. Честно говоря, большинство презентаций WebAssembly также демонстрируют некоторую видеоигру, запускаемую на C++ и скомпилированную с помощью WebAssembly. Каковы некоторые случаи для WebAssembly, помимо включения в игру насыщенных графикой видеоигр, или это единственный прецедент, и этот случай использования просто невероятно привлекателен с ростом WebVR или по каким-то другим причинам?
[0:25:05.1] BE: Думаю, что описанный пример — хороший момент, но это не единственный случай использования сложных конструкций (long shot). Во-первых, игры очень сложны. Я ходил на конференцию разработчиков игр. Помнится, слышал от одного из руководителей Valve — он подчеркнул, что игры заняли место практических системных исследований в операционных системах. Они вошли в GPU, когда еще можно было управлять GPU не вредоносным кодом, пока мы находимся в песочнице [и имеем] разные потоки исполнения. Они используют многоядерность. Они перешли к блокам векторной обработки, так называемым модулям SIMD, единым командам с несколькими единицами данных, которые сейчас используются почти во всех аппаратно-программных модулях компании.
Игры — действительно, использовали всё; Они используют потоки. Они занимались DSP. Они занимаются физикой — это не рендеринг, но всё равно, требуется много вычислений. Они используют функции ИИ — про ИИ теперь говорят на каждом углу.
WebAssembly хорош для всех этих случаев. Он хорош для машинного обучения, алгоритмов на вашем устройстве, что бывает весьма практично. Им не нужно быть в облаке и использовать суперкомпьютеры. Они могут иногда очень эффективно выполнять более простые алгоритмы на ваших локальных данных. Это было интересно и для проекта Brave — люди нуждаются в AI (ИИ) не только для игр, но и для всех вещей сейчас, для помощи и утилит, для озвучивания текстов и наоборот.
WebAssembly подходит для всех этих интенсивных вычислений. Игры великолепны, потому что они забавны для демо и для их зрителей. Как я уже говорил, они действительно задействуют всё это вместе. Единственное — мы не умеем делать пикселизацию, это — динамическая загруженность JavaScript. Люди думают: «О, WebAssembly! Это значит, что можно избавиться от JavaScript!». Ну, пока нет. WebAssembly запускается в виде JS с фиксированным объемом памяти для C и C++, и в планах есть сборка мусора, что должно быть сделано в интеграции со сборщиком мусора единственной рабочей среды — движка JavaScript.
В противном случае, вы столкнётесь с проблемой коллектора циклов гостевого хоста, где в любое время, когда у вас есть две системы сбора мусора, которые могут вместе формировать ссылки в кучах, они смогут формировать циклические ссылки. Если сборщики мусора не имеют специальных протоколов для общения друг с другом, или нет главного исполнителя (supercaller), эти циклы становятся неприемлемыми. Это — аргумент в пользу того, что имеет .NET, который является многоязычным, полиглотом, виртуальной машиной с одним менеджером памяти. Это — то, во что JavaScript вырастает сейчас, улучшается поддержка многоязычности для сборки.
WebAssembly в текущем минимально жизнеспособном продукте (MVP, minimum viable product) действительно, отражает то, что является большим достижением для C и C++ и, возможно, некоторых других языков, которые могут соответствовать модели [сборки мусора]. Со временем нужно добавить сборку мусора в этом консолидированном виде, чтобы каждый использовал GC (Garbage Collector) и Java Search Engine, не запуская гостевой GC и/или код сборки. Вы, конечно, можете это сделать когда угодно, но если когда-нибудь создадите ссылки, у вас будут неустранимые циклы.
Хочется, чтобы динамические языки быстро, динамически выполняли метод, который может быть, а может не быть в объекте. Как и в случае с движком JavaScript на Python, иногда нет системы типов, нет стабильного представления в коде, что означает тип объекта, и вы вызываете его метод. Вы всё время вызываете один и тот же метод в одной и той же конфигурации вызова. Именно так тестируются JIT-компиляторы. Тем не менее, WebAssembly пока не имеет соответствующих инструкций. Даже гуру JavaVM вызывают методы динамически, если знают, что делает инструкция в байт-коде Java.
Думаю, это можно поставить в планы (roadmap), и это будет, но в конце. Вначале нужны несколько вещей, чтобы действительно поддерживать действительно динамические нетипизированные языки, а также статически типизированные языки: C, C++, Rust от Mozilla и других компаний, которые, как мне кажется, будут хорошо работать с WebAssembly в качестве целевого языка компилятора сейчас или в ближайшем будущем. Это значит, что нельзя быстро избавиться от JavaScript. На самом деле, JS будет таким обязательным надолго. Нет никакого определенного графика, когда вы сможете сказать: «О, да. К четвертому кварталу 2018 года мы освободимся от JavaScript и будем иметь механизм WebAssembly, и все JavaScript в Web могут быть скомпилированы браузером в WebAssembly.» Это — сомнительный план. Такого плана пока нет. Мы будем развиваться в течение многих лет и думать, что это может случиться, но когда-то потом, за горизонтом.
Все кошки попадут в рай?
[0:29:30.7] CM: Верно, что код будет компилироваться в WebAssembly, который со временем получит доступ ко всем API-интерфейсам браузера, к которым имеет доступ JavaScript? И однажды вы сможете написать целое приложение на языке, отличном от JavaScript, который компилируется в WebAssembly?
[0:29:44.8] BE: думаю, что, в принципе, ответ — да. API-интерфейсы, к которым может обращаться JavaScript, должны быть доступны через WebAssembly. Вы можете сделать это любым способом, так как WebAssembly предназначен для работы в модуле, входящем в JavaScript, в ECMAScript 2015 или так называемый ES6. Мы по-прежнему имеем то, что модули работают в браузерах как отдельные спецификации рабочей группы. Это требует времени, но идея WebAssembly является модульной. Это означает, что у вас будет нечто, … как я уже говорил, у вас может быть приложение JavaScript, которое начнёт использовать модуль WebAssembly для машинного обучения или для физического движка, или временами — для интенсивных численных расчётов. Код алгоритмов для WebAssembly можно сразу писать на C или C++.
У вас будет модель «mix-and-match» для JavaScript в WebAssembly, поэтому всегда можно отсортировать прокси-API-вызовы, которые JavaScript может сделать с кодом WebAssembly. В группе разработки WebAssembly есть хорошие мозги, которое собраны от четырёх поставщиков браузеров и понимают, как сделать вызовы API легко, безопасно и эффективно через WebAssembly.
Я думаю, что общий ответ — да, вы получите все эти API-интерфейсы, и, конечно же, вы можете пожелать, чтобы игры были кросс-компилированы и полностью переведены на целевой язык. Сегодня это может быть asm.js, потому что WebAssemblies были только что внедрены в некоторые топовые браузеры.
Через год [будут скомпилированы] такие игры, как Ski Safari на Facebook, Heroes of Paragon. Это те игры, которые я играл в Facebook, скомпилированные в asm.js, они могут быть скомпилированы в WebAssembly. Когда они, в значительной степени, цельные программы — вы сможете делать модули, смешивать и объединять, делая единую программу.
По Сеньке ли шапка?
[0:31:31.9] CM: В мире, где разработчик может написать всю программу на любом языке, который компилируется в WebAssembly, язык JavaScript должен показать, что он на самом деле — хороший язык программирования. В конце концов, разработчик может написать своё приложение в Rust или Haskell или на неизвестном будущем языке, без связи с JavaScript. Как создатель JavaScript, я хотел бы спросить: почему кто-то сознательно решил написать своё веб-приложение на JavaScript? Есть ли какая-то заслуга JavaScript, помимо того факта, что это — часть эволюционной системы, и у неё есть доля, которую она имеет сегодня, потому что он — единственный динамический язык в браузере?
[0:32:09.4] BE: думаю, что мнения различаются по языкам. Вы заходите на Hacker News и по-прежнему видите, как люди тратят время на споры [о языках] [0:32:15.4 globs].
[0:32:16.9] CM: Я действительно хочу услышать ваше мнение.
[0:32:19.9] BE: Я выскажу его. На взгляд Пола Грэма — люди просто влюбляются в один язык, который они изучили первым, или они думают, что он лучше, и они безотчётно это утверждают. Я не собираюсь делать это для JavaScript. Я использую много языков. У JavaScript есть достоинства помимо того, что он вездесущ, благодаря достаточно раннему появлению из-за той грязной работы в мае 1995 года, что я делал, но JavaScript развился, и развитие было важно.
Вы слышите, в понедельник утром, сидя в рабочем кресле, протесты в год 22-летия: «О, это мог быть Питон». Нет, этого не могло быть, потому что Python был заморожен, погас, как летающая искорка в 1995 году. Python тогда был версии 1.3. Вы бы его не хотели.
Кроме того, Python имел небезопасный внешний интерфейс. Он по-прежнему такой же. Вы не хотели бы, чтоб он находился в Интернете, потому что это было бы подмножество Python. Затем, если он был заморожен, а внедрение JavaScript было бы слишком долгим, и прошли бы все процессы стандартизации [Пайтона], но затем у нас должен быть Firefox, чтобы перезапустить рынок браузеров; У вас была бы эволюция Python по другой линии. Это был бы Web Python. Он был бы очень старым, устаревшим. Люди проклинали бы его за то, что им не хватало одного Python 2, и тогда он попытался бы развиться, но пришлось бы развиваться иначе, потому что Web — это другая среда.
Эволюция имеет значение. Вы можете заставить динозавров жаловаться: «О, если бы уровень кислорода не понизился, и температура не упала бы, и те свободные твари не победили бы — я бы выиграл». Это звучит беспомощно (ориг. — кислый виноград).
Я говорю, что JavaScript действительно выиграл от эволюционной ниши, в которую попал, в пространство, в огромное пространство попал, а не в нишу. Это определенно означало, что монополия вызывает недовольство людей, где JavaScript является единственным языком. Тогда, если Божьей милостью пошёл бы Python, мы бы получили эту мерцающую искорку, полурабочую версию Python, на которую люди бы ругались, а не на JavaScript.
Другая вещь относительно JavaScript, скажу вам, состоит в том, что я смог, несмотря на торопливость и грубые ошибки, сделать некоторые вещи правильно. Он имеет least authority model — принцип минимальных привилегий. Если вы избавитесь от нескольких «бекдоров» (уязвимостей), которые довольно широки, это может быть моделью возможностей объекта. Именно это Марк Миллер в исследованиях Google с Google Caja объявил безопасную атмосферу, которая в значительной степени сводится к стандартам, поэтому вы можете — со строгим режимом и несколькими другими моментами, вы можете контролировать доверие к смешанной среде. Вы можете использовать возможности объекта, модели безопасности с вашими базовыми безопасными указателями, прокси и мембранами для регулирования авторитета [управления объектом]. Это хорошо для JavaScript. Это есть не во всех языках, и они тоже развивались вместе с Интернетом.
Вопросы безопасности WebAssembly
Теперь у меня есть проблема с WebAssembly, потому что он теперь находится в W3C. В W3C есть такое мышление карго-культа, которое гласит: «У вас должна быть модель безопасности на основе междоменных запросов (cross-origin request security model)». Я думаю при этом, что забыл обо всём, что это означает — CORS. Обо всём, что касается кросс-доменности. По умолчанию вы не можете загрузить WebAssembly, это плохо. Есть ещё [у них] такой рефлекс на функцию eval в JavaScript, что все что угодно — например eval или конструктор функций — что может взять строку кода и превратить его в исполняемые объекты — плохо.
«WebAssembly должен приходить только из URL-адресов. Он никогда не должен порождаться из строк.» — я думаю, что это просто вздор. Мы постоянно составляем программы из строк. Мы делаем это различными способами в Интернете, даже если вы попытаетесь нейтрализовать eval, он возвращается. Он поднимает голову. Это очень востребовано, и безопасность — не есть «Всё — или ничего!». Это — компромисс. Вы можете ограничивать программы с использованием eval. Вы должны быть осторожны, анализируя код, который принимается как строка. Это всегда так, потому что вы используете код в качестве строки для URL-адресов.
Думаю, в современном мире есть риски. Безопасность никогда даже не была решена, и некоторые проблемы беспокоили крупные компании типа Google. Вы получаете что-то вроде, как я уже сказал, карго-культовых ограничений типа «всё или ничего», думая о безопасности, которая на самом деле, думаю, не подходит ни для безопасности, ни для удобства. Мне не нравится старый подход к юзабилити безопасности. Думаю, что лучшие решения, которые я видел, включают оба подхода.
В отношении безопасности языков, Rust — это язык, который имеет статическую модель безопасности. У вас не может быть нулевого указателя ссылки во время выполнения. Вы не можете иметь ошибки памяти за пределами массива в C-С++.