Творим дичь с помощью инструментов веб-разработки

от автора

Или что бывает если заставить очень опытного разработчика заниматься не своим делом. Думаю после этой статьи термин «overqualified» заиграет для вас новыми красками.

От авторов, запихнувших веб‑сервер на визитку и локализующих корпоративные приложения на клингонский — держим марку!

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

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

Наш волшебный дикий веб

Что первым делом приходит в голову, когда говорят о «веб-разработке»? Наверное создание сайтов или веб-приложений?

Лендинги, сайты-визитки, интернет-магазины или какие-нибудь веб-порталы в ад.

Самые продвинутые из читателей наверное вспомнят PWA или какой-нибудь React Native с Flutter — предел полета фантазии обычного разработчика.

Что плохо:

главное что отделяет человека от великих свершений это его фантазия — точно нельзя сделать только то, что невозможно вообразить.

Поэтому сейчас мы будем расширять ваше воображение — в превентивных мерах, дрелью и дыроколом подручными средствами.

Перед вами шесть проектов отборнейшей дичи — реализующих самые безумные идеи с помощью вполне обыденных инструментов современного веб-разработчика.

Пожалуйста не пытайтесь рассказывать о таком на интервью в обычных компаниях — пожалейте интервьюера и его нежную психику.

Автор когда‑то давно (когда еще ходил по собеседованиям) довел одного интервьюера до нервного срыва, просто в деталях рассказав как на самом деле работает загрузка больших файлов через форму со стороны сервера — про HTTP 100 Continue, разбор MIME и прочие радости.

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

Дичь первая: HTMLang

Не смог пропустить столь жизнеутверждающее описание от автора этого замечательного проекта:

They were laughing that HTML was not a real programming language… WHO»S LAUGHING NOW!!11

Да, это именно то что вы подумали — кто-то будучи сильно не в духе взял общий синтаксис HTML и создал на его основе полноценный язык программирования.

Вот так выглядит реализация знаменитого FizzBuzz:

<!DOCTYPE html> <html>   <head>     <title>FizzBuzz</title>   </head>   <body>     <h3>Look into the DevTools Console</h3>     <htmlang style="display: none;">       <call target="console.log"><s>Generating FizzBuzz...</s></call>       <for><v>i</v> <n>1</n> <n>100</n>         <cond>           <when>             <eq>               <mod>                 <v>i</v>                 <n>15</n>               </mod>               <n>0</n>             </eq>             <call target="console.log">               <s>FizzBuzz</s>             </call>           </when>           <when>             <eq>               <mod>                 <v>i</v>                 <n>3</n>               </mod>               <n>0</n>             </eq>             <call target="console.log">               <s>Fizz</s>             </call>           </when>           <when>             <eq>               <mod>                 <v>i</v>                 <n>5</n>               </mod>               <n>0</n>             </eq>             <call target="console.log">               <s>Buzz</s>             </call>           </when>           <else>             <call target="console.log"><v>i</v></call>           </else>         </cond>       </for>     </htmlang>     <script src="./HTMLang.js"></script>   </body> </html>

Не представляю что будет если самому Джоэлу выдать его же знаменитый «FizzBuzz» в такой реализации — есть шанс что старый сишный программист впадет в рекурсию.

Кстати кто там рассказывал на лекциях про «декларативный язык разметки» и «общую неполноценность»?

HTML (от англ. HyperText Markup Language — «язык гипертекстовой разметки») — стандартизированный язык гипертекстовой разметки документов для просмотра веб-страниц в браузере.

Зря старались, автор этого проекта тем временем спокойно пишет в консоль тегами HTML:

<call target="console.log">         <s>FizzBuzz</s> </call>

Все потому что не надо нанимать системных программистов, прошедших полноценное обучение по дисциплинам CS (вроде курса по разработке компиляторов) для работы штатным говночистом разработчиком в обычном корпоративном проекте — о чем так мечтают все рекрутеры.

Может случиться неприятность:

в самый интересный момент окажется что половина работы реализована на чем-то таком интересном.

А сотворивший это «великий гуру» внезапно пропадет, выключив телефон и переехав в поисках истины в солнечную Караганду Канаду.

Прецеденты были.

Дичь вторая: HTML-as-programming-language

Нехорошие мысли терзают очень многих опытных разработчиков — все та же идея «полноценной разработки на HTML» не дает покоя и автору данного проекта.

Но только он зашел в этом процессе несколько дальше предыдущего.

Как вам например функция на чистом HTML:

<def multiplyFunction returns=int> <!-- You can create functions -->     <param a type=int/>     <param b type=int/>     <return>a * b</return> </def>  <def main>     <var result type=int>      <!-- Create variables -->         <multiplyFunction>          <!-- and store the result of the function in the variable -->             <param>5</param>             <param>6</param>         </multiplyFunction>     </var> </def>

Известная библейская истина «многие знания — многие печали» — как раз про этот проект, например я бы очень хотел все это забыть и никогда о подобном не знать.

Но к сожалению уже слишком поздно, поэтому делюсь откровениями:

Замечательный пайплайн с вызовом компилятора HTML, правда?

Замечательный пайплайн с вызовом компилятора HTML, правда?

Да, вы все правильно поняли — это самый настоящий компилятор из HTML в нативный ELF64 бинарник.

А сейчас вам совсем поплохеет:

To write code for Adruino/AVR microcontrollers, (Arduino UNO for example) you need to put a DOCTYPE tag in your HTML file.

For example:

<!DOCTYPE avr/atmega328p>

Да, это была оригинальная задумка автора — разработка для микроконтроллеров на HTML, я ничего не додумываю.

Увидев такой вот DOCTYPE, один знакомый веб-разработчик навсегда бросил пить.

К слову, небольшая магия с #include <stdio.h> на скриншоте выше была необходима как раз потому, что компилятор предназначен для микроконтроллеров и не добавляет в генерируемый код на С этот стандартный для обычной ОС заголовок.

Вот так выглядит эта железка, если никогда не видели.

Вот так выглядит эта железка, если никогда не видели.

К сожалению у меня не оказалось под рукой такого девайса, так что полноценную работу и весь пайплайн проверить не смог.

To compile your AVR/Arduino code:

htmlc my-code.html -compile

To upload your code to an arduino or other AVR microcontroller:

htmlc my-code.html -upload

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

А мы тем временем переходим к следующему замечательному проекту.

Дичь третья: ass-js

Таким названием и не менее характерным логотипом, авторы честно намекают на суть проекта:

Assembler implemented in JavaScript

Полагаю вы еще никогда не устанавливали компилятор ассемблера с помощью npm? Что ж, все когда‑нибудь бывает в первый раз:

npm i ass-js

А так выглядит классический «Hello, world»:

import {X64} from '../src/index';  const asm = X64();  asm.code(_ => {     _('db', 'Hello World!\n');     _('mov', ['rax', 1]); // 0x48, 0xC7, 0xC0, 0x01, 0x00, 0x00, 0x00     _('mov', ['rdi', 1]);     _('lea', ['rsi', _('rip').disp(-34)]);     _('mov', ['rdx', 13]);     _('syscall');     _('ret'); });  console.log(asm.toString());

Только не показывайте любимому преподавателю курса по ассемблеру — дедушке поплохеет, сердце может не выдержать такого накала дичи.

Вот так выглядит результат работы:

К сожалению выдаваемый ассемблерный код оказался нерабочим и отказался компилироваться в бинарник на моей машине.

К сожалению выдаваемый ассемблерный код оказался нерабочим и отказался компилироваться в бинарник на моей машине.

Зато есть отдельный туториал по разбору примера с «Hello world», где по шагам разобрано как оно работает.

Еще нашелся замечательный вопрос к автору:

I was looking at your project and I couldn’t figure out a reason as to why I would (and what, rather) implement with this.

Который как бы намекает на уровень треша и угара в этом проекте. Но едем дальше — к следующему отбитому уникальному проекту.

Дичь четвертая: ts2c

Тут все просто и очевидно:

Produces readable C89 code from JS/TS code.

Собственно все кроме смысла существования этого замечательного проекта — понятно и очевидно. Как-то так выглядит весь пайплайн:

Если вам вдруг будет нужен транспилер из Typescript в чистый Си — берите и пользуйтесь, благо проект очень даже рабочий:

npm install -g ts2c

Работает кстати и из браузера:

<script src="https://unpkg.com/typescript"></script> <script src="ts2c.bundle.js"></script> <script>     var cCode = ts2c.transpile("console.log('Hello world!')");     alert(cCode); </script>

Есть даже онлайн версия:

Несмотря на то что автор честно пишет о куче недоработок:

Work in progress: it works, but only about 70% of ES3 specification is currently supported: statements and expressions — 95%, built-in objects — 17%.

Скажу что это самый работоспособный проект из серии, все остальное буквально рассыпается в руках. Рассыпается и валится как и следующий объект исследования.

Дичь пятая: nerd

Как легко и быстро понять что исследуемый проект — дикое, нерабочее и глючное говно?

По описанию, обещающему бесконечные ништяки:

Javascript’s God Mode. No VM. No Bytecode. No GC. Just native binaries.

Отсылка к чему-то божественному в описании технического проекта это вообще практически 100% диагноз, можно отбраковывать только по одному этому признаку — врядли ошибетесь.

Как нетрудно догадаться, вместо нормального JavaScript тут тоже что-то свое божественное:

NerdLang is a substract of JS with some additions, focus on efficiency.

И это «свое» скажем так застряло в далеком прошлом:

Supporting EcmaScript 3 standard

На минуточку, 3я редакция стандарта вышла еще в далеком 2000м году.

А сам проект пытается в который раз «натянуть сову на глобус» и залезть туда, где последовательно обломали клыки все крупные корпрорации уровня Google:

Nerd is a JavaScript native compiler aiming to make JavaScript universal, Nerd is able to compile native apps for Windows, Mac, Linux, iOS, Android, Raspberry, STM32 and more.

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

Пайплайн (присутствует на титульном скриншоте) выглядит вот так:

Автор настолько суров, что запихал инстукции сборки и линковки модуля работы с сокетами в package.json:

{ ..   "version": "0.0.1",   "nerd":   {     "env": ["std"],     "read_only": [],     "lib":      { "win32": [ "-D_WIN32_WINNT=0x0600", "-Wno-narrowing", "-D_GNU_SOURCE", "-I{__EXTERN__}/libuv/include/",  "-I{__EXTERN__}/libuv/src/", "-D_CRT_SECURE_NO_DEPRECATE", "-D_CRT_NONSTDC_NO_DEPRECATE",  "{__EXTERN__}/libuv/src/*.h", "{__EXTERN__}/libuv/src/*.c", "{__EXTERN__}/libuv/src/win/*.h", "{__EXTERN__}/libuv/src/win/*.c", "-I {__MODULE__}/httplib/uWS/", "-I {__MODULE__}/httplib/uSockets/", "{__MODULE__}/httplib/uSockets/*.c", "{__MODULE__}/httplib/uSockets/crypto/*.c", "{__MODULE__}/httplib/uSockets/eventing/*.c", "-DLIBUS_NO_SSL", "-DUWS_NO_ZLIB", "-fpermissive", "-w", "-lm", "-ladvapi32", "-liphlpapi", "-lpsapi", "-lshell32", "-luser32 ", "-luserenv", "-lwsock32", "-lws2_32" ]     }   } }

Увидев вот такой package.json, знакомый веб-разработчик (другой) решил навсегда уйти из профессии и теперь пасет коз в горах Кавказа.

Ну а я всего лишь не рискнул адаптировать такое для сборки под Linux, так что вы останетесь без примера запуска HTTP-сервера на этом чудище.

Дичь шестая: lemon

Наконец последний на сегодня проект, который по сравнению с предыдущими является можно сказать нормальным и где-то даже применимым:

Lemon is a framework for building Javascript runtime software, built on the Chrome V8 Javascript Engine.

Мне он понравился своей запредельной простотой (по сравнению со всеми остальными проектами) и легкостью встраивания.

Специально показываю скрипт сборки целиком:

CXX = g++ V8 = engine/lib/v8 define INCLUDE $(V8)/include engine/Core.cpp engine/Environment.cpp engine/Lemon.cpp engine/StaticHelpers.cpp engine/ObjectCreator.cpp endef define APP app/*.cpp endef define LIB $(V8)/out/x64.release/obj/ endef define OBJ v8_monolith endef export INCLUDE export APP export LIB export OBJ build: (CXX) -I " class="formula inline">$INCLUDE $$APP -L $$LIB -l $$OBJ -std=c++0x -pthread -o lemon

И.. это все.

Настолько простую сборку V8 вижу впервые в жизни, честно.

Оно действительно собирается одной командой:

Ниже показано как выглядит двойной «Hello, world», в котором есть как часть на JavaScript так и часть на C++ — немного подумав объединил два примера из документации в один.

App.js:

version(); console.log("Превед из JS"); helloworld();

App.hpp:

#ifndef APP #define APP  #include "../engine/Lemon.hpp" using v8::Context;  class App : public Lemon { public: void Start(int argc, char* argv[]); void SetupEnvironment(); }; #endif

App.cpp:

#include "App.hpp"  using namespace v8;  static void Log(const FunctionCallbackInfo<Value>& args) {     HandleScope scope(args.GetIsolate());     String::Utf8Value str(args.GetIsolate(), args[0]);     const char* cstr = StaticHelpers::ToCString(str);     fprintf(stdout, "%s", cstr);     fprintf(stdout, "\n");     fflush(stdout); } static void HelloWorld(const FunctionCallbackInfo<Value>& args) {     printf("Превед из C++ \n"); } void App::SetupEnvironment() {     this->CreateGlobalMethod("helloworld", HelloWorld); } void App::Start(int argc, char* argv[]) {  for (int i = 1; i < argc; ++i) {  // Get filename of the javascript file to run const char* filename = argv[i];  // Create a new context for executing javascript code Local<Context> context = this->CreateLocalContext();  // Enter the new context Context::Scope contextscope(context);  this->CreateGlobalObject("console") .SetPropertyMethod("log", Log) .Register();  // Run the javascript file this->RunJsFromFile(filename); } }

Чудны дела твои Господи, коль даже перебирая запредельную дичь есть шанс найти столь мощный проект.

Спросите с чего столько радости?

Потому что это самый настоящий V8, не самопал с реализацией ECMAScript «в переводе Гоблина», а именно тот самый движок, который используется в браузере Chrome — со всеми оптимизациями и наворотами.

А значит при определенных усилиях, у вас будет работать практически любой JavaScript код — в вашем нативном приложении, без всяких жирных Node.js и всех проблем с линковкой и версиями.

Словом берите на вооружение, пригодится.

Одной строкой

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

js-ziju

Compile javascript to LLVM IR, x86 assembly and self interpreting

К сожалению оказался прибит гвоздями к определенной версии MacOS, ни нормально собрать ни прогнать тесты под Linux не удалось. Интересен тем что в одном проекте собран и интерпретатор и компилятор, причем в нативный бинарник.

JS-ASM

JavaScript Assembler x86-16

Генерирует готовые COM-файлы времен DOS, но под эмулятором Dosbox они работать отказались.

Duktape

Duktape — embeddable Javascript engine with a focus on portability and compact footprint

Более продвинутый и известный аналог Lemon, который я нашел слишком поздно и не успел посмотреть.

clangor

«clang ported to js» — можно сразу в цитаты добавлять.

Сломанная и сильно устаревшая сборка, но сам проект — очень крутой, поскольку это полноценный компилятор Clang, вытащенный в веб.

Вот тут есть онлайн версия.

llvm.js

LLVM compiled to JavaScript using Emscripten

Снова сломанная и устаревшая сборка, починить за разумное время не получилось.

Она же в готовом виде онлайн.

jssat

Compile JS into LLVM IR — JavaScript Static Analysis Tool

Вот тут находится статья про этот проект, но мне собрать так и не удалось.

js2cpp

A toy js -> c++ compiler written in coffeescript. Uses escodegen to write c++ and tern to figure out types.

Опять сильно устаревшая и сломанная сборка.

js-to-c

Compiled implementation of Javascript, targeting C (for fun)

Половина тестов сломана, но сама сборка проходит — не стал детально изучать.

Letter

Letter is a compiler project built in TypeScript using LLVM node bindings.

Очень интересный, но к сожалению устаревший проект — требует 13й LLVM и старую же версию Node.js.

Подружить с новыми версиями LLVM и Node не удалось.

CaptCC

A tiny C compiler written purely in JavaScript.

Еще один интересный, но неработающий проект — сам компилятор отработал, но ассемблерный код отказался собираться.

Эпилог

Все описанные в этой статье проекты приведены в первую очередь для расширения границ вашего воображения — просто чтобы вы знали что так тоже бывает.

Пожалуйста не пытайтесь такое внедрять и использовать в рельном проекте, если не имеете за плечами серьезного опыта и/или профильного обучения по CS.

Либо умеете быстро бегать и имеете запасное гражданство.

Куда более вольная версия данной статьи доступна в нашем блоге.

0x08 Software

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

Оживляем давно умершеечиним никогда не работавшее и создаем невозможное — затем рассказываем об этом в своих статьях.


ссылка на оригинал статьи https://habr.com/ru/articles/824248/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *