إنشاء JavaScript وتشغيلها

غالبًا ما تنشئ التطبيقات المحظورة لغة JavaScript كلغة إخراجها، ويتم تشغيلها ضمن صفحة ويب بشكل عام (يمكن أن تكون الصفحة هي نفسها أو مكوّن WebView مضمّن). وكما هو الحال مع أي منشئ، فإن الخطوة الأولى هي تضمين منشئ JavaScript.

import {javascriptGenerator} from 'blockly/javascript';

لإنشاء JavaScript من مساحة العمل، اطلب:

javascriptGenerator.addReservedWords('code');
var code = javascriptGenerator.workspaceToCode(workspace);

يمكن تنفيذ الرمز الناتج مباشرةً في صفحة الويب المقصودة:

try {
  eval(code);
} catch (e) {
  alert(e);
}

في الأساس، لا ينشئ المقتطف أعلاه سوى الرمز ويصفه. ومع ذلك، هناك نوعان من التحسينات. من بين التحسينات التي يتم إجراؤها أن يتم تضمين القيمة try/catch بحيث تظهر أي أخطاء في وقت التشغيل، بدلاً من حدوث إخفاق. هناك تحسين آخر وهو إضافة code إلى قائمة الكلمات المحجوزة بحيث إذا كان الرمز البرمجي للمستخدم يحتوي على متغير من هذا الاسم، ستتم إعادة تسميته تلقائيًا بدلاً من التضارب. يجب حجز أي متغيرات محلية بهذه الطريقة.

لقطات مميَّزة

يساعد تمييز الوحدة قيد التنفيذ حاليًا أثناء عمليات تشغيل الرموز المستخدمين على فهم سلوك برنامجهم. ويمكن إجراء التمييز على مستوى كل عبارة من خلال ضبط STATEMENT_PREFIX قبل إنشاء رمز JavaScript:

javascriptGenerator.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
javascriptGenerator.addReservedWords('highlightBlock');

حدِّد highlightBlock لوضع علامة على المجموعة على مساحة العمل.

function highlightBlock(id) {
  workspace.highlightBlock(id);
}

ينتج عن ذلك إضافة العبارة highlightBlock('123'); قبل كل عبارة، حيث يكون 123 هو الرقم التسلسلي للكتلة المطلوب تسليط الضوء عليه.

حلقات لانهائية

على الرغم من أن التعليمة البرمجية الناتجة مضمونة من حيث البنية في جميع الأوقات، إلا أنها قد تحتوي على حلقات لانهائية. بما أنّ حلّ مشكلة التعليق يتخطى نطاق Blockly (!)، فإن أفضل نهج للتعامل مع هذه الحالات هو الحفاظ على عدّاد وتقليله في كل مرة يتم فيها إجراء تكرار. لتنفيذ ذلك، ما عليك سوى ضبط javascriptGenerator.INFINITE_LOOP_TRAP على مقتطف رمز سيتم إدراجه في كل حلقة وكل دالة. فيما يلي مثال:

window.LoopTrap = 1000;
javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);

مثال

إليك عرض توضيحي مباشر لإنشاء JavaScript وتنفيذه.

مترجم لغة JavaScript

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

  • نفِّذ الرمز بأي سرعة.
  • الإيقاف المؤقت/استئناف/التنفيذ خطوة بخطوة.
  • حدِّد القوالب أثناء تنفيذها.
  • معزول تمامًا عن JavaScript في المتصفح.

تشغيل ميزة "الترجمة الفورية"

أولاً، قم بتنزيل JS-intererer من GitHub:

تنزيل ملف ZIP تنزيل TAR Ball عرض على GitHub

ثم أضفه إلى صفحتك:

<script src="acorn_interpreter.js"></script>

وأبسط طريقة لطلب البيانات هي إنشاء JavaScript وإنشاء أداة الترجمة وتشغيل الرمز البرمجي:

var code = javascriptGenerator.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter.run();

خطوة "المترجم الفوري"

لتنفيذ الرمز البرمجي بشكل أبطأ أو بطريقة أكثر تحكّمًا، استبدِل استدعاء run بتكرار تكرار خطوات (في هذه الحالة خطوة واحدة كل 10 ملي ثانية):

function nextStep() {
  if (myInterpreter.step()) {
    setTimeout(nextStep, 10);
  }
}
nextStep();

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

إضافة واجهة برمجة تطبيقات

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

function initApi(interpreter, globalObject) {
  // Add an API function for the alert() block.
  var wrapper = function(text) {
    return alert(arguments.length ? text : '');
  };
  interpreter.setProperty(globalObject, 'alert',
      interpreter.createNativeFunction(wrapper));

  // Add an API function for the prompt() block.
  wrapper = function(text) {
    return prompt(text);
  };
  interpreter.setProperty(globalObject, 'prompt',
      interpreter.createNativeFunction(wrapper));
}

بعد ذلك، عليك تعديل إعدادات الترجمة الفورية لاجتيازه في دالة initApi:

var myInterpreter = new Interpreter(code, initApi);

إنّ مجموعات التنبيهات والطلبات هما المجموعتان الوحيدتان في المجموعة التلقائية من المجموعات التي تتطلّب واجهة برمجة تطبيقات مخصّصة للترجمة الفورية.

يتم الآن الاتصال بـ highlightBlock()

عند استخدام ميزة "الترجمة الفورية" في JavaScript، يجب تنفيذ "highlightBlock()" فورًا خارج وضع الحماية بينما ينتقل المستخدم خلال البرنامج. للقيام بذلك، أنشئ دالة تضمين highlightBlock() لالتقاط وسيطة الدالة، وسجلها كدالة أصلية.

function initApi(interpreter, globalObject) {
  // Add an API function for highlighting blocks.
  var wrapper = function(id) {
    return workspace.highlightBlock(id);
  };
  interpreter.setProperty(globalObject, 'highlightBlock',
      interpreter.createNativeFunction(wrapper));
}

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

مثال على مترجم لغة JavaScript

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