{"id":346292,"date":"2023-03-05T21:00:31","date_gmt":"2023-03-05T21:00:31","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=346292"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=346292","title":{"rendered":"<span>\u041a\u0430\u043a \u0441\u0430\u0439\u0442\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u0431\u043e\u0442\u043e\u0432? \u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f Akamai Bot Manager 2.0<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>Akamai Technologies &#8212; \u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f, \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0449\u0430\u044f\u0441\u044f \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u0432\u0435\u0431-\u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043e\u0442 \u0431\u043e\u0442\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0432\u043e\u0435\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 Bot Manager. \u0412 \u0435\u0451 \u043f\u043e\u0440\u0442\u0444\u043e\u043b\u0438\u043e \u0447\u0438\u0441\u043b\u044f\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u0435 \u0433\u0438\u0433\u0430\u043d\u0442\u044b \u0440\u0438\u0442\u0435\u0439\u043b\u0430, \u043a\u0430\u043a Nike, Adidas \u0438 Asos, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u0435\u043d \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0437\u0430 \u0431\u043e\u0442\u0430\u043c\u0438, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0438\u043c\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u044b\u043a\u0443\u043f\u0430 \u0440\u0435\u0434\u043a\u0438\u0445\/\u043b\u0438\u043c\u0438\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0441 \u0446\u0435\u043b\u044c\u044e \u0438\u0445 \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0434\u0430\u0436\u0438 \u043f\u043e \u0437\u0430\u0432\u044b\u0448\u0435\u043d\u043d\u043e\u0439 \u0446\u0435\u043d\u0435. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0441\u043a\u0440\u0438\u043f\u0442 \u0430\u043d\u0442\u0438\u0431\u043e\u0442\u0430 Akamai \u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 JavaScript \u0432 \u043d\u0451\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f. \u041b\u044e\u0431\u0438\u0442\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c selenium? \u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c! <\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u0434\u043e\u043f\u044b\u0442\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0434\u043b\u044f \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439 \u0432\u044b\u0431\u0435\u0440\u0435\u043c \u043b\u043e\u0433\u0438\u043d \u043d\u0430 \u0441\u0430\u0439\u0442\u0435 <a href=\"https:\/\/my.asos.com\/\" rel=\"noopener noreferrer nofollow\">Asos<\/a>. \u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u043e\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0442\u043e \u0432 \u043e\u0431\u044b\u0447\u043d\u043e\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043d\u0430\u0441 \u0436\u0434\u0451\u0442 \u043e\u0448\u0438\u0431\u043a\u0430 \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0445 \u0443\u0447\u0451\u0442\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 Access Denied.<\/p>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438\u043d \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438 playwright chromium <\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/34f\/101\/b8e\/34f101b8e5f0f1109a9e0dbd5b369aec.gif\" width=\"1103\" height=\"686\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/34f\/101\/b8e\/34f101b8e5f0f1109a9e0dbd5b369aec.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0418\u0441\u0445\u043e\u0434\u044f <a href=\"https:\/\/habr.com\/ru\/post\/716434\/\" rel=\"noopener noreferrer nofollow\">\u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043e\u043f\u044b\u0442\u0430<\/a>, \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u0434\u0435\u043b\u043e \u0432 \u043a\u0430\u043a\u0438\u0445-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u0443\u043a\u0430\u0445, \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0433\u043b\u0430\u0437\u0430 \u0441\u0430\u043c\u0438 \u0446\u0435\u043f\u043b\u044f\u044e\u0442\u0441\u044f \u0437\u0430 \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043e\u0431\u044a\u0451\u043c\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<details class=\"spoiler\">\n<summary>sensor_data request payload<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/61d\/731\/9f1\/61d7319f1c8a0576c45fd31070328177.png\" width=\"1322\" height=\"674\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/61d\/731\/9f1\/61d7319f1c8a0576c45fd31070328177.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0411\u0435\u0436\u0438\u043c \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u044b\u043b\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0438 \u0432\u0438\u0434\u0438\u043c \u043d\u0435\u0447\u0442\u043e:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0bb\/5a4\/a18\/0bb5a4a18d2d1ee81363f9465643a1f1.png\" alt=\"\u0412\u0438\u043d\u043e\u0432\u043d\u0438\u043a \u043d\u0430\u0448\u0438\u0445 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u0439\" title=\"\u0412\u0438\u043d\u043e\u0432\u043d\u0438\u043a \u043d\u0430\u0448\u0438\u0445 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u0439\" width=\"1163\" height=\"793\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0bb\/5a4\/a18\/0bb5a4a18d2d1ee81363f9465643a1f1.png\"\/><\/p>\n<div><figcaption>\u0412\u0438\u043d\u043e\u0432\u043d\u0438\u043a \u043d\u0430\u0448\u0438\u0445 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u0439<\/figcaption><\/div>\n<\/figure>\n<h2>\u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u0438<\/h2>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0423 \u043c\u0435\u043d\u044f \u0431\u0443\u0434\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u043e\u0442\u0441\u044b\u043b\u043e\u043a <a href=\"https:\/\/habr.com\/ru\/post\/716434\/\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e<\/a>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u0438 \u0442\u0435\u043c\u044b \u0442\u0435\u0441\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u044b. \u0422\u0430\u043c \u0440\u0435\u0447\u044c \u0448\u043b\u0430 \u043e \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438 \u044f \u043f\u0438\u0448\u0443 \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u043e \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440 \u0438\u043b\u0438 \u043f\u0440\u043e \u043d\u0430\u0448 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u043e\u043f\u044b\u0442, \u0442\u043e \u0438\u043c\u0435\u044e \u0432 \u0432\u0438\u0434\u0443 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0433\u0434\u0435-\u043d\u0438\u0431\u0443\u0434\u044c \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435:<\/p>\n<details class=\"spoiler\">\n<summary>debugger<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/489\/19e\/640\/48919e6400587ad2a6639d8b26673789.gif\" width=\"1273\" height=\"758\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/489\/19e\/640\/48919e6400587ad2a6639d8b26673789.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432\u0438\u0434\u0430 <code>EE.XX(foo, bar])<\/code> \u0438\u043b\u0438 <code>EE.yy.apply(null, [a,b,c,d])<\/code> \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0438, \u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u0445 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043d\u0430\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043c\u0435\u0448\u0430\u0435\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u043c. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043c\u044b \u0435\u0449\u0451 \u0438\u043c\u0435\u0435\u043c <a href=\"https:\/\/docs.jscrambler.com\/code-integrity\/tutorials\/control-flow-flattening\" rel=\"noopener noreferrer nofollow\">Control Flow Flattening<\/a>(\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u0430\u043a-\u0442\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043a\u043e\u0434 \u043d\u0430 \u0431\u043b\u043e\u043a\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0438\u0445 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435), \u043f\u0440\u043e\u043a\u0441\u0438-\u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"javascript\">function plus(a, b) {   return a + b; }  plus(plus(1, 2), plus(3, 4))<\/code><\/pre>\n<p>\u0437\u043d\u0430\u043c\u0435\u043d\u0438\u0442\u044b\u0435 <a href=\"http:\/\/www.jsfuck.com\/\" rel=\"noopener noreferrer nofollow\">JS-Fuck<\/a> \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f:<\/p>\n<details class=\"spoiler\">\n<summary>jsfuck<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c12\/287\/947\/c122879477b506b100f9804eb12728c4.png\" width=\"403\" height=\"189\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c12\/287\/947\/c122879477b506b100f9804eb12728c4.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435&#8230;<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u0435\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u044b\u0437\u043e\u0432\u044b \u0441\u0442\u0440\u043e\u043a. \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>EE<\/code> \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0442\u0430\u043a\u0438\u0445 \u0432\u044b\u0437\u043e\u0432\u0430\u0445:<\/p>\n<pre><code class=\"javascript\">EE[h8[T8]] = (function () {   var F8 = h8[T8];   return function (W8, C8, k8, l8, Y8, m8) {     var q8 = Zm(KU, [W8, Kh, vh(vh(EF)), l8, r8, m8]);     EE[F8] = function () { \/\/ \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430       return q8;     };     return q8;   }; })();<\/code><\/pre>\n<p><code>EE[F8]<\/code> &#8212; \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <code>q8<\/code>. \u0422\u0430\u043a \u0447\u0442\u043e \u0432\u0441\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0432\u044b\u0437\u043e\u0432 \u0442\u0430\u043a\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043d\u0435 \u0438\u043c\u0435\u044e\u0442. \u0421\u0432\u043e\u0451 \u0436\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>q8<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>Zm<\/code> \u0441 \u043a\u0430\u043a\u0438\u043c\u0438-\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438. \u0410 \u0447\u0442\u043e \u0437\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f Zm? \u0414\u0430\u0432\u0430\u0439 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c:<\/p>\n<details class=\"spoiler\">\n<summary>function Zm<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7aa\/973\/b96\/7aa973b968e789ff04863e3c2d100b65.gif\" width=\"1273\" height=\"627\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7aa\/973\/b96\/7aa973b968e789ff04863e3c2d100b65.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0435\u0443\u0442\u0435\u0448\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439. \u041e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440\u0430 \u043d\u0430 \u0444\u043e\u043d\u0435 \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0434\u0435\u0442\u0441\u043a\u043e\u0439. \u0423 \u043d\u0430\u0441 \u0442\u0430\u043c \u0431\u044b\u043b\u043e \u0432\u0441\u0451 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u043f\u043e\u0447\u0442\u0438 \u0441\u0440\u0430\u0437\u0443: \u0432\u043e\u0442 \u0431\u043b\u043e\u043a \u0441 \u0442\u0435\u0441\u0442\u043e\u043c, \u0432 \u043d\u0451\u043c \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432, \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443 \u0437\u0430\u0431\u0438\u0440\u0430\u043b\u0438\u0441\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u043d\u0430\u0448\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u0437\u0430\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0436\u0435 \u0431\u044b\u043b \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u044b\u0437\u043e\u0432\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c \u043a\u0430\u043a-\u0442\u043e \u043f\u043e-\u0441\u0432\u043e\u0435\u043c\u0443 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u0435\u0439 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438&#8230; &#171;\u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445&#187; \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u0430. \u0414\u0430-\u0434\u0430, \u043f\u043e\u0433\u043b\u044f\u0434\u0438\u0442\u0435 \u043d\u0430 \u0438\u0445 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e:<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/500\/e9b\/87e\/500e9b87ec4af789664e5fd71de80b09.gif\" width=\"1273\" height=\"627\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/500\/e9b\/87e\/500e9b87ec4af789664e5fd71de80b09.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043a\u043e\u0448\u043c\u0430\u0440. \u041a\u0443\u0447\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0430 \u0435\u0449\u0451 \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>JY<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u0435\u043d\u044f\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u0430. \u041f\u043e \u043a\u043e\u0434\u0443 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0442\u0430\u043a\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044f\u0445. \u0412\u043e\u043e\u0431\u0449\u0435, \u044f \u0431\u044b \u044d\u0442\u043e\u0442 \u0441\u043a\u0440\u0438\u043f\u0442 \u0441\u0440\u0430\u0432\u043d\u0438\u043b \u0441 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 \u041e\u041e\u041f , \u0432\u0435\u0434\u044c \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0441\u0432\u043e\u0451 <strong>\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435<\/strong>. \u0413\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f &#8212; &#171;\u043e\u043d\u043e \u0436\u0438\u0432\u043e\u0435&#187;&#8230;<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043b\u044e\u0434\u0435\u0439 &#171;\u0432 \u0442\u0435\u043c\u0435&#187; \u043a\u0430\u043a\u043e\u0439 \u0438\u0437 \u0430\u043d\u0442\u0438\u0431\u043e\u0442\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0441\u0430\u043c\u0443\u044e \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e \u0431\u0435\u0437 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0442\u043e \u043e\u0442\u0432\u0435\u0442\u043e\u043c \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u0430\u043a\u0430\u043c\u0430\u0439, \u0438 \u043d\u0435 \u0431\u0435\u0437 \u043f\u0440\u0438\u0447\u0438\u043d\u044b. \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439, \u0432\u0442\u043e\u0440\u043e\u0439 \u0438 \u0442\u0440\u0435\u0442\u0438\u0439 \u0432\u0437\u0433\u043b\u044f\u0434\u044b \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c. \u041d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u043c \u043e\u0434\u043d\u0443 \u0434\u0435\u0442\u0430\u043b\u044c:<\/p>\n<details class=\"spoiler\">\n<summary>\u0434\u0435\u0442\u0430\u043b\u044c<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9ba\/402\/3d8\/9ba4023d8a62435f706bb9f2e1e622d9.gif\" width=\"1769\" height=\"845\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9ba\/402\/3d8\/9ba4023d8a62435f706bb9f2e1e622d9.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442 \u043d\u0435 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0432\u043e\u0451 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435. \u0412\u0438\u0434\u0438\u043c\u043e, \u043e\u043d \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0432\u0441\u044f\u043a\u043e\u0433\u043e \u0440\u043e\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0430\u0448\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043c\u044b\u0448\u044c\u044e \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0432 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435. \u041d\u043e, \u0441\u0443\u0442\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432\u0441\u0435\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f\u043c. \u0418\u043d\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442\u0441\u044f, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u0441\u044f\u043a\u043e\u0433\u043e \u0440\u043e\u0434\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/32e\/94b\/cc3\/32e94bcc3aef6e0d8bc5c98eec1f27e3.png\" width=\"928\" height=\"467\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/32e\/94b\/cc3\/32e94bcc3aef6e0d8bc5c98eec1f27e3.png\"\/><\/figure>\n<p>\u041d\u043e \u0438\u0445 \u043d\u0435\u043c\u043d\u043e\u0433\u043e. \u0414\u0430 \u0438 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0431\u0440\u0435\u0439\u043a\u043f\u043e\u0438\u043d\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438 \u043f\u043e\u043d\u044f\u0442\u044c \u0447\u0442\u043e \u0438\u043c\u0435\u043b\u043e\u0441\u044c \u0432 \u0432\u0438\u0434\u0443, \u043d\u043e \u0438 \u0442\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e&#8230; \u042f \u0432\u043e\u0442 \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 Brave \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>isBrave()<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 true. \u041d\u043e \u043d\u0435 \u0441\u0443\u0442\u044c. \u041d\u0430\u043c \u0431\u044b \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<p>\u0417\u043d\u0430\u0435\u0442\u0435, \u0432\u043e\u0442 \u0431\u044b \u0437\u0430\u0431\u0440\u0430\u0442\u044c \u044d\u0442\u043e \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438, \u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0438\u0445 \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u0438 \u043e\u0431\u0445\u043e\u0434\u0435 AST \u0432 \u043d\u0443\u0436\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445&#8230; \u041c\u0435\u0447\u0442\u044b \u0438\u043b\u0438 \u0442\u0430\u043a\u043e\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c?<\/p>\n<p>\u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438. \u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439, \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439, \u043d\u0435\u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0438 \u043d\u0443\u0434\u043d\u044b\u0439. \u042d\u0442\u043e \u043b\u0435\u043d\u0438\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 &#171;\u0432 \u043b\u043e\u0431&#187; \u0431\u0435\u0437 \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430. \u0412 \u0434\u0440\u0443\u0433\u043e\u0439 \u0440\u0430\u0437, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u044f \u043d\u0430\u043f\u0438\u0448\u0443 \u043f\u0440\u043e \u0434\u0440\u0443\u0433\u0438\u0435 \u0434\u0435\u043b\u0438\u043a\u0430\u0442\u043d\u044b\u0435 \u0438 \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0441\u043a\u0440\u0438\u043f\u0442 \u0445\u043e\u0447\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e!<\/p>\n<h2>\u0421\u0432\u043e\u0439 \u043e\u0431\u0445\u043e\u0434 \u0434\u0435\u0440\u0435\u0432\u0430?<\/h2>\n<p>\u0414\u0430. \u041c\u044b \u0441\u0430\u043c\u0438 \u043e\u0431\u043e\u0439\u0434\u0451\u043c \u0434\u0435\u0440\u0435\u0432\u043e \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0432 \u043d\u0451\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b. \u0415\u0441\u043b\u0438 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0441\u043a\u0440\u0438\u043f\u0442, \u0442\u043e \u0432 \u043d\u0451\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e JS. \u0412\u044b, \u043c\u043e\u0436\u0435\u0442, \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u0442\u0430\u043c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e ES3 \u0441 var-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438, \u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u0438\u0445 \u043d\u043e\u0432\u043e\u043c\u043e\u0434\u043d\u044b\u0445 rest-spread \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u0441\u0442\u0440\u0435\u043b\u043e\u0447\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0422\u0430\u043a\u0436\u0435, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0433\u0440\u044f\u0437\u043d\u044b\u0445 \u0445\u0430\u043a\u043e\u0432 \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0442 \u043d\u0430\u043c \u044d\u0442\u043e\u0442 \u043d\u0443\u0434\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441.<\/p>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u0417\u043d\u0430\u043d\u0438\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 AST. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u044b \u0438\u0437\u0443\u0447\u0438\u043b\u0438 \u044d\u0442\u043e\u0442 \u0432 \u043f\u0443\u043d\u043a\u0442 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0431\u0435\u0433\u0438\u0442\u0435\u0441\u044c \u043f\u043e \u043d\u0435\u0439 \u0433\u043b\u0430\u0437\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u044c \u0447\u0435\u0433\u043e \u0432\u044b \u0437\u043d\u0430\u0435\u0442\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442\u0435. \u0414\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0441\u043b\u043e\u0432\u0430 traverse(), parse(), astexplorer, callExpression \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432\u0430\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u044b;<\/p>\n<\/li>\n<li>\n<p>Babel, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.npmjs.com\/package\/jsdom\" rel=\"noopener noreferrer nofollow\">jsdom<\/a> \u0438 <a href=\"https:\/\/www.npmjs.com\/package\/canvas\" rel=\"noopener noreferrer nofollow\">canvas<\/a>, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 &#171;\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e&#187; \u043e\u0431\u044a\u0435\u043a\u0442\u0430 window;<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043f\u0438\u0448\u0435\u043c JavaScript \u043d\u0430 JavaScript, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432: \u043e\u0431\u044a\u0435\u043a\u0442 &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u0444\u0443\u043d\u043a\u0446\u0438\u044f &#8212; \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043c\u0430\u0441\u0441\u0438\u0432 \u0435\u0441\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0438 \u0432\u0441\u0451-\u0432\u0441\u0451-\u0432\u0441\u0451 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u044f\u0437\u044b\u043a\u0435 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043f\u0438\u0441\u043e\u043a \u0443\u0437\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c<\/summary>\n<div class=\"spoiler__content\">\n<p>\u042f \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u043b\u0441\u044f \u043f\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>traverse()<\/code>, \u0438 \u0443\u0437\u043d\u0430\u043b \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0435:<\/p>\n<pre><code> 'EmptyStatement',  'ExpressionStatement',  'SequenceExpression',  'Identifier',  'BinaryExpression',  'UnaryExpression',  'StringLiteral',  'NumericLiteral',  'NullLiteral'  'BooleanLiteral'  'RegExpLiteral',  'IfStatement',  'BlockStatement'  'CallExpression',  'FunctionExpression',  'VariableDeclaration',  'VariableDeclarator',  'FunctionDeclaration',  'AssignmentExpression',  'ObjectExpression',  'ThisExpression',  'ReturnStatement',  'ObjectProperty',  'WhileStatement',  'DoWhileStatement',  'UpdateExpression',  'LogicalExpression',  'ForStatement',  'ContinueStatement',  'BreakStatement',  'MemberExpression',  'SwitchStatement',  'SwitchCase',  'ArrayExpression',  'ConditionalExpression',  'NewExpression',  'TryStatement',  'CatchClause',  'ThrowStatement',  'ForInStatement',<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0418\u0442\u0430\u043a, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432. \u0417\u043d\u0430\u043a\u043e\u043c\u0430\u044f \u0432\u0430\u043c \u043f\u0440\u0435\u043b\u044e\u0434\u0438\u044f:<\/p>\n<pre><code class=\"javascript\">const { parse } = require('@babel\/parser'); const fs = require('fs');  const srcCode = fs.readFileSync('.\/input\/src.js', { encoding: 'utf-8' });  const ast = parse(srcCode);<\/code><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b\u0438 \u043a\u043e\u0434 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u0438 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043b\u0438 AST \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a class=\"mention\" href=\"\/users\/babel\/parser.\">@babel\/parser.<\/a><\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0445\u043e\u0447\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c, \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442:<\/p>\n<pre><code>10;<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/080\/16b\/de5\/08016bde53618eafa475de74f37b253e.png\" width=\"613\" height=\"439\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/080\/16b\/de5\/08016bde53618eafa475de74f37b253e.png\"\/><\/figure>\n<p>\u041c\u044b \u0438\u043c\u0435\u0435\u0442 \u0443\u0437\u0435\u043b <code>Program<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>body<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0441\u0435\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0441\u043a\u0440\u0438\u043f\u0442\u0430. \u041d\u0430\u0448\u0430 \u043f\u0435\u0440\u0432\u0430\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f &#8212; <code>ExpressionStatement<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u0432 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435 <code>expression<\/code> \u0443\u0437\u0435\u043b <code>NumericLiteral<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0447\u0438\u0441\u043b\u043e 10 \u0432 \u0441\u0432\u043e\u0451\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435 <code>value<\/code>.<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <code>Interpreter<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043c\u0435\u0442\u043e\u0434, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u0443\u0437\u0435\u043b \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0439 \u0435\u0433\u043e:<\/p>\n<pre><code class=\"javascript\">\/\/ .\/libs\/Interpreter.js const t = require('@babel\/types');  class Interpreter {   constructor() {     \/\/... \u043f\u043e\u043a\u0430 \u043f\u0443\u0441\u0442\u043e   }    eval(node) {     if (t.isProgram(node)) { \/\/ \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0443\u0437\u0435\u043b Program       let result;       node.body.forEach(node => { \/\/ \u0422\u043e \u0431\u0435\u0436\u0438\u043c \u043f\u043e \u0432\u0441\u0435\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 node.body,         result = this.eval(node); \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044f \u043a\u0430\u0436\u0434\u0443\u044e \u0438\u0437 \u043d\u0438\u0445       });       return result;     }      if (t.isExpressionStatement(node)) { \/\/ \u0415\u0441\u043b\u0438 \u0443\u0437\u0435\u043b ExpressionStatement, \u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c       return this.eval(node.expression); \/\/ \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u0437 \u0441\u0432\u043e\u0439\u0441\u0432\u0430 expression     }      if (t.isNumericLiteral(node)) { \/\/ \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043b\u0438\u0442\u0435\u0440\u0430\u043b \u0447\u0438\u0441\u043b\u0430       return node.value; \/\/ \u041f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0447\u0438\u0441\u043b\u043e \u0438\u0437 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0443\u0437\u043b\u0430 value     }   } }  module.exports = Interpreter;<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u044b \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439. \u0412\u0441\u0435\u0433\u043e 20 \u0441\u0442\u0440\u043e\u0447\u0435\u043a \u043a\u043e\u0434\u0430, \u0430 \u043a\u0430\u043a\u043e\u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442!<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/841\/f41\/4d6\/841f414d6f3e41634b4d006f0047a063.gif\" alt=\"\u041e\u043d\u043e \u0436\u0438\u0432\u043e\u0435\" title=\"\u041e\u043d\u043e \u0436\u0438\u0432\u043e\u0435\" width=\"1583\" height=\"634\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/841\/f41\/4d6\/841f414d6f3e41634b4d006f0047a063.gif\"\/><\/p>\n<div><figcaption>\u041e\u043d\u043e \u0436\u0438\u0432\u043e\u0435<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0418\u0434\u0451\u043c \u0434\u0430\u043b\u044c\u0448\u0435. \u0425\u043e\u0442\u0438\u043c \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0447\u0438\u0441\u043b\u0430:<\/p>\n<pre><code>10 + 20; \/\/ 30<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0421\u043b\u043e\u0436\u0435\u043d\u0438\u0435 &#8212; \u044d\u0442\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0448 \u0443\u0437\u0435\u043b \u0438\u043c\u0435\u043d\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a BinaryExpression.  \u0423 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u0440\u0435\u0431\u0451\u043d\u043a\u0430 &#8212; left \u0438 right, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0442\u0438\u043f\u043e\u043c NumericLiteral, \u0430 \u0435\u0433\u043e \u043c\u044b \u0443\u0436\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u043d\u0430\u0443\u0447\u0438\u043b\u0438\u0441\u044c:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a53\/915\/6e0\/a539156e012a1bea3fd367ad019fa94f.PNG\" alt=\"10 + 20\" title=\"10 + 20\" width=\"494\" height=\"612\"\/><\/p>\n<div><figcaption>10 + 20<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">\/\/ ... \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0443\u0437\u043b\u044b if (t.isBinaryExpression(node)) {   const left = this.eval(node.left); \/\/ \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043b\u0435\u0432\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u043d\u0434   const right = this.eval(node.right); \/\/ \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043f\u0440\u0430\u0432\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u043d\u0434   switch (node.operator) {     case '+':       return left + right; \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442     default:       throw `Unknown operator ${node.operator}`;   } }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/edb\/7bd\/5ec\/edb7bd5ec4538d56e2a68cc1a9c6363b.gif\" width=\"1583\" height=\"634\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/edb\/7bd\/5ec\/edb7bd5ec4538d56e2a68cc1a9c6363b.gif\"\/><\/figure>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0438\u0437-\u0437\u0430 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0439 \u043f\u0440\u0438\u0440\u043e\u0434\u044b \u043d\u0430\u0448\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430, \u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0438 \u0442\u0430\u043a\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code>10 + 20 + 30 + 100 + (100 + 200); \/\/ 460<\/code><\/pre>\n<p>\u041f\u0430\u0440\u0441\u0435\u0440 \u0441\u0430\u043c \u0437\u0430\u0431\u043e\u0442\u0438\u0442\u0441\u044f \u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b:<\/p>\n<pre><code class=\"javascript\">if (t.isBinaryExpression(node)) {   const left = this.eval(node.left);   const right = this.eval(node.right);   switch (node.operator) {     case '+':       return left + right;     case '-':       return left - right;     case '*':       return left * right;     case '\/':       return left \/ right;     case '%':       return left % right;     case '**':       return left ** right;     case '==':       return left == right;     case '===':       return left === right;     case '!=':       return left != right;     case '!==':       return left !== right;     case '&lt;':       return left &lt; right;     case '&lt;=':       return left &lt;= right;     case '>':       return left > right;     case '>=':       return left >= right;     case '|':       return left | right;     case '&amp;':       return left &amp; right;     case '^':       return left ^ right;     case '&lt;&lt;':       return left &lt;&lt; right;     case '>>':       return left >> right;     case '>>>':       return left >>> right;     case 'in':       return left in right;     case 'instanceof':       return left instanceof right;     default:       throw `Unknown operator ${node.operator}`;   } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0443 \u043f\u043e \u0441\u0438\u043b\u0430\u043c \u0438 \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code>10 + 100 * 20 - 40 \/ 50 + 4 * 100; \/\/ 2409.2<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0434\u043b\u044f \u0443\u043d\u0430\u0440\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439:<\/p>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2e4\/71d\/a2c\/2e471da2c7307ac70ce635614dc9d7b0.PNG\" width=\"445\" height=\"316\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isUnaryExpression(node)) {   const arg = this.eval(node.argument);   switch (node.operator) {     case '+':       return +arg;     case '-':       return -arg;     case '!':       return !arg;     case '~':       return ~arg;     case 'typeof':       return typeof arg;     case 'void':       return void arg;     default:       throw new Error(`Unknown unary operator ${node.operator}`);   } }<\/code><\/pre>\n<p>\u041f\u043e \u0442\u043e\u043c\u0443 \u0436\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u041d\u043e \u0438\u0445 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u043e\u0431\u0430 \u043e\u043f\u0435\u0440\u0430\u043d\u0434\u0430 \u0441\u0440\u0430\u0437\u0443, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0438\u0437 \u043d\u0438\u0445:<\/p>\n<pre><code class=\"javascript\">1 || 0; \/\/ true, \u043f\u0440\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0438 \u0435\u0434\u0438\u043d\u0438\u0446\u044b \u043c\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435 \u0432\u0430\u0436\u0435\u043d \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043e\u043f\u0435\u0440\u0430\u043d\u0434 0 &amp;&amp; 1; \/\/ false, \u0435\u0441\u043b\u0438 \u043c\u044b \u0432 \u043a\u043e\u043d\u044a\u044e\u043d\u043a\u0446\u0438\u0438 \u0443\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 0, \u0442\u043e \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/code><\/pre>\n<pre><code class=\"javascript\">if (t.isLogicalExpression(node)) {   switch (node.operator) {     case '||':       return this.eval(node.left) || this.eval(node.right);     case '&amp;&amp;':       return this.eval(node.left) &amp;&amp; this.eval(node.right);     case '??':       return this.eval(node.left) ?? this.eval(node.right);     default:       throw new Error(`Unknown logical operator ${node.operator}`);   } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0443\u043c\u0435\u0435\u043c \u0442\u0430\u043a:<\/p>\n<pre><code>1 &amp;&amp; !0 + 1 || 0; \/\/ 2<\/code><\/pre>\n<h3>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435<\/h3>\n<p>\u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0441\u0442\u0435\u0439. \u0418 \u044d\u0442\u043e, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0441\u0430\u043c\u043e\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0435, \u0447\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u0442\u044c \u0432 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0435. \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0439\u0434\u0451\u0442 \u043a\u0443\u0434\u0430 \u043f\u0440\u043e\u0449\u0435.<\/p>\n<p>\u041d\u0430 \u043f\u043e\u0432\u0435\u0441\u0442\u043a\u0435 \u0434\u043d\u044f \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">var foo = 10;<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/502\/297\/b6d\/502297b6db7547613318a0d79af37e3f.PNG\" width=\"461\" height=\"438\"\/><\/figure>\n<p>\u0423\u0437\u0435\u043b \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>VariableDeclaration<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>declarations<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432\u0441\u0435 <code>VariableDeclarator<\/code>&#8216;\u044b. \u042d\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"javascript\">var foo, bar;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0443\u0437\u0435\u043b <code>VariableDeclaration<\/code>, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0443 <code>declarations<\/code> \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 <code>VariableDeclarator<\/code>. <\/p>\n<pre><code class=\"javascript\">if (t.isVariableDeclaration(node)) {   let result;   node.declarations.forEach(variableDeclarator => {     result = this.eval(variableDeclarator);   });   return result; }<\/code><\/pre>\n<p><code>VariableDeclarator<\/code> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0443\u0437\u0435\u043b \u0441 \u0434\u0432\u0443\u043c\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 <code>id<\/code> &#8212; \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440(\u0438\u043c\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439) \u0438 <code>init<\/code> &#8212; \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0441\u0440\u0430\u0437\u0443 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a\u0438\u043c-\u043b\u0438\u0431\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c.<\/p>\n<h3>\u041b\u0435\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 <\/h3>\n<p>\u041a\u0430\u043a \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0443 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438? \u041c\u044b \u0432\u0441\u0435 \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c \u043f\u0440\u043e \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043f\u0440\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438 \u043f\u0440\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438\u043c\u0451\u043d: \u0438\u0449\u0435\u043c \u0438\u043c\u044f \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0435\u0441\u043b\u0438 \u0438\u043c\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0438\u043c\u0435\u043d\u0438, \u0430 \u0435\u0441\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0442\u043e \u0438\u0434\u0451\u043c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438 \u0442\u0430\u043a \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0434\u043e\u0439\u0434\u0451\u043c \u0434\u043e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0435\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f. \u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0438 \u0442\u0430\u043c, \u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u043d\u0430\u043c\u0435\u043d\u0438\u0442\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443 &#171;ReferenceError &#8212; variable &#171;foo&#187; is not defined&#187;. <\/p>\n<p>\u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 Environment:<\/p>\n<pre><code class=\"javascript\">\/\/ .\/libs\/Environment class Environment {   constructor(record = {}, parent = null) {     this.record = record;     this.parent = parent;   }   \/\/ ... }<\/code><\/pre>\n<p>\u041a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u0430\u044f:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e37\/34d\/f1e\/e3734df1ed765c83f666f694dcdbea3a.png\" alt=\"record - \u044d\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043b\u044e\u0447\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f - \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0441 \u044d\u0442\u0438\u043c\u0438 \u0438\u043c\u0435\u043d\u0430\u043c\u0438. parent - \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\" title=\"record - \u044d\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043b\u044e\u0447\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f - \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0441 \u044d\u0442\u0438\u043c\u0438 \u0438\u043c\u0435\u043d\u0430\u043c\u0438. parent - \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\" width=\"506\" height=\"257\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e37\/34d\/f1e\/e3734df1ed765c83f666f694dcdbea3a.png\"\/><\/p>\n<div><figcaption>record &#8212; \u044d\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043b\u044e\u0447\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f &#8212; \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0441 \u044d\u0442\u0438\u043c\u0438 \u0438\u043c\u0435\u043d\u0430\u043c\u0438. parent &#8212; \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u0435\u0442\u043e\u0434 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442 \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"javascript\">\/\/ --- Environment class --- define(name, value = undefined) {   this.record[name] = value;   return value; }<\/code><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0432 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 <code>record<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0430\u0440\u0443 \u0438\u043c\u044f-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u043e\u0438\u0442 \u043e\u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439. \u041f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043d\u0435\u0442 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438, \u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0438\u0441\u043a\u0430\u0442\u044c \u0435\u0451 \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c. \u042f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>resolve()<\/code>, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0439 \u043d\u0443\u0436\u043d\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435(\u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0438\u043b\u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435, \u0438\u043b\u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e&#8230;), \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f:<\/p>\n<pre><code class=\"javascript\">resolve(name) {   if (this.record.hasOwnProperty(name)) { \/\/ \u0435\u0441\u043b\u0438 \u0438\u043c\u044f \u0435\u0441\u0442\u044c \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 record,      return this; \/\/ \u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435   }    if (this.parent === null) { \/\/ \u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u043d\u0438 \u043d\u0435\u0442 \u0438 \u043d\u0435\u0433\u0434\u0435 \u0435\u0433\u043e \u0438\u0441\u043a\u0430\u0442\u044c, \u0442\u043e \u044d\u0442\u043e ReferenceError     throw new ReferenceError(`Variable \"${name}\" is not defined`);   }    return this.parent.resolve(name); \/\/ \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0435\u0433\u043e }<\/code><\/pre>\n<p>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439. \u041e\u043d\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 <code>record<\/code> \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0435\u0440\u043d\u0451\u0442 <code>resolve()<\/code>:<\/p>\n<pre><code class=\"javascript\">lookup(name) { \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439   return this.resolve(name).record[name];   \/\/         ^   \/\/ \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 }<\/code><\/pre>\n<p>\u041d\u0443 \u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439:<\/p>\n<pre><code class=\"javascript\">assign(name, value) { \/\/ \u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0438\u043c\u0435\u043d\u0438 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435   this.resolve(name).record[name] = value;   return value; }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 Environment<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">class Environment {   constructor(record = {}, parent = null) {     this.record = record;     this.parent = parent;   }    define(name, value = undefined) {     this.record[name] = value;     return value;   }    lookup(name) {     return this.resolve(name).record[name];   }    resolve(name) {     if (this.record.hasOwnProperty(name)) {       return this;     }      if (this.parent === null) {       throw new ReferenceError(`Variable \"${name}\" is not defined`);     }      return this.parent.resolve(name);   }    assign(name, value) {     this.resolve(name).record[name] = value;     return value;   } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h3>\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041a\u043e\u0434 \u0432 JavaScript \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u0430\u043a\u043e\u0433\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430. \u042d\u0442\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u043c\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u041c\u044b \u0437\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u0432 \u044f\u0437\u044b\u043a\u0435 \u0435\u0441\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u0441\u043b\u043e\u0432\u043e <code>this<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 <code>window<\/code>, \u043d\u043e \u0441 \u043a\u043e\u0434\u043e\u043c \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u0435\u043b\u0430 \u043e\u0431\u0441\u0442\u043e\u044f\u0442 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u0438 \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u044b \u0435\u0449\u0451 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c.<\/p>\n<p>\u041d\u0430\u0448 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u0432\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 &#8212; <code>thisValue<\/code> \u0438, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, <code>Environment<\/code>:<\/p>\n<pre><code class=\"javascript\">\/\/ .\/libs\/ExecutionContext class ExecutionContext {   constructor(thisValue, env) {     this.thisValue = thisValue;     this.env = env;   } }<\/code><\/pre>\n<p>\u0418&#8230; \u042d\u0442\u043e \u0432\u0435\u0441\u044c \u043a\u043b\u0430\u0441\u0441.<\/p>\n<h4>\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442<\/h4>\n<p>\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c JSDOM, \u0447\u0442\u043e\u0431\u044b \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442 window. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043c\u044b \u0442\u0443\u0434\u0430 \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0431\u0443\u0434\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c.<\/p>\n<pre><code class=\"javascript\">\/\/ .\/browser-env\/window.js const jsdom = require(\"jsdom\"); const { JSDOM } = jsdom; const { window } = new JSDOM(`   (*) `, {   url: 'http:\/\/127.0.0.1:3000',   userAgent: 'Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/105.0.0.0 Safari\/537.36',   contentType: 'text\/html', });<\/code><\/pre>\n<p>\u041d\u0430 \u043c\u0435\u0441\u0442\u043e (*) \u044f \u0441\u043a\u043e\u0440\u043c\u0438\u043b jsdom&#8217;\u0443 html-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 my.asos.com, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0435 \u0441\u043f\u043e\u0442\u043a\u043d\u0443\u043b\u0441\u044f, \u0435\u0441\u043b\u0438 \u0432\u0434\u0440\u0443\u0433 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u043e\u043b\u044f \u0444\u043e\u0440\u043c\u044b \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0432\u043e\u0438 \u0444\u0440\u0435\u0439\u043c\u044b \u0432 <code>document.body<\/code> \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a.<\/p>\n<p>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 GlobalEnvironment:<\/p>\n<pre><code class=\"javascript\">\/\/ .\/libs\/GlobalEnvironment  const Environment = require(\".\/Environment\") const window = require('.\/..\/browser-env\/window');  module.exports = new Environment(window);<\/code><\/pre>\n<p>GlobalExecutionContext:<\/p>\n<pre><code class=\"javascript\">\/\/ .\/libs\/GlobalExecutionContext const ExecutionContext = require(\".\/ExecutionContext\"); const GlobalEnvironment = require(\".\/GlobalEnvironment\"); const window = require('.\/..\/browser-env\/window');   module.exports = new ExecutionContext(window, GlobalEnvironment);<\/code><\/pre>\n<p>\u0414\u0430, \u044d\u0442\u043e \u043d\u0435 \u043c\u0438\u0440\u0430\u0436. <code>thisValue<\/code> \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 <code>window<\/code>, \u0430 \u043f\u043e\u043b\u0435 <code>record<\/code> \u043a\u043b\u0430\u0441\u0441\u0430 <code>GlobalEnvironment<\/code> \u0442\u043e\u0436\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e <code>window<\/code>. \u0422\u0430\u043a \u043e\u043d\u043e \u0432 JavaScript \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0418\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u043d\u0430\u043f\u0438\u0441\u0430\u0432 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c \u043a\u043e\u0434\u0435<\/p>\n<pre><code class=\"javascript\">var a = 10;<\/code><\/pre>\n<p>\u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043a\u0430\u043a \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430:<\/p>\n<pre><code class=\"javascript\">window.a; \/\/ 10<\/code><\/pre>\n<p>\u041c\u044b \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 <code>Interpreter<\/code> \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0439:<\/p>\n<details class=\"spoiler\">\n<summary>Interpreter<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">const t = require('@babel\/types'); const Environment = require('.\/Environment'); const ExecutionContext = require('.\/ExecutionContext'); const GlobalExecutionContext = require('.\/GlobalExecutionContext');  class Interpreter {   constructor(execCtx = GlobalExecutionContext) {     this.callStack = [execCtx];   }    eval(node, ctx = this.callStack[this.callStack.length - 1]) {     if (t.isProgram(node)) {       let result;       node.body.forEach((node) => {         result = this.eval(node, ctx);       });       return result;     }      if (t.isExpressionStatement(node)) {       return this.eval(node.expression, ctx);     }      if (t.isNumericLiteral(node)) {       return node.value;     }      if (t.isBinaryExpression(node)) {       const left = this.eval(node.left, ctx);       const right = this.eval(node.right, ctx);       switch (node.operator) {         case '+':           return left + right;         \/\/ \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b         default:           throw `Unknown operator ${node.operator}`;       }     }      if (t.isUnaryExpression(node)) {       const arg = this.eval(node.argument, ctx);       switch (node.operator) {         case '+':           return +arg;         case '-':           return -arg;         case '!':           return !arg;         case '~':           return ~arg;         case 'typeof':           return typeof arg;         case 'void':           return void arg;         default:           throw new Error(`Unknown unary operator ${node.operator}`);       }     }      if (t.isLogicalExpression(node)) {       switch (node.operator) {         case '||':           return this.eval(node.left, ctx) || this.eval(node.right, ctx);         case '&amp;&amp;':           return this.eval(node.left, ctx) &amp;&amp; this.eval(node.right, ctx);         case '??':           return this.eval(node.left, ctx) ?? this.eval(node.right, ctx);         default:           throw new Error(`Unknown operator ${node.operator}`);       }     }      if (t.isVariableDeclaration(node)) {       let result;       node.declarations.forEach(variableDeclarator => {         result = this.eval(variableDeclarator, ctx);       });       return result;     }      throw `Unimplemented ${node.type} node`;   } }  module.exports = Interpreter;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0427\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u043e\u0441\u044c: <\/p>\n<ul>\n<li>\n<p>this.callStack &#8212; \u0441\u0442\u0435\u043a \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u044e\u0434\u0430 \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>eval(node, ctx)<\/code> \u043e\u0431\u0437\u0430\u0432\u0451\u043b\u0441\u044f \u043d\u043e\u0432\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c &#8212; <code>ctx<\/code>. \u0423\u0437\u0435\u043b \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e &#8212; \u0432 \u0432\u0435\u0440\u0445\u0443\u0448\u043a\u0435 callStack&#8217;\u0430. <\/p>\n<\/li>\n<li>\n<p>\u0412\u043e \u0432\u0441\u0435 \u0432\u044b\u0437\u043e\u0432\u044b <code>this.eval(node)<\/code> \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442: <code>this.eval(node, ctx)<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u043e\u0442 \u0434\u043e\u043b\u0433\u043e\u0436\u0434\u0430\u043d\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0443\u0437\u043b\u0430 <code>VariableDeclarator<\/code>:<\/p>\n<pre><code class=\"javascript\">if (t.isVariableDeclarator(node)) {   const name = node.id.name;   const value = this.eval(node.init, ctx);   return ctx.env.define(name, value); \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0430\u0440\u0443 \u0438\u043c\u044f-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e:<\/p>\n<pre><code class=\"javascript\">foo;<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0443\u0437\u0435\u043b \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"javascript\">if (t.isIdentifier(node)) {   return ctx.env.lookup(node.name); \/\/ \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e }<\/code><\/pre>\n<p>\u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u044e, \u0432\u044b \u0434\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0434\u043e\u0441\u044e\u0434\u0430! <\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/881\/7e5\/22f\/8817e522f4f417955a07034059e6720d.gif\" width=\"1583\" height=\"634\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/881\/7e5\/22f\/8817e522f4f417955a07034059e6720d.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<h3>\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u0435<\/h3>\n<pre><code class=\"javascript\">var a = 12213; a = 100; a; \/\/ 100<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d6e\/ec8\/b92\/d6eec8b92a377a71b331192dd906fd0e.PNG\" width=\"437\" height=\"392\"\/><\/figure>\n<p>\u0421\u043b\u0435\u0432\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u0438\u043c\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0431\u0440\u0430\u0442\u044c, \u0430 \u0441\u043f\u0440\u0430\u0432\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043d\u0430\u0448\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0443\u0437\u043b\u0430 Identifier \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439. \u041d\u043e \u0434\u043b\u044f \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u043c\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u044f\u0432\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439. \u0421\u043b\u0435\u0432\u0430 \u043e\u0442 \u0437\u043d\u0430\u043a\u0430 <code>=<\/code> \u043c\u043e\u0436\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043d\u043e \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430: foo.bar = 100; \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0430\u043a\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0442\u043e\u0436\u0435 \u043c\u044b \u043f\u043e\u0442\u043e\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c. <\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u044f \u0432 \u044f\u0437\u044b\u043a\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e: <code>=<\/code> <code>+=<\/code> <code>-=<\/code> <code>&amp;=<\/code> \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435&#8230; \u0421\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code class=\"javascript\">if (t.isAssignmentExpression(node)) {   if (t.isIdentifier(node.left)) {     const left = node.left.name; \/\/ \u042f\u0432\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043c\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430     const right = this.eval(node.right, ctx); \/\/ \u0442\u043e, \u0447\u0442\u043e \u0441\u043f\u0440\u0430\u0432\u0430 \u043e\u0442 \u0437\u043d\u0430\u043a\u0430 \u0440\u0430\u0432\u043d\u043e     let prevValue = this.eval(node.left, ctx); \/\/ \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439     switch(node.operator) {       case '=':         return ctx.env.assign(left, right);       case '+=':         return ctx.env.assign(left, prevValue + right);       case '-=':         return ctx.env.assign(left, prevValue - right);       case '*=':         return ctx.env.assign(left, prevValue * right);       case '\/=':         return ctx.env.assign(left, prevValue \/ right);       case '^=':         return ctx.env.assign(left, prevValue ^ right);       case '&amp;=':         return ctx.env.assign(left, prevValue &amp; right);       case '|=':         return ctx.env.assign(left, prevValue | right);       case '%=':         return ctx.env.assign(left, prevValue % right);       default:         throw `Unimplement operator assignment ${node.operator}`     }   } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">var a = 121341430; a; a = 100; a += 200; a; \/\/ 300<\/code><\/pre>\n<p>\u041f\u043e\u0447\u0442\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b <code>++<\/code> <code>--<\/code>:<\/p>\n<pre><code class=\"javascript\">if (t.isUpdateExpression(node)) {   if (t.isIdentifier(node.argument)) {     const varName = node.argument.name;     const varValue = this.eval(node.argument, ctx);     const newValue = node.operator === '++' ? varValue + 1 : varValue - 1;     if (node.prefix) {       return ctx.env.assign(varName, newValue);     }     ctx.env.assign(varName, newValue);     return varValue;   } }<\/code><\/pre>\n<p>\u041d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043f\u0440\u043e \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043d\u044b\u043c \u0438 \u043f\u043e\u0441\u0442\u0444\u0438\u043a\u0441\u043d\u044b\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">var a = 0; ++a; \/\/ 1 a = 0; a++; \/\/ 0<\/code><\/pre>\n<p>\u0418\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0434\u043b\u044f \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043d\u043e\u0433\u043e \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0438 \u043e\u043d\u043e \u0436\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f, \u0430 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0444\u0438\u043a\u0441\u043d\u043e\u0433\u043e \u043c\u044b \u0442\u043e\u0436\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435.<\/p>\n<h3>EmptyStatement, SequenceExpression<\/h3>\n<p>\u041c\u0435\u0436\u0434\u0443 \u043f\u0440\u043e\u0447\u0435\u043c, \u043c\u044b \u0443\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 15 \u0443\u0437\u043b\u043e\u0432! \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0451 \u043f\u0430\u0440\u043e\u0447\u043a\u0443.<\/p>\n<p>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 EmptyStatement?<\/p>\n<pre><code>;<\/code><\/pre>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u043e\u0442&#8230; <\/p>\n<pre><code class=\"javascript\">if (t.isEmptyStatement(node)) {   return; }<\/code><\/pre>\n<p>SequenceExpression &#8212; \u044d\u0442\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c <code>,<\/code>:<\/p>\n<pre><code class=\"javascript\">1,2,3,3,4,5,6; \/\/ 6<\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0435\u0441\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f:<\/p>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f62\/992\/a52\/f62992a526b279edc14f2a60d7ea2615.PNG\" width=\"439\" height=\"375\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isSequenceExpression(node)) {   let result;   const { expressions } = node;   expressions.forEach(expr => {     result = this.eval(expr, ctx);   });   return result; }<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043c\u0430\u043b\u043e \u0447\u0435\u043c \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0443\u0437\u043b\u0430 Program.<\/p>\n<h3>ThisExpression<\/h3>\n<p>\u042d\u0442\u043e \u0442\u043e\u0436\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<pre><code class=\"javascript\">if (t.isThisExpression(node)) {   return ctx.thisValue; }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/17a\/0f0\/aee\/17a0f0aeeb1d10824744fe5f46181e1a.gif\" width=\"1583\" height=\"634\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/17a\/0f0\/aee\/17a0f0aeeb1d10824744fe5f46181e1a.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<h3>ObjectExpression<\/h3>\n<pre><code class=\"javascript\">var foo = {   bar: 'baz' }  foo;<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST \u0438 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f88\/44f\/326\/f8844f3260edd12afe7e6ff44a4d4792.PNG\" width=\"464\" height=\"501\"\/><\/figure>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u0437\u0434\u0435\u0441\u044c &#8212; \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e properties. \u042d\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432 ObjectProperty, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043f\u0430\u0440\u0443 \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u041d\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u0441\u0435 \u0442\u0430\u043a\u0438\u0435 \u043f\u0430\u0440\u044b \u0432 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442<\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isObjectExpression(node)) {   const object = {};   node.properties.forEach(prop => { \/\/ \u0411\u0435\u0436\u0438\u043c \u043f\u043e \u0432\u0441\u0435\u043c ObjectProperty     const key = prop.key.name || prop.key.value; \/\/ \u043a\u043b\u044e\u0447 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0447\u0438\u0441\u043b\u043e\u043c \u0438\u043b\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c     const value = this.eval(prop.value, ctx); \/\/ \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435     object[key] = value; \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442   })   return object; }<\/code><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0433\u043e. <\/p>\n<p>\u041c\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043f\u043e\u0440\u0443\u0433\u0430\u043b\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a: <strong>Unimplemented StringLiteral node<\/strong>. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c:<\/p>\n<pre><code class=\"javascript\">if (t.isLiteral(node)) {   if (t.isNullLiteral(node)) {     return null;   }   return node.value; }<\/code><\/pre>\n<p>NullLiteral \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e value, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u044f\u0432\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439. \u041f\u043e\u0442\u043e\u043c \u043c\u044b \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0435\u0449\u0451 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043f\u043e\u043c\u0435\u043d\u044f\u0435\u043c. <\/p>\n<h3>ArrayExpression<\/h3>\n<pre><code class=\"javascript\">var array = [1, 2, 3]; array; \/\/ [1, 2, 3]<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2b2\/25f\/ae3\/2b225fae3e106d43c950e5cf25b59f22.PNG\" width=\"391\" height=\"197\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f, \u0434\u0443\u043c\u0430\u044e, \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f. \u042d\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u043c\u044b \u043c\u0438\u043d\u0443\u0442 \u043d\u0430\u0437\u0430\u0434 \u0434\u0435\u043b\u0430\u043b\u0438 \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">if (t.isArrayExpression(node)) {   const elements = node.elements.map(el => this.eval(el, ctx));   const array = [...elements];   return array; }<\/code><\/pre>\n<h3>ConditionalExpression<\/h3>\n<p>\u042d\u0442\u043e \u0442\u0435\u0440\u043d\u0430\u0440\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440:<\/p>\n<pre><code>var a = true ? 100 : 200; a; \/\/ 100;<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST \u0438 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/28f\/6cc\/a72\/28f6cca72e2556b280bc8f76b25788d6.PNG\" width=\"397\" height=\"423\"\/><\/figure>\n<p>\u0421\u043d\u043e\u0432\u0430 \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e. \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0443\u0437\u0435\u043b <code>test<\/code> \u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043d\u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043b\u0438\u0431\u043e \u0443\u0437\u0435\u043b <code>consequen<\/code>, \u043b\u0438\u0431\u043e <code>alternate<\/code><\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isConditionalExpression(node)) {   if (this.eval(node.test, ctx)) {     return this.eval(node.consequent, ctx)   } else {     return this.eval(node.alternate, ctx);   } }<\/code><\/pre>\n<h3>IfStatement<\/h3>\n<p>\u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u043c \u0443\u0437\u043b\u043e\u043c \u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c if-else:<\/p>\n<pre><code class=\"javascript\">var a = true; var b = 0; if (a)   b = 20; else   b = 40; b; \/\/ 20<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ed4\/d24\/27d\/ed4d2427d542abb8980bdfe105f46382.PNG\" width=\"583\" height=\"376\"\/><\/figure>\n<p>\u042d\u0442\u043e \u0447\u0443\u0442\u044c \u043b\u0438 \u043d\u0435 1 \u0432 1 \u0441 \u0442\u0435\u0440\u043d\u0430\u0440\u043d\u044b\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c. \u041e\u0442\u043b\u0438\u0447\u0438\u0435 \u043b\u0438\u0448\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0435\u0442\u043a\u0430 <code>else<\/code> \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c. <\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isIfStatement(node)) {   const test = this.eval(node.test, ctx);   if (test) {     return this.eval(node.consequent, ctx)   } else if (node.alternate !== null) {     return this.eval(node.alternate, ctx)   } else {     return undefined   } }<\/code><\/pre>\n<h3>BlockStatement<\/h3>\n<p>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0431\u043b\u043e\u043a? \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439:<\/p>\n<pre><code class=\"javascript\">{   var a = 10;   var b = 20;   var c = a + b; }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/619\/1f7\/2c3\/6191f72c3e3bba4679e977ba0f839015.PNG\" width=\"443\" height=\"225\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0425\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"javascript\">if (t.isBlockStatement(node)) {   let result;   node.body.forEach(stmt => {     result = this.eval(stmt, ctx);   });   return result; }<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043d\u043e \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<pre><code class=\"javascript\">{   a = 10; } var a = 0;<\/code><\/pre>\n<p>\u041d\u0430\u0448 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0437\u0430\u043a\u0440\u0438\u0447\u0438\u0442: <strong>ReferenceError: Variable &#171;a&#187; is not defined. <\/strong>\u0410 \u0447\u0442\u043e \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u043a\u043e\u043d\u0441\u043e\u043b\u044c devtools?<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f1c\/041\/80c\/f1c04180c8d4eefc9c42107069fa1674.PNG\" width=\"248\" height=\"81\"\/><\/figure>\n<p>\u041e\u0445 \u0443\u0436 \u044d\u0442\u043e\u0442 <strong>hoisting<\/strong>&#8230; \u0412\u0441\u043f\u043e\u043c\u043d\u0438\u043b\u0438? var-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 &#171;\u043f\u043e\u0434\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f&#187; \u0432\u0432\u0435\u0440\u0445 \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d. \u0415\u0441\u043b\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043f\u0440\u043e \u043d\u0430\u0448 \u0441\u043b\u0443\u0447\u0430\u0439, \u0442\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0442\u0435\u043b\u043e \u0431\u043b\u043e\u043a\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>\u0415\u0449\u0451 \u043f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/43c\/1c9\/a7b\/43c1c9a7ba7e12c6a62494e2509a19f8.PNG\" width=\"227\" height=\"89\"\/><\/figure>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <code>x<\/code> \u0432 \u043f\u0435\u0440\u0432\u043e\u043c <code>console.log()<\/code> \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>undefined<\/code>, \u043d\u043e \u043e\u043d\u0430 <strong>\u0443\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430<\/strong>. <\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u0434\u044a\u0451\u043c\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"javascript\">_hoistVariables(block, ctx) {   block.body.forEach(stmt => {     if (t.isVariableDeclaration(stmt)) {       for (const variableDeclarator of stmt.declarations) {         const name = variableDeclarator.id.name;         ctx.env.define(name, undefined);       }     }   }); }<\/code><\/pre>\n<p>\u041c\u044b \u044f\u0432\u043d\u043e \u043e\u0431\u0445\u043e\u0434\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 <strong>variableDeclarator<\/strong>, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>undefined<\/code>. \u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e! \u041c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u043d\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c \u0438\u043c \u043d\u0438\u043a\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0449\u0451 \u043f\u043e\u0434\u044a\u0451\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0439:<\/p>\n<pre><code class=\"javascript\">_hoistVariables(block, ctx) {   block.body.forEach(stmt => {     if (t.isFunctionDeclaration(stmt)) {       this.eval(stmt, ctx)     }      if (t.isVariableDeclaration(stmt)) {       for (const variableDeclarator of stmt.declarations) {         const name = variableDeclarator.id.name;         ctx.env.define(name, undefined);       }     }   }); }<\/code><\/pre>\n<p>\u041c\u044b \u043f\u043e\u043a\u0430 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 FunctionDeclaration, \u043d\u043e \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u044b\u0437\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0432 \u043d\u0443\u0436\u043d\u044b\u0435 \u043c\u0435\u0441\u0442\u0430:<\/p>\n<pre><code class=\"javascript\">if (t.isProgram(node)) {   this._hoistVariables(node, ctx); \/\/ \u0441\u044e\u0434\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043e\u0431\u0434\u0435\u043b\u044f\u0442\u044c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434   let result;   node.body.forEach((node) => {     result = this.eval(node, ctx);   });   return result; } \/\/ ... if (t.isBlockStatement(node)) {   this._hoistVariables(node, ctx); \/\/ \u0438 \u0441\u044e\u0434\u0430   let result;   node.body.forEach(stmt => {     result = this.eval(stmt, ctx);   });   return result; }<\/code><\/pre>\n<p>\u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e, \u043d\u043e \u043c\u044b \u043c\u043d\u043e\u0433\u043e \u0433\u0434\u0435 \u043d\u0430\u0432\u0440\u0430\u043b\u0438. \u0418\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d:<\/p>\n<pre><code class=\"javascript\">a = 10; {   {     {       var a = 0;     }   } } a; \/\/ 0<\/code><\/pre>\n<p>\u041c\u044b \u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u043d\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u0434\u044a\u0451\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f \u0432 JS \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0438 \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u0438\u043a\u043e\u043b\u044b:<\/p>\n<pre><code class=\"javascript\">for (var i = 0; i &lt; 10; ++i) {   \/\/ ... } i; \/\/ 10<\/code><\/pre>\n<p>\u041c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c. \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432. \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Akamai \u0437\u0430 \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438. <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430 \u043f\u043e\u0432\u0435\u0441\u0442\u043a\u0435 \u0434\u043d\u044f \u043c\u043d\u043e\u0433\u043e \u0433\u0440\u044f\u0437\u043d\u044b\u0445 \u0445\u0430\u043a\u043e\u0432 \u0438 \u043a\u043e\u0441\u0442\u044b\u043b\u0435\u0439. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0432\u044b \u0443\u0436\u0435 \u043f\u0440\u0438\u0442\u0443\u043f\u0438\u043b\u0438 \u0441\u0432\u043e\u0451 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0440\u0443\u0433\u0430\u0442\u044c \u043c\u0435\u043d\u044f \u0437\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a?<\/summary>\n<div class=\"spoiler__content\">\n<p>\u042f \u043e\u0447\u0435\u043d\u044c \u043d\u0435 \u0445\u043e\u0447\u0443 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0441 \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u041e\u041e\u041f \u0438 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u043e\u0432. \u0415\u0441\u043b\u0438 \u0447\u0435\u0441\u0442\u043d\u043e, \u043c\u044b \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b-\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443. \u041e\u0431\u044a\u0435\u043a\u0442 &#8212; \u044d\u0442\u043e \u0432\u0435\u0434\u044c \u0442\u043e\u0436\u0435 \u0441\u0432\u043e\u0435\u0433\u043e \u0440\u043e\u0434\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435(Environment). \u041a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430\u0432\u0435\u0438\u0432\u0430\u044e\u0442 \u043c\u044b\u0441\u043b\u0438 \u043e\u0431 \u044d\u0442\u043e\u043c.<\/p>\n<p>\u041d\u043e \u0447\u0442\u043e \u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0447\u0443, \u0442\u0430\u043a \u044d\u0442\u043e \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430\u0449\u0438\u0442\u044b \u0430\u043a\u0430\u043c\u0430\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438. \u042f \u043d\u0435 \u0445\u043e\u0447\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/div>\n<\/details>\n<h3>FunctionDeclaration<\/h3>\n<p>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044f? \u042d\u0442\u043e \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u043c\u0438-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438. \u0413\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u043f\u043e\u0434 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c, \u0430 \u0437\u0430\u0442\u0435\u043c \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u0447\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435. \u041a\u0430\u043a \u043c\u044b \u043f\u043e\u043c\u043d\u0438\u043c, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 JavaScript &#8212; \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u043a\u043e\u0434\u0430 \u0445\u0440\u0430\u043d\u044f\u0442 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b. \u0418\u0437\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">\/\/ global code \/\/ ... function square(x) {   return x * x; } \/\/ ...<\/code><\/pre>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dce\/a22\/9ba\/dcea229ba17297e7d089a4e7c93371cd.png\" alt=\"\u0412\u043e\u0442 \u043e\u043d\u043e \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435! \u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430\" title=\"\u0412\u043e\u0442 \u043e\u043d\u043e \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435! \u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430\" width=\"351\" height=\"251\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/dce\/a22\/9ba\/dcea229ba17297e7d089a4e7c93371cd.png\"\/><\/p>\n<div><figcaption>\u0412\u043e\u0442 \u043e\u043d\u043e \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435! \u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>AST FunctionDeclaration<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a7e\/080\/ac8\/a7e080ac872fbdda2c2f0d139bca06c1.PNG\" width=\"422\" height=\"392\"\/><\/figure>\n<p>\u0418\u043c\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 &#8212; <code>node.id.name<\/code>. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u0438\u043c\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u0441\u044b\u043b\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e.<\/p>\n<p>\u041c\u0430\u0441\u0441\u0438\u0432 <code>node.params<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<p>\u0422\u0435\u043b\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 &#8212; <code>node.body<\/code><\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isFunctionDeclaration(node)) {   const parentEnv = ctx.env; \/\/ \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e   const func = function(...args) {     \/\/ \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043a\u043e\u0434   }   ctx.env.define(node.id.name, func); \/\/ \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438   return; }<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 ExecutionContext, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0435\u0440\u0445\u0443\u0448\u043a\u0443 \u043d\u0430\u0448\u0435\u0433\u043e <code>callStack<\/code>. ExecutionContext, \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u043c\u043d\u0438\u043c, \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>thisValue<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f &#8212; <code>Environment<\/code>. \u041f\u0435\u0440\u0435\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u0442\u0435\u043b\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u044d\u0442\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438:<\/p>\n<pre><code class=\"javascript\">if (t.isFunctionDeclaration(node)) {   const self = this;   const parentEnv = ctx.env; \/\/ \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e   const func = function(...args) {     const activationRecord = {}; \/\/ record \u043d\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f     for (let i = 0; i &lt; node.params.length; ++i) { \/\/ \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438       activationRecord[node.params[i].name] = args[i];     }     \/\/ \u0412\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0441\u0435\u0445 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432     \/\/ \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0441 \u0438\u043c\u0435\u043d\u0435\u043c 'arguments'     activationRecord['arguments'] = [...args];      \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442     const execCtx = new ExecutionContext(       this,       new Environment(activationRecord, parentEnv) \/\/ parentEnv - \u0417\u0410\u041c\u042b\u041a\u0410\u041d\u0418\u0415!!!     );      self.callStack.push(execCtx); \/\/ \u041a\u043b\u0430\u0434\u0451\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043d\u0430 \u0432\u0435\u0440\u0445\u0443\u0448\u043a\u0443          \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0442\u0435\u043b\u043e \u0432 \u041d\u041e\u0412\u041e\u041c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435     let result = self._evalFunctionBlock(node.body, execCtx);     return result;   }    ctx.env.define(node.id.name, func);   return; }<\/code><\/pre>\n<p>\u0415\u0449\u0451 \u0440\u0430\u0437 \u043f\u043e\u044f\u0441\u043d\u044e: \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0442\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>parentEnv<\/code> \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>func<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\u043c, \u0438\u043c\u0435\u044e\u0449\u0438\u043c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u0435 <code>parentEnv<\/code>. \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0433\u0434\u0435-\u043b\u0438\u0431\u043e, \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0432 \u043d\u0435\u0439 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\u043c, \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e <code>parentEnv<\/code>. \u0417\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435 \u043f\u043e\u043c\u043e\u0433\u043b\u043e \u043d\u0430\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435. <\/p>\n<p><code>this<\/code> \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u044f\u0432\u043d\u043e \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0443\u0437\u043b\u0435 CallExpression \u0447\u0435\u0440\u0435p <code>call()<\/code>.<\/p>\n<p>\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <\/p>\n<pre><code class=\"javascript\">_evalFunctionBlock(block, ctx) {   this._hoistVariables(block, ctx); \/\/ \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c var-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 \u0431\u043b\u043e\u043a\u0435    let result;   \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e   for (let s = 0; s &lt; block.body.length; ++s) {     const stmt = block.body[s];     result = this.eval(stmt, ctx);   }   this.callStack.pop(); \/\/ \u0441\u043d\u0438\u043c\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0442 \u0441 \u0432\u0435\u0440\u0445\u0443\u0448\u043a\u0438 \u0441\u0442\u0435\u043a\u0430 \u0432\u044b\u0437\u043e\u0432\u043e\u0432   return result; }<\/code><\/pre>\n<p>\u041d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c ReturnStatement. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043e\u043d \u043f\u0440\u043e\u0441\u0442, \u043d\u043e \u0435\u0441\u0442\u044c \u043d\u044e\u0430\u043d\u0441. \u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 return \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0430 \u043a\u043e\u0434\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f. \u041d\u043e \u0431\u043b\u043e\u043a\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u0430\u0433\u043e\u043d:<\/p>\n<pre><code class=\"javascript\">function square(x) {   {     {       {         {           {             return x * x;           }         }       }     }   } }<\/code><\/pre>\n<p>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0439\u0442\u0438 \u043d\u0435 \u0438\u0437 \u0431\u043b\u043e\u043a\u0430, \u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u0438\u0437 \u0432\u0441\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438&#8230; \u0418 \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432 try-catch \u0431\u043b\u043e\u043a\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0439\u043c\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u0418\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0443\u043c\u0435\u044e\u0442 \u0440\u0430\u0441\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0442\u044c \u0441\u0442\u0435\u043a \u0432\u044b\u0437\u043e\u0432\u043e\u0432. \u041d\u043e \u043c\u044b \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u0438\u043d\u0430\u0447\u0435&#8230; \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043d\u0430\u0448\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 return:<\/p>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e49\/012\/d94\/e49012d9415ea606f431ee302f8f13ba.PNG\" width=\"490\" height=\"103\"\/><\/figure>\n<p>\u041d\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438 \u0434\u0440\u0443\u0433\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"javascript\">function foo() {   return; \/\/ \u043f\u0443\u0441\u0442\u043e }<\/code><\/pre>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0434\u043e \u0438 \u0435\u0451 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. <\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isReturnStatement(node)) {   let functionResult;   if (node.argument !== null) { \/\/ \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c, \u0447\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c, \u0442\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u044d\u0442\u043e     functionResult = this.eval(node.argument, ctx);   }   this.callStack.pop(); \/\/ \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u0441 callStack \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442   return functionResult; }<\/code><\/pre>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, ReturnStatement \u0443\u0431\u0435\u0440\u0451\u0442 \u043e\u0434\u0438\u043d ExecutionContext \u0441 <code>this.callStack<\/code>.<\/p>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0430\u0445 \u043a\u043e\u0434\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u044f\u0432\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435, \u0435\u0441\u043b\u0438 \u0436\u0435 \u043d\u0435\u0442, \u0442\u043e \u043d\u0430\u0434\u043e \u043f\u043e\u043a\u0438\u043d\u0443\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0430:<\/p>\n<pre><code class=\"javascript\">_evalFunctionBlock(block, ctx) {   this._hoistVariables(block, ctx);   let result;   for (let s = 0; s &lt; block.body.length; ++s) {     const stmt = block.body[s];     result = this.eval(stmt, ctx);     \/\/ \u042f\u0432\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0442\u0435\u043a\u0443\u0449\u0438\u0439 ctx \u044d\u0442\u043e \u0432\u0435\u0440\u0445\u0443\u0448\u043a\u0430 \u0441\u0442\u0435\u043a\u0430 \u0432\u044b\u0437\u043e\u0432\u043e\u0432     if (this.callStack[this.callStack.length - 1] !== ctx) {        return result;     }   }   this.callStack.pop();   return result; }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u043e\u0431\u043d\u043e \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c BlockStatement:<\/p>\n<pre><code class=\"javascript\">if (t.isBlockStatement(node)) {   this._hoistVariables(node, ctx);   let result;   for (let i = 0; i &lt; node.body.length; ++i) {     const stmt = node.body[i];     result = this.eval(stmt, ctx);     if (this.callStack[this.callStack.length - 1] !== ctx) {       return result;     }   }   return result; }<\/code><\/pre>\n<h3>CallExpression<\/h3>\n<p>\u041c\u044b \u0443\u043c\u0435\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043d\u043e \u043d\u0435 \u0443\u043c\u0435\u0435\u043c \u0438\u0445 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c. \u041f\u043e\u0440\u0430 \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c.<\/p>\n<pre><code class=\"javascript\">function square(x) {   return x * x; }  square(10);<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/722\/46f\/785\/72246f7853c27be45607051ec38dc874.PNG\" width=\"396\" height=\"241\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isCallExpression(node)) {   let thisCtx;   let fn;   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u0437 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f   fn = this.eval(node.callee, ctx);    \/\/ \u0412\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u0443\u0437\u043b\u044b \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 node.arguments,   \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a\u043e\u0439 \u0432\u044b\u0437\u043e\u0432: square(getNumber(10));   const args = node.arguments.map(arg => this.eval(arg, ctx));    \/\/ \u041c\u044b \u043f\u043e\u043a\u0430 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b,   \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435   thisCtx = ctx.thisValue;    \/\/ \u0417\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442 \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435,   \/\/ \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 \u0441\u0432\u043e\u0451 \u0442\u0435\u043b\u043e \u0432 \u043d\u043e\u0432\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438   return fn.call(thisCtx, ...args); }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">function getNumber(number) {   return number; }  function square(x) {   return x * x; }  var a = getNumber(1) || getNumber(0); var b = 5; if (a) {   square(getNumber(b)); } else {   square(100) }<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/194\/9c4\/1c0\/1949c41c0fd55d37b970c1b0d22b0bb6.gif\" width=\"1583\" height=\"634\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/194\/9c4\/1c0\/1949c41c0fd55d37b970c1b0d22b0bb6.gif\"\/><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0439:<\/p>\n<pre><code class=\"javascript\">var x = 0; function foo() {   var x = 10;      function bar() {     return x;   }      return bar(); }  foo();<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fe9\/02a\/296\/fe902a296f13fb1fd43e2eeaa51dd179.gif\" width=\"1583\" height=\"634\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fe9\/02a\/296\/fe902a296f13fb1fd43e2eeaa51dd179.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<h3>MemberExpression<\/h3>\n<p>\u041c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043d\u043e \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443. \u0417\u0430\u043a\u0440\u043e\u0435\u043c \u044d\u0442\u043e\u0442 \u0433\u0435\u0448\u0442\u0430\u043b\u044c\u0442. <\/p>\n<pre><code class=\"javascript\">var object = {   foo: 'bar' }  console['log'](object.foo);<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/466\/fb6\/12a\/466fb612ad5f6d9db6afc0b2efcd0ab4.png\" width=\"512\" height=\"727\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/466\/fb6\/12a\/466fb612ad5f6d9db6afc0b2efcd0ab4.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u042f \u043d\u0435 \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043d\u0443\u0436\u043d\u044b \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"javascript\">if (t.isMemberExpression(node)) {   const object = this.eval(node.object, ctx);   let prop;   if (node.computed) { \/\/ \u0415\u0441\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u044b\u0445 \u0441\u043a\u043e\u0431\u043a\u0430\u0445     prop = this.eval(node.property, ctx);   } else {     prop = node.property.name;   }   return object[prop]; }<\/code><\/pre>\n<p>\u041c\u044b \u0431\u0435\u0440\u0451\u043c \u0438\u0437 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442 \u0447\u0435\u0440\u0435\u0437 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043a \u043d\u0435\u043c\u0443 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f, \u0438 \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u043c \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u043e \u0438\u043c\u0435\u043d\u0438.<\/p>\n<h3>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 this \u0432 CallExpression<\/h3>\n<p>\u0412 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 <code>this<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e \u0444\u043e\u0440\u043c\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u044b\u0437\u043e\u0432\u0430, \u0442\u043e \u0435\u0441\u0442\u044c, \u0433\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f, <code>this<\/code> \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0441\u043b\u0435\u0432\u0430 \u043e\u0442 \u0442\u043e\u0447\u043a\u0438:<\/p>\n<pre><code class=\"javascript\">var foo = {   bar: function() {     console.log(this);   } };  foo.bar(); \/\/ foo object<\/code><\/pre>\n<p>\u0415\u0441\u0442\u044c \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438:<\/p>\n<pre><code class=\"javascript\">var foo = {   bar: function() {     console.log(this);   } };  (foo.bar, foo.bar)(); \/\/ window<\/code><\/pre>\n<p>\u041c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0443\u0437\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">if (t.isCallExpression(node)) {   let thisCtx;   let fn;    \/\/ \u0415\u0441\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u0430,    \/\/ \u0442\u043e this - \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442,   \/\/ \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430   if (t.isMemberExpression(node.callee)) {     thisCtx = this.eval(node.callee.object, ctx);     const prop = node.callee.computed       ? this.eval(node.callee.property, ctx)       : node.callee.property.name;     fn = thisCtx[prop];   } else {     fn = this.eval(node.callee, ctx);     thisCtx = ctx.thisValue;   }    if (fn === undefined) {     throw `function is not defined ${generate(node).code}`;   }    const args = node.arguments.map(arg => this.eval(arg, ctx));    return fn.call(thisCtx, ...args) }<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0443\u0437\u043b\u0430 FunctionExpression:<\/p>\n<pre><code class=\"javascript\">if (t.isFunctionExpression(node)) {   const name = node.id ? node.id.name : undefined;   const self = this;   const parentEnv = ctx.env;   const func = function(...args) {     const activationRecord = {};     if (name) {       activationRecord[name] = func;     }     for (let i = 0; i &lt; node.params.length; ++i) {       activationRecord[node.params[i].name] = args[i];     }     activationRecord['arguments'] = [...args];     const execCtx = new ExecutionContext(       this,       new Environment(activationRecord, parentEnv)     );      self.callStack.push(execCtx);      let result = self._evalFunctionBlock(node.body, execCtx);     return result;   }    const funcString = this.scriptCode.substring(node.loc.start.column, node.loc.end.column);   userFunctionToString.set(func, funcString);    return func; }<\/code><\/pre>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044d\u0442\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0430 FunctionDeclaration \u0437\u0430 \u0442\u0435\u043c \u043b\u0438\u0448\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c, \u0447\u0442\u043e \u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u043c\u044b \u0441\u0430\u043c\u0443 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0430 \u0442\u0430\u043a\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u044b \u0441\u0441\u044b\u043b\u0430\u0435\u043c\u0441\u044f \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u0440\u043e\u0447\u043a\u0435 \u043c\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<pre><code class=\"javascript\">var a = function() {}<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0443 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u043c\u044f, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u0443 \u0441\u0435\u0431\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0432 <code>activationRecord<\/code>. <\/p>\n<p>\u0422\u0435\u0441\u0442:<\/p>\n<pre><code class=\"javascript\">var goodBot = {   name: 'goodBot',   getThis: function() {     return this.name;   } }  console.log(goodBot.getThis()); \/\/ goodBot<\/code><\/pre>\n<h3>new()<\/h3>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 JS \u0438\u043c\u0435\u044e\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e prototype, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f(<code>__proto__<\/code>) \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>new()<\/code>.<\/p>\n<pre><code class=\"javascript\">function A() {   this.x = 10; }  var a = new A();  console.log(a.x); \/\/ 10 console.log(a instanceof A); \/\/ true<\/code><\/pre>\n<p>\u0413\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 new() \u043c\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0430 <code>this<\/code>. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043d\u0430\u043c \u0441\u043e\u0432\u0441\u0435\u043c \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c FunctionExpression \u0438 FunctionDeclaration:<\/p>\n<pre><code class=\"javascript\">if (t.isFunctionDeclaration(node)) {   const self = this;   const parentEnv = ctx.env;   const func = function(callContext, ...args) {     const activationRecord = {};     \/\/ ...     \/\/ \u0415\u0441\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 new     \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0451 \u0442\u0435\u043b\u043e \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c this     if (new.target) {       self._evalFunctionBlock(node.body, execCtx);       return this;     }      let result = self._evalFunctionBlock(node.body, execCtx);     return result;   }    \/\/ ...    ctx.env.define(node.id.name, func);   return; }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST NewExpression<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/454\/1a5\/a14\/4541a5a14cc741d09fc907ac200c9155.PNG\" width=\"360\" height=\"131\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isNewExpression(node)) {   const callee = this.eval(node.callee, ctx);   const args = node.arguments.map(arg => this.eval(arg, ctx));   const result = new callee(...args);   return result }<\/code><\/pre>\n<h3>toString()<\/h3>\n<p>\u041c\u044b \u043f\u043e\u0442\u043e\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 <code>window.Function.prototype.toString<\/code>, \u043d\u043e \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u043d\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u043a\u0440\u0438\u043f\u0442 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0441\u0432\u043e\u044e \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0411\u043b\u0430\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442 \u0430\u043a\u0430\u043c\u0430\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0432 \u043e\u0434\u043d\u0443 \u0441\u0442\u0440\u043e\u0447\u043a\u0443, \u0430 \u043d\u0430\u0448 \u043f\u0430\u0440\u0441\u0435\u0440 \u043b\u044e\u0431\u0435\u0437\u043d\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043d\u0430\u0447\u0430\u043b\u0430 \u0438 \u043a\u043e\u043d\u0446\u0430 \u043b\u044e\u0431\u043e\u0433\u043e \u0443\u0437\u043b\u0430, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442 \u0432\u044b\u0440\u0435\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0443. \u042f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 Map&lt;function, functionString>, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0433\u043e \u0437\u0430\u0431\u0440\u0430\u0442\u044c.<\/p>\n<pre><code class=\"javascript\">\/\/ .\/utils\/constants const userFunctionToString = new Map();  module.exports = {   userFunctionToString } <\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ .\/libs\/Interpreter \/\/ ... const { userFunctionToString } = require('.\/..\/utils\/constants');  class Interpreter {   \/\/ \u0431\u0443\u0434\u0435\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043a\u043e\u0434, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0440\u0435\u0437\u0430\u0442\u044c \u0438\u0437 \u043d\u0435\u0433\u043e \u0441\u0442\u0440\u043e\u043a\u0438   constructor(code, execCtx = GlobalExecutionContext) {     this.scriptCode = code;     this.callStack = [execCtx];   }   \/\/ ...   if (t.isFunctionDeclaration(node)) {     const self = this;     const parentEnv = ctx.env; \/\/ \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e     const func = function(callContext, ...args) {       \/\/ ...     }      \/\/ \u0412\u044b\u0440\u0435\u0437\u0430\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435     const funcString = this.scriptCode.substring(node.loc.start.column, node.loc.end.column);     userFunctionToString.set(func, funcString);        ctx.env.define(node.id.name, func);     return;   }   \/\/ ... }<\/code><\/pre>\n<h3>\u0426\u0438\u043a\u043b\u044b<\/h3>\n<p>\u042f \u043d\u0435 \u0432\u0438\u0436\u0443 \u0441\u043c\u044b\u0441\u043b\u0430 \u0440\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0438 \u0432\u0441\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436\u0438 \u0434\u0440\u0443\u0433 \u043d\u0430 \u0434\u0440\u0443\u0433\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0440\u0430\u0441\u043f\u0438\u0448\u0443 \u043f\u0440\u043e WhileStatement, \u0430 \u043d\u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043d\u0435 \u0431\u0443\u0434\u0443 \u0437\u0430\u043e\u0441\u0442\u0440\u044f\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435.<\/p>\n<pre><code class=\"javascript\">var i = 0; while (i &lt; 10) {   console.log(i++); }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3a3\/c13\/8eb\/3a3c138eb28c05b58080c8aa6ecc0bc7.png\" width=\"455\" height=\"273\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3a3\/c13\/8eb\/3a3c138eb28c05b58080c8aa6ecc0bc7.png\"\/><\/figure>\n<p>\u0412\u0441\u0451 \u043f\u0440\u043e\u0449\u0435 \u043d\u0435\u043a\u0443\u0434\u0430: \u0443 \u0443\u0437\u043b\u0430 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e test, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u0443\u044e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044e, \u0438 \u0442\u0435\u043b\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0443\u0436\u0435 \u0443\u043c\u0435\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c.<\/p>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u0430:<\/p>\n<pre><code class=\"javascript\">if (t.isWhileStatement(node)) {   const { test, body } = node;   let result;   while(this.eval(test, ctx)) {     result = this.eval(body, ctx);   }   return result; }<\/code><\/pre>\n<p>\u041d\u043e \u043d\u0430\u0434\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e <code>while<\/code> \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c <code>return<\/code>:<\/p>\n<pre><code class=\"javascript\">function foo() {   var i = 0;   while (i &lt; 10) {     if (i == 5) return;     ++i;   } }  foo();<\/code><\/pre>\n<p>\u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u044f\u0432\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u0432\u0441\u0451 \u0435\u0449\u0451 \u0432 \u043d\u0443\u0436\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435, \u0442\u043e \u0435\u0441\u0442\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0436\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443, \u043a\u0430\u043a \u0432 \u0431\u043b\u043e\u043a\u0430\u0445:<\/p>\n<pre><code class=\"javascript\">if (t.isWhileStatement(node)) {   const { test, body } = node;   let result;   while(this.callStack[this.callStack.length - 1] === ctx &amp;&amp; this.eval(test, ctx)) {     result = this.eval(body, ctx);   }   return result; }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u043e\u0438\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 <code>continue<\/code> \u0438 <code>break<\/code>. \u041c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u044d\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0432\u0443\u0445 \u0444\u043b\u0430\u0436\u043a\u043e\u0432:<\/p>\n<pre><code class=\"javascript\">class Interpreter {   constructor(code, execCtx = GlobalExecutionContext) {     this.scriptCode = code;     this.callStack = [execCtx];     \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0444\u043b\u0430\u0433\u0438     this.flags = {       continue: false,       break: false     }   } \/\/ ....<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c, \u0435\u0441\u043b\u0438 \u043c\u044b \u043d\u0430\u0442\u043a\u043d\u0451\u043c\u0441\u044f \u043d\u0430 \u0442\u0430\u043a\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438, \u0442\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u043c \u044d\u0442\u0438 \u0444\u043b\u0430\u0433\u0438 \u0432 true:<\/p>\n<pre><code class=\"javascript\">if (t.isContinueStatement(node)) {   this.flags.continue = true;   return; }  if (t.isBreakStatement(node)) {   this.flags.break = true;   return; }<\/code><\/pre>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u044d\u0442\u0438\u0445 \u0444\u043b\u0430\u0433\u043e\u0432:<\/p>\n<pre><code class=\"javascript\">if (t.isBlockStatement(node)) {   this._hoistVariables(node, ctx);   let result;   for (let i = 0; i &lt; node.body.length; ++i) {     const stmt = node.body[i];     result = this.eval(stmt, ctx);     if (this.callStack[this.callStack.length - 1] !== ctx) {       return result;     }      if (this.flags.continue || this.flags.break) {       break;     }   }   return result; }<\/code><\/pre>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u043c\u044b \u043f\u0440\u0435\u043a\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0430, \u0435\u0441\u043b\u0438 \u043d\u0430\u0442\u044b\u043a\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u043e\u0434\u0438\u043d \u0438\u0437 \u0444\u043b\u0430\u0433\u043e\u0432. \u0418 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 \u0441\u0430\u043c \u0446\u0438\u043a\u043b:<\/p>\n<pre><code class=\"javascript\">if (t.isWhileStatement(node)) {   const { test, body } = node;   let result;   while(this.callStack[this.callStack.length - 1] === ctx &amp;&amp; this.eval(test, ctx)) {     result = this.eval(body, ctx);     if (this.flags.continue) {       this.flags.continue = false;     }     if (this.flags.break) {       this.flags.break = false;       break;      }   }   return result; }<\/code><\/pre>\n<p>\u0424\u043b\u0430\u0433 <code>continue<\/code> \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u043d\u0443\u043b\u044f\u0435\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0438\u0437 \u0431\u043b\u043e\u043a\u0430 \u0443\u0436\u0435 \u0432\u044b\u0448\u043b\u0438 \u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u043d\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u043d\u0430\u0442\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u043d\u0430 \u0444\u043b\u0430\u0433 <code>break<\/code>, \u0442\u043e \u0446\u0438\u043a\u043b \u043d\u0443\u0436\u043d\u043e \u0435\u0449\u0451 \u0438 \u043f\u043e\u043a\u0438\u043d\u0443\u0442\u044c. \u042d\u0442\u043e \u0432\u0441\u0451. \u041c\u044b \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u0430\u0432\u0440\u0430\u043b\u0438, \u043d\u043e \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/p>\n<details class=\"spoiler\">\n<summary>ForStatement, DoWhileStatement<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">if (t.isForStatement(node)) {   const { init, test, body } = node;   let result;   if (node.init) this.eval(init, ctx);   while(this.callStack[this.callStack.length - 1] === ctx &amp;&amp; (test ? this.eval(test, ctx) : 1)) {     result = this.eval(body, ctx);     if (this.flags.continue) {       this.flags.continue = false;     }     if (this.flags.break) {       this.flags.break = false;       break;     }     if (node.update) {       this.eval(node.update, ctx);     }   }   return result; }<\/code><\/pre>\n<pre><code class=\"javascript\">if (t.isDoWhileStatement(node)) {   const { test, body } = node;   let result;   do {     result = this.eval(body, ctx);     if (this.flags.continue) {       this.flags.continue = false;     }     if (this.flags.break) {       this.flags.break = false;       break;     }   } while(this.callStack[this.callStack.length - 1] === ctx &amp;&amp; this.eval(test, ctx));   return result; }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h3>Try-Catch, Throw<\/h3>\n<pre><code class=\"javascript\">try {   throw 'error' } catch(err) {   constole.log(err) }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/094\/2ef\/3a1\/0942ef3a1e32fe6e5ba1fb49f23da121.PNG\" width=\"501\" height=\"711\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0437\u0434\u0435\u0441\u044c &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>throw<\/code>:<\/p>\n<pre><code class=\"javascript\">if (t.isThrowStatement(node)) {   throw this.eval(node.argument, ctx); }<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0442\u043e\u0436\u0435 \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 AST:<\/p>\n<pre><code class=\"javascript\">if (t.isTryStatement(node)) {   let result;   try {     result = this.eval(node.block, ctx);   } catch(e) {     const paramName = node.handler.param.name; \/\/ \u0431\u0435\u0440\u0451\u043c \u0438\u043c\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430     ctx.env.define(paramName, e); \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0432 \u043d\u0430\u0448\u0435\u043c catch-\u0431\u043b\u043e\u043a\u0435     result = this.eval(node.handler.body, ctx); \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0431\u043b\u043e\u043a catch   }   if (node.finalizer) { \/\/ \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c finally, \u0442\u043e \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043e \u043d\u0451\u043c \u0437\u0430\u0431\u044b\u0432\u0430\u0442\u044c     return this.eval(node.finalizer, ctx)   }   return result; }<\/code><\/pre>\n<p>JS \u0443\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e try-catch, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043d\u0430 \u043d\u0430\u0441 \u043e\u0447\u0435\u043d\u044c \u0432\u044b\u0440\u0443\u0447\u0430\u0435\u0442. \u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c \u0437\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u0432\u0435 \u0447\u0442\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u0448\u0438\u0431\u043a\u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u043d\u0435\u0433\u043e \u0438 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442. <\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 try-catch \u043e\u0447\u0435\u043d\u044c \u043e\u043f\u0430\u0441\u043d\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0432\u0435\u0434\u044c \u0435\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u0432 \u0441\u0430\u043c\u043e\u043c  \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0435 \u043f\u043e\u0439\u0434\u0451\u0442 \u043d\u0435 \u0442\u0430\u043a, \u0430 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432 ThrowStatement, \u0442\u043e \u043c\u044b \u044d\u0442\u043e\u0433\u043e \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043c \u0438\u0437-\u0437\u0430 \u0441\u0432\u043e\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 catch, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0441\u043e\u0432\u0435\u0442\u0443\u044e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0445\u043e\u0442\u044f \u0431\u044b console.debug \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0442\u044c \u0432 \u043a\u0443\u0440\u0441\u0435 \u0432\u0441\u0435\u0445 \u043e\u0448\u0438\u0431\u043e\u043a, \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0449\u0438\u0445 \u0432 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u043a\u043e\u0434\u0430. <\/p>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c 3 \u0443\u0437\u043b\u0430.<\/p>\n<h3>ForInStatement<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0430:<\/p>\n<pre><code class=\"javascript\">var obj = {   a: 1,   b: 2 }  for (var prop in obj) {   console.log(obj[prop]); }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/484\/7f2\/900\/4847f29002ab84f8a91beda2ff89a8c6.PNG\" width=\"420\" height=\"294\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e, \u0432 \u043a\u043e\u0434\u0435 \u0430\u043a\u0430\u043c\u0430\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432 \u044d\u0442\u043e\u043c \u0446\u0438\u043a\u043b\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a\u0436\u0435:<\/p>\n<pre><code class=\"javascript\">if (t.isForInStatement(node)) {   \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442, \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0438\u0442\u044c   const object = this.eval(node.right, ctx);   \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043c\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0432 \u044d\u0442\u043e\u043c \u0446\u0438\u043a\u043b\u0435   const varName = node.left.declarations[0].id.name;       for (var key in object) {     ctx.env.define(varName, key); \/\/ \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438     this.eval(node.body, ctx);    \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0442\u0435\u043b\u043e   }   return; }<\/code><\/pre>\n<h3>SwitchStatement<\/h3>\n<p>\u0412\u043e \u0432\u0441\u0451\u043c \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 switch-case:<\/p>\n<pre><code class=\"javascript\">var a = 11;  switch (a) {   case 1: {     console.log('\"1\"')   };   break;   case 2: {     console.log('\"2\"')   }   break;   case 10: {     console.log('\"10\"')   }   break;   default: {     console.log('default')   } }<\/code><\/pre>\n<p>case-block-break, case-block-break, case-block-break&#8230; \u041c\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u043a\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439:<\/p>\n<details class=\"spoiler\">\n<summary>AST \u0438 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c1c\/870\/620\/c1c8706200b999682f06a5f7ee591afe.PNG\" width=\"441\" height=\"349\"\/><\/figure>\n<p>\u0418\u0442\u0430\u043a, \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f switch(<strong>\u0417\u0414\u0415\u0421\u042c<\/strong>) &#8212; \u044d\u0442\u043e <code>node.discriminant<\/code>. \u041c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0435\u0433\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0432\u0441\u0435\u043c <code>node.cases<\/code> \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>test<\/code> \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 <code>test<\/code>\u0440\u0430\u0432\u0435\u043d <code>node.discriminant,<\/code>\u0442\u043e \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0432\u0441\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e case \u0438 \u0443\u0437\u043b\u0430 <code>node.consequent<\/code>. \u0423 \u0432\u0435\u0442\u043a\u0438 <code>default:<\/code> node.test \u0440\u0430\u0432\u0435\u043d null, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u043e\u0436\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u044d\u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439.<\/p>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">if (t.isSwitchStatement(node)) {   const test = this.eval(node.discriminant, ctx); \/\/ \u0412\u044b\u0447\u0438\u0441\u043b\u044f\u043c switch (\u042d\u0422\u041e\u0422 \u041f\u0410\u0420\u0410\u041c\u0415\u0422\u0420)   let result;   for (let i = 0; i &lt; node.cases.length; ++i) {     const caseClause = node.cases[i];     if (       caseClause.test !== null &amp;&amp; \/\/ \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u044b\u0439 case, \u0430 \u043d\u0435 default \u0432\u0435\u0442\u043a\u0430       this.eval(caseClause.test, ctx) === test     ) {       result = this._evalCaseClause(caseClause, ctx); \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0442\u0435\u043b\u043e       if (this.flags.break === true) { \/\/ \u043f\u043e\u043c\u043d\u0438\u043c \u043f\u0440\u043e \u0444\u043b\u0430\u0433\u0438         this.flags.break = false;       }       break; \/\/ break \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0446\u0438\u043a\u043b\u0430 for. \u041c\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0443\u0437\u043b\u043e\u043c     } else if (caseClause.test === null) { \/\/ \u0415\u0441\u043b\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u0434\u043e\u0448\u043b\u043e, \u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c default       result = this._evalCaseClause(caseClause, ctx);       if (this.flags.break === true) {         this.flags.break = false;       }     }   }   return result; }<\/code><\/pre>\n<p>\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043f\u043e\u0445\u043e\u0436\u0430\u044f \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0430:<\/p>\n<pre><code class=\"javascript\">_evalCaseClause(caseClause, ctx) {   let result;   for (let i = 0; i &lt; caseClause.consequent.length; ++i) {     const stmt = caseClause.consequent[i];     result = this.eval(stmt, ctx);     \/\/ switch-case \u043c\u043e\u0433 \u0431\u044b\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438,     \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0433 \u043d\u0430\u0442\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u043d\u0430 return     if (this.callStack[this.callStack.length - 1] !== ctx) {       if (this.flags.break === true) {         this.flags.break = false;       }       return result;     }   }   return result; }<\/code><\/pre>\n<h3>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0448\u0442\u0440\u0438\u0445\u0438<\/h3>\n<p>\u041c\u044b \u0437\u0430\u0431\u044b\u043b\u0438 \u043f\u0440\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 MemberExpression \u0443\u0437\u043b\u0430\u0445 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u0439:<\/p>\n<details class=\"spoiler\">\n<summary>AssignmentExpression<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">if (t.isAssignmentExpression(node)) {   if (t.isIdentifier(node.left)) {     \/\/ \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438   }    \/\/ \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443\u0437\u0435\u043b \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430   if (t.isMemberExpression(node.left)) {     let objectName = node.left.object.name;     let object;     if (objectName === undefined) {       object = this.eval(node.left.object, ctx);     } else {       object = ctx.env.lookup(objectName);     }     if (!object) {       throw `Undefined object in assignment... ${generate(node).code}`;     }     let prop;     if (node.left.computed) {       prop = this.eval(node.left.property, ctx);     } else {       prop = node.left.property.name;     }     if (prop == undefined) {       throw `Undefined property in assignment... ${generate(node).code}`     }     const propValue = this.eval(node.right, ctx);     const prevValue = object[prop];     switch(node.operator) {       case '=':         return object[prop] = propValue;       case '+=':         return object[prop] = prevValue + propValue;       case '-=':         return object[prop] = prevValue + propValue;       case '*=':         return object[prop] = prevValue * propValue;       case '\/=':         return object[prop] = prevValue \/ propValue;       case '^=':         return ctx.env.assign(left, prevValue ^ propValue);       default:         throw `Unimplement operator assignment ${node.operator}`     }   }    throw `Unimplement assignment for node type ${node.left.type}`; }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>UpdateExpression<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">if (t.isUpdateExpression(node)) {   if (t.isIdentifier(node.argument)) {     \/\/ ...   }    if (t.isMemberExpression(node.argument)) {     const objectEnv = this.eval(node.argument.object, ctx);     const prop = node.argument.computed ? this.eval(node.argument.property, ctx) : node.argument.property.name;     const propValue = objectEnv[prop];     const newValue = node.operator === '++' ? propValue + 1 : propValue - 1;     if (node.prefix) {       return objectEnv[prop] = newValue;     }     objectEnv[prop] = newValue;     return propValue;   } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0445, \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445, null \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u043e\u0432 \u0435\u0441\u0442\u044c \u0435\u0449\u0451 \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u044b \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u0438 \u043f\u0440\u043e \u043d\u0438\u0445:<\/p>\n<pre><code class=\"javascript\">if (t.isLiteral(node)) {   if (t.isNullLiteral(node)) {     return null;   }   if (t.isRegExpLiteral(node)) {     return new RegExp(node.pattern, node.flags);   }   return node.value; }<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0432\u0441\u0451. \u041d\u0430\u0448 \u043e\u0431\u0445\u043e\u0434 \u0433\u043e\u0442\u043e\u0432. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0430 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c V8.<\/p>\n<h2>\u0427\u0442\u043e \u0437\u0430 \u0447\u0443\u0434\u043e \u043d\u0430\u043c\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e?<\/h2>\n<p>\u0421\u0430\u043c\u043e\u043c\u0443 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 &#8212; \u044d\u0442\u043e \u0441\u0443\u043f\u0435\u0440\u0441\u0438\u043b\u0430. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u043e\u043c\u0430\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u0434\u0443\u0448\u0435 \u0443\u0433\u043e\u0434\u043d\u043e! \u0425\u043e\u0442\u0438\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432\u0435\u0442\u043a\u0438 if \u0438 else \u0432\u043c\u0435\u0441\u0442\u0435? \u041d\u0435 \u0432\u043e\u043f\u0440\u043e\u0441. \u041d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442\u0435 \u0433\u0434\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u0434\u0430\u043d\u043d\u044b\u0435? \u041b\u043e\u0433\u0438\u0440\u0443\u0439\u0442\u0435 \u0443\u0437\u043b\u044b! \u0414\u0430, \u0432\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043b\u044e\u0431\u043e\u0433\u043e \u0443\u0437\u043b\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u042d\u0442\u043e \u043a\u0430\u043a \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043e\u0442\u043b\u0430\u0434\u0447\u0438\u043a! \u0421\u0442\u043e\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0444\u0430\u043d\u0442\u0430\u0437\u0438\u044e. <\/p>\n<p>\u041d\u043e \u0443 \u043d\u0430\u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 &#8212; \u0434\u043e\u0441\u0442\u0430\u0442\u044c &#171;\u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0435&#187; \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439.<\/p>\n<h2>\u041a\u0430\u043a \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u0432\u043e\u044e \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c?<\/h2>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435:<\/p>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5a3\/537\/661\/5a3537661227924918aca9b35be13353.gif\" width=\"1208\" height=\"694\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5a3\/537\/661\/5a3537661227924918aca9b35be13353.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412 \u043d\u0435\u0439 \u0431\u0435\u0440\u0451\u0442\u0441\u044f <code>toString()<\/code> \u0432\u0441\u0435\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u043a. \u0417\u0430\u0442\u0435\u043c \u0441 \u044d\u0442\u0438\u043c\u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u044f\u043c\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043a\u0430\u043a\u0430\u044f-\u0442\u043e \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430&#8230; \u0422\u043e \u0435\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u0443\u0435\u0442\u0435 \u043a\u043e\u0434 \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0435 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u0438\u043d \u043b\u0438\u0448\u043d\u0438\u0439 \u043f\u0440\u043e\u0431\u0435\u043b, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0431\u044b\u043b\u043e, \u0442\u043e \u0432\u044b \u0443\u0432\u044f\u0437\u043d\u0438\u0442\u0435 \u0432 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0446\u0438\u043a\u043b\u0435. \u0414\u0430, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0440\u0435\u0437\u0430\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435, \u043d\u0438\u043a\u0442\u043e \u0432\u0430\u043c \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442, \u043d\u043e \u0433\u0434\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0438, \u0447\u0442\u043e \u043e\u043d\u0430 \u043e\u0434\u043d\u0430? \u0418 \u043e\u043d\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435 \u043e\u0434\u043d\u0430, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 <code>toString()<\/code> \u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b. <\/p>\n<p>\u042d\u0442\u0438\u043c \u043c\u044b \u0443\u0436\u0435 \u043e\u0437\u0430\u0431\u043e\u0442\u0438\u043b\u0438\u0441\u044c \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0443\u0437\u043b\u043e\u0432 FunctionDeclaration \u0438 FunctionExpression. \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043c\u044b \u0435\u0449\u0451 \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u043c \u0435\u0451 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0437 \u043a\u043e\u0434\u0430. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e toString:<\/p>\n<pre><code class=\"javascript\">\/\/ .\/browser-env\/toString.js const { userFunctionToString } = require('.\/..\/utils\/constants');  const defineToString = window => {   const orgToString = window.Function.prototype.toString;   window.Function.prototype.toString = function toString() {     if (userFunctionToString.has(this)) {       return userFunctionToString.get(this);     }     return orgToString.call(this);   }  }  module.exports = defineToString;  \/\/ .\/browser-env\/window.js \/\/ ... const defineToString = require('.\/toString'); \/\/ ... defineToString(window);<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 <code>toString()<\/code> \u043c\u044b \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u043b\u043e\u0432\u0430\u0440\u044c <code>userFunctionToString<\/code> \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0432 \u043d\u0451\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438, \u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u0435\u0441\u0442\u044c, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u0435\u0451 \u0441\u0442\u0440\u043e\u043a\u0443. \u0418\u043d\u0430\u0447\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 <code>toString()<\/code>.<\/p>\n<p>\u041f\u043e\u0434\u043e\u0431\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b.<\/p>\n<h2>Window object<\/h2>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442 window, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0445\u043e\u0434\u0438\u043b \u043d\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0439. \u041d\u0430\u043c \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0438 \u043c\u0435\u0442\u043e\u0434\u044b &#171;\u043d\u0435 \u043f\u0430\u043b\u0438\u043b\u0438\u0441\u044c&#187;, \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u0440\u0438\u043f\u0442 \u043c\u043e\u0433 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c userAgent \u0447\u0435\u0440\u0435\u0437 <code>navigator.userAgent<\/code>, \u0435\u0441\u043b\u0438 \u0437\u0430\u0445\u043e\u0447\u0435\u0442. \u0421\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0441\u0442\u0438 \u0440\u0430\u0434\u0438, \u043d\u0430\u043c \u0434\u0430\u0436\u0435 \u043d\u0435 \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u043b\u0438 \u043e\u043d \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u044e\u0437\u0435\u0440\u0430\u0433\u0435\u043d\u0442 \u0438\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0443 &#171;\u0437\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u044e\u0437\u0435\u0440\u0430\u0433\u0435\u043d\u0442\u0430&#187;. \u0412\u0430\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u043c\u043e\u0433 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u043f\u043e\u043b\u044e <code>navigator.userAgent<\/code><\/p>\n<h4>\u0427\u0435\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0442\u044c Window?<\/h4>\n<p>\u0420\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c \u0432\u0441\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u0430\u043a\u0438\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u043a\u043d\u043e, \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0438\u0437\u043b\u0438\u0448\u043d\u0438\u043c. \u0412\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u044d\u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0444\u0430\u0439\u043b\u0430\u0445. \u041d\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u043c\u0435\u0442\u043e\u0434\u0438\u043a\u0443 \u043f\u043e\u0438\u0441\u043a\u0430 \u044d\u0442\u0438\u0445 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/p>\n<p>\u041a\u0430\u043a \u044f \u0443\u0436\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b, \u043c\u044b \u0443\u043c\u0435\u0435\u043c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0437\u043b\u044b. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0451\u043c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c CallExpression:<\/p>\n<pre><code class=\"javascript\">if (t.isCallExpression(node)) {   \/\/ ...   \/\/ return fn.call(thisCtx, ...args) &lt;----- \u0440\u0430\u043d\u044c\u0448\u0435 \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442   \/\/ \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442   const result = fn.call(thisCtx, ...args);    \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442   const resultBlackList = ['length', 'push', 'pop', 'charCodeAt', 'charAt', 'toString'];   if (     typeof result === 'string' &amp;&amp;     !resultBlackList.includes(result) &amp;&amp;     result.length > 1 &amp;&amp; result.length &lt; 100   ) {     fs.appendFileSync('.\/interpreter-logs\/callsLog.txt', result + '\\n');   }    \/\/ \u0432\u0435\u0440\u043d\u0443\u043b\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442   return result; }<\/code><\/pre>\n<p>\u0412\u0441\u044f\u043a\u0438\u0445 length, push, pop \u0438 \u0442\u0434 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0445 \u0441\u0442\u043e\u0438\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c. \u0411\u0443\u043a\u0432\u044b \u0438 \u0432\u0441\u044f\u043a\u0438\u0435 toString() \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043d\u0430\u043c \u0442\u043e\u0436\u0435 \u0432\u0438\u0434\u0435\u0442\u044c \u043d\u0438 \u043a \u0447\u0435\u043c\u0443(<code>result.length > 1 &amp;&amp; result.length &lt; 100<\/code>).<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 AST, \u0447\u0442\u043e \u0441\u0430\u043c\u043e \u043f\u043e \u0441\u0435\u0431\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e\u0431 \u043e\u0447\u0435\u043d\u044c \u043d\u0438\u0437\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430. \u0412\u044b\u0432\u043e\u0434\u044b \u0432 \u0444\u0430\u0439\u043b\u044b \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u043b\u0443\u0447\u0448\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0442\u043e\u0438\u0442, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0445\u043e\u0442\u044f \u0431\u044b \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u0431\u0443\u0444\u0435\u0440 \u0437\u0430\u0432\u0435\u0441\u0442\u0438 \u0438 \u043e\u043f\u0443\u0441\u0442\u043e\u0448\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u043e \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0442\u0440\u043e\u043a. \u041d\u0443 \u0430 \u0442\u0430\u043a\u0436\u0435 \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0432\u0438\u0434\u0438\u043c\u043e, \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044f\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c\/\u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0432\u044b\u0432\u043e\u0434\u044b \u0432 \u0444\u0430\u0439\u043b \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0443\u0437\u043b\u0435 \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0441\u0435\u0431\u0435 \u0437\u0430\u043d\u044f\u0442\u0438\u0435&#8230;<\/p>\n<\/div>\n<\/details>\n<p>\u0418\u0442\u0430\u043a, \u0432\u043e\u0442 \u044f \u0432\u0438\u0436\u0443 \u0432 \u043d\u0430\u0448\u0435\u043c \u043b\u043e\u0433\u0435 \u0442\u0430\u043a\u0438\u0435 \u0441\u0442\u0440\u043e\u0447\u043a\u0438:<\/p>\n<pre><code>document document document currentScript currentScript currentScript<\/code><\/pre>\n<p><code>document.currentScript<\/code> \u0438\u043c\u0435\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e HTMLScriptElement, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u044d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">\/\/ .\/browser-env\/document\/currentScript.js const defineCurrentScript = window => {   Object.defineProperty(window.Document.prototype, 'currentScript', {     get: () => {       return new Proxy({}, {         get(target, prop, r) {           console.log('currentScript:', prop); \/\/ &lt;-- \u0434\u0435\u043b\u0430\u0435\u043c \u0432\u044b\u0432\u043e\u0434 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c         }       })     }   }); }<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u0432\u0438\u0434\u0438\u043c \u044d\u0442\u043e: <\/p>\n<pre><code>currentScript: src currentScript: src currentScript: src<\/code><\/pre>\n<p>\u0421\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0443 \u043b\u0438\u0448\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0433\u043e \u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"javascript\">const defineCurrentScript = window => {   Object.defineProperty(window.Document.prototype, 'currentScript', {     get: () => {       return new Proxy({}, {         get(target, prop, r) {           if (prop === 'src') {             return 'https:\/\/my.asos.com\/cPYhw7js-taKj\/GV\/951_KziztRsQ\/f5OEkf5rkY5Qit\/fSovAg\/WXQ\/MOWY5XCs'           }         }       })     }   }); }<\/code><\/pre>\n<p>\u042f \u0432\u0437\u044f\u043b \u0441\u0441\u044b\u043b\u043a\u0443 \u0438\u0437 \u0434\u0435\u0431\u0430\u0433\u0433\u0435\u0440\u0430 \u0445\u0440\u043e\u043c\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0430\u0441\u043e\u0441\u0430.<\/p>\n<h4>\u0415\u0449\u0451 \u043f\u0440\u0438\u043c\u0435\u0440<\/h4>\n<p>\u041b\u043e\u0433:<\/p>\n<pre><code>window speechSynthesis speechSynthesis<\/code><\/pre>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b \u0433\u043e\u043b\u043e\u0441\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0438 \u0438\u0445 \u043a\u043e\u0435-\u043a\u0430\u043a \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c:<\/p>\n<details class=\"spoiler\">\n<summary>\u0413\u043e\u043b\u043e\u0441\u0430<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0434\u0435\u0432\u0442\u0443\u043b\u0437\u0430 \u0432\u0438\u0434\u043d\u043e \u0447\u0442\u043e \u0438\u0437 \u0441\u0435\u0431\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 speechSynthesis:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ba4\/0e6\/2c0\/ba40e62c0ab020ec6c1e138c24e9685f.png\" width=\"1085\" height=\"732\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ba4\/0e6\/2c0\/ba40e62c0ab020ec6c1e138c24e9685f.png\"\/><\/figure>\n<p>\u0421\u0440\u0430\u0437\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u0437\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0433\u043e\u043b\u043e\u0441\u043e\u0432 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 getVoices(), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0435\u0433\u043e. \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0438\u0441\u043a\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0438\u043b\u0438 \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0443 ChatGpt. \u0421\u0430\u043c \u0433\u043e\u043b\u043e\u0441 \u0438\u043c\u0435\u0435\u0442 5 \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u043e\u0436\u0435 \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c. <\/p>\n<p>\u042f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e \u0432\u0441\u0451 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">\/\/ .\/browser-env\/ const defineSpeechSynthesis = window => {   class SpeechSynthesisVoice {     constructor(def, lang, localService, name) {       this.default_ = def;       this.lang_ = lang;       this.localService_ = localService;       this.name_ = name;       this.voiceURI_ = name;     }      get default() {       return this.default_;     }     get lang() {       return this.lang_;     }     get localService() {       return this.localService_;     }     get name() {       return this.name_;     }     get voiceURI() {       return this.voiceURI_;     }   }    \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0433\u043e\u043b\u043e\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u0440\u0438\u043f\u0442\u0443 \u0431\u044b\u043b\u043e \u0447\u0435\u0433\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c   const speech1 = new SpeechSynthesisVoice(true, \"ru-RU\", true, \"Microsoft Irina - Russian (Russia)\");   const speech2 = new SpeechSynthesisVoice(false, \"en-US\", true, \"Microsoft Mark - English (United States)\");   const speech3 = new SpeechSynthesisVoice(false, \"en-US\", true, \"Microsoft Zira - English (United States)\");    class speechSynthesis extends Object {     constructor() {       super();       this.onvoiceschanged = null;     }      getVoices() {       return [         speech1,         speech2,         speech3       ]     }      get onvoiceschanged() {       return this.onvoiceschanged;     }      set onvoiceschanged(value) {       this.onvoiceschanged = value;       this.onvoiceschanged();     }   }   window.speechSynthesis = new speechSynthesis(); }  module.exports = defineSpeechSynthesis;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 \u21163<\/h4>\n<p>\u041b\u043e\u0433:<\/p>\n<pre><code>navigator permissions permissions permissions<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>navigator.permissions<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4e3\/90e\/096\/4e390e0962507d21043efe4e8fe7082e.png\" width=\"652\" height=\"422\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4e3\/90e\/096\/4e390e0962507d21043efe4e8fe7082e.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <code>navigator.permissions<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0433\u0434\u0435 \u0443\u0433\u043e\u0434\u043d\u043e. \u041c\u0435\u0442\u043e\u0434 <code>query()<\/code> \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0435\u0440\u043d\u0451\u043c \u043f\u0440\u043e\u043c\u0438\u0441:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">const definePermissions = window => {   class PermissionStatus {     constructor(name) {       this.name_ = name; \/\/ \u041c\u044b \u0442\u0443\u0442 \u043d\u0430\u0432\u0440\u0430\u043b\u0438, \u043d\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u0442\u0440\u0430\u0448\u043d\u043e\u0433\u043e       this.onchangeCallBack = null;     }      get name() {       return this.name_     }      get onchange() {       return this.onchangeCallBack;     }      set onchange(value) {       this.onchangeCallBack = value;       this.onchangeCallBack();     }      get state() {       return 'denied'     }   }   window.PermissionStatus = PermissionStatus;    window.Permissions = function() {}   window.Permissions.prototype.query = async function(permission) {     const { name } = permission;     return Promise.resolve(new window.PermissionStatus(name));   } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0443 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435 \u0438 \u0442\u043e\u043c\u0443 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435&#8230; \u041d\u0443\u0434\u043d\u043e\u0435 \u0437\u0430\u043d\u044f\u0442\u0438\u0435 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u043d\u0443 \u0430 \u0447\u0442\u043e \u0436 \u043f\u043e\u0434\u0435\u043b\u0430\u0442\u044c&#8230;<\/p>\n<h2>\u0414\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f<\/h2>\n<p>\u041a\u0430\u043a \u044f \u0443\u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442 \u0441\u0432\u043e\u0451 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0438\u0437-\u0437\u0430 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 <code>window.setTimeout()<\/code>. \u0427\u0442\u043e \u0436, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043c \u044d\u0442\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u044b\u0437\u043e\u0432\u043e\u0432:<\/p>\n<pre><code class=\"javascript\">window.setTimeout = function(callBack, time) {   console.log('timeout', timeoutCallCounter);   ++timeoutCallCounter;   if (timeoutCallCounter === 6) {     \/\/ \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0436\u043e\u043a \u0435\u0441\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0438\u0439 \u0441\u0438\u0433\u043d\u0430\u043b \u0442\u043e\u0433\u043e,     \/\/ \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e     global.allTimeoutsCleaned = true;     return;   }   if (time === 300000) time = 10000;   return windowTimeout(callBack, time) }<\/code><\/pre>\n<p>\u042f \u0441\u0434\u0435\u043b\u0430\u043b \u0432\u044b\u0432\u043e\u0434 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0432\u044b\u0437\u043e\u0432\u0430\u0445 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0438 \u0443\u0432\u0438\u0434\u0435\u043b, \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u0430\u0436 \u043d\u0430 5 \u043c\u0438\u043d\u0443\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443 \u0435\u0433\u043e&#8230; \u0418\u0437\u043c\u0435\u043d\u0438\u043b \u043d\u0430 10 \u0441\u0435\u043a\u0443\u043d\u0434. \u0421 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430\u043c\u0438 \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b \u043f\u043e\u0445\u043e\u0436\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. <\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u043c\u044b \u0443\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u0432\u0438\u0434\u0435\u0442\u044c \u0442\u0430\u043a\u043e\u0435:<\/p>\n<details class=\"spoiler\">\n<summary>\u0422\u0430\u043a\u043e\u0435 \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u0444\u0430\u043a\u0442<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1b1\/a80\/b8b\/1b1a80b8b72805dff4828dff40e7bfaf.gif\" width=\"1064\" height=\"197\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1b1\/a80\/b8b\/1b1a80b8b72805dff4828dff40e7bfaf.gif\"\/><\/figure>\n<p>\u0414\u0430, \u044f \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b XMLHttpRequest:<\/p>\n<pre><code class=\"javascript\">const defineXMLHttpRequest = window => {   const XMLHttpRequestSend = window.XMLHttpRequest.prototype.send;   window.XMLHttpRequest.prototype.send = function send(...args) {     console.log(...args);     return XMLHttpRequestSend.call(this, ...args);   }    const XMLHttpRequestOpen = window.XMLHttpRequest.prototype.open;   window.XMLHttpRequest.prototype.open = function open(...args) {     args[1] = 'http:\/\/127.0.0.1:3000\/send'; \/\/ \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439...     console.log('OPEN: ', ...args);     return XMLHttpRequestOpen.call(this, ...args);   } }<\/code><\/pre>\n<p>\u042d\u0442\u0430 \u0437\u0430\u0440\u0430\u0437\u0430 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0435\u0439\u043b\u043e\u0430\u0434\u044b &#8212; \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e!<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u0444\u0430\u043a\u0442<\/summary>\n<div class=\"spoiler__content\">\n<p>\u042f \u0443\u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043b\u043e\u043c\u0430\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430? \u041a\u0430\u0436\u0435\u0442\u0441\u044f \u0434\u0430. <\/p>\n<p>\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0435 \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u0438\u0445 \u0434\u0443\u0440\u0430\u0446\u043a\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u043e \u0442\u0438\u043f\u0443 <code>^=<\/code>, <code>&amp;=<\/code> \u0438 \u0442\u0434&#8230; \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u0445 \u0443\u0431\u0435\u0440\u0451\u043c \u043d\u0435\u043d\u0430\u0434\u043e\u043b\u0433\u043e:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6a4\/b9b\/b8a\/6a4b9bb8a1aa875bfed734ad30ad5375.png\" width=\"573\" height=\"533\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6a4\/b9b\/b8a\/6a4b9bb8a1aa875bfed734ad30ad5375.png\"\/><\/figure>\n<p>\u041a\u0430\u043a\u043e\u0439 \u043f\u0435\u0439\u043b\u043e\u0430\u0434 \u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0443\u0432\u0438\u0434\u0438\u043c?<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1cc\/489\/0f1\/1cc4890f1b8f27473fd0ef2a7ec4866e.png\" width=\"1034\" height=\"241\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1cc\/489\/0f1\/1cc4890f1b8f27473fd0ef2a7ec4866e.png\"\/><\/figure>\n<p>\u0414\u0430, \u043e\u043d \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439, \u043d\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0449\u0438 \u0432 \u043d\u0451\u043c \u043f\u043e\u043d\u044f\u0442\u043d\u044b. \u0422\u0430\u043c \u0438 \u044e\u0437\u0435\u0440\u0430\u0433\u0435\u043d\u0442, \u0438 \u0447\u0442\u043e-\u0442\u043e \u0438\u0437 \u043d\u0430\u0432\u0438\u0433\u0430\u0442\u043e\u0440\u0430, \u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u044f \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u043b. \u0412 \u043e\u0431\u0449\u0435\u043c, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043a\u043e\u043f\u0430\u0442\u044c\u0441\u044f, &#171;\u043f\u043e\u0434\u0435\u0431\u0430\u0436\u0438\u0442\u044c&#187; \u0438 \u0441\u0442\u0430\u043d\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u043e\u0442\u043a\u0443\u0434\u0430 \u043d\u0430\u0447\u0430\u0442\u044c \u0438 \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0442\u0430\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u041d\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0438 \u0432 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435 \u0435\u0441\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f. \u0410\u043d\u0442\u0438\u0431\u043e\u0442-\u0442\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439<\/p>\n<p>PS. \u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u044f \u0441\u043b\u043e\u043c\u0430\u043b \u0441\u043a\u0440\u0438\u043f\u0442, \u0430 \u043e\u043d \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043b \u0441\u0432\u043e\u0451 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435. \u042d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u0442\u0430 \u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u044f \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0430\u043b \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 try-catch. <\/p>\n<\/div>\n<\/details>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e. \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0444\u043b\u0430\u0433\u0430 <code>allTimeoutsCleaned<\/code>:<\/p>\n<pre><code class=\"javascript\">eval(node, ctx = this.callStack[this.callStack.length - 1]) {   if (global.allTimeoutsCleaned) {     global.interpreterState = ctx; \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043a\u0443\u0434\u0430 \u043d\u0430\u0434\u043e \u0447\u0435\u0440\u0435\u0437 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e     global.allTimeoutsCleaned = false;     return;   }   \/\/ ... \u0443\u0437\u043b\u044b ...<\/code><\/pre>\n<p>\u0410 \u0441 index.js \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"javascript\">\/\/ ... const ast = parse(srcCode);  function deobfucateCode(ctx) {   const { env } = ctx;   const deobfuscator = new Deobfuscator(ast, env);   deobfuscator.deobfuscate();   const code = deobfuscator.getCode();   fs.writeFileSync('.\/output\/deobfuscated.js', code); }  const interval = setInterval(() => {   console.log('waiting interpreterState...');   if (global.interpreterState) {     clearInterval(interval);     deobfucateCode(global.interpreterState)   } }, 3000);  console.log(new Interpreter(srcCode).eval(ast.program))<\/code><\/pre>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, \u043c\u044b \u0441\u0430\u043c\u0438 \u0441\u0442\u0430\u0432\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u0438, \u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430, \u0442\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435\u0435 \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432\u0441\u0451 \u0434\u0435\u043b\u043e \u0438\u043d\u0430\u0447\u0435, \u0430 \u043d\u0435 \u0442\u0430\u043a \u0445\u0430\u043b\u0442\u0443\u0440\u043d\u043e, \u043d\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/p>\n<blockquote>\n<p><em>\u0425\u0432\u0430\u0442\u0438\u0442 \u043f\u043e\u043b\u0443\u043c\u0435\u0440<\/em>,\u00a0<em>\u0423\u043e\u043b\u0442\u0435\u0440.<br \/><\/em><sub>\u00a9 \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438, \u0447\u0438\u0442\u0430\u044e\u0449\u0438\u0435 \u044d\u0442\u043e\u0442 \u043f\u043e\u0441\u0442<\/sub><\/p>\n<\/blockquote>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0442\u043e\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">\/\/ .\/libs\/Deobfuscator.js const traverse = require('@babel\/traverse').default; const generate = require('@babel\/generator').default; const t = require('@babel\/types'); const ExecutionContext = require('.\/ExecutionContext'); const window = require('.\/..\/browser-env\/window'); const Interpreter = require('.\/Interpreter');  class Deobfuscator {   constructor(ast, env) {     this.ast = ast;     this.env = env;     this.exec = new ExecutionContext(window, env);     this.interpreter = new Interpreter();   }    getCode() {     return generate(this.ast).code;   }    deobfuscate() {     this._replaceStrings();   }    _replaceStrings() {     const self = this;     traverse(this.ast, {       CallExpression: path => {         const { node } = path;         if (           t.isMemberExpression(node.callee) &amp;&amp;           (             (t.isIdentifier(node.callee.object) &amp;&amp;             node.callee.object.name === 'EE') ||             (t.isMemberExpression(node.callee.object) &amp;&amp;             t.isIdentifier(node.callee.object.object) &amp;&amp;             node.callee.object.object.name === 'EE')           ) &amp;&amp;           t.isIdentifier(node.callee.property)         ) {           try {             let result = self.interpreter.eval(node, self.exec);             if (typeof result === 'string') {               path.replaceWith(t.stringLiteral(result));             } else if (typeof result === 'number') {               path.replaceWith(t.numericLiteral(result));             }           } catch(err) { console.log(err) }         }       }     });   }    }  module.exports = Deobfuscator;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u042f \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u043d\u0430\u044e \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u0437\u0434\u0435\u0441\u044c \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u043f\u043e\u044f\u0441\u043d\u044f\u0442\u044c&#8230; \u041c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>_replaceStrings()<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c <code>traverse()<\/code> \u043e\u0431\u0445\u043e\u0434\u0438\u0442 \u0434\u0435\u0440\u0435\u0432\u043e \u0438 \u0438\u0449\u0435\u0442 \u0432\u0441\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u0432\u0438\u0434\u0430 <code>EE.P3.call(null,Gk,Sl,rd,Nh(vK))<\/code> \u0438 <code>EE.gj(OB,Fk,DW,hv)<\/code>. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0439\u0442\u0438 \u043d\u0430 astexplorer \u0438 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u044d\u0442\u0438 \u0443\u0437\u043b\u044b. \u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c eval() \u0438, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0445\u0430, \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0443\u0437\u0435\u043b \u043d\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u041f\u043e\u0438\u0441\u043a \u0438 \u0437\u0430\u043c\u0435\u043d\u0443 \u0443\u0437\u043b\u043e\u0432 \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438 \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c \u043f\u043e\u0441\u0442\u0435 \u043f\u043e \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440\u0443. <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u0430\u0439\u0442 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c sensor_data \u0447\u0435\u0440\u0435\u0437 XMLHttpRequest, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043e\u0442\u0432\u0435\u0442\u044b. \u0412\u0434\u0440\u0443\u0433 \u043e\u043d\u0438 \u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u044b. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0441\u0432\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0447\u0435\u0440\u0435\u0437 express.js:<\/p>\n<pre><code class=\"javascript\">\/\/ utils\/server.js const express = require('express');  const app = express();  app.post('\/send', (req, res) => {   res.send('{\"success\": true}'); });  app.listen(3000, () => console.log('Server started at 3000'));<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041d\u0443 \u0447\u0442\u043e \u0442\u0430\u043c \u0447\u0442\u043e \u0442\u0430\u043c<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c4a\/75c\/f6c\/c4a75cf6cc46c5c563825690477cc994.gif\" width=\"1221\" height=\"702\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c4a\/75c\/f6c\/c4a75cf6cc46c5c563825690477cc994.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0415\u0449\u0451 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u043a\u0441\u0438-\u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c <a href=\"https:\/\/deobfuscate.io\/\" rel=\"noopener noreferrer nofollow\">https:\/\/deobfuscate.io\/<\/a>, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u043d\u0438\u0445 \u0438 \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435 \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e.<\/p>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043c\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u043d\u043e\u0432\u0430 \u0443\u0434\u0435\u043b\u044f\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043e\u0431\u0445\u043e\u0434\u0443 \u0434\u0435\u0440\u0435\u0432\u0430. \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437 \u043c\u044b \u043c\u043d\u043e\u0433\u043e \u043e\u0431 \u044d\u0442\u043e\u043c \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438. \u0427\u0442\u043e\u0431\u044b \u0443\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u043f\u0440\u043e \u043c\u0435\u0442\u043e\u0434\u044b <code>path.scope<\/code>, <code>path.scope.getBinding<\/code> \u0438 \u0443\u043c\u0435\u0442\u044c \u0437\u0430\u043c\u0435\u043d\u044f\u0442\u044c \u0443\u0437\u043b\u044b. \u0415\u0441\u043b\u0438 \u0432\u044b \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u0435\u043d \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u0442\u043e \u043e\u0442\u043f\u0438\u0448\u0438\u0442\u0435\u0441\u044c, \u0438 \u044f \u043f\u043e\u043a\u0430\u0436\u0443 \u0435\u0449\u0451 \u0440\u0430\u0437 \u043a\u0430\u043a \u0432\u0441\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0438, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0443\u0431\u0438\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u043a\u0441\u0438-\u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<h2>\u0411\u043e\u0442 \u0438\u043b\u0438 \u043d\u0435 \u0431\u043e\u0442?<\/h2>\n<p>\u042d\u0442\u043e\u0442 \u0432\u044b\u0432\u043e\u0434 Akamai Bot Manager \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0437 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0435\u043c\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0432 &#171;sensor_data&#187;. \u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u0439\u043c\u0451\u043c, \u043a\u0430\u043a\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0442\u0443\u0434\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442, \u0442\u043e \u0441\u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u043e\u0442. \u0414\u0430, \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u0437\u043d\u0430\u0442\u044c \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u043a\u0430\u043a \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0441\u0430\u043c\u0438\u043c \u0430\u043a\u0430\u043c\u0430\u0435\u043c. <\/p>\n<p>\u0418\u0442\u0430\u043a, \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e XMLHttpRequest.send(), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0438\u0441\u043a\u043e\u043c \u043f\u043e \u043a\u043e\u0434\u0443 \u043d\u0430\u0442\u044b\u043a\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u044d\u0442\u043e:<\/p>\n<details class=\"spoiler\">\n<summary>send<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f70\/62e\/36e\/f7062e36e126fc66195ab0e4d2965cda.png\" width=\"432\" height=\"247\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f70\/62e\/36e\/f7062e36e126fc66195ab0e4d2965cda.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412 <code>send()<\/code> \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <code>J0E<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>wPE<\/code>, \u043e\u0431\u043b\u0430\u0434\u0430\u044e\u0449\u0435\u0439 \u0432\u0441\u0435\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u0435\u043d\u0441\u043e\u0440\u043d\u043e\u0433\u043e \u043e\u0442\u043f\u0435\u0447\u0430\u0442\u043a\u0430. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043f\u043e \u0445\u043e\u0434\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043e\u043d\u0430 \u043a\u0430\u043a-\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442 \u0441\u0430\u043c\u0430 \u0441\u0435\u0431\u044f \u0432 \u043a\u0430\u043a\u043e\u043c-\u0442\u043e \u0442\u0430\u043a\u043e\u043c \u0441\u0442\u0438\u043b\u0435:<\/p>\n<pre><code class=\"javascript\">wPE = 'bar'; \/\/ ... wPE = 'foo' + wPE; \/\/ foobar<\/code><\/pre>\n<p>\u043d\u043e \u043d\u0430\u043c \u044d\u0442\u043e \u043d\u0435 \u0432\u0430\u0436\u043d\u043e, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043e\u0442\u043f\u0435\u0447\u0430\u0442\u043a\u043e\u0432, \u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435. <\/p>\n<p>\u041a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u044c \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>wPE<\/code>? \u041d\u0430\u0439\u0442\u0438 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u0443\u0436\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0438\u0437 \u0443\u0437\u043b\u0430 AssignmentExpression:<\/p>\n<pre><code class=\"javascript\">if (t.isAssignmentExpression(node)) {   if (t.isIdentifier(node.left)) {     const left = node.left.name;     const right = this.eval(node.right, ctx);     if (left === 'wPE') {       console.log(`CODE: ${generate(node).code} | RESULT: ${right}`);     }     \/\/ ...<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u0435\u0440\u0432\u043e\u0435 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d6c\/a0a\/d45\/d6ca0ad458a40b8d35ff384ff1d2d6ec.png\" width=\"1016\" height=\"784\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d6c\/a0a\/d45\/d6ca0ad458a40b8d35ff384ff1d2d6ec.png\"\/><\/figure>\n<p>\u0412 \u0434\u0435\u043e\u0431\u0444\u0443\u0441\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0439\u0442\u0438 \u0441\u0430\u043c\u0443 \u0441\u0442\u0440\u043e\u043a\u0443:<\/p>\n<pre><code class=\"javascript\">wPE = x5E.join(Q5E)<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041c\u0435\u0436\u0434\u0443 \u0447\u0438\u0441\u043b\u0430\u043c\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043e\u0442\u043a\u0443\u0434\u0430 \u043e\u043d\u0438 \u0431\u0435\u0440\u0443\u0442\u0441\u044f:<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043b\u0435\u0434\u0438\u0442\u0435 \u0437\u0430 \u0440\u0443\u043a\u0430\u043c\u0438<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7c5\/9c9\/069\/7c59c906985d78212f9c978e587a87b2.gif\" width=\"1221\" height=\"574\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7c5\/9c9\/069\/7c59c906985d78212f9c978e587a87b2.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043a \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044e \u043d\u0430\u0441 \u0442\u0430\u0449\u0438\u0442 \u043d\u0430 \u0441\u0442\u0440\u043e\u0447\u043a\u0443 \u00a0var <code>O5E = Ah(b0, [H5E, IW])<\/code>. \u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>Ah<\/code> &#8212; \u044d\u0442\u043e \u043a\u0430\u043a\u0430\u044f-\u0442\u043e \u0431\u0443\u0440\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f, <strong>\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e<\/strong>, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 <code>H5E<\/code> \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b. <code>H5E<\/code> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432:<\/p>\n<details class=\"spoiler\">\n<summary>props<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">window.screen.availWidth window.screen.availHeight window.screen.width window.screen.height window.innerHeight window.innerWidth 'outerWidth' in window window._phantom window.webdriver window.domAutomation window.addEventListener window.XMLHttpRequest window.XDomainRequest window.emit window.DeviceOrientationEvent window.DeviceMotionEvent window.TouchEvent window.spawn window.chrome Function.prototype.bind window.Buffer window.PointerEvent window.innerWidth window.outerWidth window.callPhantom window.ActiveXObject 'ActiveXObject' in window 'number' == typeof document.documentMode window.chrome &amp;&amp; window.chrome.webstore navigator.onLine window.opera 'undefined' != typeof window.InstallTrigger window.HTMLElement &amp;&amp; Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 'function' == typeof window.RTCPeerConnection 'mozInnerScreenY' in window 'function' == navigator.vibrate 'function' == typeof navigator.getBattery Array.prototype.forEach 'FileReader' in window<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f: \u0435\u0441\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u0442\u043e \u0432 sensor_data \u043f\u043e\u043f\u0430\u0434\u0451\u0442 <code>1<\/code> \u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0430 \u0435\u0441\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u0442\u043e <code>0<\/code>. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f \u043d\u0430\u0431\u043e\u0440 \u044d\u0442\u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043a \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443. <code>ActiveXObject<\/code> \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 IE, <code>InstallTrigger<\/code> \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Firefox, <code>_phantom<\/code>, <code>callPhantom<\/code>, <code>webdriver<\/code>, <code>domAutomation<\/code> \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445, <code>window.opera<\/code> \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 Opera, <code>Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor')<\/code> \u0431\u0443\u0434\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 0 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u0442\u0430\u0440\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445 Safari \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435&#8230; \u0421\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0435\u0441\u043b\u0438 \u0432\u044b \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u044e\u0437\u0435\u0440\u0430\u0433\u0435\u043d\u0442 \u043e\u0442 FireFox, \u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0432 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043d\u0430 \u0434\u0432\u0438\u0436\u043a\u0435 \u0445\u0440\u043e\u043c\u0438\u0443\u043c\u0430, \u0442\u043e \u0430\u043a\u0430\u043c\u0430\u0439 \u0432\u0430\u0441 \u0437\u0430\u043c\u0435\u0442\u0438\u0442.<\/p>\n<details class=\"spoiler\">\n<summary>\u0410\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b20\/8f5\/701\/b208f5701ee9a729d673f9f84097039c.png\" width=\"511\" height=\"180\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b20\/8f5\/701\/b208f5701ee9a729d673f9f84097039c.png\"\/><\/figure>\n<p>\u041c\u044b \u0432\u0438\u0434\u0438\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0432 \u043a\u043e\u0434\u0435, \u043d\u043e \u0437\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u0447\u0442\u043e \u043e\u043d\u0438 \u043d\u0435 \u043c\u0435\u0448\u0430\u044e\u0442 \u043d\u0430\u043c \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435. \u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0418\u041b\u0418 <code>||<\/code>, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0434\u0430\u043b\u044c\u0448\u0435 <code>window.innerWidth<\/code> \u043d\u0435 \u043f\u043e\u0439\u0434\u0451\u0442. \u041d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e \u0432 \u043a\u043e\u0434\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 asos, \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0431\u0440\u0435\u0439\u043a\u043f\u043e\u0438\u043d\u0442 \u0438 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u044d\u0442\u0438\u043c\u0438 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c\u0438 \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438. \u041f\u043e\u043b\u0430\u0433\u0430\u044e, \u0442\u0430\u043c <code>clientWidth<\/code>.<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u044f \u043d\u0430\u0436\u0438\u043c\u0430\u044e F12 \u0432 \u043a\u043e\u0434\u0435, \u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0431\u0443\u0434\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0447\u0442\u043e \u0432\u0438\u0436\u0443.<\/p>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043b\u043e\u0433\u0438\u043d\u0430:<\/p>\n<details class=\"spoiler\">\n<summary>VE === window<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">function W5E() {   Gh.push(Rl);   for (     var B4E = '',       d4E = -Fh,       R4E = VE.document.getElementsByTagName('input'),       b4E = EF;     b4E &lt; R4E.length;     b4E++   ) {     var S4E = R4E[b4E],       M4E = Ah(b0, [V3E, EF, S4E.getAttribute('name')]),       K4E = Ah(b0, [V3E, EF, S4E.getAttribute('id')]),       v4E =         null == S4E.getAttribute('required')           ? NF[nF]           : EE.sEL(),       V0E = S4E.getAttribute('type'),       E0E = null == V0E ? -Fh : RxE(V0E),       g0E = S4E.getAttribute('autocomplete');     d4E =       null == g0E         ? -Fh         : 'off' === (g0E = g0E.toLowerCase())         ? EF         : '0B' === g0E         ? Fh         : nF;     var Z0E = S4E.defaultValue,       P0E = S4E.value,       c0E = NF[nF],       z0E = EF;     Z0E &amp;&amp; NF[nF] !== Z0E.length &amp;&amp; (z0E = Fh),       !P0E ||         NF[nF] === P0E.length ||         (z0E &amp;&amp; P0E === Z0E) ||         (c0E = Fh),       nF !== E0E &amp;&amp;         (B4E = ''           .concat(B4E + E0E, ',')           .concat(d4E, ',')           .concat(c0E, ',')           .concat(v4E, ',')           .concat(K4E, ',')           .concat(M4E, ',')           .concat(z0E, ';'));   }   var j0E;   return (j0E = B4E), Gh.pop(), j0E; }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u043e\u043e\u0431\u0449\u0435, \u044d\u0442\u043e \u043d\u0435\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e. \u041f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0438\u043d\u043f\u0443\u0442\u044b, \u0438 \u043e\u0442 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u043d\u043f\u0443\u0442\u0430 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 <code>name<\/code>, <code>id<\/code>, <code>required<\/code>, <code>type<\/code>, <code>autocomplete<\/code>. \u0421\u0442\u0440\u043e\u0447\u043a\u0438 \u0432\u0438\u0434\u0430 <code>M4E = Ah(b0, [V3E, EF, S4E.getAttribute('name')])<\/code>, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0444\u0443\u043d\u043a\u0446\u0438\u044e V3E(\u043c\u044b \u0443\u0436\u0435 \u043f\u043e\u043d\u044f\u043b\u0438, \u0447\u0442\u043e Ah &#8212; \u044d\u0442\u043e \u043a\u0430\u043a\u0430\u044f-\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f-\u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0441):<\/p>\n<details class=\"spoiler\">\n<summary>V3E<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">function V3E(pxE) {   Gh.push(X9);   if (null == pxE) {     var txE;     return (txE = -1), Gh.pop(), txE;   }   try {     var GxE = Gh.slice();     for (var JxE = 0, NxE = 0; NxE &lt; pxE.length; NxE++) {       var nxE = pxE.charCodeAt(NxE);       nxE &lt; 128 &amp;&amp; (JxE += nxE);     }     var XxE;     return (XxE = JxE), Gh.pop(), XxE;   } catch (BxE) {     Gh = GxE.slice();     var dxE;     return (dxE = -2), Gh.pop(), dxE;   }   Gh.pop(); }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041e\u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443(\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430) \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0435 \u0432\u0435\u0449\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u0442\u0440\u0430\u043d\u043d\u044b\u0435 \u0432\u0435\u0449\u0438<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4e9\/4a4\/ea0\/4e94a4ea0ce15c9d79de7d868991d6c7.png\" width=\"439\" height=\"425\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4e9\/4a4\/ea0\/4e94a4ea0ce15c9d79de7d868991d6c7.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0442\u043e \u0435\u0441\u0442\u044c \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u0432\u043c\u0435\u0441\u0442\u0435 \u043a\u043e\u0434\u044b \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0431\u0443\u043a\u0432\u044b \u0441\u0442\u0440\u043e\u043a\u0438. \u041e\u0447\u0435\u0440\u0435\u0434\u043d\u0430\u044f \u0447\u0443\u0448\u044c \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043e\u0442\u043f\u0435\u0447\u0430\u0442\u043a\u043e\u0432. \u0411\u043e\u043b\u044c\u0448\u0435 \u044f \u043d\u0430 \u0442\u0430\u043a\u043e\u043c \u0438 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u043c \u0437\u0430\u043e\u0441\u0442\u0440\u044f\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0435 \u0431\u0443\u0434\u0443.<\/p>\n<p>\u0418\u0434\u0451\u043c \u0434\u0430\u043b\u0435\u0435:<\/p>\n<details class=\"spoiler\">\n<summary>\u041d\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0440\u0430\u0437&#8230;<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7a3\/b82\/36d\/7a3b8236dd55ed00020c5a4fe154be60.gif\" width=\"1221\" height=\"574\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7a3\/b82\/36d\/7a3b8236dd55ed00020c5a4fe154be60.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u0430\u0432\u0435\u0448\u0435\u043d\u043d\u044b\u0445 \u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439. \u0415\u0441\u043b\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u043a \u0447\u0435\u043c\u0443, \u0442\u043e \u043d\u0435 \u0441\u0442\u0435\u0441\u043d\u044f\u0439\u0442\u0435\u0441\u044c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a ChatGPT, \u043a\u0430\u043a \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438 \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435:<\/p>\n<details class=\"spoiler\">\n<summary>ChatGPT<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7a4\/863\/180\/7a486318049e16f9c4e0b82a94a21d88.png\" width=\"797\" height=\"770\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7a4\/863\/180\/7a486318049e16f9c4e0b82a94a21d88.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u043f\u044f\u0442\u044c \u043a\u0430\u043a\u0430\u044f-\u0442\u043e \u0441\u0432\u043e\u044f \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0451 \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u0430\u043c\u044b\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439&#8230;<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c1d\/890\/4a1\/c1d8904a1fac301f5906ed648c4c3600.gif\" width=\"1221\" height=\"574\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c1d\/890\/4a1\/c1d8904a1fac301f5906ed648c4c3600.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u0443\u0436 \u0441\u043e\u0432\u0441\u0435\u043c \u0441\u0442\u0430\u043b\u0430 \u043f\u043e\u043d\u044f\u0442\u043d\u0430, \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c&#8230;<\/p>\n<details class=\"spoiler\">\n<summary>\u0422\u043e\u0447\u043d\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439(ChatGPT)<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/28b\/b4d\/08c\/28bb4d08c78fe438bdf2059d28e51624.gif\" width=\"1221\" height=\"574\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/28b\/b4d\/08c\/28bb4d08c78fe438bdf2059d28e51624.gif\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0441\u0435\u043b\u0435\u043d\u0438\u0443\u043c:<\/p>\n<details class=\"spoiler\">\n<summary>collectSeleniumData<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/40c\/e34\/112\/40ce34112e05033606d7d840c8abd741.png\" width=\"549\" height=\"569\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/40c\/e34\/112\/40ce34112e05033606d7d840c8abd741.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u0432 \u0432\u0430\u0448\u0435\u043c window \u0438\u043b\u0438 document \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u044d\u0442\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0442\u043e \u044d\u0442\u043e \u0444\u043b\u0430\u0436\u043e\u043a&#8230;<\/p>\n<details class=\"spoiler\">\n<summary>navigator.permissions<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0427\u0435\u0440\u0435\u0437 <code>navigator.permissions.query()<\/code> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u044d\u0442\u0438\u0445 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3fc\/406\/d1a\/3fc406d1aff49894e653915cf8acdf6e.png\" width=\"322\" height=\"401\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3fc\/406\/d1a\/3fc406d1aff49894e653915cf8acdf6e.png\"\/><\/figure>\n<p>\u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0445 \u0441\u0442\u0430\u0442\u0443\u0441\u044b. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0437\u043d\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043a \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u0438 \u043e\u0442 \u044e\u0437\u0435\u0440\u0430 \u043a \u044e\u0437\u0435\u0440\u0443&#8230;<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>HTMLIframeElement srcdoc<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9f8\/50a\/34e\/9f850a34e8f94a9dbe2788b83e8e852c.png\" width=\"557\" height=\"568\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9f8\/50a\/34e\/9f850a34e8f94a9dbe2788b83e8e852c.png\"\/><\/figure>\n<pre><code class=\"javascript\">var frame = VE.window.document.createElement('iframe'); frame.style.display = 'none'; window.document.head.appendChild(frame); var contentWindow = frame.contentWindow; var srcdoc; var rndInt = randomInt().toString(); var err = 'Maximum call stack size exceeded'; try {   srcdoc = frame.srcdoc; } catch(e) {   e.message.includes(err) } frame.srcdoc = rndInt; frame.srcdoc !== rndInt; \/\/ must be false<\/code><\/pre>\n<p>\u042f, \u0447\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043d\u0435 \u0437\u043d\u0430\u044e \u0437\u0430\u0447\u0435\u043c \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e \u0441\u0435\u0439 \u0434\u0435\u043d\u044c \u0432 \u043a\u043e\u0434\u0435&#8230; \u041a\u043e\u0433\u0434\u0430-\u0442\u043e \u0432 \u0434\u0430\u043b\u0451\u043a\u043e\u043c \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u0432 \u0437\u043d\u0430\u043c\u0435\u043d\u0438\u0442\u043e\u043c \u0441\u0442\u0435\u043b\u0441-\u043f\u043b\u0430\u0433\u0438\u043d\u0435 \u0431\u044b\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b\u0430 \u043a \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438(<a href=\"https:\/\/github.com\/berstend\/puppeteer-extra\/issues\/543\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/berstend\/puppeteer-extra\/issues\/543<\/a>). \u0414\u0430\u0432\u043d\u043e \u0443\u0436\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e, \u043d\u043e \u0430\u043a\u0430\u043c\u0430\u0439 \u0432\u0441\u0451 \u0435\u0449\u0451 \u044d\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442. \u0422\u0430\u043a\u0436\u0435 \u043e\u043d \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0440\u0430\u043d\u0434\u043e\u043c\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0444\u0440\u0435\u0439\u043c\u0430 \u0447\u0435\u0440\u0435\u0437 <code>srcdoc<\/code> \u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u0442, \u0447\u0442\u043e \u043e\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u043e\u0441\u044c(<code>frame.srcdoc !== rndInt;<\/code>). \u0422\u043e \u0435\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c srcdoc \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0441\u0435\u0442\u0442\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0442\u043e \u0432\u0430\u0441 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0430\u0442. \u041d\u043e \u043a\u0442\u043e \u0442\u0430\u043a \u0432 \u0437\u0434\u0440\u0430\u0432\u043e\u043c \u0443\u043c\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c&#8230;<\/p>\n<\/div>\n<\/details>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c \u0442\u0435\u0441\u0442\u0435 \u0438\u0437 \u0444\u0440\u0435\u0439\u043c\u0430 \u0431\u0435\u0440\u0451\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u0447\u0435\u0440\u0435\u0437 <code>frame.contentWindow<\/code> \u0438 \u0432 \u043d\u0451\u043c \u043f\u0440\u043e\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0442\u0435\u0441\u0442\u044b:<\/p>\n<details class=\"spoiler\">\n<summary>chrome<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">if (   frameWin.chrome &amp;&amp;   window.Object.keys(frameWin.chrome).length > 0 ) {   var arr = [];   for (var prop in frameWin.chrome)     VE.Object.prototype.hasOwnProperty.call(       frameWin.chrome,       prop     ) &amp;&amp; arr.push(prop]);   var ZOE;   return (ZOE = P5E(HgE(EOE.join(',')))), Gh.pop(), ZOE; }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442 chrome \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u043e\u043a\u043d\u0435 \u0444\u0440\u0435\u0439\u043c\u0430<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>contentWindow.toString<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">var regex = new window.RegExp(   \/function (get )?contentWindow(\\(\\)) \\{(\\n {3})? \\[native code\\][\\n ]\\}\/ );  var contentWindowString = Object.getOwnPropertyDescriptor(   window.HTMLIFrameElement.prototype,   'contentWindow' ).get.toString() regex.test(contentWindowString); \/\/ must be true<\/code><\/pre>\n<p>\u0422\u0435\u0441\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0432\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>contentWindow<\/code>, \u043d\u0443 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u0435\u0433\u043e \u043f\u043b\u043e\u0445\u043e&#8230;<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>navigator<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/afd\/345\/319\/afd345319ae5c0b430c0cef191436da5.gif\" width=\"1221\" height=\"574\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/afd\/345\/319\/afd345319ae5c0b430c0cef191436da5.gif\"\/><\/figure>\n<p>\u041f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432 \u043e\u043a\u043d\u0435 \u0444\u0440\u0435\u0439\u043c\u0430 \u0432\u0441\u0451 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u0438 \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u043e\u043a\u043d\u0435.<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>webgl<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">var frame = window.document.createElement('iframe'); frame.src = 'https:\/\/' frame.style.display = 'none'; window.document.head.appendChild(frame); var contentWindow = frame.contentWindow; var UNMASKED_VENDOR_WEBGL = 'NA'; var UNMASKED_RENDERER_WEBGL = 'NA'; if (contentWindow.document) {   var context = contentWindow.document     .createElement('canvas')     .getContext('webgl');   if (context) {     var WEBGL_debug_renderer_info = context.getExtension(       'WEBGL_debug_renderer_info'     );     WEBGL_debug_renderer_info &amp;&amp;       ((UNMASKED_VENDOR_WEBGL = context.getParameter(         WEBGL_debug_renderer_info.UNMASKED_VENDOR_WEBGL       )),       (UNMASKED_RENDERER_WEBGL = context.getParameter(         WEBGL_debug_renderer_info.UNMASKED_RENDERER_WEBGL       )));   } } console.log(UNMASKED_VENDOR_WEBGL); console.log(UNMASKED_RENDERER_WEBGL);<\/code><\/pre>\n<p>\u041c\u043e\u0436\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u0434 \u0432 \u0441\u0432\u043e\u044e \u043a\u043e\u043d\u0441\u043e\u043b\u044c, \u0438 \u043e\u043d\u0430 \u0432\u0430\u043c \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u0432\u0430\u0448\u0443 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442\u0443.<\/p>\n<\/div>\n<\/details>\n<p><code>HTMLIFrameElement.prototype.loading<\/code>:<\/p>\n<pre><code class=\"javascript\">return (   (cIE = VE.window.HTMLIFrameElement     ? VE.Object.getOwnPropertyDescriptor(         VE.window.HTMLIFrameElement.prototype,         'loading'       )       ? '1'       : '-2'     : '-1'),   Gh.pop(),   cIE );<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430. \u0412\u0440\u043e\u0434\u0435 \u043a\u0430\u043a \u0432 \u0441\u0442\u0430\u0440\u043e\u043c headless-\u0440\u0435\u0436\u0438\u043c\u0435 \u0435\u0433\u043e \u043d\u0435\u0442.<\/p>\n<details class=\"spoiler\">\n<summary>css<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">var div = document.createElement(\"div\"); document.body.append(div); var obj = {}; var res; [   \"ActiveBorder\",   \"ActiveCaption\",   \"ActiveText\",   \"AppWorkspace\",   \"Background\",   \"ButtonBorder\",   \"ButtonFace\",   \"ButtonHighlight\",   \"ButtonShadow\",   \"ButtonText\",   \"Canvas\",   \"CanvasText\",   \"CaptionText\",   \"Field\",   \"FieldText\",   \"GrayText\",   \"Highlight\",   \"HighlightText\",   \"InactiveBorder\",   \"InactiveCaption\",   \"InactiveCaptionText\",   \"InfoBackground\",   \"InfoText\",   \"LinkText\",   \"Mark\",   \"MarkText\",   \"Menu\",   \"MenuText\",   \"Scrollbar\",   \"ThreeDDarkShadow\",   \"ThreeDFace\",   \"ThreeDHighlight\",   \"ThreeDLightShadow\",   \"ThreeDShadow\",   \"VisitedText\",   \"Window\",   \"WindowFrame\",   \"WindowText\", ].forEach(function (el) {   div.style = \"background-color: \".concat(     el,     \" !important\"   ); \/\/ \"background-color: \" + el + \" !important\"   var backColor = getComputedStyle(div).backgroundColor;   obj[el] = backColor; }); res = JSON.stringify(obj)<\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043a \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0443 \u0438 \u043e\u0442 \u0434\u0432\u0438\u0436\u043a\u0430 \u043a \u0434\u0432\u0438\u0436\u043a\u0443. \u041f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u044e\u0437\u0435\u0440\u0430\u0433\u0435\u043d\u0442 \u043e\u0442 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430, \u0430 \u043d\u0430\u0431\u043e\u0440 \u0438\u043c\u0435\u0435\u0442 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u044b\u0439? \u041f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u044e\u0437\u0435\u0440\u0430\u0433\u0435\u043d\u0442 \u0445\u0440\u043e\u043c\u0430 99, \u0430 \u043d\u0430\u0431\u043e\u0440 \u0438\u043c\u0435\u0435\u0442\u0435 \u043e\u0442 \u0445\u0440\u043e\u043c\u0430 105? \u0410\u043a\u0430\u043c\u0430\u0439 \u0432\u0430\u0441 \u043f\u043e\u0439\u043c\u0430\u0435\u0442 \u043d\u0430 \u044d\u0442\u043e\u043c. <\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>navigator.connection, performance.memory<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">navigator.connection.rtt.toString();<\/code><\/pre>\n<pre><code class=\"javascript\">if (win.window.performance &amp;&amp; win.window.performance.memory) {   var memoryInfo = win.window.performance.memory;   SOE = ''     .concat(memoryInfo.jsHeapSizeLimit, ',')     .concat(memoryInfo.totalJSHeapSize, ',')     .concat(memoryInfo.usedJSHeapSize); }<\/code><\/pre>\n<p>\u0412 headless \u043c\u043e\u0434\u0435 <code>rtt<\/code> \u0432\u0440\u043e\u0434\u0435 \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0432\u0435\u043d \u043d\u0443\u043b\u044e. \u041f\u0440\u043e <code>memoryInfo<\/code> \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>chrome object<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/255\/7bb\/b15\/2557bbb158a596e282dcb358cb77b460.PNG\" width=\"608\" height=\"458\"\/><\/figure>\n<p>\u0412 \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 <code>chrome.runtime<\/code> \u043d\u0435\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u0431\u0435\u0441\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u044b. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0434\u0435\u0442\u0435\u043a\u0442 \u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u043b\u043a\u0443 \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0437\u0434\u0435\u0441\u044c \u043f\u043e\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u0447\u0435\u043c \u0443 \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a97\/1d8\/c3d\/a971d8c3db908538beb0562a345033ab.PNG\" width=\"793\" height=\"99\"\/><\/figure>\n<p>\u0442\u043e \u0435\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u0440\u0438 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043d\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0441\u043b\u0443\u0447\u0430\u0439 \u0432\u044b\u0437\u043e\u0432\u0430 \u043e\u0442 new(), \u0442\u043e \u0431\u0443\u0434\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0447\u0435\u043d\u044b. <\/p>\n<\/div>\n<\/details>\n<p>\u0415\u0441\u0442\u044c \u0435\u0449\u0451 \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u0434\u0435\u0442\u0435\u043a\u0442 \u043d\u0430 \u043f\u043b\u043e\u0445\u043e\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043d\u0430\u0432\u0438\u0433\u0430\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"javascript\">Object.keys(Object.getOwnPropertyDescriptors(navigator))<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0430 \u043d\u0435 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f, \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"javascript\">Object.defineProperty(navigator, 'webdriver', {     get: () => return false; })<\/code><\/pre>\n<p>\u0422\u043e \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 \u043f\u0443\u0441\u0442 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438 \u0432\u0430\u0441 \u0441\u043d\u043e\u0432\u0430 \u0437\u0430\u043c\u0435\u0442\u044f\u0442. \u041d\u043e \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0441\u0442\u0438 \u0440\u0430\u0434\u0438, \u043d\u0438\u043a\u0442\u043e \u0443\u0436\u0435 \u0441\u0442\u043e \u043b\u0435\u0442 \u0442\u0430\u043a \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442, \u044f \u0443\u0432\u0435\u0440\u0435\u043d.<\/p>\n<details class=\"spoiler\">\n<summary>\u041d\u0430\u0431\u043e\u0440 \u0433\u043e\u043b\u043e\u0441\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/23d\/529\/be8\/23d529be81d0cdd081c10d8030705054.PNG\" width=\"592\" height=\"416\"\/><\/figure>\n<p>\u041e\u043d\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438, \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u043d\u0430 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044e<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>File.path<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435 File \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u043e\u043a\u043d\u0430 \u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f56\/3af\/86f\/f563af86f3a51ffc5a24ad3e55bb84ec.PNG\" width=\"576\" height=\"391\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>crossOriginIsolated<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e78\/ae2\/132\/e78ae2132aff5f735d720c4a9ae3c578.PNG\" width=\"497\" height=\"236\"\/><\/figure>\n<p>SharedArrayBuffer \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043b\u0438\u0431\u043e \u043f\u0440\u0438 <code>crossOriginIsolated = true<\/code>, \u043b\u0438\u0431\u043e \u0432 \u0441\u0440\u0435\u0434\u0435 NodeJS<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>canvas<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/297\/5a8\/084\/2975a8084c729daf57ae736ce1047f7f.PNG\" width=\"505\" height=\"584\"\/><\/figure>\n<p>\u041e\u043d \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a-\u0442\u043e \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f. \u041c\u043d\u0435 \u044d\u0442\u043e \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u0438. \u041d\u0435 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0448\u0443\u043c\u0430. \u0425\u043e\u0442\u044f, \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0432\u0430\u0441, \u0442\u043e \u044d\u0442\u043e \u0444\u043b\u0430\u0436\u043e\u043a \u0438 \u043e\u0447\u0435\u043d\u044c \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u044b\u0439 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u0430 \u0441 \u0434\u0440\u0443\u0433\u043e\u0439&#8230; \u041e\u0431 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0441\u0442 \u043f\u0438\u0441\u0430\u0442\u044c<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>timezoneOffset<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">new window.Date().getTimezoneOffset()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>plugins<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u044d\u0442\u0438\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b64\/f1b\/b09\/b64f1bb09f26dd4327384afb3a4ec771.png\" width=\"558\" height=\"576\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b64\/f1b\/b09\/b64f1bb09f26dd4327384afb3a4ec771.png\"\/><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e mimetype&#8217;\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0432\u043e\u0438\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/952\/cb0\/30e\/952cb030ec87fa866dc57251dee49a19.PNG\" width=\"542\" height=\"213\"\/><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f <code>navigator.plugins.item<\/code>, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e refresh \u044d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e PluginArray, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 <code>configurable: true<\/code>, <code>writable: true<\/code>:<\/p>\n<pre><code class=\"javascript\">navigator.plugins.refresh = 'somevalue'; navigator.plugins.refresh === 'somevalue' ? ...<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0415\u0449\u0451 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432:<\/p>\n<details class=\"spoiler\">\n<summary>selen&amp;CO<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">var hsE = Gh.slice(); var FsE =   win.Boolean(win.window.__nightmare) +   (win.Boolean(win.window.cdc_adoQpoasnfa76pfcZLmcfl_Array) &lt;&lt;     Fh); var WsE; return (   (FsE +=     (win.Boolean(       win.window.cdc_adoQpoasnfa76pfcZLmcfl_Promise     ) &lt;&lt;       nF) +     (win.Boolean(       win.window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol     ) &lt;&lt;       IW)),   (FsE +=     (win.Boolean(win.window.OSMJIF) &lt;&lt; NF[OF]) +     (win.Boolean(win.window._Selenium_IDE_Recorder) &lt;&lt;       NF[hh])),   (FsE +=     (win.Boolean(win.window.__$webdriverAsyncExecutor) &lt;&lt;       bF) +     (win.Boolean(win.window.__driver_evaluate) &lt;&lt; Ph)),   (FsE +=     (win.Boolean(win.window.__driver_unwrapped) &lt;&lt; DF) +     (win.Boolean(win.window.__fxdriver_evaluate) &lt;&lt; Fk)),   (FsE +=     (win.Boolean(win.window.__fxdriver_unwrapped) &lt;&lt; hh) +     (win.Boolean(win.window.__lastWatirAlert) &lt;&lt; NF[AF])),   (FsE +=     (win.Boolean(win.window.__lastWatirConfirm) &lt;&lt; nC) +     (win.Boolean(win.window.__lastWatirPrompt) &lt;&lt; JF)),   (FsE +=     (win.Boolean(win.window.__phantomas) &lt;&lt; wq) +     (win.Boolean(win.window.__selenium_evaluate) &lt;&lt; bG)),   (FsE +=     (win.Boolean(win.window.__selenium_unwrapped) &lt;&lt; cF) +     (win.Boolean(win.window.__webdriverFuncgeb) &lt;&lt; SF)),   (FsE +=     (win.Boolean(win.window.__webdriver__chr) &lt;&lt; CC) +     (win.Boolean(win.window.__webdriver_evaluate) &lt;&lt; kF)),   (FsE +=     (win.Boolean(win.window.__webdriver_script_fn) &lt;&lt;       EE.sExI()) +     (win.Boolean(win.window.__webdriver_script_func) &lt;&lt; GF)),   (FsE +=     (win.Boolean(win.window.__webdriver_script_function) &lt;&lt;       EE.sExx()) +     (win.Boolean(win.window.__webdriver_unwrapped) &lt;&lt; zl)),   (FsE +=     (win.Boolean(win.window.awesomium) &lt;&lt; hl) +     (win.Boolean(win.window.callSelenium) &lt;&lt; pJ)),   (FsE +=     (win.Boolean(win.window.calledPhantom) &lt;&lt; Sl) +     (win.Boolean(win.window.calledSelenium) &lt;&lt; KF)),   (FsE +=     (win.Boolean(win.window.domAutomationController) &lt;&lt; kh) +     (win.Boolean(win.window.watinExpressionError) &lt;&lt; YW)),   (FsE +=     (win.Boolean(win.window.watinExpressionResult) &lt;&lt; Xr) +     (win.Boolean(win.window.spynner_additional_js_loaded) &lt;&lt;       NF[nC])),   (WsE = FsE +=     (win.Boolean(win.document.$chrome_asyncScriptInfo) &lt;&lt;       YF) +     (win.Boolean(win.window.fmget_targets) &lt;&lt; NF[JF]) +     (win.Boolean(win.window.geb) &lt;&lt; TF)),<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>navigator.webdriver<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/28c\/b60\/5f4\/28cb605f447fde17eb1f8484b276c95f.PNG\" width=\"447\" height=\"356\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u0418 \u0441\u043d\u043e\u0432\u0430 webgl<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6c2\/262\/324\/6c2262324227e2e04f31ac3d971df0fa.PNG\" width=\"568\" height=\"587\"\/><\/figure>\n<p>\u041a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0431\u044b\u043b\u043e, \u0435\u0449\u0451 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432 getSupportedExtensions().<\/p>\n<\/div>\n<\/details>\n<p>\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0444\u0438\u043d\u0433\u0435\u0440\u043f\u0440\u0438\u043d\u0442 \u043d\u0430 \u0442\u043e, \u043a\u0430\u043a \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u0443 \u0432\u0430\u0441 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435:<\/p>\n<details class=\"spoiler\">\n<summary>\u0428\u0440\u0438\u0444\u0442\u044b<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4f0\/b10\/f6c\/4f0b10f6c4a808379d633c6a591b1798.PNG\" width=\"560\" height=\"786\"\/><\/figure>\n<p>\u041e\u0431\u044b\u0447\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0434\u043e \u043a\u0443\u0447\u0438 \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041d\u0430 MacOS \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0434\u0438\u043d \u0445\u044d\u0448, \u043d\u0430 Windows \u0434\u0440\u0443\u0433\u043e\u0439. \u0414\u0430 \u0438 \u043e\u0442 \u041f\u041a \u043a \u041f\u041a \u0445\u044d\u0448\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0441\u043b\u0443\u0447\u0430\u044f\u0445.<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 webrtc \u0432 \u0432\u0430\u0448\u0435\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435:<\/p>\n<pre><code class=\"javascript\">'function' == typeof win.window.RTCPeerConnection || 'function' == typeof win.window.mozRTCPeerConnection || 'function' == typeof win.window.webkitRTCPeerConnection),<\/code><\/pre>\n<p>\u0415\u0449\u0451 \u0441\u0431\u043e\u0440 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043d\u0430\u0432\u0438\u0433\u0430\u0442\u043e\u0440\u0430:<\/p>\n<details class=\"spoiler\">\n<summary>Navigator<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cdb\/ab4\/496\/cdbab449603788728118bc6ee4e0c56b.PNG\" width=\"575\" height=\"815\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0415\u0449\u0451 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432:<\/p>\n<details class=\"spoiler\">\n<summary>some props<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c7c\/45e\/ec9\/c7c45eec9d24f28e261dbac7e8229468.PNG\" width=\"413\" height=\"308\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0418 \u043d\u0430 \u044d\u0442\u043e\u043c, \u043f\u043e\u0436\u0430\u043b\u0443\u0439, \u0441\u0442\u043e\u0438\u0442 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f&#8230; <\/p>\n<h2>\u0427\u0442\u043e \u043a \u0447\u0435\u043c\u0443?<\/h2>\n<p>\u0423 \u0430\u043a\u0430\u043c\u0430\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f, \u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043d\u0435\u0437\u0440\u0435\u043b\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430. \u0414\u0430, \u043e\u043d \u0443\u0432\u0438\u0434\u0438\u0442 \u0432\u0430\u0448 \u0441\u0435\u043b\u0435\u043d\u0438\u0443\u043c &#171;\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438&#187; \u0438\u043b\u0438 \u0441\u044b\u0440\u043e\u0439 headless \u0431\u0440\u0430\u0443\u0437\u0435\u0440, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0431\u043e\u0439\u0442\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044e \u0438\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u0430 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e \u043e\u0442\u043f\u0435\u0447\u0430\u0442\u043a\u0430, \u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0442\u0440\u0443\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c. \u041d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0430\u0445 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u0435\u0441\u0442\u044c <a href=\"https:\/\/abrahamjuliot.github.io\/creepjs\/\" rel=\"noopener noreferrer nofollow\">CreepJS<\/a>, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435. <\/p>\n<p>\u0412\u0441\u044f \u044d\u0442\u0430 \u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 \u0446\u0435\u043b\u044c\u044e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442\u044c \u0432\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0433\u0435\u043d\u0430(Akamai Sensor Data Generator). \u041d\u043e \u0443\u0436\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c.<\/p>\n<p>\u0414\u0430, \u043c\u044b \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u043a\u0430\u043a \u0430\u043a\u0430\u043c\u0430\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0432\u0435\u0434\u044c \u043f\u043e\u043c\u0438\u043c\u043e JavaScript, \u0435\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0435\u0449\u0435\u0439, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a ip, TLS, Ja3 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435&#8230; \u041d\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u0430\u0448\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u043e\u0434 \u0431\u0440\u0430\u0443\u0437\u0435\u0440.<\/p>\n<p>\u0415\u0449\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0430\u043a\u0430\u043c\u0430\u0439, \u043d\u0443\u0436\u043d\u044b \u043b\u0438\u0448\u044c \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0430 \u0432\u044b\u0432\u043e\u0434\u044b \u043e\u0431 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0435\u043b\u0430\u044e\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0447\u0435\u0441\u043a\u0438\u0445 \u0444\u0430\u043a\u0442\u043e\u0440\u043e\u0432(\u043a\u0430\u043a \u0432\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u0442\u0435 \u043c\u044b\u0448\u044c, \u0441 \u043a\u0430\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442\u0435-\u043e\u0442\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0443 \u043f\u0440\u0438 \u043d\u0430\u0431\u043e\u0440\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0442\u0434&#8230;). \u041d\u043e \u043d\u0430 \u043a\u0430\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0431\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0418\u0418, \u0435\u0441\u043b\u0438 \u0430\u043d\u0442\u0438\u0431\u043e\u0442 \u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e\u0442 \u0431\u043e\u0442\u0430? \u0418\u043b\u0438 \u0432\u0441\u044f \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e \u0441\u0430\u0439\u0442\u0443 \u0431\u0440\u043e\u0434\u044f\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u043b\u044e\u0434\u0438?.. \u0412\u043e\u0442 \u0442\u0430\u043a\u0438\u0435 \u0444\u0438\u043b\u043e\u0441\u043e\u0444\u0441\u043a\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442.<\/p>\n<h2>\u0424\u0430\u0439\u043b\u044b<\/h2>\n<p><a href=\"https:\/\/github.com\/rastvl\/akamai-deobfuscator-2.0\" rel=\"noopener noreferrer nofollow\">GitHub<\/a><\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \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\/post\/720588\/\"> https:\/\/habr.com\/ru\/post\/720588\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>Akamai Technologies &#8212; \u0430\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f, \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0449\u0430\u044f\u0441\u044f \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u0432\u0435\u0431-\u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043e\u0442 \u0431\u043e\u0442\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0432\u043e\u0435\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 Bot Manager. \u0412 \u0435\u0451 \u043f\u043e\u0440\u0442\u0444\u043e\u043b\u0438\u043e \u0447\u0438\u0441\u043b\u044f\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u0435 \u0433\u0438\u0433\u0430\u043d\u0442\u044b \u0440\u0438\u0442\u0435\u0439\u043b\u0430, \u043a\u0430\u043a Nike, Adidas \u0438 Asos, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u0435\u043d \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0437\u0430 \u0431\u043e\u0442\u0430\u043c\u0438, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0438\u043c\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u044b\u043a\u0443\u043f\u0430 \u0440\u0435\u0434\u043a\u0438\u0445\/\u043b\u0438\u043c\u0438\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0441 \u0446\u0435\u043b\u044c\u044e \u0438\u0445 \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0434\u0430\u0436\u0438 \u043f\u043e \u0437\u0430\u0432\u044b\u0448\u0435\u043d\u043d\u043e\u0439 \u0446\u0435\u043d\u0435. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0441\u043a\u0440\u0438\u043f\u0442 \u0430\u043d\u0442\u0438\u0431\u043e\u0442\u0430 Akamai \u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 JavaScript \u0432 \u043d\u0451\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f. \u041b\u044e\u0431\u0438\u0442\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c selenium? \u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c! <\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u0434\u043e\u043f\u044b\u0442\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0434\u043b\u044f \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439 \u0432\u044b\u0431\u0435\u0440\u0435\u043c \u043b\u043e\u0433\u0438\u043d \u043d\u0430 \u0441\u0430\u0439\u0442\u0435 <a href=\"https:\/\/my.asos.com\/\" rel=\"noopener noreferrer nofollow\">Asos<\/a>. \u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u043e\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0442\u043e \u0432 \u043e\u0431\u044b\u0447\u043d\u043e\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043d\u0430\u0441 \u0436\u0434\u0451\u0442 \u043e\u0448\u0438\u0431\u043a\u0430 \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0445 \u0443\u0447\u0451\u0442\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 Access Denied.<\/p>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438\u043d \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438 playwright chromium <\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0418\u0441\u0445\u043e\u0434\u044f <a href=\"https:\/\/habr.com\/ru\/post\/716434\/\" rel=\"noopener noreferrer nofollow\">\u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043e\u043f\u044b\u0442\u0430<\/a>, \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u0434\u0435\u043b\u043e \u0432 \u043a\u0430\u043a\u0438\u0445-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u0443\u043a\u0430\u0445, \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0433\u043b\u0430\u0437\u0430 \u0441\u0430\u043c\u0438 \u0446\u0435\u043f\u043b\u044f\u044e\u0442\u0441\u044f \u0437\u0430 \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043e\u0431\u044a\u0451\u043c\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<details class=\"spoiler\">\n<summary>sensor_data request payload<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0411\u0435\u0436\u0438\u043c \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u044b\u043b\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0438 \u0432\u0438\u0434\u0438\u043c \u043d\u0435\u0447\u0442\u043e:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0412\u0438\u043d\u043e\u0432\u043d\u0438\u043a \u043d\u0430\u0448\u0438\u0445 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u0439<\/figcaption><\/div>\n<\/figure>\n<h2>\u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u0438<\/h2>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0423 \u043c\u0435\u043d\u044f \u0431\u0443\u0434\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u043e\u0442\u0441\u044b\u043b\u043e\u043a <a href=\"https:\/\/habr.com\/ru\/post\/716434\/\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e<\/a>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u0438 \u0442\u0435\u043c\u044b \u0442\u0435\u0441\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u044b. \u0422\u0430\u043c \u0440\u0435\u0447\u044c \u0448\u043b\u0430 \u043e \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438 \u044f \u043f\u0438\u0448\u0443 \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u043e \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440 \u0438\u043b\u0438 \u043f\u0440\u043e \u043d\u0430\u0448 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u043e\u043f\u044b\u0442, \u0442\u043e \u0438\u043c\u0435\u044e \u0432 \u0432\u0438\u0434\u0443 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0433\u0434\u0435-\u043d\u0438\u0431\u0443\u0434\u044c \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435:<\/p>\n<details class=\"spoiler\">\n<summary>debugger<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432\u0438\u0434\u0430 <code>EE.XX(foo, bar])<\/code> \u0438\u043b\u0438 <code>EE.yy.apply(null, [a,b,c,d])<\/code> \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0438, \u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u0445 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043d\u0430\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043c\u0435\u0448\u0430\u0435\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u043c. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043c\u044b \u0435\u0449\u0451 \u0438\u043c\u0435\u0435\u043c <a href=\"https:\/\/docs.jscrambler.com\/code-integrity\/tutorials\/control-flow-flattening\" rel=\"noopener noreferrer nofollow\">Control Flow Flattening<\/a>(\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u0430\u043a-\u0442\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043a\u043e\u0434 \u043d\u0430 \u0431\u043b\u043e\u043a\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0438\u0445 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435), \u043f\u0440\u043e\u043a\u0441\u0438-\u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"javascript\">function plus(a, b) {   return a + b; }  plus(plus(1, 2), plus(3, 4))<\/code><\/pre>\n<p>\u0437\u043d\u0430\u043c\u0435\u043d\u0438\u0442\u044b\u0435 <a href=\"http:\/\/www.jsfuck.com\/\" rel=\"noopener noreferrer nofollow\">JS-Fuck<\/a> \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f:<\/p>\n<details class=\"spoiler\">\n<summary>jsfuck<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435&#8230;<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u0435\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u044b\u0437\u043e\u0432\u044b \u0441\u0442\u0440\u043e\u043a. \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>EE<\/code> \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0442\u0430\u043a\u0438\u0445 \u0432\u044b\u0437\u043e\u0432\u0430\u0445:<\/p>\n<pre><code class=\"javascript\">EE[h8[T8]] = (function () {   var F8 = h8[T8];   return function (W8, C8, k8, l8, Y8, m8) {     var q8 = Zm(KU, [W8, Kh, vh(vh(EF)), l8, r8, m8]);     EE[F8] = function () { \/\/ \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430       return q8;     };     return q8;   }; })();<\/code><\/pre>\n<p><code>EE[F8]<\/code> &#8212; \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <code>q8<\/code>. \u0422\u0430\u043a \u0447\u0442\u043e \u0432\u0441\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0432\u044b\u0437\u043e\u0432 \u0442\u0430\u043a\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043d\u0435 \u0438\u043c\u0435\u044e\u0442. \u0421\u0432\u043e\u0451 \u0436\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>q8<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>Zm<\/code> \u0441 \u043a\u0430\u043a\u0438\u043c\u0438-\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438. \u0410 \u0447\u0442\u043e \u0437\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f Zm? \u0414\u0430\u0432\u0430\u0439 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c:<\/p>\n<details class=\"spoiler\">\n<summary>function Zm<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0435\u0443\u0442\u0435\u0448\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439. \u041e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044f \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440\u0430 \u043d\u0430 \u0444\u043e\u043d\u0435 \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0434\u0435\u0442\u0441\u043a\u043e\u0439. \u0423 \u043d\u0430\u0441 \u0442\u0430\u043c \u0431\u044b\u043b\u043e \u0432\u0441\u0451 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u043f\u043e\u0447\u0442\u0438 \u0441\u0440\u0430\u0437\u0443: \u0432\u043e\u0442 \u0431\u043b\u043e\u043a \u0441 \u0442\u0435\u0441\u0442\u043e\u043c, \u0432 \u043d\u0451\u043c \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432, \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443 \u0437\u0430\u0431\u0438\u0440\u0430\u043b\u0438\u0441\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u043d\u0430\u0448\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u0437\u0430\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0436\u0435 \u0431\u044b\u043b \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u044b\u0437\u043e\u0432\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c \u043a\u0430\u043a-\u0442\u043e \u043f\u043e-\u0441\u0432\u043e\u0435\u043c\u0443 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u0435\u0439 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438&#8230; &#171;\u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445&#187; \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u0430. \u0414\u0430-\u0434\u0430, \u043f\u043e\u0433\u043b\u044f\u0434\u0438\u0442\u0435 \u043d\u0430 \u0438\u0445 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e:<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043a\u043e\u0448\u043c\u0430\u0440. \u041a\u0443\u0447\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0430 \u0435\u0449\u0451 \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>JY<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u0435\u043d\u044f\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u0430. \u041f\u043e \u043a\u043e\u0434\u0443 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0442\u0430\u043a\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044f\u0445. \u0412\u043e\u043e\u0431\u0449\u0435, \u044f \u0431\u044b \u044d\u0442\u043e\u0442 \u0441\u043a\u0440\u0438\u043f\u0442 \u0441\u0440\u0430\u0432\u043d\u0438\u043b \u0441 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 \u041e\u041e\u041f , \u0432\u0435\u0434\u044c \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0441\u0432\u043e\u0451 <strong>\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435<\/strong>. \u0413\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f &#8212; &#171;\u043e\u043d\u043e \u0436\u0438\u0432\u043e\u0435&#187;&#8230;<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043b\u044e\u0434\u0435\u0439 &#171;\u0432 \u0442\u0435\u043c\u0435&#187; \u043a\u0430\u043a\u043e\u0439 \u0438\u0437 \u0430\u043d\u0442\u0438\u0431\u043e\u0442\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0441\u0430\u043c\u0443\u044e \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0446\u0438\u044e \u0431\u0435\u0437 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0442\u043e \u043e\u0442\u0432\u0435\u0442\u043e\u043c \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u0430\u043a\u0430\u043c\u0430\u0439, \u0438 \u043d\u0435 \u0431\u0435\u0437 \u043f\u0440\u0438\u0447\u0438\u043d\u044b. \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439, \u0432\u0442\u043e\u0440\u043e\u0439 \u0438 \u0442\u0440\u0435\u0442\u0438\u0439 \u0432\u0437\u0433\u043b\u044f\u0434\u044b \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c. \u041d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u043c \u043e\u0434\u043d\u0443 \u0434\u0435\u0442\u0430\u043b\u044c:<\/p>\n<details class=\"spoiler\">\n<summary>\u0434\u0435\u0442\u0430\u043b\u044c<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442 \u043d\u0435 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0432\u043e\u0451 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435. \u0412\u0438\u0434\u0438\u043c\u043e, \u043e\u043d \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0432\u0441\u044f\u043a\u043e\u0433\u043e \u0440\u043e\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0430\u0448\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043c\u044b\u0448\u044c\u044e \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0432 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435. \u041d\u043e, \u0441\u0443\u0442\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432\u0441\u0435\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f\u043c. \u0418\u043d\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442\u0441\u044f, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u0441\u044f\u043a\u043e\u0433\u043e \u0440\u043e\u0434\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u043e \u0438\u0445 \u043d\u0435\u043c\u043d\u043e\u0433\u043e. \u0414\u0430 \u0438 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0431\u0440\u0435\u0439\u043a\u043f\u043e\u0438\u043d\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438 \u043f\u043e\u043d\u044f\u0442\u044c \u0447\u0442\u043e \u0438\u043c\u0435\u043b\u043e\u0441\u044c \u0432 \u0432\u0438\u0434\u0443, \u043d\u043e \u0438 \u0442\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e&#8230; \u042f \u0432\u043e\u0442 \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 Brave \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>isBrave()<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 true. \u041d\u043e \u043d\u0435 \u0441\u0443\u0442\u044c. \u041d\u0430\u043c \u0431\u044b \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<p>\u0417\u043d\u0430\u0435\u0442\u0435, \u0432\u043e\u0442 \u0431\u044b \u0437\u0430\u0431\u0440\u0430\u0442\u044c \u044d\u0442\u043e \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438, \u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0438\u0445 \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u0438 \u043e\u0431\u0445\u043e\u0434\u0435 AST \u0432 \u043d\u0443\u0436\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445&#8230; \u041c\u0435\u0447\u0442\u044b \u0438\u043b\u0438 \u0442\u0430\u043a\u043e\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c?<\/p>\n<p>\u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438. \u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439, \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439, \u043d\u0435\u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0438 \u043d\u0443\u0434\u043d\u044b\u0439. \u042d\u0442\u043e \u043b\u0435\u043d\u0438\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 &#171;\u0432 \u043b\u043e\u0431&#187; \u0431\u0435\u0437 \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430. \u0412 \u0434\u0440\u0443\u0433\u043e\u0439 \u0440\u0430\u0437, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u044f \u043d\u0430\u043f\u0438\u0448\u0443 \u043f\u0440\u043e \u0434\u0440\u0443\u0433\u0438\u0435 \u0434\u0435\u043b\u0438\u043a\u0430\u0442\u043d\u044b\u0435 \u0438 \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0441\u043a\u0440\u0438\u043f\u0442 \u0445\u043e\u0447\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e!<\/p>\n<h2>\u0421\u0432\u043e\u0439 \u043e\u0431\u0445\u043e\u0434 \u0434\u0435\u0440\u0435\u0432\u0430?<\/h2>\n<p>\u0414\u0430. \u041c\u044b \u0441\u0430\u043c\u0438 \u043e\u0431\u043e\u0439\u0434\u0451\u043c \u0434\u0435\u0440\u0435\u0432\u043e \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0432 \u043d\u0451\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b. \u0415\u0441\u043b\u0438 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0441\u043a\u0440\u0438\u043f\u0442, \u0442\u043e \u0432 \u043d\u0451\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e JS. \u0412\u044b, \u043c\u043e\u0436\u0435\u0442, \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u0442\u0430\u043c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e ES3 \u0441 var-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438, \u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u0438\u0445 \u043d\u043e\u0432\u043e\u043c\u043e\u0434\u043d\u044b\u0445 rest-spread \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u0441\u0442\u0440\u0435\u043b\u043e\u0447\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0422\u0430\u043a\u0436\u0435, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0433\u0440\u044f\u0437\u043d\u044b\u0445 \u0445\u0430\u043a\u043e\u0432 \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0442 \u043d\u0430\u043c \u044d\u0442\u043e\u0442 \u043d\u0443\u0434\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441.<\/p>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u0417\u043d\u0430\u043d\u0438\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 AST. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u044b \u0438\u0437\u0443\u0447\u0438\u043b\u0438 \u044d\u0442\u043e\u0442 \u0432 \u043f\u0443\u043d\u043a\u0442 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e \u043a\u043b\u0430\u0443\u0434\u0444\u043b\u0435\u0435\u0440, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0431\u0435\u0433\u0438\u0442\u0435\u0441\u044c \u043f\u043e \u043d\u0435\u0439 \u0433\u043b\u0430\u0437\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u044c \u0447\u0435\u0433\u043e \u0432\u044b \u0437\u043d\u0430\u0435\u0442\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442\u0435. \u0414\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0441\u043b\u043e\u0432\u0430 traverse(), parse(), astexplorer, callExpression \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432\u0430\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u044b;<\/p>\n<\/li>\n<li>\n<p>Babel, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.npmjs.com\/package\/jsdom\" rel=\"noopener noreferrer nofollow\">jsdom<\/a> \u0438 <a href=\"https:\/\/www.npmjs.com\/package\/canvas\" rel=\"noopener noreferrer nofollow\">canvas<\/a>, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 &#171;\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e&#187; \u043e\u0431\u044a\u0435\u043a\u0442\u0430 window;<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043f\u0438\u0448\u0435\u043c JavaScript \u043d\u0430 JavaScript, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432: \u043e\u0431\u044a\u0435\u043a\u0442 &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u0444\u0443\u043d\u043a\u0446\u0438\u044f &#8212; \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043c\u0430\u0441\u0441\u0438\u0432 \u0435\u0441\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0438 \u0432\u0441\u0451-\u0432\u0441\u0451-\u0432\u0441\u0451 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u044f\u0437\u044b\u043a\u0435 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043f\u0438\u0441\u043e\u043a \u0443\u0437\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c<\/summary>\n<div class=\"spoiler__content\">\n<p>\u042f \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u043b\u0441\u044f \u043f\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>traverse()<\/code>, \u0438 \u0443\u0437\u043d\u0430\u043b \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0435:<\/p>\n<pre><code> 'EmptyStatement',  'ExpressionStatement',  'SequenceExpression',  'Identifier',  'BinaryExpression',  'UnaryExpression',  'StringLiteral',  'NumericLiteral',  'NullLiteral'  'BooleanLiteral'  'RegExpLiteral',  'IfStatement',  'BlockStatement'  'CallExpression',  'FunctionExpression',  'VariableDeclaration',  'VariableDeclarator',  'FunctionDeclaration',  'AssignmentExpression',  'ObjectExpression',  'ThisExpression',  'ReturnStatement',  'ObjectProperty',  'WhileStatement',  'DoWhileStatement',  'UpdateExpression',  'LogicalExpression',  'ForStatement',  'ContinueStatement',  'BreakStatement',  'MemberExpression',  'SwitchStatement',  'SwitchCase',  'ArrayExpression',  'ConditionalExpression',  'NewExpression',  'TryStatement',  'CatchClause',  'ThrowStatement',  'ForInStatement',<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0418\u0442\u0430\u043a, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432. \u0417\u043d\u0430\u043a\u043e\u043c\u0430\u044f \u0432\u0430\u043c \u043f\u0440\u0435\u043b\u044e\u0434\u0438\u044f:<\/p>\n<pre><code class=\"javascript\">const { parse } = require('@babel\/parser'); const fs = require('fs');  const srcCode = fs.readFileSync('.\/input\/src.js', { encoding: 'utf-8' });  const ast = parse(srcCode);<\/code><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b\u0438 \u043a\u043e\u0434 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u0438 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043b\u0438 AST \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a class=\"mention\" href=\"\/users\/babel\/parser.\">@babel\/parser.<\/a><\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0445\u043e\u0447\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c, \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442:<\/p>\n<pre><code>10;<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><\/figure>\n<p>\u041c\u044b \u0438\u043c\u0435\u0435\u0442 \u0443\u0437\u0435\u043b <code>Program<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>body<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0441\u0435\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0441\u043a\u0440\u0438\u043f\u0442\u0430. \u041d\u0430\u0448\u0430 \u043f\u0435\u0440\u0432\u0430\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f &#8212; <code>ExpressionStatement<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u0432 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435 <code>expression<\/code> \u0443\u0437\u0435\u043b <code>NumericLiteral<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0447\u0438\u0441\u043b\u043e 10 \u0432 \u0441\u0432\u043e\u0451\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435 <code>value<\/code>.<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <code>Interpreter<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043c\u0435\u0442\u043e\u0434, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u0443\u0437\u0435\u043b \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0439 \u0435\u0433\u043e:<\/p>\n<pre><code class=\"javascript\">\/\/ .\/libs\/Interpreter.js const t = require('@babel\/types');  class Interpreter {   constructor() {     \/\/... \u043f\u043e\u043a\u0430 \u043f\u0443\u0441\u0442\u043e   }    eval(node) {     if (t.isProgram(node)) { \/\/ \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0443\u0437\u0435\u043b Program       let result;       node.body.forEach(node => { \/\/ \u0422\u043e \u0431\u0435\u0436\u0438\u043c \u043f\u043e \u0432\u0441\u0435\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 node.body,         result = this.eval(node); \/\/ \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044f \u043a\u0430\u0436\u0434\u0443\u044e \u0438\u0437 \u043d\u0438\u0445       });       return result;     }      if (t.isExpressionStatement(node)) { \/\/ \u0415\u0441\u043b\u0438 \u0443\u0437\u0435\u043b ExpressionStatement, \u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c       return this.eval(node.expression); \/\/ \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u0437 \u0441\u0432\u043e\u0439\u0441\u0432\u0430 expression     }      if (t.isNumericLiteral(node)) { \/\/ \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043b\u0438\u0442\u0435\u0440\u0430\u043b \u0447\u0438\u0441\u043b\u0430       return node.value; \/\/ \u041f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0447\u0438\u0441\u043b\u043e \u0438\u0437 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0443\u0437\u043b\u0430 value     }   } }  module.exports = Interpreter;<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u044b \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439. \u0412\u0441\u0435\u0433\u043e 20 \u0441\u0442\u0440\u043e\u0447\u0435\u043a \u043a\u043e\u0434\u0430, \u0430 \u043a\u0430\u043a\u043e\u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442!<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\">\n<div><figcaption>\u041e\u043d\u043e \u0436\u0438\u0432\u043e\u0435<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0418\u0434\u0451\u043c \u0434\u0430\u043b\u044c\u0448\u0435. \u0425\u043e\u0442\u0438\u043c \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0447\u0438\u0441\u043b\u0430:<\/p>\n<pre><code>10 + 20; \/\/ 30<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>AST<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0421\u043b\u043e\u0436\u0435\u043d\u0438\u0435 &#8212; \u044d\u0442\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0448 \u0443\u0437\u0435\u043b \u0438\u043c\u0435\u043d\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a BinaryExpression.  \u0423 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u0440\u0435\u0431\u0451\u043d\u043a\u0430 &#8212; left \u0438 right, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0442\u0438\u043f\u043e\u043c NumericLiteral, \u0430 \u0435\u0433\u043e \u043c\u044b \u0443\u0436\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u043d\u0430\u0443\u0447\u0438\u043b\u0438\u0441\u044c:<\/p>\n<figure class=\"\">\n<div><figcaption>10 + 20<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<pre><code class=\"javascript\">\/\/ ... \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0443\u0437\u043b\u044b if (t.isBinaryExpression(node)) {   const left = this.eval(node.left); \/\/ \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043b\u0435\u0432\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u043d\u0434   const right = this.eval(node.right); \/\/ \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043f\u0440\u0430\u0432\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u043d\u0434   switch (node.operator) {     case '+':       return left + right; \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442     default:       throw `Unknown operator ${node.operator}`;   } }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0438\u0437-\u0437\u0430 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0439 \u043f\u0440\u0438\u0440\u043e\u0434\u044b \u043d\u0430\u0448\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430, \u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0438 \u0442\u0430\u043a\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code>10 + 20 + 30 + 100 + (100 + 200); \/\/ 460<\/code><\/pre>\n<p>\u041f\u0430\u0440\u0441\u0435\u0440 \u0441\u0430\u043c \u0437\u0430\u0431\u043e\u0442\u0438\u0442\u0441\u044f \u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b:<\/p>\n<pre><code class=\"javascript\">if (t.isBinaryExpression(node)) {   const left = this.eval(node.left);   const right = this.eval(node.right);   switch (node.operator) {     case '+':       return left + right;     case '-':       return left - right;     case '*':       return left * right;     case '\/':       return left \/ right;     case '%':       return left % right;     case '**':       return left ** right;     case '==':       return left == right;     case '===':       return left === right;     case '!=':       return left != right;     case '!==':<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-346292","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/346292","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=346292"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/346292\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=346292"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=346292"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=346292"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}