Search
Write a publication
Pull to refresh

Comments 12

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

Использование eval для пересоднания объектов гипотетически небезопасно

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

Можно же просто заменить eval на имена функций, которые будут выполнять "десериализацию" существующих объектов?

Можно в принципе без eval обойтись, если для пересоздания объекта не критично, чтобы аргументы конструктора отсутствовали (т.к. всё равно после пересоздания произойдёт merge с сериализацией).

Это нужно только для тех случаев, в которых аргумент в конструкторе критичен. Например, когда сам конструктор устанавливает свои внутренние переменные (которые не содержатся в объекте) на основе переданных данных. Но такие переменные на самом деле трудно восстановить, потому что они могут меняться по ходу работы объекта, а доступа из вне к ним нет. Т.е. по сути, случаи, в которых нужно делать eval для сборки аргументов конструктора, высосаны из пальца.

Вот небольшой пример:

function town(country){
	var isCapitol=0;
	if(country=='russia') isCapitol=1;
	this.country=country;
	this.getCapitol=()=>isCapitol;
}
let msk=new town('russia');
console.log(msk.getCapitol());

В этом случае, после сериализации/десериализации объекта, метод getCapitol будет работать неправильно, т.к. связанная с ним переменная isCapitol обнулится. Но если использовать текущий метод десериализации, то она сохранится.

А теперь пусть будет

var isCapitol = Math.random()>0.5;

– справится ваша либа?

Естественно нет. Я по этому и написал выше, что "такие переменные на самом деле трудно восстановить, потому что они могут меняться по ходу работы объекта, а доступа из вне к ним нет" и что практического применения втыкания переменных в конструктор может и не быть.

Если можно без него обойтись, то зачем его использовать? На самом деле, даже без «если», просто нельзя его использовать.

Это же дыра в безопасности вида «выполнение произвольного кода». Даже если у вас нету секретов, то можно досить сторонние сайты. Или представьте себе игрока, который будет монетизировать дыру показывая противнику рекламный баннер каждый ход. :)

Кому как удобно. Если есть вероятность правки данных пользователем (и эта правка критична, т.к. например в тех же героях 3/HOTa сохранёнки никак не защищены от подобного) - можно использовать без этой фичи, в методе распаковки можно выбрать вариант пересоздания объектов. Тогда также будет сохранена возможность сохранения ссылок и цепочки прототипов.

Ну а вообще Вы правы. Я когда писал предыдущий комментарий понял, что особой необходимости держать там eval нет, можно его опционально включать, а по умолчанию выключить.

Фиксится валидацией на сервере

Сложно представить, как бы выглядела эта валидация. Или вы хотите eval еще и на сервере запускать?

  • С WeakMap всё это делается линейно (никакого переобхода) и никакие внутренние ID не нужны

  • Хранить методы имеет мало смысла, т.к. замыкания сохранить всё равно не удастся

Интересно, можете объяснить почему нельзя сохранить замыкания?

Может и можно. Сейчас посмотрел - конструктор объекта отдаёт [[scopes]]

А как? Единственный способ сериализовать метод это fn.toString() + eval (либо new Function(rawFnStr)). В обоих случаях вы по сути работаете со строкой. Просто перевыполнить декларацию этой строки как код недостаточно чтобы зацепить scopes. А [[scopes]] как ниже указал nerd220 это просто удобная тула для дебага. Её нет в реальном runtime-е.

Sign up to leave a comment.

Articles