باز کردن قفل کلون ساختاریافته برای پیام‌رسانی افزونه‌های کروم

جاستین لولجیان
Justin Lulejian

منتشر شده: ۱۳ آوریل ۲۰۲۶

ارتباط بین اجزای مختلف افزونه (اسکریپت‌های پس‌زمینه، اسکریپت‌های محتوا، پنجره‌های بازشو) به طور سنتی بر سریال‌سازی JSON متکی بوده است. اگرچه JSON قابل اعتماد است، اما محدودیت‌هایی دارد.

ما مفتخریم اعلام کنیم که از کروم ۱۴۸ به بعد، توسعه‌دهندگان افزونه‌ها می‌توانند به جای JSON، از الگوریتم کلون ساختاریافته برای سریال‌سازی پیام استفاده کنند! این مدرن‌سازی به شما امکان می‌دهد انواع داده‌های پیچیده‌تری را بین زمینه‌های افزونه‌های خود بدون نیاز به راه‌حل‌های سریال‌سازی دستی ارسال کنید.

چرا کلون ساختاریافته؟

سریال‌سازی JSON (از طریق JSON.stringify در زیر هود) کاربردی است، اما گاهی اوقات توسعه‌دهندگان را ملزم می‌کند که هنگام کار با انواع مدرن جاوا اسکریپت، از موانع عبور کنند.

در اینجا یک مثال خاص وجود دارد که ممکن است هنگام توسعه یک افزونه با آن مواجه شده باشید:

// Sending a Map with JSON serialization
const myMap = new Map([['id', 123]]);

// Arrives as {} on the other side!
chrome.runtime.sendMessage(myMap);

// Workaround: Convert Map to an Array of entries before sending
const message = Array.from(myMap.entries());
chrome.runtime.sendMessage(message);

// On the receiving side:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  const receivedMap = new Map(message);
});

برخی موقعیت‌های دیگر که در آن‌ها JSON با شکست مواجه می‌شود و ممکن است مجبور به راه‌حل‌هایی برای آن شده باشید، اشیاء Set ، BigInt ، NaN و Infinity ، Date و Error هستند.

استفاده از سریال‌سازی کلون ساختاریافته به این معنی است که اکنون می‌توانید اشیاء مختلفی را که قبلاً ارسال آنها از طریق پیام‌رسانی افزونه دشوار یا غیرممکن بود، ارسال کنید. برای مثال، ارسال یک شیء Map اکنون مستقیم است:

// Sending a Map with Structured Clone
const myMap = new Map([['id', 123]]);

// Arrives as a Map on the other side!
chrome.runtime.sendMessage(myMap);

// On the receiving side:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  // message is already a Map instance!
  console.log(message.get('id')); // 123
});

انواع پشتیبانی‌شده‌ی بیشتر

کلون ساختاریافته از طیف گسترده‌ای از انواع دیگر مانند File و Blob پشتیبانی می‌کند.

نحوه عضویت

برای اطمینان از سازگاری با نسخه‌های قبلی و جلوگیری از خرابی افزونه‌های موجود، این ویژگی اختیاری است. می‌توانید با اضافه کردن یک کلید واحد به manifest.json خود، آن را به صورت سراسری برای افزونه خود فعال کنید:

{
  "name": "My Extension",
  "version": "1.0",
  "manifest_version": 3,
  "message_serialization": "structured_clone"
}

اگر حذف شود، یا در نسخه کروم پایین‌تر از ۱۴۸ باشد، مرورگر به طور پیش‌فرض از پیاده‌سازی مبتنی بر JSON فعلی خود برای افزونه استفاده می‌کند.

با پشتیبانی از الگوریتم کلون ساختاریافته، ما API پیام‌رسانی افزونه را به هم‌ترازی با قابلیت‌های استاندارد پلتفرم وب (مشابه postMessage مورد استفاده در Web Workerها و ارتباطات iframe) نزدیک‌تر می‌کنیم و انعطاف‌پذیری و قدرت بیشتری به شما می‌دهیم.

قابلیت همکاری و مشکلات

اگرچه پیاده‌سازی سریال‌سازی کلون ساختاریافته ما از انواع بسیار بیشتری نسبت به JSON پشتیبانی می‌کند، اما چند فرض معماری و ناسازگاری با پیاده‌سازی وجود دارد که باید در نظر داشته باشید.

انواع پشتیبانی نشده

اشیاء مشترک مانند SharedArrayBuffer و انتقال اشیاء مانند ArrayBuffer با پیاده‌سازی ما پشتیبانی نمی‌شوند. SharedArrayBuffer در سریال‌سازی یا غیر سریال‌سازی (بسته به شرایط) با شکست مواجه می‌شود و تلاش برای ارسال یک شیء قابل انتقال مانند Uint8Array به جای آن یک کپی ارسال می‌کند.

ارتباط از یک امتداد به امتداد دیگر

ما برای اطمینان از یکپارچگی داده‌ها، قالب‌های سریال‌سازی منطبق را اعمال می‌کنیم. افزونه‌هایی که قالب‌های سریال‌سازی ناهماهنگ دارند، نمی‌توانند مستقیماً از طریق runtime.sendMessage یا runtime.connect ارتباط برقرار کنند. برای مثال، اگر افزونه A از سریال‌سازی JSON استفاده کند و سعی کند با استفاده از کلون ساختاریافته به افزونه B پیام دهد، ارسال پیام ناموفق خواهد بود و پورت بسته می‌شود (و برعکس).

ارتباط صفحه وب

صفحات وب که externally_connectable استفاده می‌کنند، به‌طور خودکار با فرمت سریال‌سازی افزونه‌ی هدف سازگار می‌شوند. اگر افزونه‌ی شما از کلون ساختاریافته استفاده می‌کند، زمینه‌های وب که پیام‌ها را با استفاده از API runtime ارسال می‌کنند، به‌طور خودکار از کلون ساختاریافته (و برعکس) استفاده می‌کنند. این بدان معناست که وب‌سایت و افزونه باید در فرمت سریال‌سازی مورد انتظار خود همگام‌سازی شوند تا از خطاهای سریال‌سازی جلوگیری شود.

پیام‌رسانی بومی

کانال‌های پیام‌رسانی بومی همچنان همواره سریال‌سازی JSON را اجباری می‌کنند. تلاش برای ارسال انواع صرفاً کلون‌شده‌ی ساختاریافته (مانند BigInt ) به یک میزبان بومی، قبل از اینکه پیام از چارچوب افزونه‌ی شما خارج شود، با شکست مواجه خواهد شد.

متدهای toJSON()

اگر از کلاس‌ها یا اشیاء با متدهای سفارشی toJSON() برای انجام سریال‌سازی سفارشی (مثلاً پاکسازی داده‌ها با حذف رمزهای عبور قبل از ارسال یک شیء) استفاده می‌کنید، توجه داشته باشید که کلون ساختاریافته، toJSON() را نادیده می‌گیرد . این متد مقادیر ویژگی را مستقیماً کپی می‌کند. اگر برای سریال‌سازی سفارشی به toJSON() تکیه می‌کنید، ممکن است قبل از ارسال، به برخی کارهای دستی نیاز باشد. برای مثال:

class User {
  constructor(name, password) {
    this.name = name;
    this.password = password;
  }

  // This will be ignored by structured clone!
  toJSON() {
    return { name: this.name };
  }
}

const user = new User("Alice", "secret123");

// JSON -> {"name":"Alice"}
// Structured Clone -> { name: "Alice", password: "secret123" }

آیا سریال‌سازی JSON از بین می‌رود؟

خیر! کروم متعهد است که در آینده‌ی قابل پیش‌بینی از هر دو قالب سریال‌سازی پشتیبانی کند.

بازخورد را به اشتراک بگذارید

ما امیدواریم که این قابلیت جدید، گردش‌های کاری روان‌تر و قدرتمندتری را برای توسعه افزونه‌های شما فراهم کند.

در حالی که ما یک مجموعه آزمایشی برای اعتبارسنجی عملکرد پیاده‌سازی کلون ساختاریافته خود ایجاد کرده‌ایم، پلتفرم وب دارای تنوع گسترده‌ای از اشیاء است. این ویژگی جدید را امتحان کنید و هرگونه اشکال یا مورد حاشیه‌ای را که با آن مواجه می‌شوید گزارش دهید ! بازخورد شما به ما کمک می‌کند تا پیاده‌سازی را برای کل جامعه بهبود بخشیم.