كيف تعمل المترجمات عبر الإنترنت: تشغيل الشيفرة في المتصفح

تشغّل المترجمات داخل المتصفح شيفرتك داخل صفحة الويب نفسها بواسطة WebAssembly، وهو تنسيق ثنائي مدمج ومعزول يحوّله المتصفح إلى شيفرة آلة سريعة. أما المترجمات والمفسّرات الحقيقية مثل Clang وCPython وR وSQLite فقد جرى تصريفها هي نفسها إلى WebAssembly، فتُنزَّل مرة واحدة ثم تترجم برنامجك أو تشغّله على جهازك أنت، دون إرسال أي شيء إلى خادم. أما المترجمات التقليدية عبر الإنترنت فتعمل بالعكس: ترفع شيفرتك إلى خادم يشغّلها ويعيد إليك المخرجات.

أهم النقاط
  • WebAssembly هو هدف ترجمة محمول تشغّله جميع المتصفحات الرئيسية بسرعات قريبة من الشيفرة الأصلية، داخل بيئة العزل الأمنية نفسها التي تعمل فيها JavaScript.
  • يشغّل مترجما C وC++ لدينا Clang داخل التبويب: يحوّل شيفرتك إلى وحدة WebAssembly، ثم تُنفَّذ بمساعدة طبقة WASI صغيرة توفّر الإدخال والإخراج.
  • تعمل Python وR وSQL وRuby وPHP وLua وProlog كإصدارات WebAssembly من مفسّراتها الرسمية؛ أما لغات عائلة JavaScript فتستخدم محرك المتصفح نفسه.
  • التشغيل المحلي يعني الخصوصية، وعدم وجود طابور انتظار على الخادم، والعمل دون اتصال بعد تخزين بيئة التشغيل مؤقتًا.
  • في المقابل: تنزيل لمرة واحدة، وعدم دعم الخيوط أو مقابس الشبكة، ونظام ملفات مؤقت في الذاكرة، وعدم دعم الاستثناءات في إصدار C++ لدينا.

ما هو WebAssembly

WebAssembly (يُختصر غالبًا إلى Wasm) هو تنسيق تعليمات منخفض المستوى صُمّم ليكون هدف ترجمة. لا يكتبه الناس عادةً يدويًا؛ بل يُنتج مترجم مثل Clang أو مترجم Rust ملف .wasm من شيفرة مصدرية عادية، بالطريقة نفسها التي ينتج بها ملفًا تنفيذيًا لمعالج x86 أو ARM. التنسيق معيار مفتوح طُوّر في W3C، وتوثيقه على webassembly.org، وتدعمه متصفحات Chrome وEdge وFirefox وSafari.

ثلاث خصائص تجعله مفيدًا لتشغيل الشيفرة في المتصفح:

  • محمول. يعمل ملف .wasm نفسه على Windows وmacOS وLinux وAndroid وiOS وعلى أي معالج، لأن المتصفح يحوّله إلى شيفرة الآلة المحلية.
  • سريع. WebAssembly محدّد الأنواع وقريب من العتاد، ولذلك تستطيع محركات المتصفح ترجمته قبل التنفيذ إلى شيفرة آلة فعّالة. وعادةً ما تعمل الشيفرة كثيفة المعالجة أسرع بكثير من JavaScript المكافئة وضمن النطاق العام للشيفرة الأصلية، وإن كانت أبطأ منها قليلًا في العادة.
  • معزول. تحصل وحدة WebAssembly على كتلة ذاكرة خاصة ولا تستطيع استدعاء سوى الدوال التي مُنحت لها صراحةً. ولا تقدر على قراءة ملفاتك أو فتح اتصالات شبكية أو لمس بقية الصفحة ما لم توفّر لها شيفرة المضيف طريقة لذلك.

WASI: واجهة نظام لـ WebAssembly

يتوقع برنامج C وجود نظام تشغيل: شيء يقرأ منه الإدخال القياسي ويكتب إليه المخرجات ويفتح الملفات ويعرف الوقت. أما WebAssembly فلا يحتوي على شيء من ذلك. وتحدّد واجهة نظام WebAssembly (WebAssembly System Interface، أي WASI) مجموعة قياسية من هذه الدوال يستطيع برنامج WebAssembly استيرادها. خارج المتصفح تنفّذ بيئات تشغيل مثل Wasmtime واجهة WASI فوق نظام تشغيل حقيقي. أما داخل المتصفح فتنفّذ مكتبة JavaScript صغيرة تُسمّى WASI shim هذه الدوال فوق بيانات في الذاكرة.

كيف تعمل المترجمات التقليدية عبر الإنترنت

تشغّل معظم المترجمات الراسخة عبر الإنترنت ومواقع تمارين البرمجة شيفرتك على خوادمها:

  1. يرسل متصفحك الشيفرة المصدرية (وأي مدخلات) إلى خادم الموقع.
  2. يضعها الخادم في بيئة معزولة، عادةً حاوية أو آلة افتراضية خفيفة، مع حدود للوقت والذاكرة والعمليات.
  3. يبني المترجم أو المفسّر الحقيقي المثبّت هناك البرنامج ويشغّله.
  4. تُلتقط المخرجات وتُرسل إلى متصفحك، ثم يُتخلَّص من البيئة.

لهذا النموذج مزايا حقيقية. فالخادم يستطيع تقديم أي لغة وإصدار تقريبًا، مع كامل ميزات نظام التشغيل مثل الخيوط والعمليات، وأحيانًا الوصول إلى الشبكة والمكتبات الكبيرة. لكن شيفرتك تغادر جهازك، وقد تصطف الطلبات في طابور في الخدمات المزدحمة، ويعتمد كل تشغيل على رحلة ذهاب وإياب عبر الشبكة، ويتحمل المشغّل تكلفة القدرة الحاسوبية عن كل تنفيذ، ولهذا يحدّ كثير منهم عدد مرات التشغيل أو يطلب حسابًا.

كيف تعمل مترجماتنا داخل المتصفح

في المترجمات عبر الإنترنت لدينا، تُنزَّل بيئة تشغيل كل لغة إلى متصفحك وتعمل داخل Web Worker، وهو خيط في الخلفية يُبقي الصفحة سريعة الاستجابة أثناء تشغيل برنامجك. ويتيح الحدّ الزمني وزر «إيقاف» للصفحة إنهاء الـ worker إذا استمر برنامج في العمل طويلًا، مثلًا بسبب حلقة لا نهائية. وتُثبَّت ملفات بيئة التشغيل على إصدارات محددة، ويُتحقَّق من معظمها بتجزئة تشفيرية قبل تنفيذها.

C وC++: مترجم حقيقي داخل التبويب

يستخدم مترجم C ومترجم C++ المترجم Clang 21 المبني على LLVM، مُجهَّزًا بصيغة WebAssembly بواسطة مشروع YoWASP. ويجري كل تشغيل على مرحلتين:

  1. الترجمة. يترجم Clang، الذي يعمل هو نفسه كـ WebAssembly، الملف main.c أو main.cpp مع تفعيل التحسين والتحذيرات (C17 أو C++20). ولا يكون ناتجه ملفًا تنفيذيًا لمعالج x86 أو ARM بل وحدة WebAssembly جديدة تستهدف WASI. وتُعرض تحذيرات المترجم وأخطاؤه كما يطبعها Clang تمامًا.
  2. التشغيل. يترجم المتصفح تلك الوحدة إلى شيفرة آلة ويبدأ تشغيلها مع WASI shim. وتربط هذه الطبقة الإدخال القياسي بالنص الموجود في خانة الإدخال، وتوجّه المخرجات القياسية وأخطاءها إلى لوحة المخرجات.

أي أن مترجمًا جرى تصريفه إلى WebAssembly ينتج برنامجك مترجَمًا إلى WebAssembly، ويعمل الاثنان في التبويب نفسه.

مفسّرات جرى تصريفها إلى WebAssembly

اللغةبيئة التشغيلما هي
PythonPyodideCPython، المفسّر المرجعي للغة Python، مصرَّفًا إلى WebAssembly. وتتوفر له أيضًا حزم جاهزة مثل NumPy وpandas.
RwebRالإصدار الرسمي من R بصيغة WebAssembly، ويشمل الرسوم الأساسية.
SQLsql.jsمحرك قواعد البيانات SQLite مصرَّفًا إلى WebAssembly، مع بقاء قاعدة البيانات في الذاكرة.
Rubyruby.wasmمفسّر CRuby الرسمي المبني لـ WASI، مع مكتبته القياسية.
PHPphp-wasmمفسّر PHP مصرَّفًا إلى WebAssembly.
Luawasmoonمفسّر Lua 5.4 المرجعي مصرَّفًا إلى WebAssembly.
Prologswipl-wasmSWI-Prolog مصرَّفًا إلى WebAssembly.

ولأن هذه هي المفسّرات نفسها التي يثبّتها الناس على حواسيبهم، فإن السلوك ورسائل الخطأ تطابق إصدارات سطح المكتب إلى حد بعيد. يمكنك تجربتها في مترجم Python ومترجم R ومترجم SQL.

لغات تستخدم محرك المتصفح نفسه

بعض اللغات لا تحتاج إلى WebAssembly إطلاقًا. فـمترجم JavaScript يشغّل الشيفرة مباشرةً في محرك JavaScript الخاص بالمتصفح. أما TypeScript وCoffeeScript فتحوّلهما مترجماتهما الرسمية، التي تُوزَّع بصيغة JavaScript، إلى JavaScript، ثم تُشغَّل النتيجة بالطريقة نفسها. وتستخدم Scheme المفسّر BiwaScheme، وتستخدم Clojure المفسّر SCI (مفسّر Clojure الصغير)، وكلاهما مفسّر يعمل هو نفسه بصيغة JavaScript.

مزايا تشغيل الشيفرة في المتصفح

  • الخصوصية. تبقى شيفرتك المصدرية ومدخلاتك على جهازك. لا تُرفع ولا تُخزَّن ولا تُسجَّل في خادمنا، لأن الخادم لا يتلقاها أصلًا.
  • بلا طابور وبلا حساب. يستخدم كل زائر معالجه الخاص، فلا يوجد طابور تنفيذ مشترك ولا حاجة إلى تقنين عدد مرات التشغيل.
  • يعمل دون اتصال بعد التحميل. بعد تنزيل الصفحة وبيئة التشغيل وتخزينهما مؤقتًا، تستطيع متابعة التحرير وتشغيل الشيفرة إذا انقطع اتصالك، ما دام التبويب مفتوحًا. أما الحزم الإضافية التي تُحمَّل عند الطلب، مثل بعض مكتبات Python، فتحتاج إلى اتصال في المرة الأولى.
  • تشغيل متكرر سريع. بعد التحميل الأول تبدأ اللغات المفسَّرة فورًا تقريبًا، ولا توجد رحلة ذهاب وإياب عبر الشبكة بين الضغط على «تشغيل» ورؤية المخرجات.

الحدود والمقايضات

الحدسبب وجودهماذا يعني عمليًا
حجم التنزيليجب أن يصل المترجم أو المفسّر كاملًا إلى متصفحك.يبلغ حجم Clang وR وRuby عشرات الميغابايتات؛ أما Lua وSQLite فأقل من ميغابايت واحد. وتستخدم الزيارات اللاحقة ذاكرة التخزين المؤقت للمتصفح.
لا خيوطتعمل بيئات التشغيل لدينا بخيط واحد؛ فخيوط WebAssembly تحتاج إلى إعدادات عزل إضافية في المتصفح ودعمًا من بيئة التشغيل.لن تعمل pthread أو std::thread أو threading في Python لتحقيق توازٍ حقيقي كما تعمل على سطح المكتب.
لا مقابس شبكةلا تمنح بيئة العزل البرامج أي وسيلة لفتح اتصالات شبكية خام.ستفشل الشيفرة التي تفتح مقابس أو ترسل طلبات HTTP من C أو Python أو R. أما JavaScript في المتصفح فتستطيع استخدام fetch.
لا نظام ملفات حقيقيتحصل بيئات التشغيل، في أفضل الأحوال، على نظام ملفات افتراضي في الذاكرة، ولا تصل أبدًا إلى قرصك.تستطيع Python وبعض بيئات التشغيل الأخرى إنشاء ملفات أثناء الجلسة، لكنها تختفي عند إغلاق الصفحة؛ أما برامج C وC++ لدينا فتحصل على الإدخال والإخراج القياسيين فقط.
لا استثناءات في C++إصدار C++ لدينا مترجَم مع تعطيل الاستثناءات (-fno-exceptions).الشيفرة التي تستخدم try أو catch أو throw لن تُترجم؛ استخدم قيم الإرجاع أو رموز الأخطاء بدلًا منها.
الذاكرةيستطيع WebAssembly بنظام 32 بت عنونة 4 GiB على الأكثر، وقد تسمح المتصفحات أو الأجهزة بأقل من ذلك.قد تفشل المصفوفات أو مجموعات البيانات الكبيرة جدًا بأخطاء نفاد الذاكرة، خصوصًا على الهواتف.
الإدخال غير تفاعلييُوفَّر الإدخال القياسي قبل بدء البرنامج.اكتب كل المدخلات في خانة الإدخال أولًا؛ فلا يمكن لمطالبات الإدخال أن تنتظرك في منتصف التشغيل.

في التعلم واختبار الخوارزميات والواجبات الدراسية نادرًا ما تهم هذه الحدود. أما البرامج التي تحتاج إلى الشبكة أو عمليات متعددة أو ذاكرة كبيرة، فاستخدم تثبيتًا محليًا أو بيئة قائمة على خادم.

النموذج الأمني

يبدو تشغيل شيفرة عشوائية محفوفًا بالمخاطر، لكن المترجمات داخل المتصفح تعتمد على حمايات يطبّقها المتصفح أصلًا على كل موقع ويب.

  • عزل WebAssembly. لا تستطيع الوحدة قراءة أو كتابة سوى ذاكرتها الخطية الخاصة، وهي تخضع لفحص الحدود، ولا تستطيع استدعاء سوى الدوال المستوردة إليها صراحةً. وقد يُفسد برنامج C ذو فيض في المخزن المؤقت ذاكرته هو، لكنه لا يستطيع الخروج إلى المتصفح أو إلى نظام التشغيل.
  • بيئة عزل المتصفح. تعمل كل شيفرة الصفحة، بما فيها WebAssembly وWeb Workers، داخل بيئة عزل العمليات في المتصفح وقواعد المصدر نفسه، فلا تستطيع قراءة بيانات المواقع الأخرى أو ملفاتك.
  • الـ workers والحدود الزمنية. يعني التشغيل داخل worker أنه يمكن إنهاء برنامج منفلت دون تجميد الصفحة أو إعادة تحميلها.
  • بيئات تشغيل موثَّقة. يحمي تثبيت إصدارات بيئة التشغيل بدقة، والتحقق من التجزئات حيث تسمح طريقة التحميل بذلك، من أن تقدّم شبكة توصيل المحتوى ملفًا مختلفًا أو معدَّلًا دون أن تعلن ذلك.

وثمة تنبيه واحد: شيفرة JavaScript التي تشغّلها في مترجم JavaScript لها القدرات نفسها التي لأي سكربت في صفحة ويب، بما فيها إرسال طلبات الشبكة. وكما هو الحال مع أي شيفرة، لا تشغّل إلا المقتطفات التي تفهمها، خصوصًا تلك المنسوخة من غرباء.

متى تستخدم أي نوع من المترجمات عبر الإنترنت

  1. إذا كانت شيفرتك خاصة، مثل واجب دراسي أو شيفرة عمل، ففضّل مترجمًا داخل المتصفح حتى لا تغادر جهازك.
  2. إذا كنت تحتاج إلى خيوط أو مقابس أو مكتبة نظام محددة أو لغة لا يتوفر لها إصدار WebAssembly، فاستخدم خدمة قائمة على خادم أو تثبيتًا محليًا.
  3. إذا كان اتصالك بطيئًا أو محدود الحجم، فابدأ ببيئات التشغيل الأخف؛ فالتحميل الأول لبيئة كبيرة هو التكلفة الرئيسية.

الأسئلة الشائعة

هل تُرسَل شيفرتي إلى خادم عند استخدام مترجماتكم عبر الإنترنت؟

لا. تنزّل الصفحة المترجم أو المفسّر، وتُترجم شيفرتك ومدخلاتك وتُشغَّل على جهازك. ولا يقدّم الخادم سوى الصفحة وملفات بيئة التشغيل.

هل WebAssembly بسرعة الشيفرة الأصلية؟

هو عادةً قريب منها لكنه أبطأ قليلًا، ويتوقف الفارق على طبيعة العمل والمتصفح. وفي التمارين والخوارزميات المعتادة لا يكون الفرق ملحوظًا؛ فالتنزيل في المرة الأولى هو التأخير الأكبر.

لماذا يستغرق التشغيل الأول وقتًا أطول؟

يُنزِّل التشغيل الأول بيئة التشغيل ويهيّئها، وهذا يعني عشرات الميغابايتات في Clang وR وRuby. ويخزّن المتصفح هذه الملفات مؤقتًا، فتبدأ الزيارات اللاحقة أسرع بكثير.

لماذا لا تُترجم شيفرة C++ التي تستخدم try وcatch؟

إصدار C++ لدينا مترجَم مع تعطيل الاستثناءات، لأن معالجة الاستثناءات في WebAssembly تحتاج إلى دعم إضافي من سلسلة الأدوات وبيئة التشغيل لا يستخدمه هذا الإعداد. أعد كتابة معالجة الأخطاء لتستخدم قيم الإرجاع أو std::optional أو رموز الأخطاء، أو ترجم محليًا إذا كنت تحتاج إلى الاستثناءات.

هل يستطيع برنامج في مترجم عبر الإنترنت أن يضر حاسوبي؟

الشيفرة التي تعمل كـ WebAssembly في المتصفح محصورة في ذاكرتها الخاصة وفي الدوال التي توفرها الصفحة، وتضيف بيئة عزل المتصفح طبقة أخرى. فلا تستطيع قراءة ملفاتك ولا تثبيت برامج. أما شيفرة JavaScript فتستطيع إرسال طلبات ويب كأي سكربت في صفحة، لذا تجنّب تشغيل شيفرة لا تثق بها.

جرّبها بنفسك

طبّق هذا الدليل عمليًا باستخدام أدواتنا المجانية.

تابع القراءة

تم النسخ إلى الحافظة