{"id":484965,"date":"2026-06-25T09:14:32","date_gmt":"2026-06-25T09:14:32","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=484965"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=484965","title":{"rendered":"8 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0431\u0435\u0437 Docker: \u043a\u0430\u043a \u043c\u044b \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u043d\u0430\u043c \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u0434\u043b\u044f \u043a\u043e\u0434\u0430 \u2014 \u0442\u0430\u043a\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c JavaScript-\u0441\u043d\u0438\u043f\u043f\u0435\u0442, \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u043b\u0438 \u043f\u043e\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 Python. \u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e, \u0431\u0435\u0437 \u0440\u0435\u043a\u043b\u0430\u043c\u044b \u0438 \u0431\u0435\u0437 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438. \u041f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0448\u044c \u0438 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0448\u044c\u0441\u044f. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u00ab\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Pro-\u0432\u0435\u0440\u0441\u0438\u0438\u00bb \u0438\u043b\u0438 \u00ab\u0432\u044b \u0438\u0441\u0447\u0435\u0440\u043f\u0430\u043b\u0438 \u043b\u0438\u043c\u0438\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432\u00bb. <br \/>\u041d\u043e \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0435, \u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u2014 \u044f\u0449\u0438\u043a \u041f\u0430\u043d\u0434\u043e\u0440\u044b. \u0414\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u2014 \u0437\u043d\u0430\u0447\u0438\u0442 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0434\u0432\u0435\u0440\u044c \u0434\u043b\u044f \u0446\u0435\u043b\u043e\u0433\u043e \u0431\u0443\u043a\u0435\u0442\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c: \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0435 \u0446\u0438\u043a\u043b\u044b, XSS-\u0432\u0435\u043a\u0442\u043e\u0440\u044b, \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a DOM, \u0443\u0442\u0435\u0447\u043a\u0438 \u043f\u0430\u043c\u044f\u0442\u0438, \u0432\u0440\u0435\u0434\u043e\u043d\u043e\u0441\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0443\u043d\u043a\u0442 \u043f\u043e-\u0441\u0432\u043e\u0435\u043c\u0443 \u043e\u043f\u0430\u0441\u0435\u043d, \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c. <\/p>\n<p>\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043c\u044b \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u044b. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 Docker-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u043e\u043a, \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434. \u0412\u0441\u0451 \u0434\u043e\u043b\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u2014 \u0431\u044b\u0441\u0442\u0440\u043e, \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e \u0438 \u0431\u0435\u0437 \u0437\u0430\u0442\u0440\u0430\u0442 \u043d\u0430 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443.<\/p>\n<p>\u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u043b\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0436\u0438\u0432\u0451\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u041f\u0440\u0438\u0447\u0451\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0440\u0435\u0434\u044b \u2014 JavaScript, Python, SQL, HTML\/CSS, Markdown, Bash, Regex, Cron \u2014 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434. \u0413\u0434\u0435-\u0442\u043e \u0445\u0432\u0430\u0442\u0430\u0435\u0442 Web Worker, \u0433\u0434\u0435-\u0442\u043e \u043d\u0443\u0436\u0435\u043d WebAssembly \u0441 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439, \u0430 \u0433\u0434\u0435-\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0441 \u043d\u0443\u043b\u044f.<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0432\u043e\u0441\u0435\u043c\u044c \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438. \u0414\u0430\u043b\u044c\u0448\u0435 \u2014 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u0440\u0430\u0437\u0431\u043e\u0440 \u043a\u0430\u0436\u0434\u043e\u0439: \u043a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u0430, \u043a\u0430\u043a\u0438\u0435 \u0443\u0433\u0440\u043e\u0437\u044b \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0438 \u0441 \u043a\u0430\u043a\u0438\u043c\u0438 \u0433\u0440\u0430\u0431\u043b\u044f\u043c\u0438 \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c.<\/p>\n<h3>JavaScript: Web Worker \u0438 \u0440\u0443\u0447\u043d\u043e\u0439 \u0442\u0430\u0439\u043c\u0430\u0443\u0442<\/h3>\n<p>JavaScript-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u2014 \u0441\u0430\u043c\u0430\u044f \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u0430\u044f \u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441\u0430\u043c\u0430\u044f \u043e\u043f\u0430\u0441\u043d\u0430\u044f. \u0414\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u2014 \u0437\u043d\u0430\u0447\u0438\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0435\u043c\u0443 \u0434\u043e\u0442\u044f\u043d\u0443\u0442\u044c\u0441\u044f \u0434\u043e DOM, window, \u043a\u0443\u043a\u0438 \u0438 \u0432\u0441\u0435\u0433\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u043e\u0435 \u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435: \u043a\u043e\u0434 \u043b\u0435\u0442\u0438\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 Web Worker.<\/p>\n<p>\u0423 \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a DOM, <code>document<\/code> \u0438 <code>window<\/code> \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430. \u041d\u043e \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0434\u0432\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u0432\u044b\u0432\u043e\u0434 <code>console.log<\/code> \u0438 \u043a\u0430\u043a \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430.<\/p>\n<p><strong>\u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442 \u043a\u043e\u043d\u0441\u043e\u043b\u0438.<\/strong> \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0433\u043b\u0443\u0448\u0438\u0442\u044c \u0432\u044b\u0432\u043e\u0434 \u0441\u043e\u0432\u0441\u0435\u043c, \u043c\u044b \u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0435\u043c <code>console.log<\/code>, <code>error<\/code>, <code>warn<\/code> \u0438 <code>info<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u0430. \u041a\u0430\u0436\u0434\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0438 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0430\u0441\u0441\u0438\u0432 <code>logs<\/code>. \u041a\u043e\u0433\u0434\u0430 \u043a\u043e\u0434 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u2014 \u043c\u0430\u0441\u0441\u0438\u0432 \u0443\u043b\u0435\u0442\u0430\u0435\u0442 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0447\u0435\u0440\u0435\u0437 <code>postMessage<\/code>:<\/p>\n<pre><code class=\"typescript\">const logs: string[] = [];const cons = {  log: (...a: unknown[]) =&gt; {    logs.push(a.map((x) =&gt;      typeof x === \"object\" ? JSON.stringify(x) : String(x)    ).join(\" \"));  },  error: (...a: unknown[]) =&gt; {    logs.push(\"[error] \" + a.map((x) =&gt;      typeof x === \"object\" ? JSON.stringify(x) : String(x)    ).join(\" \"));  },  \/\/ ...warn, info \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0434\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u0439 console \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u0434 \u043a\u0430\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u2014 \u0447\u0435\u0440\u0435\u0437 <code>new Function(\"console\", ...)<\/code>. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u0435\u043c, \u043a\u043e\u0434 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f.<\/p>\n<p><strong>\u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b.<\/strong> \u0412\u043e\u0440\u043a\u0435\u0440 \u2014 \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a, \u0442\u0430\u043a \u0447\u0442\u043e UI \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u043d\u0435\u0442 \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435. \u041d\u043e \u0441\u0430\u043c \u0432\u043e\u0440\u043a\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0432\u0438\u0441\u0435\u0442\u044c \u0432\u0435\u0447\u043d\u043e, \u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u043c\u0435\u0442\u044c \u0435\u0433\u043e \u043f\u0440\u0438\u0431\u0438\u0432\u0430\u0442\u044c. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u2014 <code>setTimeout<\/code> \u0441 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0438\u0442 <code>terminate<\/code>:<\/p>\n<pre><code class=\"typescript\">const timer = setTimeout(() =&gt; finish({ kind: \"timeout\" }), timeoutMs);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u2014 \u0432\u043e\u0440\u043a\u0435\u0440 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 <code>{ kind: \"timeout\" }<\/code> \u0438 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0444\u043b\u0430\u0433 finished, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u044b\u0437\u043e\u0432\u044b finish \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <code>async\/await<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f \u2014 \u0435\u0441\u043b\u0438 \u043e\u043d \u0437\u0430\u0432\u0438\u0441 \u0432 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0446\u0438\u043a\u043b\u0435, \u0442\u043e \u0434\u043e <code>await<\/code> \u0434\u0435\u043b\u043e \u043d\u0435 \u0434\u043e\u0439\u0434\u0451\u0442, \u043d\u043e \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0432\u043e\u0440\u043a\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0435\u043d \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u0432\u044b\u0437\u043e\u0432\u043e\u043c <code>terminate<\/code>.<\/p>\n<p>\u0415\u0441\u0442\u044c \u043d\u044e\u0430\u043d\u0441: \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0432\u043d\u0443\u0442\u0440\u0438 <code>setTimeout<\/code> \u0438\u043b\u0438 <code>Promise<\/code>, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c, \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u043d\u0435 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442 \u2014 \u043d\u043e \u0441\u0430\u043c \u0432\u043e\u0440\u043a\u0435\u0440 \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 <code>terminated<\/code> \u043a \u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443.<\/p>\n<p><strong>\u041b\u0438\u043c\u0438\u0442\u044b:<\/strong> 200 000 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u043a\u043e\u0434, \u0442\u0430\u0439\u043c\u0430\u0443\u0442 10 \u0441\u0435\u043a\u0443\u043d\u0434. \u0412\u043e\u0440\u043a\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0437\u0430\u043d\u043e\u0432\u043e \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u2014 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0443\u0442\u0435\u0447\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.<\/p>\n<h3>Python: Pyodide \u0441 \u0446\u0435\u043f\u043e\u0447\u043a\u043e\u0439 \u0437\u0435\u0440\u043a\u0430\u043b<\/h3>\n<p>Python-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043d\u0430 Pyodide \u2014 CPython, \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0432 WebAssembly. \u0418 \u0432 \u044d\u0442\u043e\u043c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: Pyodide \u2014 \u044d\u0442\u043e \u0437\u0434\u043e\u0440\u043e\u0432\u0435\u043d\u043d\u044b\u0439 Wasm-\u0444\u0430\u0439\u043b, \u0438 \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043a\u0443\u0434\u0430-\u0442\u043e \u0433\u0440\u0443\u0437\u0438\u0442\u044c.<\/p>\n<p><strong>Fallback \u043f\u043e \u0437\u0435\u0440\u043a\u0430\u043b\u0430\u043c.<\/strong> \u041c\u044b \u043d\u0435 \u0441\u0442\u0430\u043b\u0438 \u0437\u0430\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043e\u0434\u0438\u043d CDN. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u0442\u0440\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0438 \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0438\u0445 \u043f\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u0438:<\/p>\n<pre><code class=\"typescript\">const INDEX_CANDIDATES = [  \"https:\/\/cdn.jsdelivr.net\/pyodide\/v0.26.1\/full\/\",  \"https:\/\/cdn.jsdelivr.net\/pyodide\/v0.25.0\/full\/\",  \"https:\/\/unpkg.com\/pyodide@0.26.1\/full\/\",];<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>pickWorkingIndexBase<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 HEAD-\u0437\u0430\u043f\u0440\u043e\u0441 \u043a <code>pyodide.js<\/code> \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0435\u0440\u043a\u0430\u043b\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0432\u043e\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0435. \u0422\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>importScripts<\/code> \u0438 <code>loadPyodide<\/code>. \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 Web Worker \u2014 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435.<\/p>\n<p><strong>\u0418\u0437\u043e\u043b\u044f\u0446\u0438\u044f.<\/strong> Pyodide \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u043d\u0435 \u0434\u0430\u0451\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0445\u043e\u0441\u0442\u0430. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u2014 <code>json<\/code>, <code>re<\/code>, <code>math<\/code> \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041d\u043e <code>import os<\/code> \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c. \u041d\u0438\u043a\u0430\u043a\u043e\u0433\u043e pip \u0442\u043e\u0436\u0435 \u043d\u0435\u0442 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e, \u0447\u0442\u043e \u0443\u0436\u0435 \u0432\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0432 Pyodide.<\/p>\n<p><strong>\u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442 \u0432\u044b\u0432\u043e\u0434\u0430.<\/strong> Pyodide \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b <code>setStdout<\/code> \u0438 <code>setStderr<\/code>. \u041c\u044b \u0432\u0435\u0448\u0430\u0435\u043c \u043d\u0430 \u043d\u0438\u0445 batched-\u043a\u043e\u043b\u0431\u044d\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442 \u0432\u044b\u0432\u043e\u0434 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443. \u0412\u0430\u0436\u043d\u044b\u0439 \u043d\u044e\u0430\u043d\u0441: Pyodide \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e print \u0432 \u043e\u0434\u043d\u043e\u043c \u0431\u0430\u0442\u0447\u0435, \u0431\u0435\u0437 <code>\\n<\/code> \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u043f\u043e\u043b\u043d\u044b\u0445 \u0447\u0430\u043d\u043a\u043e\u0432:<\/p>\n<pre><code class=\"typescript\">const appendLine = (buf: string, s: string) =&gt; {  if (!s) return buf;    return buf + (s.endsWith(\"\\n\") ? s : `${s}\\n`);};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0422\u0430\u0439\u043c\u0430\u0443\u0442.<\/strong> \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0432 JS-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435: <code>setTimeout<\/code> \u043d\u0430 \u043d\u0443\u0436\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434 \u043f\u043b\u044e\u0441 \u0437\u0430\u043f\u0430\u0441 \u043d\u0430 \u0442\u043e\u0440\u043c\u043e\u0437\u0430 Wasm. \u041f\u0440\u0438 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>{ type: \"run-timeout\" }<\/code>. \u041f\u043b\u044e\u0441 \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 <code>{ type: \"cancel\" }<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u0430\u0439\u043c\u0435\u0440 \u2014 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u043a\u043e\u0434 \u0437\u0430\u043d\u043e\u0432\u043e, \u043d\u0435 \u0434\u043e\u0436\u0438\u0434\u0430\u044f\u0441\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e.<\/p>\n<p><strong>\u041b\u0438\u043c\u0438\u0442\u044b:<\/strong> 100 000 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u043a\u043e\u0434, \u0442\u0430\u0439\u043c\u0430\u0443\u0442 25 \u0441\u0435\u043a\u0443\u043d\u0434 (Python \u0432 Wasm \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e JS).<\/p>\n<h3>SQL: SQL.js \u0432 Web Worker \u0441 \u0440\u0443\u0447\u043d\u044b\u043c locateFile<\/h3>\n<p>\u0414\u043b\u044f SQL-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 SQL.js \u2014 SQLite, \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432 WebAssembly. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 Web Worker, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u043f\u0440\u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0435 \u0442\u044f\u0436\u0451\u043b\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p><strong>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 Wasm \u0431\u0435\u0437 CDN.<\/strong> sql.js \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c wasm-\u0444\u0430\u0439\u043b \u0441 CDN (<a href=\"http:\/\/sql.js.org\" rel=\"noopener noreferrer nofollow\">sql.js.org<\/a>). \u042d\u0442\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442: \u0432\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043b\u0438\u0448\u043d\u044f\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430, \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445 \u2014 \u043d\u0430 <a href=\"http:\/\/sql.js.org\" rel=\"noopener noreferrer nofollow\">sql.js.org<\/a> \u043d\u0435\u0442 \u0444\u0430\u0439\u043b\u0430 <code>sql-wasm-browser.wasm<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0431\u0430\u043d\u0434\u043b (\u0442\u0430\u043c \u043b\u0435\u0436\u0438\u0442 HTML \u0432\u043c\u0435\u0441\u0442\u043e wasm, \u0438 \u0434\u0432\u0438\u0436\u043e\u043a \u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c <code>locateFile<\/code>:<\/p>\n<pre><code class=\"typescript\">function locateSqlWasm(file: string): string {  const origin = self.location?.origin;    if (!origin || !file.endsWith('.wasm')) {    return `https:\/\/sql.js.org\/dist\/${file}`;  }    if (file.includes('sql-wasm-browser')) {    return `${origin}\/wasm\/sql-wasm-browser.wasm`;  }    return `${origin}\/wasm\/sql-wasm.wasm`;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Wasm-\u0444\u0430\u0439\u043b\u044b \u0440\u0430\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0441 \u0442\u043e\u0433\u043e \u0436\u0435 origin, \u0447\u0442\u043e \u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 CDN \u2014 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0438 \u043d\u0430\u0434\u0451\u0436\u043d\u0435\u0435.<\/p>\n<p><strong>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b.<\/strong> \u041a\u0430\u0436\u0434\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438: \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 Database, \u043d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0445\u0435\u043c\u0430 \u0438\u0437 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430:<\/p>\n<pre><code class=\"typescript\">db = new S.Database();if (msg.payload.schemaSql.trim()) {  db.run(msg.payload.schemaSql);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0441\u0440\u0430\u0437\u0443 \u043f\u0438\u0441\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u043d\u0438\u043c.<\/p>\n<p><strong>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 AbortController.<\/strong> \u0413\u043b\u0430\u0432\u043d\u0430\u044f \u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c SQL-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u2014 \u0437\u0430\u043f\u0440\u043e\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0448\u0430\u0435\u0442 \u0431\u0430\u0437\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, cross join \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445 \u0438\u043b\u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 CTE). sql.js \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u0438 \u043f\u0440\u043e\u0441\u0442\u043e <code>setTimeout<\/code> \u0442\u0443\u0442 \u043d\u0435 \u043f\u043e\u043c\u043e\u0436\u0435\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>AbortController<\/code>:<\/p>\n<pre><code class=\"typescript\">const ac = new AbortController();const timer = setTimeout(() =&gt; ac.abort(), timeoutMs);const results = db.exec(sql);if (ac.signal.aborted) {  post({ type: \"error\", payload: { message: \"\u041f\u0440\u0435\u0432\u044b\u0448\u0435\u043d \u0442\u0430\u0439\u043c\u0430\u0443\u0442...\" } });  return;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043d\u0435 \u0431\u044b\u043b \u043b\u0438 \u0441\u0438\u0433\u043d\u0430\u043b \u043f\u0440\u0435\u0440\u0432\u0430\u043d \u0437\u0430 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b db.exec. \u0415\u0441\u043b\u0438 \u0431\u044b\u043b \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430.<\/p>\n<p><strong>\u0412\u044b\u0432\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432.<\/strong> \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 (SELECT), \u043c\u044b \u043e\u0442\u0434\u0430\u0451\u043c \u0438\u0445 \u043a\u0430\u043a <code>{ kind: \"select\", columns, rows }<\/code>. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e INSERT\/UPDATE\/DELETE \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c<code> { kind: \"ok\", message }<\/code>. \u0415\u0441\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0430 \u2014 <code>{ kind: \"error\", message }<\/code>.<\/p>\n<p><strong>\u041b\u0438\u043c\u0438\u0442\u044b:<\/strong> 200 000 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u0441\u043a\u0440\u0438\u043f\u0442 (\u0441\u0445\u0435\u043c\u0430 + \u0437\u0430\u043f\u0440\u043e\u0441), \u0442\u0430\u0439\u043c\u0430\u0443\u0442 5 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<h3>HTML\/CSS: iframe \u0441 sandbox \u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 srcdoc<\/h3>\n<p>HTML\/CSS-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u0441\u0442\u043e\u0438\u0442 \u043e\u0441\u043e\u0431\u043d\u044f\u043a\u043e\u043c. \u0417\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u043c \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u0438 \u0441\u0442\u0438\u043b\u0438, \u0430 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<p><strong>\u0418\u0437\u043e\u043b\u044f\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 iframe sandbox.<\/strong> \u041f\u0440\u0435\u0432\u044c\u044e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u0432 <code>&lt;iframe sandbox=\"allow-scripts\"&gt;<\/code>. \u0410\u0442\u0440\u0438\u0431\u0443\u0442 <code>sandbox<\/code> \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044e, \u0430 <code>allow-scripts<\/code> \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 JavaScript \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0435\u0432\u044c\u044e, \u043d\u043e \u0431\u0435\u0437 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a cookie \u0438 DOM \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b. \u0414\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u0442 <code>&lt;script&gt;document.cookie&lt;\/script&gt;<\/code>, \u043e\u043d \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0441\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 Halfcoder.<\/p>\n<p><strong>\u0421\u0431\u043e\u0440\u043a\u0430 srcdoc.<\/strong> \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 HTML \u0438 CSS \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e. \u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442:<\/p>\n<pre><code class=\"typescript\">function buildSrcDoc(html: string, css: string): string {  const style = css.trim() ? `&lt;style&gt;${css}&lt;\/style&gt;` : \"\";    if (\/&lt;html[\\s&gt;]\/i.test(html)) {    if (\/&lt;head[\\s&gt;]\/i.test(html)) {      return html.replace(\/&lt;\\\/head&gt;\/i, `${style}&lt;\/head&gt;`);    }        return html.replace(\/&lt;html[^&gt;]*&gt;\/i, (m) =&gt; `${m}&lt;head&gt;${style}&lt;\/head&gt;`);  }    return `&lt;!DOCTYPE html&gt;&lt;html&gt;&lt;head&gt;&lt;meta charset=\"utf-8\"&gt;${style}&lt;\/head&gt;&lt;body&gt;${html}&lt;\/body&gt;&lt;\/html&gt;`;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432 <code>srcDoc<\/code> \u0430\u0442\u0440\u0438\u0431\u0443\u0442 <code>iframe<\/code>. \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 500 \u043c\u0441 \u0447\u0435\u0440\u0435\u0437 <code>debounce<\/code> \u2014 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0432\u044c\u044e \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438.<\/p>\n<p><strong>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f.<\/strong> \u041f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u043d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 CSS-\u0438\u043d\u044a\u0435\u043a\u0446\u0438\u0438 \u2014 \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0438\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u043e\u043c\u0430\u0435\u0442 \u0432\u0451\u0440\u0441\u0442\u043a\u0443 \u0432\u043d\u0443\u0442\u0440\u0438 <code>iframe<\/code>, \u043d\u043e \u043d\u0430\u0440\u0443\u0436\u0443 \u044d\u0442\u043e \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442. JavaScript \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0435\u0432\u044c\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0439\u0442\u0438 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b <code>iframe<\/code>.<\/p>\n<h3>Markdown: DOMPurify \u0441 \u0436\u0451\u0441\u0442\u043a\u0438\u043c \u0432\u0430\u0439\u0442\u043b\u0438\u0441\u0442\u043e\u043c<\/h3>\n<p>Markdown-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430, \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u0441\u0430\u043c\u0430\u044f \u0431\u0435\u0437\u043e\u0431\u0438\u0434\u043d\u0430\u044f. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0438\u0448\u0435\u0442 Markdown, \u043c\u044b \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043c HTML. \u041e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u2014 XSS \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 HTML \u0438\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u0437\u0430\u043c\u0430\u0441\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434 Markdown-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443.<\/p>\n<p><strong>\u0421\u0430\u043d\u0438\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 DOMPurify.<\/strong> \u041f\u043e\u0441\u043b\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0447\u0435\u0440\u0435\u0437 marked, \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u0439\u0441\u044f HTML \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 DOMPurify \u0441 \u0436\u0451\u0441\u0442\u043a\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0445 \u0442\u0435\u0433\u043e\u0432:<\/p>\n<pre><code class=\"typescript\">function sanitizeMarkdownHtml(raw: string): string {  return DOMPurify.sanitize(raw, {    USE_PROFILES: { html: true },    ALLOWED_TAGS: [      \"p\", \"br\", \"strong\", \"em\", \"code\", \"pre\",      \"h1\", \"h2\", \"h3\", \"h4\",      \"ul\", \"ol\", \"li\", \"blockquote\", \"a\",      \"hr\", \"table\", \"thead\", \"tbody\", \"tr\", \"th\", \"td\",    ],    ALLOWED_ATTR: [\"href\", \"title\", \"class\"],    ALLOW_DATA_ATTR: false,  });}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 on*-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 data-\u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432. \u0414\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0441\u0442\u0430\u0432\u0438\u0442 <code>&lt;script&gt;alert(\"xss\")&lt;\/script&gt;<\/code> \u0432 Markdown, DOMPurify \u0432\u044b\u0440\u0435\u0436\u0435\u0442 \u044d\u0442\u043e \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0441\u0430\u043d\u0438\u0442\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p><strong>\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c HTML.<\/strong> \u041c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0432\u043e\u043e\u0431\u0449\u0435 \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c HTML \u0432 Markdown, \u043d\u043e \u044d\u0442\u043e \u0441\u043b\u043e\u043c\u0430\u043b\u043e \u0431\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442\u0430\u0431\u043b\u0438\u0446, \u0441\u0441\u044b\u043b\u043e\u043a \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0445 \u0444\u0438\u0447 GFM. DOMPurify \u0434\u0430\u0451\u0442 \u0437\u043e\u043b\u043e\u0442\u0443\u044e \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0443: HTML \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u043e\u043f\u0430\u0441\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432\u044b\u0440\u0435\u0437\u0430\u044e\u0442\u0441\u044f.<\/p>\n<h3>Bash: \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0441 \u043f\u0430\u0439\u043f\u0430\u043c\u0438<\/h3>\n<p>Bash-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0441\u0430\u043c\u0430\u044f \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u041c\u044b \u043d\u0435 \u0441\u0442\u0430\u043b\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 shell \u0447\u0435\u0440\u0435\u0437 Wasm \u0438\u043b\u0438 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u0432\u043e\u0439 \u043f\u0430\u0440\u0441\u0435\u0440 \u043a\u043e\u043c\u0430\u043d\u0434 \u0438 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u043f\u0430\u0439\u043f\u043e\u0432 \u0441 \u043d\u0443\u043b\u044f.<\/p>\n<p><strong>\u041f\u043e\u0447\u0435\u043c\u0443 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439.<\/strong> \u0413\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432\u0440\u043e\u0434\u0435 web-shell \u0438\u043b\u0438 jslinux \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0442\u044f\u0436\u0451\u043b\u044b\u0435 \u0438 \u0437\u0430\u0442\u043e\u0447\u0435\u043d\u044b \u043f\u043e\u0434 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0443\u044e \u041e\u0421. \u041d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0431\u044b\u043b \u0443\u0447\u0435\u0431\u043d\u044b\u0439 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438 \u043f\u0430\u0439\u043f\u044b, \u043d\u043e \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p><strong>\u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432.<\/strong> \u041a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0430\u0440\u0441\u044f\u0442\u0441\u044f \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043a\u0430\u0432\u044b\u0447\u0435\u043a \u0438 \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"typescript\">function splitArgs(line: string): string[] {  const out: string[] = [];    let cur = \"\";  let q: '\"' | \"'\" | null = null;    for (let i = 0; i &lt; line.length; i++) {    const c = line[i];        if (q) {      if (c === q) { q = null; } else { cur += c; }      continue;    }        if (c === '\"' || c === \"'\") { q = c as '\"' | \"'\"; continue; }        if (\/\\s\/.test(c)) {      if (cur.length) { out.push(cur); cur = \"\"; }      continue;    }        cur += c;  }    if (cur.length) out.push(cur);    return out;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u0430\u0439\u043f\u044b.<\/strong> \u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0444\u0438\u0447\u0430 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u2014 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0430\u0439\u043f\u043e\u0432. \u0421\u0442\u0440\u043e\u043a\u0430 \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e <code>|<\/code>, \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u0435\u0433\u043c\u0435\u043d\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e, <code>stdout<\/code> \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f <code>stdin<\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e:<\/p>\n<pre><code class=\"typescript\">const segments = raw.split(\"|\").map(s =&gt; trim(s));let stdin = \"\";for (let i = 0; i &lt; segments.length; i++) {  const { out, env: ne } = runSegment(segments[i], stdin, env);    e = ne;    if (i === segments.length - 1) outs.push(out);  else stdin = out.endsWith(\"\\n\") ? out : `${out}\\n`;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b.<\/strong> \u041d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u0438\u0445 \u0432\u043e\u0441\u0435\u043c\u044c: echo, export, pwd, wc, grep, head, tail, cat. \u041a\u0430\u0436\u0434\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043a\u0430\u043a \u0447\u0438\u0441\u0442\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:<\/p>\n<pre><code class=\"typescript\">function cmdEcho(args: string[]): string {  return args.join(\" \");}function cmdWc(args: string[], stdin: string): string {  const text = stdin.replace(\/\\n$\/, \"\");  const lines = text.length ? text.split(\"\\n\").length : 0;  const words = text.trim().length ? text.trim().split(\/\\s+\/).length : 0;  const bytes = new TextEncoder().encode(stdin).length;    if (args[0] === \"-l\") return String(lines);  if (args[0] === \"-w\") return String(words);  if (args[0] === \"-c\") return String(bytes);    return `${lines} ${words} ${bytes}`;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/strong> export \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c Env, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c\u0438. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 $VAR:<\/p>\n<pre><code class=\"typescript\">function expandEnv(s: string, env: Env): string {  return s.replace(\/\\$([A-Za-z_][A-Za-z0-9_]*)\/g, (_, name: string) =&gt; env[name] ?? \"\");}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f.<\/strong> \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432, \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 (\u043a\u0440\u043e\u043c\u0435 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 PWD = &#8216;\/sandbox&#8217;). \u041d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \u0441 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u043e\u0439. \u0421\u043a\u0440\u0438\u043f\u0442\u044b \u0441 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u043e\u043c \u0441\u0442\u0440\u043e\u043a\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e, \u043a\u0430\u043a \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c shell.<\/p>\n<h3>Regex: \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 JavaScript \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 ReDoS<\/h3>\n<p>Regex-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u2014 \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438. \u041c\u044b \u043d\u0435 \u0441\u0442\u0430\u043b\u0438 \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0442\u044c \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 RegExp \u0434\u0432\u0438\u0436\u043e\u043a \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430. \u041d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u0438\u043d \u0432\u0430\u0436\u043d\u044b\u0439 \u043d\u044e\u0430\u043d\u0441 \u2014 ReDoS.<\/p>\n<p><strong>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0439.<\/strong> \u041f\u0440\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0438\u0441\u043a\u0435 \u043c\u044b \u043d\u0430\u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439 \u0434\u043e 5000:<\/p>\n<pre><code class=\"typescript\">let m: RegExpExecArray | null;const copy = new RegExp(pattern, flagStr);while ((m = copy.exec(haystack)) !== null) {  matches.push({ index: m.index, match: m[0], groups: m.slice(1) });    if (m[0].length === 0) copy.lastIndex++;  if (matches.length &gt; 5000) break; }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043b\u044e\u0441 \u0440\u0443\u0447\u043d\u0430\u044f \u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u043f\u0443\u0441\u0442\u044b\u0445 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0439 \u2014 \u0435\u0441\u043b\u0438 \u0434\u043b\u0438\u043d\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f 0, \u043c\u044b \u0441\u0434\u0432\u0438\u0433\u0430\u0435\u043c <code>lastIndex<\/code> \u043d\u0430 1, \u0447\u0442\u043e\u0431\u044b \u0446\u0438\u043a\u043b \u043d\u0435 \u0437\u0430\u0432\u0438\u0441.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0441 ReDoS.<\/strong> \u0412 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 <code>infinite<\/code> \u0441 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u043c <code>a<\/code> \u0438 \u0441\u0442\u0440\u043e\u043a\u043e\u0439 \u0438\u0437 5000 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u2014 \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0430\u0435\u0442 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c ReDoS-\u0432\u0435\u043a\u0442\u043e\u0440\u0435.<\/p>\n<h3>Cron: \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0435\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h3>\n<p>Cron-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u2014 \u044d\u0442\u043e \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430, \u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 cron-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0438 \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0447\u0430\u0441\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u044f\u0441\u0430.<\/p>\n<p><strong>\u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u0447\u0435\u0440\u0435\u0437 cron-parser.<\/strong> \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c cron-parser v5 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 cron-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"typescript\">export function parseCronExpression(expression: string, options?: { currentDate?: Date; tz?: string }) {  return CronExpressionParser.parse(expression.trim(), {    currentDate: options?.currentDate ?? new Date(),    ...(options?.tz ? { tz: options.tz } : {}),  });}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0427\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435.<\/strong> <code>cronstrue<\/code> \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, &#171;\u041a\u0430\u0436\u0434\u044b\u0435 15 \u043c\u0438\u043d\u0443\u0442&#187;). \u0414\u0430\u0442\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 Luxon \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0447\u0430\u0441\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u044f\u0441\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p><strong>\u0418\u0437\u043e\u043b\u044f\u0446\u0438\u044f.<\/strong> \u0417\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u0432 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0441\u043c\u044b\u0441\u043b\u0435 \u2014 cron-\u043f\u0430\u0440\u0441\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0438 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u0434. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0437\u0430\u0449\u0438\u0442\u0430 \u2014 try\/catch \u043d\u0430 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h3>\u041e\u0431\u0449\u0438\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438<\/h3>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u0432\u043e\u0441\u0435\u043c\u044c \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446:<\/p>\n<ol>\n<li>\n<p><strong>\u041d\u0438\u043a\u0430\u043a\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/strong> \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u041c\u044b \u043d\u0435 \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>Web Worker \u0434\u043b\u044f \u0442\u044f\u0436\u0451\u043b\u043e\u0433\u043e.<\/strong> JS, Python, SQL \u2014 \u0432\u0441\u0451, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0438\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u0434, \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u043e \u0432 \u0432\u043e\u0440\u043a\u0435\u0440\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>\u0422\u0430\u0439\u043c\u0430\u0443\u0442\u044b \u0432\u0435\u0437\u0434\u0435.<\/strong> \u041a\u0430\u0436\u0434\u0430\u044f \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u0438\u043c\u0435\u0435\u0442 \u043b\u0438\u043c\u0438\u0442 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041f\u0440\u0438 \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u0438\u0438 \u2014 \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 <code>terminate<\/code> \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u0438\u043b\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u043e\u0448\u0438\u0431\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a.<\/strong> \u041c\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432\u043e\u0440\u043a\u0435\u0440\u044b \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043c\u0438. \u041a\u0430\u0436\u0434\u044b\u0439 Run \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u043e\u0432\u044b\u0439 Worker, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u043e\u0434 \u0438 \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0430\u0435\u0442\u0441\u044f. \u042d\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0443\u0442\u0435\u0447\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0430\u0442\u0430\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 \u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>\u041b\u0438\u043c\u0438\u0442\u044b \u043f\u043e \u043e\u0431\u044a\u0451\u043c\u0443.<\/strong> \u041a\u0430\u0436\u0434\u0430\u044f \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u0438\u043c\u0435\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0432\u043e \u0432\u0445\u043e\u0434\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u2014 \u043e\u0442 100 000 (Python) \u0434\u043e 200 000 (JS, SQL). \u042d\u0442\u043e \u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0434\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.<\/strong> \u0412\u0441\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u043f\u0443\u0441\u0442\u043e\u0442\u0443 \u0438 \u0434\u043b\u0438\u043d\u0443 \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c. \u042d\u0442\u043e \u043e\u0442\u0441\u0435\u043a\u0430\u0435\u0442 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435 \u0430\u0442\u0430\u043a\u0438 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430.<\/p>\n<\/li>\n<\/ol>\n<h3>\u0427\u0442\u043e \u043c\u044b \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430<\/h3>\n<p><strong>\u0421\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 Bash \u2014 \u044d\u0442\u043e \u0431\u043e\u043b\u044c.<\/strong> \u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u043f\u0430\u0439\u043f\u043e\u0432, \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u0440\u0430\u0435\u0432\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u0441 \u043a\u0430\u0432\u044b\u0447\u043a\u0430\u043c\u0438 \u2014 \u043d\u0430 \u044d\u0442\u043e \u0443\u0448\u043b\u043e \u043d\u0435\u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041d\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043b\u0451\u0433\u043a\u0438\u0445 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432 \u043c\u044b \u043d\u0435 \u043d\u0430\u0448\u043b\u0438, \u0430 \u0442\u0430\u0449\u0438\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c.<\/p>\n<p><strong>Pyodide \u2014 \u0442\u044f\u0436\u0451\u043b\u044b\u0439, \u043d\u043e \u0431\u0435\u0437\u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439.<\/strong> \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 Wasm-\u0444\u0430\u0439\u043b\u0430 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445. \u041d\u043e \u0431\u0435\u0437 Pyodide \u043c\u044b \u043d\u0435 \u0441\u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 Python \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. Fallback \u043f\u043e \u0437\u0435\u0440\u043a\u0430\u043b\u0430\u043c \u0441\u043f\u0430\u0441\u0430\u0435\u0442 \u043e\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 CDN.<\/p>\n<p><strong>SQL.js \u0438 AbortController \u2014 \u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u043a\u0430.<\/strong> db.exec \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u0438 <code>AbortController<\/code> \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0444\u043b\u0430\u0433 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0448\u0430\u0435\u0442 SQLite \u043d\u0430 10 \u0441\u0435\u043a\u0443\u043d\u0434, \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0432\u0435\u0448\u0430\u0435\u0442 \u0432\u043e\u0440\u043a\u0435\u0440 \u043d\u0430 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u2014 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043e\u0431 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0444\u0430\u043a\u0442\u0443\u043c.<\/p>\n<p><strong>DOMPurify \u2014 \u043c\u0430\u0441\u0442\u0445\u0435\u0432.<\/strong> \u0411\u0435\u0437 \u043d\u0435\u0433\u043e Markdown-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u0431\u044b\u043b\u0430 \u0431\u044b \u0434\u044b\u0440\u043e\u0439 \u0432 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438. \u0412\u0430\u0439\u0442\u043b\u0438\u0441\u0442 \u0442\u0435\u0433\u043e\u0432 \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0430\u0440\u0430\u043d\u043e\u0439\u044f, \u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0448\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 HTML.<\/p>\n<p><strong>Web Worker \u2014 \u0441\u0435\u0440\u0435\u0431\u0440\u044f\u043d\u0430\u044f \u043f\u0443\u043b\u044f \u0434\u043b\u044f JS.<\/strong> \u041f\u0440\u043e\u0441\u0442\u043e, \u043d\u0430\u0434\u0451\u0436\u043d\u043e, \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0438\u0437\u043e\u043b\u0438\u0440\u0443\u0435\u0442. \u0416\u0430\u043b\u044c \u0442\u043e\u043b\u044c\u043a\u043e, \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0435 \u0446\u0438\u043a\u043b\u044b \u0432\u043d\u0443\u0442\u0440\u0438 <code>setTimeout<\/code> \u2014 \u043d\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u043d\u0435 \u043d\u0430\u0448\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430.<\/p>\n<h3>\u041e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u044c \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h3>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u2014 \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <strong>Halfcoder<\/strong>, \u043d\u0430\u0431\u043e\u0440\u0430 \u0438\u0437 167+ \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u043d\u0438\u0445 \u0432\u0436\u0438\u0432\u0443\u044e \u0438\u043b\u0438 \u043f\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u2014 \u0437\u0430\u0445\u043e\u0434\u0438\u0442\u0435 \u043d\u0430 <a href=\"http:\/\/halfcoder.ru\" rel=\"noopener noreferrer nofollow\">halfcoder.ru<\/a>.<\/p>\n<p>\u0411\u0443\u0434\u0443 \u0440\u0430\u0434 \u043b\u044e\u0431\u043e\u0439 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438: \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438 \u0432\u044b \u0431\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b\u0438, \u0433\u0434\u0435 \u043c\u044b \u043f\u0435\u0440\u0435\u043c\u0443\u0434\u0440\u0438\u043b\u0438, \u0430 \u0433\u0434\u0435 \u043d\u0435\u0434\u043e\u0436\u0430\u043b\u0438. \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043f\u043e\u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0442\u0435\u0445, \u043a\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u043b \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u2014 \u0441 \u043a\u0430\u043a\u0438\u043c\u0438 \u0443\u0433\u0440\u043e\u0437\u0430\u043c\u0438 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0438\u0441\u044c, \u043a\u0430\u043a \u0440\u0435\u0448\u0430\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u043e\u0432, \u0447\u0435\u043c \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u0434. \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u0434\u043e\u043a\u043b\u0430\u0434\u044b \u0438\u043b\u0438 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u043e \u0442\u0435\u043c\u0435 \u2014 \u043a\u0438\u0434\u0430\u0439\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445, \u0431\u0443\u0434\u0443 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0435\u043d.<\/p>\n<p>\u0415\u0449\u0451 \u044f \u0432\u0435\u0434\u0443 \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c-\u043a\u0430\u043d\u0430\u043b <a href=\"https:\/\/t.me\/itsisyphus\" rel=\"noopener noreferrer nofollow\"><strong>\u0421\u0438\u0437\u0438\u0444 IT<\/strong><\/a>, \u0433\u0434\u0435 \u043f\u0438\u0448\u0443 \u043f\u0440\u043e IT-\u043d\u043e\u0432\u043e\u0441\u0442\u0438, \u0434\u0435\u043b\u044e\u0441\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u043a\u0438\u0434\u0430\u044e \u043c\u0435\u043c\u044b. <\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1051752\/\">https:\/\/habr.com\/ru\/articles\/1051752\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u043d\u0430\u043c \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u0434\u043b\u044f \u043a\u043e\u0434\u0430 \u2014 \u0442\u0430\u043a\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c JavaScript-\u0441\u043d\u0438\u043f\u043f\u0435\u0442, \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u043b\u0438 \u043f\u043e\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 Python. \u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e, \u0431\u0435\u0437 \u0440\u0435\u043a\u043b\u0430\u043c\u044b \u0438 \u0431\u0435\u0437 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438. \u041f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0448\u044c \u0438 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0448\u044c\u0441\u044f. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u00ab\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Pro-\u0432\u0435\u0440\u0441\u0438\u0438\u00bb \u0438\u043b\u0438 \u00ab\u0432\u044b \u0438\u0441\u0447\u0435\u0440\u043f\u0430\u043b\u0438 \u043b\u0438\u043c\u0438\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432\u00bb. \u041d\u043e \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0435, \u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u2014 \u044f\u0449\u0438\u043a \u041f\u0430\u043d\u0434\u043e\u0440\u044b. \u0414\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u2014 \u0437\u043d\u0430\u0447\u0438\u0442 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0434\u0432\u0435\u0440\u044c \u0434\u043b\u044f \u0446\u0435\u043b\u043e\u0433\u043e \u0431\u0443\u043a\u0435\u0442\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c: \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0435 \u0446\u0438\u043a\u043b\u044b, XSS-\u0432\u0435\u043a\u0442\u043e\u0440\u044b, \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a DOM, \u0443\u0442\u0435\u0447\u043a\u0438 \u043f\u0430\u043c\u044f\u0442\u0438, \u0432\u0440\u0435\u0434\u043e\u043d\u043e\u0441\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0443\u043d\u043a\u0442 \u043f\u043e-\u0441\u0432\u043e\u0435\u043c\u0443 \u043e\u043f\u0430\u0441\u0435\u043d, \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043c\u044b \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u044b. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 Docker-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u043e\u043a, \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434. \u0412\u0441\u0451 \u0434\u043e\u043b\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u2014 \u0431\u044b\u0441\u0442\u0440\u043e, \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e \u0438 \u0431\u0435\u0437 \u0437\u0430\u0442\u0440\u0430\u0442 \u043d\u0430 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443.\u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u043b\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0436\u0438\u0432\u0451\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u041f\u0440\u0438\u0447\u0451\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0440\u0435\u0434\u044b \u2014 JavaScript, Python, SQL, HTML\/CSS, Markdown, Bash, Regex, Cron \u2014 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434. \u0413\u0434\u0435-\u0442\u043e \u0445\u0432\u0430\u0442\u0430\u0435\u0442 Web Worker, \u0433\u0434\u0435-\u0442\u043e \u043d\u0443\u0436\u0435\u043d WebAssembly \u0441 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439, \u0430 \u0433\u0434\u0435-\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0441 \u043d\u0443\u043b\u044f.\u0412 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0432\u043e\u0441\u0435\u043c\u044c \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438. \u0414\u0430\u043b\u044c\u0448\u0435 \u2014 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u0440\u0430\u0437\u0431\u043e\u0440 \u043a\u0430\u0436\u0434\u043e\u0439: \u043a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u0430, \u043a\u0430\u043a\u0438\u0435 \u0443\u0433\u0440\u043e\u0437\u044b \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0438 \u0441 \u043a\u0430\u043a\u0438\u043c\u0438 \u0433\u0440\u0430\u0431\u043b\u044f\u043c\u0438 \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c.JavaScript: Web Worker \u0438 \u0440\u0443\u0447\u043d\u043e\u0439 \u0442\u0430\u0439\u043c\u0430\u0443\u0442JavaScript-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u2014 \u0441\u0430\u043c\u0430\u044f \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u0430\u044f \u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441\u0430\u043c\u0430\u044f \u043e\u043f\u0430\u0441\u043d\u0430\u044f. \u0414\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u2014 \u0437\u043d\u0430\u0447\u0438\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0435\u043c\u0443 \u0434\u043e\u0442\u044f\u043d\u0443\u0442\u044c\u0441\u044f \u0434\u043e DOM, window, \u043a\u0443\u043a\u0438 \u0438 \u0432\u0441\u0435\u0433\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u043e\u0435 \u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435: \u043a\u043e\u0434 \u043b\u0435\u0442\u0438\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 Web Worker.\u0423 \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a DOM, document \u0438 window \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430. \u041d\u043e \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0434\u0432\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u0432\u044b\u0432\u043e\u0434 console.log \u0438 \u043a\u0430\u043a \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430.\u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442 \u043a\u043e\u043d\u0441\u043e\u043b\u0438. \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0433\u043b\u0443\u0448\u0438\u0442\u044c \u0432\u044b\u0432\u043e\u0434 \u0441\u043e\u0432\u0441\u0435\u043c, \u043c\u044b \u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0435\u043c console.log, error, warn \u0438 info \u0432\u043d\u0443\u0442\u0440\u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u0430. \u041a\u0430\u0436\u0434\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0438 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0430\u0441\u0441\u0438\u0432 logs. \u041a\u043e\u0433\u0434\u0430 \u043a\u043e\u0434 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u2014 \u043c\u0430\u0441\u0441\u0438\u0432 \u0443\u043b\u0435\u0442\u0430\u0435\u0442 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0447\u0435\u0440\u0435\u0437 postMessage:const logs: string[] = [];const cons = {  log: (&#8230;a: unknown[]) =&gt; {    logs.push(a.map((x) =&gt;      typeof x === &#171;object&#187; ? JSON.stringify(x) : String(x)    ).join(&#187; &#171;));  },  error: (&#8230;a: unknown[]) =&gt; {    logs.push(&#171;[error] &#187; + a.map((x) =&gt;      typeof x === &#171;object&#187; ? JSON.stringify(x) : String(x)    ).join(&#187; &#171;));  },  \/\/ &#8230;warn, info \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e};\u041f\u043e\u0434\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u0439 console \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u0434 \u043a\u0430\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u2014 \u0447\u0435\u0440\u0435\u0437 new Function(&#171;console&#187;, &#8230;). \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u0435\u043c, \u043a\u043e\u0434 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f.\u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b. \u0412\u043e\u0440\u043a\u0435\u0440 \u2014 \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a, \u0442\u0430\u043a \u0447\u0442\u043e UI \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u043d\u0435\u0442 \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435. \u041d\u043e \u0441\u0430\u043c \u0432\u043e\u0440\u043a\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0432\u0438\u0441\u0435\u0442\u044c \u0432\u0435\u0447\u043d\u043e, \u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u043c\u0435\u0442\u044c \u0435\u0433\u043e \u043f\u0440\u0438\u0431\u0438\u0432\u0430\u0442\u044c. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u2014 setTimeout \u0441 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0438\u0442 terminate:const timer = setTimeout(() =&gt; finish({ kind: &#171;timeout&#187; }), timeoutMs);\u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u2014 \u0432\u043e\u0440\u043a\u0435\u0440 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 { kind: &#171;timeout&#187; } \u0438 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0444\u043b\u0430\u0433 finished, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u044b\u0437\u043e\u0432\u044b finish \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 async\/await \u0432\u043d\u0443\u0442\u0440\u0438 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f \u2014 \u0435\u0441\u043b\u0438 \u043e\u043d \u0437\u0430\u0432\u0438\u0441 \u0432 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0446\u0438\u043a\u043b\u0435, \u0442\u043e \u0434\u043e await \u0434\u0435\u043b\u043e \u043d\u0435 \u0434\u043e\u0439\u0434\u0451\u0442, \u043d\u043e \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0432\u043e\u0440\u043a\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0435\u043d \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u0432\u044b\u0437\u043e\u0432\u043e\u043c terminate.\u0415\u0441\u0442\u044c \u043d\u044e\u0430\u043d\u0441: \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0432\u043d\u0443\u0442\u0440\u0438 setTimeout \u0438\u043b\u0438 Promise, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c, \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u043d\u0435 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442 \u2014 \u043d\u043e \u0441\u0430\u043c \u0432\u043e\u0440\u043a\u0435\u0440 \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 terminated \u043a \u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443.\u041b\u0438\u043c\u0438\u0442\u044b: 200 000 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u043a\u043e\u0434, \u0442\u0430\u0439\u043c\u0430\u0443\u0442 10 \u0441\u0435\u043a\u0443\u043d\u0434. \u0412\u043e\u0440\u043a\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0437\u0430\u043d\u043e\u0432\u043e \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u2014 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0443\u0442\u0435\u0447\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.Python: Pyodide \u0441 \u0446\u0435\u043f\u043e\u0447\u043a\u043e\u0439 \u0437\u0435\u0440\u043a\u0430\u043bPython-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043d\u0430 Pyodide \u2014 CPython, \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0432 WebAssembly. \u0418 \u0432 \u044d\u0442\u043e\u043c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: Pyodide \u2014 \u044d\u0442\u043e \u0437\u0434\u043e\u0440\u043e\u0432\u0435\u043d\u043d\u044b\u0439 Wasm-\u0444\u0430\u0439\u043b, \u0438 \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043a\u0443\u0434\u0430-\u0442\u043e \u0433\u0440\u0443\u0437\u0438\u0442\u044c.Fallback \u043f\u043e \u0437\u0435\u0440\u043a\u0430\u043b\u0430\u043c. \u041c\u044b \u043d\u0435 \u0441\u0442\u0430\u043b\u0438 \u0437\u0430\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043e\u0434\u0438\u043d CDN. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u0442\u0440\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0438 \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0438\u0445 \u043f\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u0438:const INDEX_CANDIDATES = [  &#171;https:\/\/cdn.jsdelivr.net\/pyodide\/v0.26.1\/full\/&#187;,  &#171;https:\/\/cdn.jsdelivr.net\/pyodide\/v0.25.0\/full\/&#187;,  &#171;https:\/\/unpkg.com\/pyodide@0.26.1\/full\/&#187;,];\u0424\u0443\u043d\u043a\u0446\u0438\u044f pickWorkingIndexBase \u0434\u0435\u043b\u0430\u0435\u0442 HEAD-\u0437\u0430\u043f\u0440\u043e\u0441 \u043a pyodide.js \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0435\u0440\u043a\u0430\u043b\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0432\u043e\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0435. \u0422\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f importScripts \u0438 loadPyodide. \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 Web Worker \u2014 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435.\u0418\u0437\u043e\u043b\u044f\u0446\u0438\u044f. Pyodide \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u043d\u0435 \u0434\u0430\u0451\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0445\u043e\u0441\u0442\u0430. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u2014 json, re, math \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041d\u043e import os \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c. \u041d\u0438\u043a\u0430\u043a\u043e\u0433\u043e pip \u0442\u043e\u0436\u0435 \u043d\u0435\u0442 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e, \u0447\u0442\u043e \u0443\u0436\u0435 \u0432\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0432 Pyodide.\u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442 \u0432\u044b\u0432\u043e\u0434\u0430. Pyodide \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b setStdout \u0438 setStderr. \u041c\u044b \u0432\u0435\u0448\u0430\u0435\u043c \u043d\u0430 \u043d\u0438\u0445 batched-\u043a\u043e\u043b\u0431\u044d\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442 \u0432\u044b\u0432\u043e\u0434 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443. \u0412\u0430\u0436\u043d\u044b\u0439 \u043d\u044e\u0430\u043d\u0441: Pyodide \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e print \u0432 \u043e\u0434\u043d\u043e\u043c \u0431\u0430\u0442\u0447\u0435, \u0431\u0435\u0437 \\n \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u043f\u043e\u043b\u043d\u044b\u0445 \u0447\u0430\u043d\u043a\u043e\u0432:const appendLine = (buf: string, s: string) =&gt; {  if (!s) return buf;    return buf + (s.endsWith(&#171;\\n&#187;) ? s : `${s}\\n`);};\u0422\u0430\u0439\u043c\u0430\u0443\u0442. \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0432 JS-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435: setTimeout \u043d\u0430 \u043d\u0443\u0436\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434 \u043f\u043b\u044e\u0441 \u0437\u0430\u043f\u0430\u0441 \u043d\u0430 \u0442\u043e\u0440\u043c\u043e\u0437\u0430 Wasm. \u041f\u0440\u0438 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f { type: &#171;run-timeout&#187; }. \u041f\u043b\u044e\u0441 \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 { type: &#171;cancel&#187; }, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u0430\u0439\u043c\u0435\u0440 \u2014 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u043a\u043e\u0434 \u0437\u0430\u043d\u043e\u0432\u043e, \u043d\u0435 \u0434\u043e\u0436\u0438\u0434\u0430\u044f\u0441\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e.\u041b\u0438\u043c\u0438\u0442\u044b: 100 000 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u043a\u043e\u0434, \u0442\u0430\u0439\u043c\u0430\u0443\u0442 25 \u0441\u0435\u043a\u0443\u043d\u0434 (Python \u0432 Wasm \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e JS).SQL: SQL.js \u0432 Web Worker \u0441 \u0440\u0443\u0447\u043d\u044b\u043c locateFile\u0414\u043b\u044f SQL-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 SQL.js \u2014 SQLite, \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432 WebAssembly. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 Web Worker, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u043f\u0440\u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0435 \u0442\u044f\u0436\u0451\u043b\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 Wasm \u0431\u0435\u0437 CDN. sql.js \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c wasm-\u0444\u0430\u0439\u043b \u0441 CDN (sql.js.org). \u042d\u0442\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442: \u0432\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043b\u0438\u0448\u043d\u044f\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430, \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445 \u2014 \u043d\u0430 sql.js.org \u043d\u0435\u0442 \u0444\u0430\u0439\u043b\u0430 sql-wasm-browser.wasm, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0431\u0430\u043d\u0434\u043b (\u0442\u0430\u043c \u043b\u0435\u0436\u0438\u0442 HTML \u0432\u043c\u0435\u0441\u0442\u043e wasm, \u0438 \u0434\u0432\u0438\u0436\u043e\u043a \u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c locateFile:function locateSqlWasm(file: string): string {  const origin = self.location?.origin;    if (!origin || !file.endsWith(&#8216;.wasm&#8217;)) {    return `https:\/\/sql.js.org\/dist\/${file}`;  }    if (file.includes(&#8216;sql-wasm-browser&#8217;)) {    return `${origin}\/wasm\/sql-wasm-browser.wasm`;  }    return `${origin}\/wasm\/sql-wasm.wasm`;}Wasm-\u0444\u0430\u0439\u043b\u044b \u0440\u0430\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0441 \u0442\u043e\u0433\u043e \u0436\u0435 origin, \u0447\u0442\u043e \u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 CDN \u2014 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0438 \u043d\u0430\u0434\u0451\u0436\u043d\u0435\u0435.\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b. \u041a\u0430\u0436\u0434\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438: \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 Database, \u043d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0445\u0435\u043c\u0430 \u0438\u0437 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430:db = new S.Database();if (msg.payload.schemaSql.trim()) {  db.run(msg.payload.schemaSql);}\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0441\u0440\u0430\u0437\u0443 \u043f\u0438\u0441\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u043d\u0438\u043c.\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 AbortController. \u0413\u043b\u0430\u0432\u043d\u0430\u044f \u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c SQL-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u2014 \u0437\u0430\u043f\u0440\u043e\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0448\u0430\u0435\u0442 \u0431\u0430\u0437\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, cross join \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445 \u0438\u043b\u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 CTE). sql.js \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u0438 \u043f\u0440\u043e\u0441\u0442\u043e setTimeout \u0442\u0443\u0442 \u043d\u0435 \u043f\u043e\u043c\u043e\u0436\u0435\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c AbortController:const ac = new AbortController();const timer = setTimeout(() =&gt; ac.abort(), timeoutMs);const results = db.exec(sql);if (ac.signal.aborted) {  post({ type: &#171;error&#187;, payload: { message: &#171;\u041f\u0440\u0435\u0432\u044b\u0448\u0435\u043d \u0442\u0430\u0439\u043c\u0430\u0443\u0442&#8230;&#187; } });  return;}\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043d\u0435 \u0431\u044b\u043b \u043b\u0438 \u0441\u0438\u0433\u043d\u0430\u043b \u043f\u0440\u0435\u0440\u0432\u0430\u043d \u0437\u0430 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b db.exec. \u0415\u0441\u043b\u0438 \u0431\u044b\u043b \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430.\u0412\u044b\u0432\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 (SELECT), \u043c\u044b \u043e\u0442\u0434\u0430\u0451\u043c \u0438\u0445 \u043a\u0430\u043a { kind: &#171;select&#187;, columns, rows }. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e INSERT\/UPDATE\/DELETE \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c { kind: &#171;ok&#187;, message }. \u0415\u0441\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0430 \u2014 { kind: &#171;error&#187;, message }.\u041b\u0438\u043c\u0438\u0442\u044b: 200 000 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u0441\u043a\u0440\u0438\u043f\u0442 (\u0441\u0445\u0435\u043c\u0430 + \u0437\u0430\u043f\u0440\u043e\u0441), \u0442\u0430\u0439\u043c\u0430\u0443\u0442 5 \u0441\u0435\u043a\u0443\u043d\u0434.HTML\/CSS: iframe \u0441 sandbox \u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 srcdocHTML\/CSS-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u0441\u0442\u043e\u0438\u0442 \u043e\u0441\u043e\u0431\u043d\u044f\u043a\u043e\u043c. \u0417\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u043c \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u0438 \u0441\u0442\u0438\u043b\u0438, \u0430 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.\u0418\u0437\u043e\u043b\u044f\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 iframe sandbox. \u041f\u0440\u0435\u0432\u044c\u044e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u0432 &lt;iframe sandbox=&#187;allow-scripts&#187;&gt;. \u0410\u0442\u0440\u0438\u0431\u0443\u0442 sandbox \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044e, \u0430 allow-scripts \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 JavaScript \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0435\u0432\u044c\u044e, \u043d\u043e \u0431\u0435\u0437 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a cookie \u0438 DOM \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b. \u0414\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u0442 &lt;script&gt;document.cookie&lt;\/script&gt;, \u043e\u043d \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0441\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 Halfcoder.\u0421\u0431\u043e\u0440\u043a\u0430 srcdoc. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 HTML \u0438 CSS \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e. \u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442:function buildSrcDoc(html: string, css: string): string {  const style = css.trim() ? `&lt;style&gt;${css}&lt;\/style&gt;` : &#171;&#187;;    if (\/&lt;html[\\s&gt;]\/i.test(html)) {    if (\/&lt;head[\\s&gt;]\/i.test(html)) {      return html.replace(\/&lt;\\\/head&gt;\/i, `${style}&lt;\/head&gt;`);    }        return html.replace(\/&lt;html[^&gt;]*&gt;\/i, (m) =&gt; `${m}&lt;head&gt;${style}&lt;\/head&gt;`);  }    return `&lt;!DOCTYPE html&gt;&lt;html&gt;&lt;head&gt;&lt;meta charset=&#187;utf-8&#8243;&gt;${style}&lt;\/head&gt;&lt;body&gt;${html}&lt;\/body&gt;&lt;\/html&gt;`;}\u0413\u043e\u0442\u043e\u0432\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432 srcDoc \u0430\u0442\u0440\u0438\u0431\u0443\u0442 iframe. \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 500 \u043c\u0441 \u0447\u0435\u0440\u0435\u0437 debounce \u2014 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0432\u044c\u044e \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438.\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f. \u041f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430 \u043d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 CSS-\u0438\u043d\u044a\u0435\u043a\u0446\u0438\u0438 \u2014 \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0438\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u043e\u043c\u0430\u0435\u0442 \u0432\u0451\u0440\u0441\u0442\u043a\u0443 \u0432\u043d\u0443\u0442\u0440\u0438 iframe, \u043d\u043e \u043d\u0430\u0440\u0443\u0436\u0443 \u044d\u0442\u043e \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442. JavaScript \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0435\u0432\u044c\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0439\u0442\u0438 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b iframe.Markdown: DOMPurify \u0441 \u0436\u0451\u0441\u0442\u043a\u0438\u043c \u0432\u0430\u0439\u0442\u043b\u0438\u0441\u0442\u043e\u043cMarkdown-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430, \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u0441\u0430\u043c\u0430\u044f \u0431\u0435\u0437\u043e\u0431\u0438\u0434\u043d\u0430\u044f. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0438\u0448\u0435\u0442 Markdown, \u043c\u044b \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043c HTML. \u041e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u2014 XSS \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 HTML \u0438\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u0437\u0430\u043c\u0430\u0441\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434 Markdown-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443.\u0421\u0430\u043d\u0438\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 DOMPurify. \u041f\u043e\u0441\u043b\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0447\u0435\u0440\u0435\u0437 marked, \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u0439\u0441\u044f HTML \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 DOMPurify \u0441 \u0436\u0451\u0441\u0442\u043a\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0445 \u0442\u0435\u0433\u043e\u0432:function sanitizeMarkdownHtml(raw: string): string {  return DOMPurify.sanitize(raw, {    USE_PROFILES: { html: true },&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-484965","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/484965","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=484965"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/484965\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=484965"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=484965"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=484965"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}