Задать вопрос
  • Как webpack собирает импорты и экспорты?

    bingo347
    @bingo347
    Crazy on performance...
    Есть 2 основных подхода для решения проблемы изоляции имен в модулях:
    - подход webpack до 4 версии включительно - завернуть каждый исходный модуль в свою функцию и переложить эту задачу на средства языка js;
    - подход rollup и последователей типа vite - произвести переименование сущностей так, чтоб разные сущности из разных модулей названные одинаково назывались по разному, а одни и те же сущности названные по разному в разных модулей назывались одинаково.

    У каждого из подходов есть свои плюсы и минусы.
    В подходе webpack с одной стороны получается очень надежная изоляция, так как работают средства самого языка, но с другой на выходе получается больше кода, так как добавляются обертки + некий рантайм для взаимодействия виртуальных модулей. Так же такой код хуже оптимизируется на постобработке, так как тулзы вроде terser банально не могут восстановить связи между разными модулями. Хотя тот же рантайм позволяет гибко разбивать код на чанки и эмулировать динамические импорты.
    В подходе rollup возможны ошибки на промежуточной обработке (сам rollup предусматривает большинство из них, а вот плагины могут накосячить, особенно на больших проектах), зато нет дополнительного кода и тулзы вроде terser могут обрабатывать весь бандл целиком со всеми межмодульными связями, а значит делать более эффективные оптимизации.

    В webpack 5 был использован гибридный подход. Модули все так же изолируются средствами языка и соединяются посредством рантайма. Но часть модулей могут быть соединены в один по принципу rollup, что улучшает общий размер бандла и оптимизацию на постобработке.

    P.S. сделайте небольшой проект из примерно 10 модулей, соберите его webpack/rollup в dev режиме и посмотрите что получается на выходе, очень многое станет понятно, если просто почитать код получившегося бандла.
    Ответ написан
    1 комментарий
  • Как скопировать текст из iframe в переменную js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Если в iframe загружена страница с того же origin (протокол + домен + порт) откуда загружена текущая - то Вы имеете полный доступ к его window через свойство contentWindow. Соответственно можете обращаться к его DOM, глобальным переменным, менять их и т.д.

    Если в iframe будет страница с другого origin, то ничего этого нет, с ней можно лишь общаться через postMessage api, но если страница не Ваша, то и скрипт для обработки postMessage + каких-либо еще действий Вы туда не вставите.

    Если сторонний сайт отдает нормальные CORS заголовки при запросе с Вашего сайта (что судя по вопросу не так, но все же), то можно скачать страницу как текст через fetch api и распарсить ее через DOMParser.

    В противном случае остается только делать прослойку у себя на сервере, тут простор фантазии может быть очень широким, от банального reverse proxy прямо в nginx до чего-то более умного на любом серверном ЯП.
    Ответ написан
    Комментировать
  • Какой тип данных у переменной a?

    bingo347
    @bingo347
    Crazy on performance...
    У переменной a указан тип встроенный массив [T; n]. Но у такого типа нет метода get_unchecked_mut(). Он есть у среза на массив [T]
    Тут нужно понять как в Rust работает оператор точка.

    Во-первых, мало кто пишет, но операторов точка на самом деле в Rust целых 2:
    - Доступ к полю структуры/кортежа/юниона
    - Вызов метода
    Rust различает их по наличию круглых скобок:
    struct S {
        a: i32,
        f: fn(),
    }
    
    impl S {
        fn a(&self) {}
    }
    
    let s = S { a: 0, f: || {} };
    s.a; // Доступ к полю
    s.a(); // Вызов метода
    (s.f)(); // Вызов функции по указателю, который лежит в поле f

    С доступом к полю все просто, компилятор преобразует его в смещение в памяти где это поле лежит относительно самой структуры.
    А вот с вызовом метода все интереснее, Rust пытается рассахарить его в одну из следующих конструкций в следующем порядке:
    S::a(s);
    S::a(&s);
    S::a(&mut s);
    <S as Deref>::Target::a(S::deref(&s));
    <S as DerefMut>::Target::a(S::deref_mut(&mut s));
    <<S as Deref>::Target as Deref>::Target::a(<S as Deref>::Target::deref(S::deref(&s)));
    <<S as DerefMut>::Target as DerefMut>::Target::a(<S as DerefMut>::Target::deref_mut(S::deref_mut(&mut s)));
    // ...
    и так пока либо не найдет вариант, который компилируется, либо пока не обнаружит что для очередного типа не реализован трейт Deref.
    Подробнее можно почитать тут: https://doc.rust-lang.org/stable/nomicon/dot-opera...

    У всех массивов есть Deref к слайсу, в core библиотеке прописано что-то вроде:
    impl<T, const N: usize> Deref for [T; N] {
        type Target = [T];
        fn deref(&self) -> &[T] {
            // ...
        }
    }
    За счет этого все массивы (а так же векторы, у которых тоже Deref к слайсу) получают методы слайса. И по тому же принципу String получает методы str.

    Ну и кстати, неявный вызов deref может еще происходить при взятии ссылки.

    Ну и из комментов к вопросу:
    Что тут делает unsafe код как раз понятно
    Однозначно понятно, он здесь делает UB так как обращается к памяти владелец которой неизвестен.
    Ответ написан
    1 комментарий
  • Как подружить VS Code + Remote SSH + WSL?

    bingo347
    @bingo347
    Crazy on performance...
    Ваша проблема в том, то Вы абсолютно не понимаете как работает WSL. Давайте немного объясню.

    Начиная с WSL2 подсистема Linux крутится в полноценной виртуальной машине. И винда кстати тоже. Это работает следующим образом: когда Вы запускаете свой компьютер первой загружается на самом деле не винда, а гипервизор HyperV. Для пользователя происходит все прозрачно, так как HyperV настроен сразу запускать 2 виртуальные машины - с виндой и с линем. В машину с виндой HyperV сразу прокидывает все Ваши устройства (видеокарту, USB и прочее). Так же HyperV поднимает виртуальную сеть между этими двумя виртуалками. В машине с линем еще не Ваша Ubuntu, там легковесная ОС состоящая только из ядра и оркестратора LXC контейнерами (с ней кстати можно по взаимодействовать по сети, как это делает Docker Desktop например, ну или утилита wsl.exe). Ваша Ubuntu запускается в контейнере, так попросту быстрее ее запускать и останавливать, ибо ядро всегда висит в памяти. Опционально в линь монтируются папки (диски) из винды, делается это посредством патча ядра Linux от Microsoft. Обратный доступ предоставляется из винды посредством сетевого ресурса wsl$.
    Главное что тут стоит понять - винда и линь в WSL по сути работают на разных компах, пусть и виртуальных.

    Теперь ответьте на вопрос, на каком из этих компов работает Ваш VSCode?
    Правильный ответ на винде. А значит и взаимодействовать он будет с виндой. И искать ключи для подключения к ssh будет в домашней папке юзера в винде.

    Можете просто скопировать ключи из линя на винду и все заработает.
    Ответ написан
    2 комментария
  • Как передать объект в класс js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Можно записать объект в свойство prototype временной функции и наследоваться от нее:
    function fromPrototype(proto) {
        function F() {}
        F.protoype = proto;
        return F;
    }
    
    const obj = {
        _sayHi() {
            console.log(`Hello, my name is ${this.name}!`);
        },
    };
    
    class Person extends fromPrototype(obj) {
        constructor(name, age) {
            this.name = name;
            this.age = age;
          
           if (this.age < 0 ) {
                this.age = 0;
            }
        }
    }
    Ответ написан
    2 комментария
  • Как подключить и использовать json конфиг в rust?

    bingo347
    @bingo347
    Crazy on performance...
    В константах как не странно можно использовать только константы.
    Варианта 2:
    1. Написать процедурный макрос, который прочитает нужный JSON в компайл-тайм и сгенерирует код константы, так кстати и саму структуру можно генерировать.
    2. Зашить байты JSON в бинарь через макрос include_bytes!, а парсить при старте программы или в lazy_static.

    Но вообще у меня есть ощущение, что Вы в принципе неправильно решаете свою задачу. Константы - это по своей сути компайл-тайм сущности, а смысл конфига обычно - получить параметры в ран-тайм.
    Скорее всего Вам достаточно будет простого lazy_static
    Ответ написан
    5 комментариев
  • Как удалить папку WSL?

    bingo347
    @bingo347
    Crazy on performance...
    Не отключая WSL - никак, потому что это не папка, а специальный шорткат проводника на виртуальную сеть WSL.
    Ну и да, начиная с win11 WSL включен по умолчанию, так как в планах запуск андроид приложений, а андроид как не странно - это Linux.
    Но по идее, если отключить WSL в системных компонентах, то и шорткат из проводника должен исчезнуть.
    Ответ написан
    Комментировать
  • Как сделать, чтобы событие вызывалось один раз?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Проблема вот тут:
    const remove = this.on(events

    Метод on у Вас ничего не возвращает, соответственно в remove будет undefined, функции там взяться неоткуда.
    Переменной events нет в скоупе данного метода, очевидно имелась в виду eventName

    А вообще, вместо массива колбэков для события лучше использовать Set, так метод off будет работать за O(1), а не за O(n) как сейчас.

    В методе once можно подписываться на событие через метод on, и отписываться через метод off при его наступлении (так например делает EventEmitter из node.js). Но стоит учесть момент, что off должен работать и для once событий, а у Вас будет записан колбэк созданный в once, а не тот, что передал пользователь. Вообще проще хранить 2 коллекции: для многоразовых для одноразовых событий, ну или параметризовать колбэки (тогда лучше хранить их в Map, где ключи - колбэки, а значения - их параметры).

    Ну и еще обратите внимание, что у Вас в методах emit и once колбэк пользователя вызывается по разному:
    callback.apply(this, args) и callback.call(null, args)
    Ответ написан
    1 комментарий
  • Как итерировать несколько объектов в одном цикле RUST?

    bingo347
    @bingo347
    Crazy on performance...
    let a = [1, 2];
    let b = [3, 4];
    for (a, b) in a.into_iter().zip(b.into_iter()) {
        println!("{a}, {b}");
    }

    Метод zip есть у любого объекта реализующего трэйт итератора
    https://doc.rust-lang.org/std/iter/trait.Iterator....
    Ответ написан
    Комментировать
  • Какой нужен фреймворк для js, под мою задачу?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ответ написан
    Комментировать
  • Как отменить несколько коммитов в форкнутом репозитории?

    bingo347
    @bingo347
    Crazy on performance...
    git checkout <хэш нужного коммита>
    git checkout -b <имя новой ветки>

    И продолжаем разработку в этой ветке.
    Или если просто собрать приложение, то можно и без новой ветки
    Ответ написан
    Комментировать
  • Какая есть идиома для проверки [null]?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Мне нужно из: [null] получить просто []

    Если таких null много в вперемешку с полезными значениями, то можно отфильтровать:arr = arr.filter(el => el !== null);
    Ответ написан
    Комментировать
  • Стоит ли адаптировать сайт под IE 10 в 2022-м году?

    bingo347
    @bingo347
    Crazy on performance...
    С 15 июня IE в принципе больше не работает, можно не поддерживать.
    Safari как был болью похлеще IE, так ей и остается.
    А так подавляющее большинство браузеров сегодня основаны на Chromium, ну и Firefox еще есть немного.
    Ответ написан
    Комментировать
  • Что лучше использовать чтобы сделать задержку для отправки комментария?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    На клиенте просто делаем для кнопки:
    button.disable = true;
    setTimeout(() => {
      button.disable = false;
    }, 60_000);

    Основную же проверку нужно делать на сервере, просто не принимая запрос на добавление комментария пока не прошло время после предыдущего, т.к. клиентские проверки обходятся на раз.
    Ответ написан
    1 комментарий
  • Почему не происходит перезаписи значений параметров ф-ции?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Потому, что undefined в js - это специальное значение, суть которого быть значением по умолчанию для неинициализированных переменных.
    То есть инициализация переменной значением undefined - это все равно, что инициализация значением по умолчанию.
    Когда Вы в сигнатуре функции пишете b = 10 - это означает, что инициализируй b значением 10 если там инициализация по умолчанию (undefined).
    Ответ написан
    Комментировать
  • Удалил большой файл, а оно всё равно не пушится и жалуется на этот файл, как исправить?

    bingo347
    @bingo347
    Crazy on performance...
    Даже если Вы сделали коммит с удалением большого файла, он все равно остается в истории git, а значит будет заливаться на удаленный репозиторий.

    Можно сделать так:
    1. Сделать git checkout на коммит перед тем, где был добавлен большой файл
    2. Создать от этого коммита новую ветку.
    3. Если в коммите, где был добавлен большой файл, были другие изменения, то воспроизвести их (скорее всего вручную, но может кто еще подскажет как это автоматизировать).
    4. Сделать git cherry-pick последующих коммитов из старой ветки в новую.
    5. Удалить старую ветку и переименовать новую в то как называлась старая.

    UPD: по 3 пункту, думаю можно взять diff проблемного коммита, убрать из него добавление большого файла, а затем накатить этот исправленный diff как patch.
    Ответ написан
  • Как проверить токен?

    bingo347
    @bingo347
    Crazy on performance...
    Как лучше проверить токен сохраненный в localstorage при заходе на сайт?
    Хранить токен в localStorage - не очень хорошая идея, так как любой скрипт на любой странице сайта сможет прочитать такой токен и сделать с ним что угодно (например отправить на свой сервер для последующего массового взлома).

    отправлять холостой запрос на авторизованный эндпоинт и если приходит 401 то менять статус?
    Токен должен отправляться в каждый запрос, который требует не гостевых привилегий, иначе смысла нет в токене.

    Единственный адекватный на сегодня вариант хранения токенов - это кука с флагами secure и http-only.
    Флаг secure обеспечит, что кука будет доступна только по https.
    Флаг http-only не даст доступ к этой куке из JS, прочитать ее сможет только сервер.
    Ответ написан
    Комментировать
  • Все циклы, кроме for..in, могут работать только с итерируемыми объектами?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    С итерируемыми объектами работают только циклы for-of и for-await-of.

    В современном JS есть следующие виды циклов:

    1. while - цикл с условием
    // где condition - это некоторое выражение, которое можно скастовать к boolean
    while (condition) {
    }
    Данный цикл выполняется, пока условие condition истинно.

    2. do-while - цикл с постусловием
    do {
    } while (condition);
    Данный цикл выполняется как минимум 1 раз, условие condition проверяется после тела цикла и если оно истинно - запускается следующая итерация.

    3. for - цикл с инициализацией, условием и финальным выражением
    for (init; condition; final_expression) {
    }
    
    // основное применение - это цикл со счетчиком, но в целом мы не ограничены в применении
    for (let i = 0; i < 10; ++i) {
    }
    Перед циклом выполняется init, который может быть выражением или оператором объявления переменных (var, let, const). Перед каждой итерацией проверяется условие condition, пока это условие истинно - цикл будет выполняться. После каждой итерации выполняется final_expression.

    4. for-in - цикл по ключам объекта
    // где object - это некоторое выражение, которое можно скастовать к типу object
    for (const key in object) {
    }
    Данный цикл перебирает все перечислимые ключи самого объекта и всех объектов из его цепочки прототипов. Может работать медленно, а ключи из прототипа обычно не требуются, поэтому данный цикл не рекомендуется использовать.

    5. for-of - цикл по итерируемым объектам
    // где iterable - это некоторый объект с методом Symbol.iterator
    for (const value_variable of iterable) {
    }
    Перед итерацией создает итератор вызывая iterable[Symbol.iterator](), перед каждой итерацией дергает метод next у итератора, работает пока в возвращаемом из метода next объекте поле done не станет true, подставляет поле value в переменную value_variable. Цикл в примере выше можно реализовать в виде обычного for:
    {
      const iter = [1, 2, 3][Symbol.iterator]();
      for (let {done, value} = iter.next(); !done; ({done, value} = iter.next())) {
        const value_variable = value;
        {
          // тело исходного цикла
        }
      }
    }


    6. for-await-of - цикл по асинхронно итерируемым объектам
    // где iterable - это некоторый объект с методом Symbol.asyncIterator или методом Symbol.iterator
    for await (const value_variable of iterable) {
    }
    Перед итерацией создает итератор, одним из следующих способов:
    Если в объекте iterable есть метод Symbol.asyncIterator - то вызывает его.
    В противном случае вызывает метод Symbol.iterator.
    В остальном работает как for-of, с той разницей, что дополнительно применяет оператор await к значению итератора и в value_variable попадает то, что вернул данный await.
    Ответ написан
    Комментировать
  • Существует ли способ быстро запускать текущий файл в среде NodeJS?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    1. В корне проекта создайте папку .vscode (если ее еще нет)
    2. Создайте в папке .vscode файл tasks.json со следующим содержимым:
    {
      "version": "2.0.0",
      "tasks": [
        {
          "label": "Run current file in node.js",
          "type": "shell",
          "command": "node",
          "args": ["${file}"]
        }
      ]
    }
    Если такой файл уже есть, то просто дополните массив tasks содержимым выше.
    3. Нажмите Ctrl+Shift+P и введите команду Preferences: Open Keyboard Shortcuts (JSON), должен открыться файл keybindings.json, добавьте в конец массива следующий объект:
    {
      "key": "alt+f5",
      "command": "workbench.action.tasks.runTask",
      "args": "Run current file in node.js",
      "when": "editorTextFocus && editorLangId == javascript"
    }


    Все, теперь по Alt+F5 в тектовом редакторе будет запускаться текущий файл нодой, если он js файл
    Ответ написан
    1 комментарий