devalue؛ وقتی JSON.stringify کم میاره
خلاصهٔ کاملتر
تو این صفحهی پروژه اومده که devalue یه ابزار سریالایز کردن دادهست که تیم Svelte نگهش میداره و قراره جای خالی JSON.stringify رو پر کنه. مشکل JSON.stringify اینه که خیلی از حالتهای واقعی رو نمیتونه هندل کنه: ارجاع حلقوی (مثلاً وقتی یه آبجکت به خودش اشاره میکنه)، ارجاعهای تکراری به یه مقدار، یا مقدارهایی مثل undefined، Infinity، NaN و -0. ولی devalue همهی اینا بهعلاوه رجکس، Date، Map، Set، BigInt، تایپاریها، URL و حتی Temporal رو پشتیبانی میکنه.
devalue دو روش اصلی برای استفاده داره. اولیش تابع uneval هست که یه مقدار جاوااسکریپتی رو میگیره و کدی برمیگردونه که اون مقدار رو دوباره میسازه؛ یه جورایی برعکس eval. این روش فشردهترین خروجی ممکن رو میده و نیازی به کد جدا برای پارس کردن نداره.
روش دوم جفت stringify و parse هستن که دقیقاً قرینهی JSON.stringify و JSON.parse کار میکنن و وقتی بهدردت میخورن که اجرا کردن کد جاوااسکریپت گزینهی خوبی نیست. یه نسخهی async هم به اسم stringifyAsync هست که میتونه Promiseها رو هم منتظر بمونه و مقدار حلشدهشون رو سریالایز کنه.
import * as devalue from 'devalue';
let obj = { message: 'hello' };
obj.self = obj;
devalue.uneval(obj); // '(function(a){a.message="hello";a.self=a;return a}({}))'به گفتهی مستندات، یکی از نقطهقوتهای اصلیش جلوگیری از XSS هست. وقتی داری یه صفحه رو سمت سرور رندر میکنی و میخوای استیتی که شاید شامل ورودی کاربر باشه رو داخل صفحه بذاری، JSON.stringify میتونه راه رو برای تزریق اسکریپت مخرب باز بذاره، چون کاراکترهای خطرناک رو فرار نمیده. devalue اون کاراکترها (مثل علامتهای تگ و اسلش) رو به فرم یونیکد escapeشده تبدیل میکنه، برای همین مهاجم نمیتونه از دل داده بیرون بزنه و تگ اسکریپت تزریق کنه.
نویسنده تأکید میکنه که این امنیت یهطرفهست: میتونی با خیال راحت داده رو از سرور به کلاینت بفرستی، ولی نباید دادهی کاربر رو از کلاینت به سرور با همین روش بفرستی، چون باید eval بشه و مهاجم میتونه سوءاستفاده کنه. توصیهش هم اینه که اگه از eval استفاده میکنی، بهصورت غیرمستقیم صداش بزنی تا کد اجراشده به اسکوپ اطرافش دسترسی نداشته باشه.
نکات کلیدی:
- جایگزین قویتر JSON.stringify با پشتیبانی از ارجاع حلقوی، Map، Set، Date، BigInt، رجکس و Promise
- سه هدف اصلی: سرعت، امنیت و خروجی فشرده
- uneval برای فشردهترین خروجی، stringify/parse وقتی اجرای کد گزینه نیست
- خروجی در برابر XSS موقع رندر سمت سرور امنه چون کاراکترهای خطرناک رو escape میکنه
- تایپهای سفارشی رو با reducer و reviver میتونی سریالایز و بازسازی کنی




