الفرق بين المراجعتين ل"Node.js/vm"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(أنشأ الصفحة ب'= VM (تنفيذ JavaScript) = مؤشر الاستقرار: 2 - مستقر. توفر الوحدة <code>vm</code> واجهات تطبيقات لترجمة وتشغيل...')
 
ط (استبدال النص - '\[\[تصنيف:(.*)\]\]' ب'{{SUBPAGENAME}}')
 
(4 مراجعات متوسطة بواسطة مستخدم واحد آخر غير معروضة)
سطر 1: سطر 1:
= VM (تنفيذ JavaScript) =
+
<noinclude>{{DISPLAYTITLE: VM (تنفيذ JavaScript) في Node.js}}</noinclude>
 
مؤشر الاستقرار: 2 - مستقر.
 
مؤشر الاستقرار: 2 - مستقر.
  
سطر 26: سطر 26:
 
console.log(x); // 1; y غير مُعرَّف.
 
console.log(x); // 1; y غير مُعرَّف.
 
</syntaxhighlight>ولا تُعد الوحدة vm آلية أمان. ولا يجب استخدامها لتشغيل شيفرة برمجية غير موثوق بها.
 
</syntaxhighlight>ولا تُعد الوحدة vm آلية أمان. ولا يجب استخدامها لتشغيل شيفرة برمجية غير موثوق بها.
 
+
==الصنف: <code>vm.SourceTextModule</code>==
== الصنف: vm.SourceTextModule ==
 
 
أضيفت مع الإصدار: v9.6.0.
 
أضيفت مع الإصدار: v9.6.0.
  
 
مؤشر الاستقرار: 1 - تجريبي.
 
مؤشر الاستقرار: 1 - تجريبي.
  
تتوفر هذه الميزة فقط عند تفعيل راية الأمر <code>‎--experimental-vm-modules</code>.
+
تتوفر هذه الميزة فقط عند تفعيل راية الأمر <code>‎--experimental-vm-modules</code>.
  
ويوفر الصنف <code>vm.SourceTextModule</code> واجهة منخفضة المستوى لاستخدام وحدات ECMAScript في سياقات VM. وهو نظير للصنف <code>vm.Script</code> الذي يعكس سجلات وحدة نَّص المصدر (Source Text Module Records) كما هو محدد في مواصفات ECMAScript.
+
ويوفر الصنف <code>vm.SourceTextModule</code> واجهة منخفضة المستوى لاستخدام وحدات ECMAScript في سياقات VM. وهو نظير للصنف <code>vm.Script</code> الذي يعكس [https://tc39.github.io/ecma262/#sec-source-text-module-records سجلات وحدة نَّص المصدر (Source Text Module Records)] كما هو محدد في مواصفات ECMAScript.
  
ومع ذلك، علي عكس vm.Script يرتبط كل كائن vm.SourceTextModule إلى سياق من إنشائه. العمليات على كائنات vm.SourceTextModule هي في جوهرها غير متزامنة، في تناقض مع الطبيعة للمتزامنة لكائنات vm.Script بيد أن التلاعب بكائنات vm.SourceTextModule يكون واضحا إلى حد ما بمساعدة الدوال المتزامنة.
+
ومع ذلك، علي عكس <code>vm.Script</code> يرتبط كل كائن <code>vm.SourceTextModule</code> إلى سياق من إنشائه. وتكون العمليات على كائنات <code>vm.SourceTextModule</code> في جوهرها غير متزامنة، في تناقض مع الطبيعة المتزامنة لكائنات <code>vm.Script</code> بيد أن التلاعب بكائنات <code>vm.SourceTextModule</code> يكون واضحا إلى حد ما بمساعدة الدوال المتزامنة.
  
باستخدام vm.SourceTextModule كائن يتطلب أربع خطوات: إنشاء/تحليل, ربط, مثيل, والتقييم. هذه الخطوات الأربع موضحة في المثال التالي.
+
يتطلب استخدام كائن <code>vm.SourceTextModule</code> أربع خطوات: إنشاء/تحليل, ربط، عمل مثيل، والتقييم. هذه الخطوات الأربع موضحة في المثال التالي.
  
يكمن هذا التنفيذ في مستوى أقل من مُحمِـل وحدة ECMAScript. كما لا يوجد حاليا أي وسيلة للتفاعل مع المُحمِـل، على الرغم من التخطيط لدعمه.
+
يكمن هذا التنفيذ في مستوى أقل من [[Node.js/esm|مُحمِـل وحدة ECMAScript]]. كما لا يوجد حاليا أي وسيلة للتفاعل مع المُحمِّـل، على الرغم من التخطيط لدعمه.<syntaxhighlight lang="javascript">
 +
const vm = require('vm');
  
 +
const contextifiedSandbox = vm.createContext({ secret: 42 });
 +
 +
(async () => {
 
// الخطوة 1
 
// الخطوة 1
  
 
//
 
//
  
// إنشاء وحدة عن طريق بناء كائن `vm.SourceTextModule` جديد. هذا
+
// إنشاء وحدة عن طريق بناء كائن `vm.SourceTextModule` جديد.
  
// يحلل نص المصدر المعطى ويطلق `SyntaxError` إذا حدث أي شيء
+
// يحلل هذا نص المصدر المعطى ويطلق `SyntaxError` إذا حدث أي خطأ.
  
// الخطأ. بشكل افتراضي ، تُنشأ وحدة في أعلى السياق. ولكن هنا،
+
// بشكل افتراضي، تُنشأ وحدة في أعلى السياق. ولكن هنا،
  
 
// نُحدد `contextifiedSandbox` كسياق تنتمي له هذه الوحدة.
 
// نُحدد `contextifiedSandbox` كسياق تنتمي له هذه الوحدة.
سطر 56: سطر 59:
 
//
 
//
  
// هنا نحاول الحصول على التصدير الافتراضي من وحدة "foo" ،  
+
// هنا نحاول الحصول على التصدير الافتراضي من وحدة "foo"،
  
ووضعه في "سرية" الربط المحلية.
+
// ووضعه في "secret" الربط المحلية.
 +
 
 +
const bar = new vm.SourceTextModule(`
 +
    import s from 'foo';
 +
    s;
  
 
// الخطوة 2
 
// الخطوة 2
سطر 68: سطر 75:
 
//
 
//
  
// تقبل دالة رد الاتصال المُعطاه ("الرابطة") وسيطين:
+
// تقبل دالةُ رد الاتصال المُعطاة ("الرابطة") وسيطين:
  
// الوحدة الأصل (' bar' في هذه الحالة) والسلسلة التي تحدد
+
// الوحدة الأصل ('bar' في هذه الحالة) والسلسلة التي تحدد
  
 
// الوحدة المستوردة. ومن المتوقع أن تعيد دالة رد الاتصال الوحدة التي
 
// الوحدة المستوردة. ومن المتوقع أن تعيد دالة رد الاتصال الوحدة التي
سطر 80: سطر 87:
 
//
 
//
  
// إذا لم يبدأ الربط للوحدة المُعادة، سيُستدعى نفس دالة رد الاتصال الرابطة
+
// إذا لم يبدأ الربط للوحدة المُعادة، ستُستدعى نفس دالة رد الاتصال الرابطة
  
 
// على الوحدة المُعادة.
 
// على الوحدة المُعادة.
سطر 86: سطر 93:
 
//
 
//
  
// ويجب ربط حتى الوحدات ذات المستوي الأعلى الخالية من التبعيات بشكل صريح. وعلى الرغم من ذلك،
+
// ويجب ربط حتى الوحدات ذات المستوي الأعلى الخالية من التبعيات بشكل صريح.  
 
+
// وعلى الرغم من ذلك، لن تستدعى دالة رد الاتصال المعطاة.
لن تستدعى دالة رد الاتصال المعطاة.
 
  
 
//
 
//
  
ويعيد التابع link()‎ وعد (Promise) والذي سيحل عندما
+
ويعيد التابع link()‎ الوعد (Promise) والذي سيُحل عندما
  
 
تُحل جميع الوعود Promises المُعادة بواسطة الرابط.
 
تُحل جميع الوعود Promises المُعادة بواسطة الرابط.
سطر 104: سطر 110:
 
// قد تستخدم ذاكرة التخزين المؤقت على الأرجح لتجنب تكرار الوحدات.
 
// قد تستخدم ذاكرة التخزين المؤقت على الأرجح لتجنب تكرار الوحدات.
  
 +
  async function linker(specifier, referencingModule) {
 +
    if (specifier === 'foo') {
 +
      return new vm.SourceTextModule(`
 
// يشير المتغير "secret" إلى المتغير العام الذي أضفناه إلى
 
// يشير المتغير "secret" إلى المتغير العام الذي أضفناه إلى
  
 
// "contextifiedSandbox" عند إنشاء السياق.
 
// "contextifiedSandbox" عند إنشاء السياق.
 +
 +
        export default secret;
 +
      `, { context: referencingModule.context });
 +
  
 
// استخدام `contextifiedSandbox` بدلا من `referencingModule.context`
 
// استخدام `contextifiedSandbox` بدلا من `referencingModule.context`
  
 
// هنا سوف يعمل أيضًا.
 
// هنا سوف يعمل أيضًا.
 +
}
 +
    throw new Error(`Unable to resolve dependency: ${specifier}`);
 +
  }
 +
  await bar.link(linker);
 +
  
 
// الخطوة 3
 
// الخطوة 3
سطر 123: سطر 141:
  
 
// وستُنشأ مثيلات لتبعياتها بشكل متكرر من قِبَل instantiate()‎.
 
// وستُنشأ مثيلات لتبعياتها بشكل متكرر من قِبَل instantiate()‎.
 +
 +
  bar.instantiate();
  
 
// الخطوة 4
 
// الخطوة 4
سطر 136: سطر 156:
 
// التصدير الافتراضي للوحدة 'foo'، و 'secret' الذي ضُبِط
 
// التصدير الافتراضي للوحدة 'foo'، و 'secret' الذي ضُبِط
  
// في بداية 42.
+
// في بداية بالقيمة 42.
  
=== المُنشئ: new vm.SourceTextModule(code[, options]) ===
+
const { result } = await bar.evaluate();
* code من النوع <string> وهو شيفرة وحدة JavaScript المراد تحليلها
 
* options
 
** url من النوع <string> وهو URL المستخدم في حل الوحدة وتتبعات المكدس. القيمة الافتراضية: 'vm:module(i)' حيث i مؤشر تصاعدي خاص بالسياق.
 
** context من النوع <Object> وهو الكائن الموضوع في السياق كما أُعيد من قبل التابع vm.createContext()‎، لترجمته وتقييمه داخل Module.
 
** lineoffset من النوع <integer> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي تنتجها الوحدة Module.
 
** columnoffset من النوع <integer> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي تنتجها الوحدة Module
 
** initalizeImportMeta من النوع <Function> تًستدعى خلال تقييم هذه الوحدة Module لإعادة تهيئة import.meta. لدى هذه الدالة التوقيع  (meta, module) مع كون meta كائن import.meta في Module، و module كائن vm.SourceTextModule.
 
إنشاء كائن ES Module جديد.
 
  
قد تسمح الخصائص المعينة لكائن import.meta التي هي كائنات للوحدة Module للوصول إلى المعلومات خارج context المحدد، إذا أنشئ الكائن في سياق المستوي الأعلى. استخدام vm.runincontext()‎‎ لإنشاء كائنات في سياق معين.
+
  console.log(result);
 +
  // طباعة 42.
 +
})();
 +
</syntaxhighlight>
 +
===المُنشئ: <code>new vm.SourceTextModule(code[, options])</code>‎===
 +
*<code>code</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو شيفرة وحدة JavaScript المراد تحليلها.
 +
*<code>options</code>
 +
**<code>url</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو URL المستخدم في حل الوحدة وتتبعات المكدس. القيمة الافتراضية: ‎<code>'vm:module(i)'</code>‎ حيث i مؤشر تصاعدي خاص بالسياق.
 +
**<code>context</code> من النوع <code>[[JavaScript/Object|<Object>]]</code> وهو الكائن الموضوع في السياق كما أُعيد من قبل التابع <code>vm.createContext()</code>‎، لترجمته وتقييمه داخل <code>Module</code>.
 +
**<code>lineoffset</code> من النوع <code>[[JavaScript/Number|<integer>]]</code> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي تنتجها الوحدة <code>Module</code>.
 +
**<code>columnoffset</code> من النوع <code>[[JavaScript/Number|<integer>]]</code> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي تنتجها الوحدة <code>Module</code>.
 +
**<code>initalizeImportMeta</code> من النوع <code>[[JavaScript/Function|<Function>]]</code> وهو يُستدعى خلال تقييم هذه الوحدة <code>Module</code> لإعادة تهيئة <code>import.meta</code>. شكل هذه الدالة هو <code>(meta, module)</code> مع كون <code>meta</code> كائن <code>import.meta</code> في <code>Module</code>، و <code>module</code> كائن <code>vm.SourceTextModule</code>.
 +
إنشاء كائن ES <code>Module</code> جديد.
  
// ملاحظة: أنشئ هذا الكائن في السياق الأعلى. وعلى هذا النحو،
+
قد تسمح الخصائص المعينة لكائن <code>import.meta</code> التي هي كائنات للوحدة <code>Module</code> للوصول إلى المعلومات خارج <code>context</code> المحدد، إذا أنشئ الكائن في سياق المستوي الأعلى. يُستخدم التابع <code>vm.runincontext()‎‎</code> لإنشاء كائنات في سياق معين.<syntaxhighlight lang="javascript">
 +
const vm = require('vm');
  
// يشير الكائن Object.getPrototypeOf(import.meta.prop) إلى
+
const contextifiedSandbox = vm.createContext({ secret: 42 });
  
// Object.prototype في أعلى السياق بدلا من ذلك الذي في
+
(async () => {
 +
  const module = new vm.SourceTextModule(
 +
    'Object.getPrototypeOf(import.meta.prop).secret = secret;',
 +
    {
 +
      initializeImportMeta(meta) {
 +
        // ملاحظة: أنشئ هذا الكائن في السياق الأعلى. وعلى هذا النحو،
 +
        // يشير الكائن Object.getPrototypeOf(import.meta.prop)‎ إلى
 +
        // Object.prototype في أعلى السياق بدلا من ذلك الذي في
 +
        // الـ sandbox.
 +
        meta.prop = {};
 +
      }
 +
    });
 +
  // وبما أن ليس للوحدة تبعيات، فلن تُستدعى دالة الرابط أبدًا.
 +
  await module.link(() => {});
 +
  module.instantiate();
 +
  await module.evaluate();
  
// الـ sandbox.
+
  // يساوي Object.prototype.secret الآن 42.
 +
  //
 +
  // لإصلاح هذه المشكلة، يستبدل
 +
  //      meta.prop = {};
 +
  // أعلاه مع،
 +
  //      meta.prop = vm.runInContext('{}', contextifiedSandbox);
 +
})();
 +
</syntaxhighlight>
 +
===<code>module.dependencySpecifiers</code>===
 +
*من النوع <code>[[JavaScript/String|<string[]‎>]]</code>.
 +
محددات كافة تبعيات هذه الوحدة. وهي تُجمَّد المصفوفة المُعادة لمنع حدوث أي تغييرات عليها.
  
// وبما أن ليس للوحدة تبعيات، فلن تُستدعى دالة الرابط أبدًا.
+
يتوافق مع الحقل <code><nowiki>[[RequestedModules]]</nowiki></code> في [https://tc39.github.io/ecma262/#sec-source-text-module-records سجلات وحدة نص المصدر] في مواصفات ECMAScript.
 +
===<code>module.error</code>===
 +
*من أي نوع من الأنواع <any>.
 +
إذا كانت الحالة <code>module.status</code> بالقيمة <code>'errored'</code>، تحتوي هذه الخاصية علي الاستثناء الذي أُجريَ بواسطة الوحدة أثناء التقييم. إذا كانت الحالة غير ذلك، سيؤدي الوصول إلى هذه الخاصية إلى إجراء استثناء.
  
// يساوي Object.prototype.secret الآن 42.
+
لا يمكن استخدام القيمة <code>undefined</code> للحالات حيث لا يوجد إجراء استثناء بسبب الغموض المحتمل حول <code>throw undefined;‎</code>.
  
//
+
يتوافق مع الحقل <code><nowiki>[[EvaluationError]]</nowiki></code> في [https://tc39.github.io/ecma262/#sec-source-text-module-records سجلات وحدة نص المصدر] في مواصفات ECMAScript.
 +
===<code>module.evaluate([options])‎</code>===
 +
*<code>options</code> من النوع <code>[[JavaScript/Object|<Object>]]</code>.
 +
**<code>timeout</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد عدد المللي ثانية اللازمة للتقييم قبل إنهاء التنفيذ. إذا تمت مقاطعة التنفيذ، سينطلق <code>[[Node.js/errors|Error]]</code>.
 +
**<code>breakOnSigint</code> من النوع <code>[[JavaScript/Boolean|<boolean>]]</code>، إذا كان <code>true</code>، سينتهي التنفيذ عند تلقي <code>SIGINT</code> (أو Ctrl + C). ستُعَّطل المعالجات الموجودة للحدث الذي أُرفِق بواسطة <code>process.on('SIGINT')‎</code> أثناء تنفيذ السكريبت، ولكنها سوف تستمر في العمل بعد ذلك. إذا تمت مقاطعة التنفيذ، سينطلق <code>[[Node.js/errors|Error]]</code>.
 +
*القيمة المُعادة: من النوع [[JavaScript/Promise|<Promise>]].
 +
يقيّم هذا التابع الوحدة. ويجب استدعاءه بعد إنشاء مثيل الوحدة؛ وإلا فانه سيُطلق خطأ. ويمكن استدعاؤه أيضًا عند تقييم الوحدة بالفعل، وفي هذه الحالة سيقوم بأحد الأمرين التاليين:
 +
*إعادة <code>undefined</code> إذا انتهى التقييم الأولي بنجاح (<code>module.status</code> تكون '<code>evaluated'</code>).
 +
*أعادة إجراء الاستثناء نفسه الذي أجراه التقييم الأولي إذا أُنهيَ التقييم الأولي مع وجود خطأ (<code>module.status</code> تكون <code>'errored'</code>).
 +
لا يمكن استدعاء هذا التابع أثناء تقييم الوحدة (<code>module.status</code> تكون <code>'evaluating'</code>) لمنع لانهائية العَوْديَّة.
  
// لإصلاح هذه المشكلة، يستبدل
+
يتوافق مع حقل [https://tc39.github.io/ecma262/#sec-moduleevaluation التابع <code>Evaluate()</code>‎ المتماسك] من [https://tc39.github.io/ecma262/#sec-source-text-module-records سجلات وحدة نص المصدر] في مواصفات ECMAScript.
 +
===<code>module.instantiate()‎</code>===
 +
ينشئ هذا التابع مثيل للوحدة. ويجب استدعاءه بعد إنهاء الربط (<code>linkingStatus</code> تكون <code>'linked'</code>)؛ وإلا فانه سيُطلق خطأ. كما يجوز إجراء استثناء إذا لم يوفر أحدُ التبعيات التصديرَ الذي تتطلبه الوحدة الأصل.
  
// meta.prop = {};
+
ومع ذلك، إذا نجحت هذه الدالة، ستكون الاستدعاءات اللاحقة لهذه الدالة بعد الإنشاء الأولي لمثيل هو no-ops، لتكون متناسقة مع مواصفات ECMAScript.
  
// أعلاه مع،
+
علي عكس التوابع الأخرى التي تعمل علي <code>Module</code>، تكمل هذه الدالة بشكل متزامن ولا تقوم بإعادة أي شيء.
  
// meta.prop = vm.runInContext('{}', contextifiedSandbox);
+
يتوافق مع حقل [https://tc39.github.io/ecma262/#sec-moduledeclarationinstantiation التابع <code>Instantiate()‎</code> المتماسك] من [https://tc39.github.io/ecma262/#sec-source-text-module-records سجلات وحدة نص المصدر] في مواصفات ECMAScript.
 +
===<code>module.link (linker)‎</code>===
 +
*<code>linker</code> من النوع <code>[[JavaScript/Function|<Function>]]</code>.
 +
*القيمة المُعادة: من النوع [[JavaScript/Promise|<Promise>]].
 +
يربط هذا التابع تبعيات الوحدة. يجب استدعاء هذا التابع قبل إنشاء مثيل، ويمكن استدعاؤه مره واحدة فقط لكل وحدة.
  
=== module.dependencySpecifiers ===
+
سيمرر مُعاملَين إلى الدالة linker:
* من النوع <string[]>
+
*<code>specifier</code> وهو محدد الوحدة المطلوبة:<syntaxhighlight lang="javascript">
محددات كافة تبعيات هذه الوحدة. تُجمَّد المصفوفة المُعادة لمنع حدوث أي تغييرات عليه.
+
import foo from 'foo';
 +
//              ^^^^^ محدد الوحدة
 +
</syntaxhighlight>
  
يتوافق مع الحقل <nowiki>[[RequestedModules]]</nowiki> في سجلات وحدة نص المصدر في مواصفات ECMAScript.
+
*<code>referencingModule</code> وهو كائن <code>Module</code> الذي يُستدعَى عليه التابع <code>link()‎</code>.
 +
والمتوقع من الدالة إعادة كائن <code>Module</code> أو كائن <code>Promise</code> الذي يُحَل إلى كائن <code>Module</code> في نهاية المطاف. يجب أن يلبي الكائن <code>Module</code> المُعاد الثابتين التالييَن:
 +
*يجب أن ينتمي إلى نفس سياق كائن <code>Module</code> الأصل.
 +
*يجب ألَّا تصبح <code>linkingStatus</code> الخاصة بها <code>'errored'</code>.
 +
إذا كانت <code>linkingStatus</code> المُعادة والخاصة بالكائن <code>Module</code> هي <code>'unlinked'،</code> سيُستدعى هذا التابع بشكل متكرر علي <code>Module</code> المُعاد مع نفس الدالة <code>linker</code> المُعطاة.
  
=== module.error ===
+
يعيد <code>link()‎</code> الكائن <code>Promise</code> والذي سيُحل عندما تحل كافة مثيلات الربط إلى <code>Module</code> صالح، أو يُرفض إذا أجرت دالة الربط استثناءً أو أعادت <code>Module</code> غير صالح.
* من أي نوع من الأنواع <any>.
 
إذا كانت الحالة module.status بالقيمة 'errored'، تحتوي هذه الخاصية علي الاستثناء الذي أُجريَ بواسطة الوحدة أثناء التقييم. إذا كانت الحالة أي شيء آخر، سيؤدي الوصول إلى هذه الخاصية إلى إجراء استثناء.
 
  
لا يمكن استخدام القيمة undefined للحالات حيث لا يوجد إجراء استثناء بسبب الغموض المحتمل حولthrow undefined;.
+
تتوافق دالة الربط بشكل تقريبي مع عملية <code>[https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule HostResolveImportedModule]</code> المُجرَدة والمعرفة من قِبَل التطبيق في مواصفة ECMAScript مع بعض الاختلافات الرئيسية:
 +
*يُسمح لدالة الربط أن تكون غير متزامنة في حين أن <code>[https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule HostResolveImportedModule]</code> متزامن.
 +
*تُنفَّذ دالة الربط أثناء الربط، وهي أحد مراحل Node.js الخاصة قبل إنشاء المثيل، في حين يُستدعى <code>[https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule HostResolveImportedModule]</code> خلال إنشاء المثيل.
 +
يُعيد تطبيقُ <code>[https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule HostResolveImportedModule]</code> الفعليُ المستخدم أثناء إنشاء مثيل الوحدة الوحداتِ المرتبطة أثناء الربط. لأن عند هذه النقطة، تكون جميع الوحدات قد رُبطت بالكامل بالفعل، ويكون تطبيق <code>[https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule HostResolveImportedModule]</code> متزامنًا تمامًا كما في المواصفات.
 +
===<code>module.linkingStatus</code>===
 +
*من النوع <code>[[JavaScript/String|<string>]]</code>.
 +
حاله الربط الحالية للوحدة <code>module</code>. وستكون إحدي القيم التالية:
 +
*<code>'unlinked'</code>: لم يُستدعى <code>module.link()‎</code> بعد.
 +
*<code>'linking'</code>: أُستدعيَ <code>module.link()</code>‎، ولكن لم تُحل كل كائنات <code>Promise</code> المُعادة من قِبَل دالة الربط بعد.
 +
*<code>'linked'</code>: أُستدعيَ <code>module.link()</code>‎، ورُبطت جميع التبعيات بنجاح.
 +
*<code>'errored'</code>: أُستدعيَ <code>module.link()‎</code>، ولكن فشل أحد تبعياته علي الأقل  في الارتباط، إما لان دالة رد الاتصال أعادت <code>Promise</code> مرفوض، أو لأن <code>Module</code> الذي أعادته دالة رد الاتصال غير صالح.
 +
===<code>module.namespace</code>===
 +
*من النوع <code>[[JavaScript/Object|<Object>]]</code>.
 +
كائن مجال الأسماء للوحدة. وهو متاح فقط بعد اكتمال إنشاء المثيل (<code>module.instantiate()‎</code>).
  
يتوافق مع الحقل <nowiki>[[EvaluationError]]</nowiki> في سجلات وحدة نص المصدر في مواصفات ECMAScript.
+
يتوافق مع عملية <code>[https://tc39.github.io/ecma262/#sec-getmodulenamespace GetModuleNamespace]</code> المجردة في مواصفة ECMAScript.
 +
===<code>module.status</code>===
 +
*من النوع <code>[[JavaScript/String|<string>]]</code>.
 +
الحالة الحالية للوحدة. وتكون واحدة من:
 +
*<code>'uninstantiated'</code>: لم يُنشأ مثيل للوحدة. قد يكون بسبب أيٍ من الأسباب التالية:
 +
**إنشاء الوحدة للتو.
 +
**استدعاء <code>module.instantiate()‎</code> علي هذه الوحدة ولكنه فشل لسبب ما.
 +
لا تنقل هذه الحالة أيَّة معلومات تتعلق بإذا كان التابع <code>module.link()</code>‎ قد أستُدعيَ أم لا. راجع <code>module.linkingstatus</code>.
 +
*<code>'instantiating'</code>: يُنشأ حاليًا مثيل الوحدة من خلال استدعاء <code>module.instantiate()‎</code> علي نفسه أو على وحدة أصل.
 +
*<code>'instantiated'</code>: نجح إنشاء مثيل للوحدة، ولكن لم يستدعى التابع <code>module.evaluate()</code>‎ حتى الآن.
 +
*<code>'evaluating'</code>: يُقيَّم مثيل الوحدة من خلال استدعاء <code>module.evaluate()‎</code> علي نفسه أو على وحدة أصل.
 +
*<code>'evaluated'</code>: نجح تقييم الوحدة.
 +
*<code>'errored'</code>: قُيّمت وحدة، ولكن أُجريَ استثناء.
 +
بخلاف <code>'errored'</code>، تتوافق سلسلة هذه الحالة مع مواصفات [https://tc39.github.io/ecma262/#sec-source-text-module-records حقل سجل وحدة نَص المصدر] <code><nowiki>[[Status]]</nowiki></code>. ويتوافق <code>'errored'</code> مع <code>'evaluated'</code> من حيث المواصفات، لكن يُضبط مع <code><nowiki>[[EvaluationError]]</nowiki></code> بقيمة غير <code>undefined</code>.
 +
===module.url===
 +
*من النوع <code>[[JavaScript/String|<string>]]</code>.
 +
عنوان URL الخاص بالوحدة الحالية، كما هو محدد في المُنشِئ.
 +
==الصنف: <code>vm.Script</code>==
 +
أضيف مع الإصدار: v0.3.1.
  
=== وحدة نمطية.تقييم([خيارات]) ===
+
يحتوي مثيلات الصنف <code>vm.Script</code> علي سكريبتات مترجمة مسبقا والتي يمكن تنفيذها في بيئات تجريبية معزولة (sandboxes) (أو "سياقات") معينة.
* options من النوع  <Object>.
+
===<code>new vm.Script(code, options)‎</code>===
** timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة للتقييم قبل إنهاء التنفيذ. إذا تمت مقاطعة التنفيذ، سينطلق Error.
+
*<code>code</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو شيفرة JavaScript المراد ترجمتها.
** breakOnSigint من النوع <boolean>، إذا كان true، سينتهي التنفيذ عند تلقي SIGINT (أو Ctrl + C). ستُعَّطل المعالجات الموجودة للحدث الذي أُرفِق بواسطة process.on('SIGINT') أثناء تنفيذ السكريبت، ولكنها سوف تستمر في العمل بعد ذلك. إذا تمت مقاطعة التنفيذ، سينطلق Error.
+
*<code>options</code>
* القيمة المُعادة: من النوع <Promise>.
+
**<code>filename</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو يحدد اسم الملف المستخدم في تتبُعات المكدس المُنتَجة بواسطة هذا السكريبت.
تقييم الوحدة.
+
**<code>lineOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم السطر المعروض في تتبُعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>columnOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم العمود المعروض في تتبُعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>cachedData</code> من النوع <code>[[Node.js/buffer|<Buffer>]]</code> وهو يوفر <code>Buffer</code> اختياري مع بيانات مؤقتة لشيفرة V8 للمصدر المُعطى. عند توفيرها، ستُضبط قيمة <code>cacheddatarejected</code> على <code>true</code> أو <code>false</code> تبعًا لقبول البيانات بواسطة V8.
 +
**<code>produceCachedData</code> من النوع <code>[[JavaScript/Boolean|<boolean>]]</code>. عندما يكون <code>true</code> ولا يوجد <code>cachedData</codeسيحاول V8 إنتاج بيانات مؤقتة لشيفرة <code>code</code>. عند النجاح، سينتَج <code>Buffer</code> مع بيانات مؤقتة لشيفرة V8 ويُخزَّن في الخاصية <code>cacheddata</code> لمثيل <code>vm.Script</code> المُعاد. ستُضبط قيمة <code>cacheddataproduced</code> على <code>true</code> أو <code>false</code> استنادا إلى ما إذا كانت البيانات المؤقتة للشيفرة قد أُنتِجت بنجاح أم لا. أهمِل هذا الخيار لصالح التابع<code>script.createCachedData()‎</code>.
 +
إنشاء كائن <code>vm.Script</code> جديد يُترجم <code>code</code> ولكن لا يُنفذها. يمكن تنفيذ <code>vm.Script</code> المُترجَم لاحقًا عدة مرات. لا يرتبط <code>code</code> بأي كائن عام، ولكن بدلًا من ذلك، فانه يرتبط قبل كل تشغيل، فقط لهذا التشغيل.
 +
===<code>script.createCachedData()‎</code>===
 +
أضيف مع الإصدار: v10.6.0.
 +
*القيمة المُعادة: من النوع <code>[[Node.js/buffer|<Buffer>]]</code>.
 +
إنشاء تخزين مؤقت للشيفرة البرمجية التي يمكن استخدامها مع خيار سكريبت المُنشِئ <code>cachedData</code>. يُعيد مخزن مؤقت. قد يستدعى هذا التابع في أي وقت ولأي عدد من المرات.<syntaxhighlight lang="javascript">
 +
const script = new vm.Script(`
 +
function add(a, b) {
 +
  return a + b;
 +
}
  
يجب استدعاءه بعد إنشاء مثيل الوحدة؛ وإلا فانه سيُطلق خطأ. ويمكن استدعاؤه أيضًا عند تقييم الوحدة بالفعل، وفي هذه الحالة سيقوم بأحد الأمرين التاليين:
+
const x = add(1, 2);
* إعادة undefined إذا انتهى التقييم الأولي بنجاح (module.status تكون 'evaluated').
+
`);
* أعادة إجراء الاستثناء نفسه الذي أجراه التقييم الأولي إذا أُنهيَ التقييم الأولي في خطأ (module.status تكون 'errored').
 
لا يمكن استدعاء هذا التابع أثناء تقييم الوحدة (module.status تكون 'evaluating') لمنع لانهائية العودية.
 
  
يتوافق مع حقل التابع Evaluate()‎ المتماسك من سجلات وحدة نص المصدر في مواصفات ECMAScript.
+
const cacheWithoutX = script.createCachedData();
  
=== module.instantiate()‎ ===
+
script.runInThisContext();
إنشاء مثيل للوحدة. يجب استدعاءه بعد إنهاء الربط (linkingStatus تكون 'linked').؛ وإلا فانه سيُطلق خطأ. كما يجوز إجراء استثناء إذا لم يوفر أحد التبعيات التصدير الذي تتطلبه الوحدة الأصل.
 
  
ومع ذلك، إذا نجحت هذه الدالة، ستكون الاستدعاءات اللاحقة لهذه الدالة بعد الإنشاء الأولي لمثيل هو no-ops، لتكون متناسقة مع مواصفات ECMAScript.
+
const cacheWithX = script.createCachedData();
 +
</syntaxhighlight>
 +
===<code>script.runInContext(contextifiedSandbox[, options])‎</code> [https://github.com/nodejs/node/blob/8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b/lib/vm.js#L100 <nowiki>[المصدر]</nowiki>]===
 +
سجل التغييرات
 +
{| class="wikitable"
 +
!الإصدار
 +
!التغييرات
 +
|-
 +
|v6.3.0
 +
|بداية دعم <code>breakOnSigint</code>.
 +
|-
 +
|v0.3.1
 +
|أضيف مع الإصدار: v0.3.1
 +
|}
 +
*<code>contextifiedSandbox</code> من النوع <code>[[JavaScript/Object|<Object>]]</code>، وهو الكائن الموضوع في السياق كما أُعيد من قبل التابع <code>vm.createContext()</code>‎.
 +
*<code>options</code> من النوع<code>[[JavaScript/Object|<Object>]]</code>.
 +
**<code>filename</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 +
**<code>lineOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**columnOffset من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**displayErrors من النوع <code>[[JavaScript/Boolean|<boolean>]]</code>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 +
**<code>timeout</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد عدد المللي ثانية اللازمة لتنفيذ <code>code</code> قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق <code>[[Node.js/error|Error]]</code>.
 +
**<code>breakOnSigint</code> من النوع <code>[[JavaScript/Boolean|<boolean>]]</code>، إذا كان <code>true</code>، سينتهي التنفيذ عند تلقي <code>SIGINT</code> (أو Ctrl + C). ستُعَّطل المعالجات الموجودة للحدث الذي أُرفِق بواسطة <code>process.on('SIGINT')‎</code> أثناء تنفيذ السكريبت، ولكنها سوف تستمر في العمل بعد ذلك. إذا انتهى التنفيذ، سينطلق <code>[[Node.js/error|Error]]</code>.
 +
تشغيل التعليمات البرمجية المترجَمة الواردة في كائن <code>vm.Script</code> داخل <code>contextifiedSandbox</code> المُعطَى وإعادة النتيجة. ليس لدى الشيفرة الجاري تشغيلها الحق في الوصول إلى النطاق المحلي.
 +
 
 +
يُترجم المثال التالي الشيفرة البرمجية التي تُزيد متغيرًا عامًا، ويضبط قيمة متغيرٍ عامٍ آخر، ثم يُنفذ التعليمات البرمجية عده مرات. المتغيرات العامة مضمنة في الكائن <code>sandbox</code>.<syntaxhighlight lang="javascript">
 +
const util = require('util');
 +
const vm = require('vm');
 +
 
 +
const sandbox = {
 +
  animal: 'cat',
 +
  count: 2
 +
};
  
علي عكس التوابع الأخرى التي تعمل علي Module، تكمل هذه الدالة بشكل متزامن ولا تقوم بإعادة أي شيء.
+
const script = new vm.Script('count += 1; name = "kitty";');
  
يتوافق مع حقل التابع Instantiate()‎ المتماسك من سجلات وحدة نص المصدر في مواصفات ECMAScript.
+
const context = vm.createContext(sandbox);
 +
for (let i = 0; i < 10; ++i) {
 +
  script.runInContext(context);
 +
}
  
=== module.link (linker) ===
+
console.log(util.inspect(sandbox));
* linker من النوع <Function>.
 
* القيمة المُعادة: من النوع <Promise>.
 
ربط تبعيات الوحدة. يجب استدعاء هذا التابع قبل إنشاء مثيل، ويمكن استدعاؤه مره واحدهة فقط لكل وحدة.
 
  
سيمرر معاملين إلى الدالة linker:
+
// { animal: 'cat', count: 12, name: 'kitty' }
* specifier وهو محدد الوحدة المطلوبة:
+
</syntaxhighlight>سيؤدي استخدام الخيارات <code>timeout</code> أو <code>breakOnSigint</code> إلى حلقات حدث جديد وبدء الخيوط المقابلة، والتي يكون لها عبء أداء (performance overhead) غير صفري.
// ^^^^^ محدد الوحدة
+
===<code>script.runInNewContext([sandbox[, options]])‎</code> [https://github.com/nodejs/node/blob/8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b/lib/vm.js#L111 <nowiki>[المصدر]</nowiki>]===
* referencingModule وهو كائن Module الذي يستدعى عليه التابع link()‎.
+
سجل التغييرات
والمتوقع من الدالةإعادة كائن Module أو Promise والذي يحل إلى كائن Module في نهاية المطاف. يجب أن يلبي الكائن Module المُعاد الثابتين التالييَن:
+
{| class="wikitable"
* ويجب أن ينتمي إلى نفس سياق كائن Module الأصل.
+
!الإصدار
* ولا يجب أن تصبح linkingStatus الخاصة بها 'errored'.
+
!التغييرات
إذا كانت linkingStatus المُعادة والخاصة بالكائن Module هي 'unlinkedسيستدعى هذا التابع بشكل متكرر علي Module المُعاد مع نفس الدالة linker المُعطاة.
+
|-
 +
|v10.0.0
 +
|بداية دعم <code>contextCodeGeneration</code>.
 +
|-
 +
|v0.3.1
 +
|أضيف مع الإصدار: v0.3.1.
 +
|}
 +
*<code>sandbox</code> من النوع<code>[[JavaScript/Object|<Object>]]</code> وهو الكائن المراد وضعه في السياق. إذا كان <code>undefined</code>، سينشأ كائن جديد.
 +
*<code>options</code> من النوع <code>[[JavaScript/Object|<Object>]]</code>.
 +
**<code>filename</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 +
**<code>lineOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>columnOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>displayErrors</code> من النوع <code>[[JavaScript/Boolean|<boolean>]]</code>، عندما يكون <code>true</code>، إذا حدث خطأ <code>[[Node.js/error|Error]]</code> أثناء ترجمة <code>code</code>، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 +
**<code>timeout</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد عدد المللي ثانية اللازمة لتنفيذ <code>code</code> قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق <code>[[Node.js/error|Error]]</code>.
 +
**<code>contextName</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو اسم قابل للقراءة للسياق المُنشَأ حديثًا. القيمة الافتراضية: <code>'VM Context i'</code>، حيث <code>i</code> هو مؤشر تصاعدي عددي للسياق المُنشَأ.
 +
**<code>contextOrigin</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو الأصل [https://developer.mozilla.org/en-US/docs/Glossary/Origin Origin] المقابل للسياق المُنشَأ حديثًا لأغراض العرض. يجب ان يكون تنسيق الأصل مثل URL، ولكن فقط مع المخطَط، والمضيف، والمَنفذ (إذا لزم الأمر)، مثل قيمة الخاصية <code>[[Node.js/url|url.origin]]</code> لكائن [[Node.js/url|URL]]. والاهم من ذلك، يجب حذف الشرطة المائلة اللاحقة، إذ إنها تشير إلى مسار. القيمة الافتراضية: <code><nowiki>''</nowiki></code>.
 +
**<code>contextCodeGeneration</code> القيمة المُعادة <code>[[JavaScript/Object|<Object>]]</code>.
 +
***<code>strings</code> من النوع <code>[[JavaScript/Boolean|<boolean>]]</code> إذا ضُبط على <code>false</code> سيُطلِق أي استدعاء إلى <code>eval</code> أو لمنشئات الدالة (<code>Function</code> و <code>GeneratorFunction</code>، الخ) خطأ <code>EvalError</code>. القيمة الافتراضية: <code>true</code>.
 +
***<code>wasm</code> من نوع <code>[[JavaScript/Boolean|<boolean>]]</code>، إذا ضُبط على <code>false</code> ستُطلِق أي محاولة لترجمة وحدة WebAssembly الخطأ <code>WebAssembly.CompileError</code>. القيمة الافتراضية: <code>true</code>.
 +
يضع أولا كائن <code>sandbox</code> المعطى في السياق، ثم ينفذ الشيفرة البرمجية المترجمة الواردة في كائن <code>vm.Script</code> الوارد في كائن sandbox المُنشَأ، وإعادة النتيجة. ليس لدى الشيفرة الجاري تشغيلها الحق في الوصول إلى النطاق المحلي.
  
يعيد link()‎ الوعد Promise والذي سيُحل عندما تحل كافة مثيلات الربط إلى Module صالح، أو يرفض إذا أجرت دالة الربط استثناءً أو أعادت Module غير صالح.
+
يُترجم المثال التالي الشيفرة البرمجية التي تضبط قيمة متغيرٍ عام، ثم يُنفذ التعليمات البرمجية عده مرات في عدة سياقات. تُضبط المتغيرات العامة وترِد ضمن كل <code>sandbox</code> فردي.<syntaxhighlight lang="javascript">
 +
const util = require('util');
 +
const vm = require('vm');
  
تتوافق دالة الربط بشكل تقريبي مع عملية HostResolveImportedModule المجردة والمعرفة من قِبَل التطبيق في مواصفة ECMAScript مع بعض الاختلافات الرئيسية:
+
const script = new vm.Script('globalVar = "set"');
* يُسمح لدالة رابط أن تكون غير متزامنة في حين أن HostResolveImportedModule متزامن.
 
* تُنفَّذ دالة الربط أثناء الربط، وهي أحد مراحل Node.js hgohwm قبل إنشاء المثيل، في حين يُستدعى HostResolveImportedModule خلال إنشاء المثيل.
 
يُعيد تطبيق HostResolveImportedModule الفعلي المستخدم أثناء إنشاء مثيل الوحدة الوحدات المرتبطة أثناء الربط. لأن في هذه النقطة، تكون جميع الوحدات قد رُبطت بالكامل بالفعل، ويكون تطبيق HostResolveImportedModule متزامنًا تمامًا كما في المواصفات.
 
  
=== module.linkingStatus ===
+
const sandboxes = [{}, {}, {}];
* من النوع <string>.
+
sandboxes.forEach((sandbox) => {
حاله الربط الحالية للوحدة module. وستكون إحدي القيم التالية:
+
  script.runInNewContext(sandbox);
* 'unlinked': لم يُستدعى module.link()‎ بعد.
+
});
* 'linking': أُستدعيَ module.link()‎، ولكن لم تُحل كل Promises المُعادة من قِبَل دالة الربط بعد.
 
* 'linked': أُستدعيَ module.link()‎، ورُبطت جميع التبعيات بنجاح.
 
* 'errored': أُستدعيَ module.link()‎، ولكن أحد تبعياته علي الأقل فشل في الارتباط، إما لان دالة رد الاتصال أعادت Promise مرفوض، أو لأن Module الذي أعادته دالة رد الاتصال غير صالحة.
 
  
=== module.namespace ===
+
console.log(util.inspect(sandboxes));
* من النوع <Object>.
 
كائن مجال الأسماء للوحدة. وهو مناح فقط بعد اكتمال إنشاء المثيل (module.instantiate()).
 
  
يتوافق مع عملية GetModuleNamespace المجردة في مواصفة ECMAScript.
+
// [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }]
 +
</syntaxhighlight>
 +
===<code>script.runInThisContext([options])‎</code> [https://github.com/nodejs/node/blob/8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b/lib/vm.js#L91 <nowiki>[المصدر]</nowiki>]===
 +
أضيف مع الإصدار: v0.3.1.
 +
*<code>options</code> من النوع <code>[[JavaScript/Object|<Object>]]</code>.
 +
**<code>filename</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 +
**<code>lineOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>columnOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>displayErrors</code> من النوع <code>[[JavaScript/Boolean|<boolean>]]</code>، عندما يكون <code>true</code>، إذا حدث خطأ <code>[[Node.js/error|Error]]</code> أثناء ترجمة <code>code</code>، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 +
**<code>timeout</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد عدد المللي ثانية اللازمة لتنفيذ <code>code</code> قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق <code>[[Node.js/error|Error]]</code>.
 +
يُنفذ هذا التابع الشيفرة البرمجية المترجمة المضمنة في <code>vm.Script</code> ضمن سياق الكائن <code>global</code> الحالي. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي ولكن لديها حق الوصول إلى الكائن <code>global</code> الحالي.
  
=== module.status ===
+
يُترجم المثال التالي الشيفرة البرمجية التي تُزيد متغير <code>global</code>، ثم يُنفذ التعليمات البرمجية عدة مرات:<syntaxhighlight lang="javascript">
* من النوع <string>.
+
const vm = require('vm');
الحالة الحالية للوحدة. سوف تكون واحدة من:
 
* 'uninstantiated': لم يُنشأ مثيل للوحدة. قد يكون بسبب أيٍ من الأسباب التالية:
 
** إنشاء الوحدة للتو.
 
** استدعاء module.instantiate()‎ علي هذه الوحدة ولكن فشل لسبب ما.
 
لا ينقل هذا الوضع أيَّة معلومات تتعلق بإذا كان التابع module.link()‎ قد أستُدعيَ. راجع module.linkingstatus.
 
* 'instantiating': يُنشأ حاليًا مثيل الوحدة من خلال استدعاء module.instantiate()‎ علي نفسه أو على وحدة أصل.
 
* 'instantiated': نجح إنشاء مثيل للوحدة، ولكن لم يستدعى التابع module.evaluate()‎ حتى الآن.
 
* 'evaluating': يُقيَّم مثيل الوحدة من خلال استدعاء module.evaluate()‎ علي نفسه أو على وحدة أصل.
 
* 'evaluated': نجح تقييم الوحدة.
 
* 'errored': قُيّمت وحدة، ولكن أُجريَ استثناء.
 
بخلاف 'errored'، تتوافق سلسلة هذه الحالة مواصفات حقل سجل وحدة نَص المصدر <nowiki>[[Status]]</nowiki>. ويتوافق 'errored' مع 'evaluated' من حيث المواصفات، لكن يُضبط مع <nowiki>[[EvaluationError]]</nowiki> بقيمة غير undefined.
 
  
=== module.url ===
+
global.globalVar = 0;
* من النوع <string>.
 
عنوان URL الخاص بالوحدة الحالية، كما هو محدد في المُنشِئ.
 
  
== الصنف: vm.Script ==
+
const script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' });
أضيف مع الإصدار: v0.3.1.
 
  
تحتوي مثيلات  الصنف vm.Script علي سكريبتات مترجمة مسبقا والتي يمكن تنفيذها في بيئات معزولة (sandboxes) (أو "سياقات") معينة.
+
for (let i = 0; i < 1000; ++i) {
 +
  script.runInThisContext();
 +
}
  
=== new vm.Script(code, options) ===
+
console.log(globalVar);
* code من النوع <string> وهو شيفرة JavaScript المراد ترجمتها.
 
* options
 
** filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 
** lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** cachedData من النوع <Buffer> وهو يوفرBuffer اختياري مع بيانات مؤقتة لشيفرة V8 للمصدر المُعطى. عند توفيرها، ستُضبط قيمة cacheddatarejected على true أو false اعتمادًا علي قبول البيانات بواسطة V8.
 
** produceCachedData من النوع <boolean>. عندما يكون true ولا يوجد cachedData، سيحاول V8 إنتاج بيانات مؤقتة لشيفرة code. عند النجاح، سينتَج Buffer مع بيانات مؤقتة لشيفرة V8 ويُخزَّن في الخاصية cacheddata من مثيل vm.Script المُعاد. ستُضبط قيمة cacheddataproduced على true أو false استنادا إلى ما إذا البيانات المؤقتة للشيفرة قد أُنتجت بنجاح أم لا. تم إهمال هذا الخيار لصالح script.createCachedData()‎.
 
إنشاء كائن vm.Script جديد يُترجم code ولكن لا يُنفذها. يمكن تنفيذ vm.Script المُترجَم لاحقًا عدة مرات. لا يرتبط code إلى أي كائن عام، ولكن بدلا من ذلك، فانه يرتبط قبل كل تشغيل، فقط لهذا التشغيل.
 
  
=== script.createCachedData()‎ ===
+
// 1000
أضيف مع الإصدار: v10.6.0.
+
</syntaxhighlight>
* القيمة المُعادة: من النوع <Buffer>.
+
==<code>vm.compileFunction(code[, params[, options]])‎</code> [https://github.com/nodejs/node/blob/8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b/lib/vm.js#L306 <nowiki>[المصدر]</nowiki>]==
إنشاء تخزين مؤقت للشيفرة البرمجية التي يمكن استخدامها مع خيار سكريبت المُنشِئ cachedData. يُعيد مخزن مؤقت. قد يستدعى هذا التابع في أي وقت ولأي عدد من المرات.
+
أُضيف مع الإصدار: v10.10.0.
 +
*<code>code</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو متن الدالة المراد ترجمتها.
 +
*<code>params</code> من النوع <code>[[JavaScript/String|<string[]‎>]]</code> وهو مصفوفة من السلاسل النصية التي تحتوي على جميع المعاملات للدالة.
 +
*<code>options</code> من النوع <code>[[JavaScript/Object|<Object>]]</code>.
 +
**<code>filename</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت. القيمة الافتراضية: <code><nowiki>''</nowiki></code>.
 +
**<code>lineOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت. القيمة الافترضية: <code>0</code>.
 +
**<code>columnOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت. القيمة الافتراضية: <code>0</code>.
 +
**<code>cachedData</code> من النوع <code>[[Node.js/buffer|<Buffer>]]</code> وهو يوفرBuffer اختياري مع بيانات مؤقتة لشيفرة V8 للمصدر المُعطى.
 +
**<code>producecacheddata</code> من النوع<code>[[JavaScript/Boolean|<boolean>]]</code>، وهو يحدد ما إذا كان ستُنتَج بيانات مؤقتة جديدة. القيمة الافتراضية: <code>false</code>.
 +
**<code>parsingContext</code> من النوع <code>[[JavaScript/Object|<boolean>]]</code> وهو sandbox/السياق الذي يجب ترجمة الدالة المعنية فيه.
 +
**<code>contextExtensions</code> من النوع <code>[[JavaScript/Object|<Object[]‎>]]</code> وهو مصفوفة تحتوي علي مجموعة من ملحقات السياق (كائنات تلتف حول النطاق الحالي) لتطبيقها أثناء الترجمة. القيمة الافتراضية: <code>[]</code>.
 +
ترجمة الشيفرة البرمجية المعطاة إلى السياق/sanbox المتوفر (إذا لم يتوفر أي سياق، يستخدم السياق الحالي)، ويقوم بإعادتها ملفوفَا داخل دالة مع <code>params</code> المُعطي.
 +
==<code>vm.createContext([sandbox[, options]])</code>‎ [https://github.com/nodejs/node/blob/8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b/lib/vm.js#L217 <nowiki>[المصدر]</nowiki>]==
 +
سجل التغييرات
 +
{| class="wikitable"
 +
!الإصدار
 +
!التغييرات
 +
|-
 +
|v10.0.0
 +
|لا يمكن أن يكون الخيار <code>sandbox</code> دالة بعد الآن.
 +
|-
 +
|v10.0.0
 +
|بداية دعم <code>codeGeneration</code>.
 +
|-
 +
|v0.3.1
 +
|أضيف مع الإصدار: v0.3.1
 +
|}
 +
*<code>sandbox</code> من النوع <code>[[JavaScript/Object|<boolean>]]</code>.
 +
*<code>options</code> من النوع <code>[[JavaScript/Object|<boolean>]]</code>.
 +
**<code>name</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو اسم قابل للقراءة للسياق المُنشَأ حديثًا. القيمة الافتراضية: <code>'VM Context i'</code>، حيث <code>i</code> هو مؤشر تصاعدي عددي للسياق المُنشَأ.
 +
**<code>origin</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو الأصل [https://developer.mozilla.org/en-US/docs/Glossary/Origin Origin] المقابل للسياق المُنشَأ حديثًا لأغراض العرض. يجب ان يكون تنسيق الأصل مثل URL، ولكن فقط مع المخطَط، والمضيف، والمَنفذ (إذا لزم الأمر)، مثل قيمة الخاصية <code>[[Node.js/url|url.origin]]</code> لكائن <code>[[Node.js/url|URL]]</code>. والاهم من ذلك، يجب حذف الشرطة المائلة اللاحقة، إذ إنها تشير إلى مسار. القيمة الافتراضية: <code><nowiki>''</nowiki></code>.
 +
**<code>codeGeneration</code> من النوع <code>[[JavaScript/Object|<Object>]]</code>.
 +
***<code>strings</code> من النوع <code>[[JavaScript/Boolean|<boolean>]]</code> إذا ضُبط على <code>false</code> سيُطلِق أي استدعاء إلى <code>eval</code> أو لمنشئات الدالة (<code>Function</code> و <code>GeneratorFunction</code>، الخ) خطأ <code>EvalError</code>. القيمة الافتراضية: <code>true</code>.
 +
***<code>wasm</code> من نوع <code>[[JavaScript/Boolean|<boolean>]]</code> إذا ضُبط على false ستُطلِق أي محاولة لترجمة وحدة WebAssembly الخطأ <code>WebAssembly.CompileError</code>. القيمة الافتراضية: <code>true</code>.
 +
إذا أُعطي كائن <code>sandbox</code>، سيُحضِـر التابع <code>vm.createContext()‎</code> كائن sandbox هذا بحيث يمكن استخدامه في استدعاء <code>vm.runInContext()‎</code> أو <code>script.runInContext()‎</code>. داخل مثل هذه السكريبتات، سيكون كائن <code>sandbox</code> هو الكائن العام، محتفظًا بكافة خصائصه الموجودة ولكنه يمتلك أيضا الكائنات المضمنة والدوال التي يمتلكها أي [https://es5.github.io/#x15.1 كائن عام] قياسي. فيما عدا السكريبتات التي تُنفَّذ بواسطة الوحدة vm، ستبقي المتغيرات العامة دون تغيير.<syntaxhighlight lang="javascript">
 +
const util = require('util');
 +
const vm = require('vm');
  
=== script.runInContext(contextifiedSandbox[, options]) [المصدر] ===
+
global.globalVar = 3;
* contextifiedSandbox من النوع <object>، وهو الكائن الموضوع في السياق كما أُعيد من قبل التابع vm.createContext()‎.
 
* options من النوع  <Object>.
 
** filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 
** lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 
** timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا أنهي التنفيذ، سينطلقError.
 
** breakOnSigint من النوع <boolean>، إذا كان true، سينتهي التنفيذ عند تلقي SIGINT (أو Ctrl + C). ستُعَّطل المعالجات الموجودة للحدث الذي أُرفِق بواسطة process.on('SIGINT') أثناء تنفيذ السكريبت، ولكنها سوف تستمر في العمل بعد ذلك. إذا أنهي التنفيذ، سينطلقError.
 
تشغيل التعليمات البرمجية المترجمة الوردة في كائن vm.Script داخل contextifiedSandbox المعطى وإعادة النتيجة. ليس لدى الشيفرة الجاري تشغيلها الحق في الوصول إلى النطاق المحلي.
 
  
يُترجم المثال التالي الشيفرة البرمجية التي تُزيد متغير عام، ويضبط قيمة متغير عام آخر، ثم يُنفذ التعليمات البرمجية عده مرات. المتغيرات العامة مضمنة في الكائن sandbox.
+
const sandbox = { globalVar: 1 };
 +
vm.createContext(sandbox);
  
سيؤدي استخدام الخيارات timeout أو breakOnSigint إلى حلقات حدث جديد وبدء الخيوط المقابلة، والتي يكون لها عبء أداء (performance overhead) غير صفري.
+
vm.runInContext('globalVar *= 2;', sandbox);
  
=== script.runInNewContext([sandbox[, options]]) [المصدر] ===
+
console.log(util.inspect(sandbox)); // { globalVar: 2 }
* sandbox من النوع <Object> وهو الكائن المراد وضعه في السياق. إذا كان undefined ، سينشأ كائن جديد.
 
* options من النوع  <Object>.
 
** filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 
** lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 
** timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا أنهي التنفيذ، سينطلقError.
 
** contextName من النوع <string> وهو اسم قابل للقراءة للسياق المُنشَأ حديثًا. القيمة الافتراضية: 'VM Context i'، حيث i هو مؤشر تصاعدي عددي للسياق المُنشَأ.
 
** contextOrigin من النوع <string> وهو الأصل المقابل للسياق المُنشَأ حديثًا لأغراض العرض. يجب ان يكون تنسيق الأصل مثل URL، ولكن فقط مع المخطَط، والمضيف ، والمنفذ (إذا لزم الأمر) ، مثل قيمة الخاصية url.originلكائن URL. والاهم من ذلك، يجب حذف الشرطة المائلة اللاحقة، إذ إنها تشير إلى مسار. القيمة الافتراضية: <nowiki>''</nowiki>.
 
** contextCodeGenerationالقيمة المُعادة <Object>.
 
*** strings من النوع <boolean> إذا ضُبط على false سيُطلِق أي استدعاء إلى eval أو لمنشئات الدالة (Function و GeneratorFunction ، الخ) خطأ EvalError. القيمة الافتراضية: true.
 
*** wasm من نوع <boolean> إذا ضُبط على false ستُطلِق أي محاولة لترجمة وحدة WebAssembly الخطأ WebAssembly.CompileError. القيمة الافتراضية: true.
 
يضع أولا sandbox المعطى في السياق، ثم ينفذ الشيفرة البرمجية المترجمة الواردة في كائن vm.Script الوارد في sandbox المُنشَأ، وإعادة النتيجة. ليس لدى الشيفرة الجاري تشغيلها الحق في الوصول إلى النطاق المحلي.
 
  
يُترجم المثال التالي الشيفرة البرمجية التي تضبط قيمة متغير عام، ثم يُنفذ التعليمات البرمجية عده مرات في عدة سياقات. تُضبط المتغيرات العامة وترِد ضمن كل sandbox فردي.
+
console.log(util.inspect(globalVar)); // 3
 +
</syntaxhighlight>إذا حُذِف <code>sandbox</code> (أو مُرِر بشكل صريح كـ <code>undefined</code>)، سيعاد كائن sandbox جديد فارغ موضوع في السياق.
  
=== script.runInThisContext([options]) [المصدر] ===
+
ويفيد التابع <code>vm.createContext()</code> في المقام الأول في إنشاء sandbox منفرد والذي يمكن استخدامه لتشغيل عدة سكريبتات. علي سبيل المثال، في حالة محاكاة متصفح ويب، يمكن استخدام التابع لإنشاء sandbox منفرد يمثل كائن عام للإطار، ثم لتشغيل كافة وسوم <code><script></code> معا ضمن سياق كائن sandbox هذا.
أضيف مع الإصدار: v0.3.1.
 
* options من النوع  <Object>.
 
** filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 
** lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 
** timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا أنهي التنفيذ، سينطلقError.
 
تشغيل الشيفرة البرمجية المترجمة المضمنة في vm.Script ضمن سياق الكائن global الحالي. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي ولكن لديه حق الوصول إلى الكائن global الحالي.
 
  
يُترجم المثال التالي الشيفرة البرمجية التي تُزيد متغير global، ثم يُنفذ التعليمات البرمجية عده مرات.
+
ويُجعَل <code>name</code> و <code>origin</code> السياق المتوفرَين مرئيـيَن من خلال مفتش API.
 +
==vm.isContext(sandbox)‎ [https://github.com/nodejs/node/blob/8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b/lib/vm.js#L209 <nowiki>[المصدر]</nowiki>]==
 +
أضيف مع الإصدار: v 0.11.7.
 +
*<code>sandbox</code> من النوع <code>[[JavaScript/Object|<Object>]]</code>.
 +
*القيمة المُعادة: من النوع <code>[[JavaScript/Boolean|<boolean>]]</code>.
 +
يُعيد <code>true</code> إذا وُضِع كائن <code>sandbox</code> المُعطي في السياق باستخدام <code>vm. createcontext()</code>‎‎.
 +
==vm.runInContext(code, contextifiedSandbox[, options])‎ [https://github.com/nodejs/node/blob/8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b/lib/vm.js#L272 <nowiki>[المصدر]</nowiki>]==
 +
*<code>code</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو شيفرة JavaScript المراد ترجمتها وتنفيذها.
 +
*<code>contextifiedSandbox</code> من النوع <code>[[JavaScript/Object|<Object>]]</code>، وهو الكائن الموضوع في السياق المستخدام كمتغير global عند ترجمة code وتشغيله.
 +
*<code>options</code> من النوع ‎<code>[[JavaScript/Object|<Object>]]</code> | <code>[[JavaScript/String|<string>‎]]</code>.
 +
**<code>filename</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 +
**<code>lineOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>columnOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>displayErrors</code> من النوع [[JavaScript/Number|<number>]]، عندما يكون <code>true</code>، إذا حدث خطأ <code>[[Node.js/error|Error]]</code> أثناء ترجمة <code>code</code>، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 +
**<code>timeout</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد عدد المللي ثانية اللازمة لتنفيذ <code>code</code> قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق <code>[[Node.js/error|Error]]</code>.
 +
يترجم التابع <code>vm.runInContext()‎</code> الشيفرة code، وينفذها ضمن سياق <code>vm contextifiedSandbox</code>، ثم يعيد النتيجة. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي. يجب أن يكون كائن <code>contextifiedSandbox</code> موضوعا مسبقا في السياق باستخدام التابع <code>vm.createcontext()</code>‎‎.
  
== vm.compileFunction(code[, params[, options]]) [المصدر] ==
+
إذا كانت قيمة <code>options</code> سلسلة نصية، ثم تحدد اسم الملف.
أُضيف مع الإصدار: v10.10.0.
 
* code من النوع <string> وهو متن الدالة المراد ترجمتها.
 
* params من النوع <string[]> وهو مصفوفة من السلاسل النصية التي تحتوي على جميع المعاملات للدالة.
 
* options من النوع  <Object>.
 
** filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت. القيمة الافتراضية: <nowiki>''</nowiki>.
 
** lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت. القيمة الافترضية: 0.
 
** columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت. القيمة الافتراضية: 0.
 
** cachedData من النوع <Buffer> وهو يوفرBuffer اختياري مع بيانات مؤقتة لشيفرة V8 للمصدر المُعطى.
 
** producecacheddata من النوع <boolean>، وهو يحدد ما إذا كان ستُنتَج بيانات مؤقتة جديدة. القيمة الافتراضية: false.
 
** parsingContext من النوع <Object> وهو sandbox/السياق الذي يجب ترجمة الدالة المعنية فيه.
 
** contextExtensions من النوع < Object [] > وهو مصفوفة تحتوي علي مجموعة من ملحقات السياق (كائنات تلتف حول النطاق الحالي) لتطبيقها أثناء الترجمة. القيمة الافتراضية: [].
 
ترجمة الشيفرة البرمجية المعطاة إلى السياق/sanbox المتوفر (إذا لم يتوفر أي سياق ، يستخدم السياق الحالي) ، ويقوم بإرجاعها ملفوفَا داخل دالة مع params المعطي.
 
  
== vm.createContext([sandbox[, options]]) [المصدر] ==
+
يُترجم المثال التالي سكريبتات مختلفة وينفذها باستخدام كائن منفرد موضوع في السياق.<syntaxhighlight lang="javascript">
* sandbox من النوع <Object>.
+
const util = require('util');
* options من النوع  <Object>.
+
const vm = require('vm');
** name من النوع <string> وهو اسم قابل للقراءة للسياق المُنشَأ حديثًا. القيمة الافتراضية: 'VM Context i'، حيث i هو مؤشر تصاعدي عددي للسياق المُنشَأ.
 
** origin من النوع <string> وهو الأصل المقابل للسياق المُنشَأ حديثًا لأغراض العرض. يجب ان يكون تنسيق الأصل مثل URL، ولكن فقط مع المخطَط، والمضيف ، والمنفذ (إذا لزم الأمر) ، مثل قيمة الخاصية url.originلكائن URL. والاهم من ذلك، يجب حذف الشرطة المائلة اللاحقة، إذ إنها تشير إلى مسار. القيمة الافتراضية: <nowiki>''</nowiki>.
 
** codeGeneration من النوع <Object>
 
*** strings من النوع <boolean> إذا ضُبط على false سيُطلِق أي استدعاء إلى eval أو لمنشئات الدالة (Function و GeneratorFunction ، الخ) خطأ EvalError. القيمة الافتراضية: true.
 
*** wasm من نوع <boolean> إذا ضُبط على false ستُطلِق أي محاولة لترجمة وحدة WebAssembly الخطأ WebAssembly.CompileError. القيمة الافتراضية: true.
 
إذا أُعطي كائن sandbox، سيُحضِـر التابع vm.createContext()‎ كائن sandbox هذا بحيث يمكن استخدامه في استدعاء vm.runInContext()‎ أو script.runInContext()‎. داخل مثل هذه السكريبتات، سيكون كائن sandbox هو الكائن العام، محتفظًا بكافة خصائصه الموجودة ولكنه يمتلك أيضا الكائنات المضمنة والدوال التي يمتلكها أي كائن عام قياسي. فيما عدا السكريبتات التي تُنفَّذ بواسطة الوحدة vm، ستبقي المتغيرات العامة دون تغيير.
 
  
إذا حذف sandbox (أو مُرِر بشكل صريح كـ undefined)، سيعاد كائن sandbox جديد فارغ موضوع في السياق.
+
const sandbox = { globalVar: 1 };
 +
vm.createContext(sandbox);
  
ويفيد التابع vm.createContext()‎ في المقام الأول في إنشاء sandbox منفرد والذي يمكن استخدامه لتشغيل عدة سكريبتات. علي سبيل المثال، في حالة محاكاة متصفح ويب، يمكن استخدام التابع لإنشاء sandbox منفرد يمثل كائن عام للإطار ، ثم لتشغيل كافة وسوم <script> معا ضمن سياق هذا ال sandbox.
+
for (let i = 0; i < 10; ++i) {
 +
  vm.runInContext('globalVar *= 2;', sandbox);
 +
}
 +
console.log(util.inspect(sandbox));
  
ويُجعَل name و origin السياق المتوفرَين مرئيـيَن من خلال مفتش API.
+
// { globalVar: 1024 }
 +
</syntaxhighlight>
 +
==<code>vm.runInNewContext(code[, sandbox[, options]])‎</code> [https://github.com/nodejs/node/blob/8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b/lib/vm.js#L288 <nowiki>[المصدر]</nowiki>]==
 +
أضيف مع الإصدار: v0.3.1.
 +
*<code>code</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو شيفرة JavaScript المراد ترجمتها وتنفيذها.
 +
*<code>sandbox</code> من النوع <code>[[JavaScript/Object|<Object>]]</code> وهو الكائن المراد وضعه في السياق. إذا كان <code>undefined</code>، سينشأ كائن جديد.
 +
*<code>options</code> من النوع ‎<code>[[JavaScript/Object|<Object>]]</code> | <code>[[JavaScript/String|<string>‎]]</code>.
 +
**<code>filename</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 +
**<code>lineOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>columnOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 +
**<code>displayErrors</code> من النوع <code>[[JavaScript/Boolean|<boolean>]]</code>، عندما يكون <code>true</code>، إذا حدث خطأ <code>[[Node.js/error|Error]]</code> أثناء ترجمة <code>code</code>، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 +
**<code>timeout</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد عدد المللي ثانية اللازمة لتنفيذ <code>code</code> قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق <code>[[Node.js/error|Error]]</code>.
 +
**<code>contextName</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو اسم قابل للقراءة للسياق المُنشَأ حديثًا. القيمة الافتراضية: <code>'VM Context i'</code>، حيث <code>i</code> هو مؤشر تصاعدي عددي للسياق المُنشَأ.
 +
**<code>contextOrigin</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو الأصل المقابل للسياق المُنشَأ حديثًا لأغراض العرض. يجب ان يكون تنسيق الأصل مثل URL، ولكن فقط مع المخطَط، والمضيف، والمنفذ (إذا لزم الأمر)، مثل قيمة الخاصية <code>[[Node.js/url|url.origin]]</code> لكائن <code>[[Node.js/url|URL]]</code>. والاهم من ذلك، يجب حذف الشرطة المائلة اللاحقة، إذ إنها تشير إلى مسار. القيمة الافتراضية: <code><nowiki>''</nowiki></code>.
 +
يضع التابع <code>vm.runInNewContext()‎</code> أولا كائنَ <code>sandbox</code> المُعطى في السياق (أو ينشئ <code>sandbox</code> جديد إذا مُرر كـ <code>undefined</code>)، ويترجم <code>code</code>، وينفذه ضمن سياق السياق المُنشَأ، ثم يعيد النتيجة. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي.
  
== vm.isContext(sandbox) [المصدر] ==
+
إذا كانت قيمة <code>options</code> سلسلة نصية، ستُحدِد اسم الملف.
أضيف مع الإصدار: v 0.11.7.
 
* sandbox من النوع <Object>.
 
* القيمة المُعادة: من النوع <boolean>.
 
يُعيد true إذا وُضِع كائن sandbox المُعطي في السياق باستخدام vm. createcontext()‎‎.
 
  
== vm.runInContext(رمز ، contextifiedSandbox [خيارات]) [المصدر] ==
+
يُترجم المثال التالي شيفرة وينفذها والتي تُزيد متغيرًا عامًا وتضبط واحدًا جديدًا. المتغيرات العامة مضمنة في الكائن <code>sandbox</code>.<syntaxhighlight lang="javascript">
* code من النوع <string> وهو شيفرة JavaScript المراد ترجمتها وتنفيذها.
+
const util = require('util');
* contextifiedSandbox من النوع <Object>، وهو الكائن الموضوع في السياق المستخدام كمتغير global عند ترجمة code وتشغيله.
+
const vm = require('vm');
* options من النوع <Object> | <string>.
 
** filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 
** lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 
** timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا أنهي التنفيذ، سينطلقError.
 
يترجم التابع vm.runInContext()‎ الشيفرة code، وينفذها ضمن سياقvm contextifiedSandbox ، ثم يعيد النتيجة. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي. يجب أن يكون كائن contextifiedSandbox موضوعا مسبقا في السياق باستخدام التابع vm.createcontext()‎‎.
 
  
إذا كانت قيمة options سلسلة نصية، ثم تحدد اسم الملف.
+
const sandbox = {
 +
  animal: 'cat',
 +
  count: 2
 +
};
  
يُترجم المثال التالي سكريبتات مختلفة وينفذها باستخدام كائن منفرد موضوع في السياق.
+
vm.runInNewContext('count += 1; name = "kitty"', sandbox);
 +
console.log(util.inspect(sandbox));
  
== vm.runInNewContext(code[, sandbox[, options]]) [المصدر] ==
+
// { animal: 'cat', count: 3, name: 'kitty' }
 +
</syntaxhighlight>
 +
==<code>vm.runInThisContext(code[, options])‎</code> [https://github.com/nodejs/node/blob/8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b/lib/vm.js#L299 <nowiki>[المصدر]</nowiki>]==
 
أضيف مع الإصدار: v0.3.1.
 
أضيف مع الإصدار: v0.3.1.
* code من النوع <string> وهو شيفرة JavaScript المراد ترجمتها وتنفيذها.
+
*<code>code</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو شيفرة JavaScript المراد ترجمتها وتنفيذها.
* sandbox من النوع <Object> وهو الكائن المراد وضعه في السياق. إذا كان undefined ، سينشأ كائن جديد.
+
*<code>options</code> من النوع ‎<code>[[JavaScript/Object|<Object>]]</code> | <code>[[JavaScript/String|<string>‎]]</code>.
* options من النوع <Object> | <string>.
+
**<code>filename</code> من النوع <code>[[JavaScript/String|<string>]]</code> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
** filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
+
**<code>lineOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
** lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
+
**<code>columnOffset</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
** columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
+
**<code>displayErrors</code> من النوع <code>[[JavaScript/Boolean|<boolean>]]</code>، عندما يكون <code>true</code>، إذا حدث خطأ <code>[[Node.js/error|Error]]</code> أثناء ترجمة <code>code</code>، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
** displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
+
**<code>timeout</code> من النوع [[JavaScript/Number|<number>]] وهو يحدد عدد المللي ثانية اللازمة لتنفيذ <code>code</code> قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق <code>[[Node.js/error|Error]]</code>.
** timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا أنهي التنفيذ، سينطلقError.
+
يترجم التابع <code>vm.runInThisContext()‎</code> الشيفرة <code>code</codeوينفذها ضمن سياق <code>global</code> الحالي، ثم يعيد النتيجة. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي ولكن لديها حق الوصول إلى الكائن <code>global</code> الحالي.
** contextName من النوع <string> وهو اسم قابل للقراءة للسياق المُنشَأ حديثًا. القيمة الافتراضية: 'VM Context i'، حيث i هو مؤشر تصاعدي عددي للسياق المُنشَأ.
 
** contextOrigin من النوع <string> وهو الأصل المقابل للسياق المُنشَأ حديثًا لأغراض العرض. يجب ان يكون تنسيق الأصل مثل URL، ولكن فقط مع المخطَط، والمضيف ، والمنفذ (إذا لزم الأمر) ، مثل قيمة الخاصية url.originلكائن URL. والاهم من ذلك، يجب حذف الشرطة المائلة اللاحقة، إذ إنها تشير إلى مسار. القيمة الافتراضية: <nowiki>''</nowiki>.
 
يضع التابع Vm.runInNewContext()‎ أولا كائنَ sandbox المُعطى في السياق (أو ينشئ sandbox جديد إذا مُرر ك undefined) ، ويترجم code، وينفذه ضمن سياق السياق المُنشَأ، ثم يعيد النتيجة. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي.
 
  
إذا كانت قيمة options سلسلة نصية، ثم تحدد اسم الملف.
+
إذا كانت قيمة <code>options</code> سلسلة نصية، ستُحدِد اسم الملف.
  
يُترجم المثال التالي شيفرة وينفذها والتي تُزيد متغيرًا عامًا وتضبط واحدًا جديدًا. المتغيرات العامة مضمنة في الكائن sandbox.
+
يوضح المثال التالي استخدام كل من <code>vm.runInThisContext()‎</code> ودالة <code>eval()‎</code> من JavaScript لتنفيذ نفس الشيفرة:<syntaxhighlight lang="javascript">
 +
const vm = require('vm');
 +
let localVar = 'initial value';
 +
 
 +
const vmResult = vm.runInThisContext('localVar = "vm";');
 +
console.log('vmResult:', vmResult);
 +
console.log('localVar:', localVar);
  
== vm.runInThisContext(code[, options]) [المصدر] ==
+
const evalResult = eval('localVar = "eval";');
أضيف مع الإصدار: v0.3.1.
+
console.log('evalResult:', evalResult);
* code من النوع <string> وهو شيفرة JavaScript المراد ترجمتها وتنفيذها.
+
console.log('localVar:', localVar);
* options من النوع <Object> | <string>.
 
** filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
 
** lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
 
** displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
 
** timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا أنهي التنفيذ، سينطلقError.
 
يترجم التابع vm.runInThisContext()‎ الشيفرة code، وينفذها ضمن سياق global الحالي، ثم يعيد النتيجة. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي ولكن لديه حق الوصول إلى الكائن global الحالي.
 
  
إذا كانت قيمة options سلسلة نصية، ثم تحدد اسم الملف.
+
// vmResult: 'vm', localVar: 'initial value'
 +
// evalResult: 'eval', localVar: 'eval'
 +
</syntaxhighlight>لا تتغير <code>localVar</code>، لأنه ليس لدى <code>vm.runInThisContext()‎</code> الحق في الوصول إلى النطاق المحلي. في المقابل، لدى eval()‎‎ حق الوصول إلى النطاق المحلي، فتتغير قيمة <code>localVar</code>. بهذه الطريقة يصبح التابع <code>vm.runInThisContext()</code>‎‎ مشابه إلى حد كبير بالاستدعاء غير المباشر للدالة <code>eval()</code>‎، علي سبيل المثال، ‎<code>(0,eval)('code')</code>‎.
 +
==أمثلة: تشغيل خادم HTTP ضمن VM.==
 +
عند استخدام إما <code>script.runInThisContext()‎</code> أو <code>vm.runInThisContext()‎‎</code>، تُنفـَذ الشيفرة البرمجية داخل سياق V8 العام الحالي. سيكون للشيفرة البرمجية الممررة إلى سياق VM نطاقها المعزول الخاص.
  
يوضح المثال التالي استخدام كل من vm.runInThisContext()‎ ودالة JavaScript eval()‎ لتنفيذ نفس الشيفرة:
+
من أجل تشغيل خادم ويب بسيط باستخدام وحدة <code>http</code>، يجب أن تستدعي الشيفرةُ البرمجية التي مُرِرت إلى السياقِ التابعَ <code>require('http')‎</code> على نفسه، أو أن يكون له مرجع إلى الوحدة <code>http</code> يمرر إليه. على سبيل المثال:<syntaxhighlight lang="javascript">
 +
'use strict';
 +
const vm = require('vm');
  
لا تتغير localVar، لأنه ليس لدى vm.runInThisContext()‎ الحق في الوصول إلى النطاق المحلي. في المقابل، eval()‎‎ لديه حق الوصول إلى النطاق المحلي، فتتغير قيمة localvar. بهذه الطريقة يصبح التابع vm.runinthiscontext()‎‎ مشابه إلى حد كبير بالاستدعاء غير المباشر للدالة eval()‎ ، علي سبيل المثال، (0,eval)('code').
+
const code = `
 +
((require) => {
 +
  const http = require('http');
  
== أمثلة: تشغيل خادم HTTP ضمن VM. ==
+
  http.createServer((request, response) => {
عند استخدام إما script.runInThisContext()‎ أو vm.runInThisContext()‎‎ ، تُنفـَذ الشيفرة البرمجية داخل سياق V8 العام الحالي. سيكون للشيفرة البرمجية الممررة إلى سياق VM نطاقها المعزول الخاص.
+
    response.writeHead(200, { 'Content-Type': 'text/plain' });
 +
    response.end('Hello World\\n');
 +
  }).listen(8124);
  
من أجل تشغيل خادم ويب بسيط باستخدام وحدة http، يجب أن تستدعي الشيفرةُ البرمجية التي مُرِرت إلى السياقِ التابعَ require('http') على نفسه، أو أن يكون له مرجع إلى الوحدة http يمرر إليه. على سبيل المثال:
+
  console.log('Server running at http://127.0.0.1:8124/');
 +
})`;
  
يشارك التابع require()‎ في الحالة السابقة الحالة مع السياق الذي مُرِر منه. وهذا قد يفرض المخاطر عند تنفيذ شيفرة برمجية غير موثوق بها، علي سبيل المثال تغيير الكائنات في السياق بطرق غير مرغوب فيها.
+
vm.runInThisContext(code)(require);
 +
</syntaxhighlight>يشارك التابع <code>require()‎</code> في الحالة السابقة الحالة مع السياق الذي مُرِر منه. وهذا قد يفرض المخاطر عند تنفيذ شيفرة برمجية غير موثوق بها، علي سبيل المثال تغيير الكائنات في السياق بطرق غير مرغوب فيها.
 +
==ماذا يعني أن يوضع كائن في السياق؟==
 +
جميع شيفرات JavaScript المنفذة داخل Node.js تعمل ضمن نطاق "السياق". فوفقًا [https://github.com/v8/v8/wiki/Embedder's%20Guide#contexts لدليل V8 Embedder]:<blockquote>في V8، يكون السياق هو بيئة تنفيذ والتي تسمح لتطبيقات JavaScript المنفصلة، غير المترابطة أن تعمل في مثيل واحد من V8. يجب تحديد السياق المراد تشغيل أي شيفرات JavaScript فيه بشكل صريح.</blockquote><span> </span>عند استدعاء التابع <code>vm.createContext()</code>‎، يقترن كائن <code>sandbox</code> الذي مُرِر فيه (أو كائن مُنشَأ حديثًا إذا كان <code>sandbox</code> قيمته <code>undefined</code>) داخليا مع مثيل جديد من سياق V8. يوفر سياق V8 هذا تشغيل <code>code</code> باستخدام توابع الوحدة <code>vm</code> مع بيئة عامة معزولة والتي يمكن أن تعمل فيها. عملية إنشاء سياق V8 واقترانه مع الكائن <code>sandbox</code> هو ما تشير إليه هذه الوثيقة بأنه "الوضع في السياق" لكائن <code>sandbox</code>.
  
== ماذا يعني أن يوضع كائن في السياق؟ ==
+
= مصادر =
جميع شيفرات JavaScript المنفذة داخل Node.js تعمل ضمن نطاق "السياق". فوفقا لدليل V8 Embedder:<blockquote>في V8، يكون السياق هو بيئة تنفيذ والتي تسمح لتطبيقات JavaScript منفصلة، غير مترابطة أن تعمل في مثيل واحد من V8. يجب تحديد السياق المراد تشغيل أي شيفرات JavaScript فيه بشكل صريح.</blockquote>عند استدعاء التابع vm.createcontext()‎، يقترن كائن sandbox الذي مُرِر فيه (أو كائن مُنشَأ حديثًا إذا كان sandbox قيمته undefined) داخليا مع مثيل جديد من سياق V8. يوفر سياق V8 هذا تشغيل code باستخدام توابع الوحدة vm مع بيئة عامة معزولة والتي يمكن أن تعمل فيها. عملية إنشاء سياق V8 واقترانه مع الكائن sandbox هو ما تشير إليه هذه الوثيقة بأنه "الوضع في السياق" لكائن sandbox.
+
<span> </span>[https://nodejs.org/dist/latest-v10.x/docs/api/vm.html#vm_module_dependencyspecifiers صفحة الوحدة VM (تنفيذ JavaScript) في توثيق Node.js الرسمي].
 +
[[تصنيف:Node.js|{{SUBPAGENAME}}]]

المراجعة الحالية بتاريخ 11:16، 23 أكتوبر 2018

مؤشر الاستقرار: 2 - مستقر.

توفر الوحدة vm واجهات تطبيقات لترجمة وتشغيل الشيفرات البرمجية ضمن سياقات آلآت V8 الافتراضية.

ويمكن ترجمة شيفرة JavaScript البرمجية وتشغيلها فورًا أو تجميعها وحفظها وتشغيلها لاحقًا.

من الاستخدامات الشائعة، تشغيل التعليمات البرمجية في بيئة تجريبية معزولة (sandbox environment). وتُستخدم شيفرة sandbox سياق V8 مختلف، مما يعني انه يحتوي علي كائن عام مختلف عن باقي الشيفرة البرمجية.

ويمكن توفير السياق عن طريق وضع كائن sandbox المعزول في السياق. وتعامل الشيفرةُ المعزولة أي خاصية في بيئة sandbox على أنها متغير عام. وتنعكس أية تغييرات علي المتغيرات العامة الحادثة بسبب الشيفرة المعزولة على كائن sandbox.

const vm = require('vm');

const x = 1;

const sandbox = { x: 2 };
vm.createContext(sandbox); // وضع الـ sandbox في السياق.

const code = 'x += 40; var y = 17;';
// x و y متغيرات عامة في بيئة معزولة.
// في البداية، تحتوي x على القيمة 2 لأن هذه هي قيمة sandbox.x.
vm.runInContext(code, sandbox);

console.log(sandbox.x); // 42
console.log(sandbox.y); // 17

console.log(x); // 1; y غير مُعرَّف.

ولا تُعد الوحدة vm آلية أمان. ولا يجب استخدامها لتشغيل شيفرة برمجية غير موثوق بها.

الصنف: vm.SourceTextModule

أضيفت مع الإصدار: v9.6.0.

مؤشر الاستقرار: 1 - تجريبي.

تتوفر هذه الميزة فقط عند تفعيل راية الأمر ‎--experimental-vm-modules.

ويوفر الصنف vm.SourceTextModule واجهة منخفضة المستوى لاستخدام وحدات ECMAScript في سياقات VM. وهو نظير للصنف vm.Script الذي يعكس سجلات وحدة نَّص المصدر (Source Text Module Records) كما هو محدد في مواصفات ECMAScript.

ومع ذلك، علي عكس vm.Script يرتبط كل كائن vm.SourceTextModule إلى سياق من إنشائه. وتكون العمليات على كائنات vm.SourceTextModule في جوهرها غير متزامنة، في تناقض مع الطبيعة المتزامنة لكائنات vm.Script بيد أن التلاعب بكائنات vm.SourceTextModule يكون واضحا إلى حد ما بمساعدة الدوال المتزامنة.

يتطلب استخدام كائن vm.SourceTextModule أربع خطوات: إنشاء/تحليل, ربط، عمل مثيل، والتقييم. هذه الخطوات الأربع موضحة في المثال التالي.

يكمن هذا التنفيذ في مستوى أقل من مُحمِـل وحدة ECMAScript. كما لا يوجد حاليا أي وسيلة للتفاعل مع المُحمِّـل، على الرغم من التخطيط لدعمه.

const vm = require('vm');

const contextifiedSandbox = vm.createContext({ secret: 42 });

(async () => {
// الخطوة 1

//

// إنشاء وحدة عن طريق بناء كائن `vm.SourceTextModule` جديد.

// يحلل هذا نص المصدر المعطى ويطلق `SyntaxError` إذا حدث أي خطأ.

// بشكل افتراضي، تُنشأ وحدة في أعلى السياق. ولكن هنا،

// نُحدد `contextifiedSandbox` كسياق تنتمي له هذه الوحدة.

//

// هنا نحاول الحصول على التصدير الافتراضي من وحدة "foo"،

// ووضعه في "secret" الربط المحلية.

 const bar = new vm.SourceTextModule(`
    import s from 'foo';
    s;

// الخطوة 2

//

// "ربط" التبعيات المستوردة لهذه الوحدة بها.

//

// تقبل دالةُ رد الاتصال المُعطاة ("الرابطة") وسيطين:

// الوحدة الأصل ('bar' في هذه الحالة) والسلسلة التي تحدد

// الوحدة المستوردة. ومن المتوقع أن تعيد دالة رد الاتصال الوحدة التي

// تتوافق مع المحدد المعطى، مع بعض المتطلبات الموثقة

// في `module.link()`.

//

// إذا لم يبدأ الربط للوحدة المُعادة، ستُستدعى نفس دالة رد الاتصال الرابطة

// على الوحدة المُعادة.

//

// ويجب ربط حتى الوحدات ذات المستوي الأعلى الخالية من التبعيات بشكل صريح. 
// وعلى الرغم من ذلك، لن تستدعى دالة رد الاتصال المعطاة.

//

ويعيد التابع link()‎ الوعد (Promise) والذي سيُحل عندما

تُحل جميع الوعود Promises المُعادة بواسطة الرابط.

//

// ملاحظة: هذا المثال مُعَد كمثال على أن دالة الرابط تُنشئ

// وحدة "foo" جديدة في كل مرة تستدعى فيها. في نظام وحدة متكامل،

// قد تستخدم ذاكرة التخزين المؤقت على الأرجح لتجنب تكرار الوحدات.

  async function linker(specifier, referencingModule) {
    if (specifier === 'foo') {
      return new vm.SourceTextModule(`
// يشير المتغير "secret" إلى المتغير العام الذي أضفناه إلى

// "contextifiedSandbox" عند إنشاء السياق.

        export default secret;
      `, { context: referencingModule.context });


// استخدام `contextifiedSandbox` بدلا من `referencingModule.context`

// هنا سوف يعمل أيضًا.
 }
    throw new Error(`Unable to resolve dependency: ${specifier}`);
  }
  await bar.link(linker);


// الخطوة 3

//

// إنشاء مثيل الوحدة في المستوي الأعلى.

//

// فقط الوحدة في المستوي الأعلى تحتاج إلى إنشاء مثيل بشكل صريح؛

// وستُنشأ مثيلات لتبعياتها بشكل متكرر من قِبَل instantiate()‎.

  bar.instantiate();

// الخطوة 4

//

// تقييم الوحدة. يُعيد التابع evaluate()‎ وعد Promise مع

// خاصية "result" منفردة والتي تحتوي علي نتيجة آخر عبارة

// نُفِذَّت في الوحدة. في حالة `bar`، يكون حرف `s` هو الذي يشير إلى

// التصدير الافتراضي للوحدة 'foo'، و 'secret' الذي ضُبِط

// في بداية بالقيمة 42.

 const { result } = await bar.evaluate();

  console.log(result);
  // طباعة 42.
})();

المُنشئ: new vm.SourceTextModule(code[, options])

  • code من النوع <string> وهو شيفرة وحدة JavaScript المراد تحليلها.
  • options
    • url من النوع <string> وهو URL المستخدم في حل الوحدة وتتبعات المكدس. القيمة الافتراضية: ‎'vm:module(i)'‎ حيث i مؤشر تصاعدي خاص بالسياق.
    • context من النوع <Object> وهو الكائن الموضوع في السياق كما أُعيد من قبل التابع vm.createContext()‎، لترجمته وتقييمه داخل Module.
    • lineoffset من النوع <integer> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي تنتجها الوحدة Module.
    • columnoffset من النوع <integer> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي تنتجها الوحدة Module.
    • initalizeImportMeta من النوع <Function> وهو يُستدعى خلال تقييم هذه الوحدة Module لإعادة تهيئة import.meta. شكل هذه الدالة هو (meta, module) مع كون meta كائن import.meta في Module، و module كائن vm.SourceTextModule.

إنشاء كائن ES Module جديد.

قد تسمح الخصائص المعينة لكائن import.meta التي هي كائنات للوحدة Module للوصول إلى المعلومات خارج context المحدد، إذا أنشئ الكائن في سياق المستوي الأعلى. يُستخدم التابع vm.runincontext()‎‎ لإنشاء كائنات في سياق معين.

const vm = require('vm');

const contextifiedSandbox = vm.createContext({ secret: 42 });

(async () => {
  const module = new vm.SourceTextModule(
    'Object.getPrototypeOf(import.meta.prop).secret = secret;',
    {
      initializeImportMeta(meta) {
        // ملاحظة: أنشئ هذا الكائن في السياق الأعلى. وعلى هذا النحو،
        // يشير الكائن Object.getPrototypeOf(import.meta.prop)‎ إلى
        // Object.prototype في أعلى السياق بدلا من ذلك الذي في
        // الـ sandbox.
        meta.prop = {};
      }
    });
  // وبما أن ليس للوحدة تبعيات، فلن تُستدعى دالة الرابط أبدًا.
  await module.link(() => {});
  module.instantiate();
  await module.evaluate();

  // يساوي Object.prototype.secret الآن 42.
  //
  // لإصلاح هذه المشكلة، يستبدل
  //      meta.prop = {};
  // أعلاه مع،
  //      meta.prop = vm.runInContext('{}', contextifiedSandbox);
})();

module.dependencySpecifiers

محددات كافة تبعيات هذه الوحدة. وهي تُجمَّد المصفوفة المُعادة لمنع حدوث أي تغييرات عليها.

يتوافق مع الحقل [[RequestedModules]] في سجلات وحدة نص المصدر في مواصفات ECMAScript.

module.error

  • من أي نوع من الأنواع <any>.

إذا كانت الحالة module.status بالقيمة 'errored'، تحتوي هذه الخاصية علي الاستثناء الذي أُجريَ بواسطة الوحدة أثناء التقييم. إذا كانت الحالة غير ذلك، سيؤدي الوصول إلى هذه الخاصية إلى إجراء استثناء.

لا يمكن استخدام القيمة undefined للحالات حيث لا يوجد إجراء استثناء بسبب الغموض المحتمل حول throw undefined;‎.

يتوافق مع الحقل [[EvaluationError]] في سجلات وحدة نص المصدر في مواصفات ECMAScript.

module.evaluate([options])‎

  • options من النوع <Object>.
    • timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة للتقييم قبل إنهاء التنفيذ. إذا تمت مقاطعة التنفيذ، سينطلق Error.
    • breakOnSigint من النوع <boolean>، إذا كان true، سينتهي التنفيذ عند تلقي SIGINT (أو Ctrl + C). ستُعَّطل المعالجات الموجودة للحدث الذي أُرفِق بواسطة process.on('SIGINT')‎ أثناء تنفيذ السكريبت، ولكنها سوف تستمر في العمل بعد ذلك. إذا تمت مقاطعة التنفيذ، سينطلق Error.
  • القيمة المُعادة: من النوع <Promise>.

يقيّم هذا التابع الوحدة. ويجب استدعاءه بعد إنشاء مثيل الوحدة؛ وإلا فانه سيُطلق خطأ. ويمكن استدعاؤه أيضًا عند تقييم الوحدة بالفعل، وفي هذه الحالة سيقوم بأحد الأمرين التاليين:

  • إعادة undefined إذا انتهى التقييم الأولي بنجاح (module.status تكون 'evaluated').
  • أعادة إجراء الاستثناء نفسه الذي أجراه التقييم الأولي إذا أُنهيَ التقييم الأولي مع وجود خطأ (module.status تكون 'errored').

لا يمكن استدعاء هذا التابع أثناء تقييم الوحدة (module.status تكون 'evaluating') لمنع لانهائية العَوْديَّة.

يتوافق مع حقل التابع Evaluate()‎ المتماسك من سجلات وحدة نص المصدر في مواصفات ECMAScript.

module.instantiate()‎

ينشئ هذا التابع مثيل للوحدة. ويجب استدعاءه بعد إنهاء الربط (linkingStatus تكون 'linked')؛ وإلا فانه سيُطلق خطأ. كما يجوز إجراء استثناء إذا لم يوفر أحدُ التبعيات التصديرَ الذي تتطلبه الوحدة الأصل.

ومع ذلك، إذا نجحت هذه الدالة، ستكون الاستدعاءات اللاحقة لهذه الدالة بعد الإنشاء الأولي لمثيل هو no-ops، لتكون متناسقة مع مواصفات ECMAScript.

علي عكس التوابع الأخرى التي تعمل علي Module، تكمل هذه الدالة بشكل متزامن ولا تقوم بإعادة أي شيء.

يتوافق مع حقل التابع Instantiate()‎ المتماسك من سجلات وحدة نص المصدر في مواصفات ECMAScript.

module.link (linker)‎

يربط هذا التابع تبعيات الوحدة. يجب استدعاء هذا التابع قبل إنشاء مثيل، ويمكن استدعاؤه مره واحدة فقط لكل وحدة.

سيمرر مُعاملَين إلى الدالة linker:

  • specifier وهو محدد الوحدة المطلوبة:
    import foo from 'foo';
    //              ^^^^^ محدد الوحدة
    
  • referencingModule وهو كائن Module الذي يُستدعَى عليه التابع link()‎.

والمتوقع من الدالة إعادة كائن Module أو كائن Promise الذي يُحَل إلى كائن Module في نهاية المطاف. يجب أن يلبي الكائن Module المُعاد الثابتين التالييَن:

  • يجب أن ينتمي إلى نفس سياق كائن Module الأصل.
  • يجب ألَّا تصبح linkingStatus الخاصة بها 'errored'.

إذا كانت linkingStatus المُعادة والخاصة بالكائن Module هي 'unlinked'، سيُستدعى هذا التابع بشكل متكرر علي Module المُعاد مع نفس الدالة linker المُعطاة.

يعيد link()‎ الكائن Promise والذي سيُحل عندما تحل كافة مثيلات الربط إلى Module صالح، أو يُرفض إذا أجرت دالة الربط استثناءً أو أعادت Module غير صالح.

تتوافق دالة الربط بشكل تقريبي مع عملية HostResolveImportedModule المُجرَدة والمعرفة من قِبَل التطبيق في مواصفة ECMAScript مع بعض الاختلافات الرئيسية:

  • يُسمح لدالة الربط أن تكون غير متزامنة في حين أن HostResolveImportedModule متزامن.
  • تُنفَّذ دالة الربط أثناء الربط، وهي أحد مراحل Node.js الخاصة قبل إنشاء المثيل، في حين يُستدعى HostResolveImportedModule خلال إنشاء المثيل.

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

module.linkingStatus

حاله الربط الحالية للوحدة module. وستكون إحدي القيم التالية:

  • 'unlinked': لم يُستدعى module.link()‎ بعد.
  • 'linking': أُستدعيَ module.link()‎، ولكن لم تُحل كل كائنات Promise المُعادة من قِبَل دالة الربط بعد.
  • 'linked': أُستدعيَ module.link()‎، ورُبطت جميع التبعيات بنجاح.
  • 'errored': أُستدعيَ module.link()‎، ولكن فشل أحد تبعياته علي الأقل في الارتباط، إما لان دالة رد الاتصال أعادت Promise مرفوض، أو لأن Module الذي أعادته دالة رد الاتصال غير صالح.

module.namespace

كائن مجال الأسماء للوحدة. وهو متاح فقط بعد اكتمال إنشاء المثيل (module.instantiate()‎).

يتوافق مع عملية GetModuleNamespace المجردة في مواصفة ECMAScript.

module.status

الحالة الحالية للوحدة. وتكون واحدة من:

  • 'uninstantiated': لم يُنشأ مثيل للوحدة. قد يكون بسبب أيٍ من الأسباب التالية:
    • إنشاء الوحدة للتو.
    • استدعاء module.instantiate()‎ علي هذه الوحدة ولكنه فشل لسبب ما.

لا تنقل هذه الحالة أيَّة معلومات تتعلق بإذا كان التابع module.link()‎ قد أستُدعيَ أم لا. راجع module.linkingstatus.

  • 'instantiating': يُنشأ حاليًا مثيل الوحدة من خلال استدعاء module.instantiate()‎ علي نفسه أو على وحدة أصل.
  • 'instantiated': نجح إنشاء مثيل للوحدة، ولكن لم يستدعى التابع module.evaluate()‎ حتى الآن.
  • 'evaluating': يُقيَّم مثيل الوحدة من خلال استدعاء module.evaluate()‎ علي نفسه أو على وحدة أصل.
  • 'evaluated': نجح تقييم الوحدة.
  • 'errored': قُيّمت وحدة، ولكن أُجريَ استثناء.

بخلاف 'errored'، تتوافق سلسلة هذه الحالة مع مواصفات حقل سجل وحدة نَص المصدر [[Status]]. ويتوافق 'errored' مع 'evaluated' من حيث المواصفات، لكن يُضبط مع [[EvaluationError]] بقيمة غير undefined.

module.url

عنوان URL الخاص بالوحدة الحالية، كما هو محدد في المُنشِئ.

الصنف: vm.Script

أضيف مع الإصدار: v0.3.1.

يحتوي مثيلات الصنف vm.Script علي سكريبتات مترجمة مسبقا والتي يمكن تنفيذها في بيئات تجريبية معزولة (sandboxes) (أو "سياقات") معينة.

new vm.Script(code, options)‎

  • code من النوع <string> وهو شيفرة JavaScript المراد ترجمتها.
  • options
    • filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبُعات المكدس المُنتَجة بواسطة هذا السكريبت.
    • lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبُعات المكدس التي ينتجها هذا السكريبت.
    • columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبُعات المكدس التي ينتجها هذا السكريبت.
    • cachedData من النوع <Buffer> وهو يوفر Buffer اختياري مع بيانات مؤقتة لشيفرة V8 للمصدر المُعطى. عند توفيرها، ستُضبط قيمة cacheddatarejected على true أو false تبعًا لقبول البيانات بواسطة V8.
    • produceCachedData من النوع <boolean>. عندما يكون true ولا يوجد cachedData، سيحاول V8 إنتاج بيانات مؤقتة لشيفرة code. عند النجاح، سينتَج Buffer مع بيانات مؤقتة لشيفرة V8 ويُخزَّن في الخاصية cacheddata لمثيل vm.Script المُعاد. ستُضبط قيمة cacheddataproduced على true أو false استنادا إلى ما إذا كانت البيانات المؤقتة للشيفرة قد أُنتِجت بنجاح أم لا. أهمِل هذا الخيار لصالح التابعscript.createCachedData()‎.

إنشاء كائن vm.Script جديد يُترجم code ولكن لا يُنفذها. يمكن تنفيذ vm.Script المُترجَم لاحقًا عدة مرات. لا يرتبط code بأي كائن عام، ولكن بدلًا من ذلك، فانه يرتبط قبل كل تشغيل، فقط لهذا التشغيل.

script.createCachedData()‎

أضيف مع الإصدار: v10.6.0.

  • القيمة المُعادة: من النوع <Buffer>.

إنشاء تخزين مؤقت للشيفرة البرمجية التي يمكن استخدامها مع خيار سكريبت المُنشِئ cachedData. يُعيد مخزن مؤقت. قد يستدعى هذا التابع في أي وقت ولأي عدد من المرات.

const script = new vm.Script(`
function add(a, b) {
  return a + b;
}

const x = add(1, 2);
`);

const cacheWithoutX = script.createCachedData();

script.runInThisContext();

const cacheWithX = script.createCachedData();

script.runInContext(contextifiedSandbox[, options])‎ [المصدر]

سجل التغييرات

الإصدار التغييرات
v6.3.0 بداية دعم breakOnSigint.
v0.3.1 أضيف مع الإصدار: v0.3.1
  • contextifiedSandbox من النوع <Object>، وهو الكائن الموضوع في السياق كما أُعيد من قبل التابع vm.createContext()‎.
  • options من النوع<Object>.
    • filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
    • lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
    • timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق Error.
    • breakOnSigint من النوع <boolean>، إذا كان true، سينتهي التنفيذ عند تلقي SIGINT (أو Ctrl + C). ستُعَّطل المعالجات الموجودة للحدث الذي أُرفِق بواسطة process.on('SIGINT')‎ أثناء تنفيذ السكريبت، ولكنها سوف تستمر في العمل بعد ذلك. إذا انتهى التنفيذ، سينطلق Error.

تشغيل التعليمات البرمجية المترجَمة الواردة في كائن vm.Script داخل contextifiedSandbox المُعطَى وإعادة النتيجة. ليس لدى الشيفرة الجاري تشغيلها الحق في الوصول إلى النطاق المحلي.

يُترجم المثال التالي الشيفرة البرمجية التي تُزيد متغيرًا عامًا، ويضبط قيمة متغيرٍ عامٍ آخر، ثم يُنفذ التعليمات البرمجية عده مرات. المتغيرات العامة مضمنة في الكائن sandbox.

const util = require('util');
const vm = require('vm');

const sandbox = {
  animal: 'cat',
  count: 2
};

const script = new vm.Script('count += 1; name = "kitty";');

const context = vm.createContext(sandbox);
for (let i = 0; i < 10; ++i) {
  script.runInContext(context);
}

console.log(util.inspect(sandbox));

// { animal: 'cat', count: 12, name: 'kitty' }

سيؤدي استخدام الخيارات timeout أو breakOnSigint إلى حلقات حدث جديد وبدء الخيوط المقابلة، والتي يكون لها عبء أداء (performance overhead) غير صفري.

script.runInNewContext([sandbox[, options]])‎ [المصدر]

سجل التغييرات

الإصدار التغييرات
v10.0.0 بداية دعم contextCodeGeneration.
v0.3.1 أضيف مع الإصدار: v0.3.1.
  • sandbox من النوع<Object> وهو الكائن المراد وضعه في السياق. إذا كان undefined، سينشأ كائن جديد.
  • options من النوع <Object>.
    • filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
    • lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
    • timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق Error.
    • contextName من النوع <string> وهو اسم قابل للقراءة للسياق المُنشَأ حديثًا. القيمة الافتراضية: 'VM Context i'، حيث i هو مؤشر تصاعدي عددي للسياق المُنشَأ.
    • contextOrigin من النوع <string> وهو الأصل Origin المقابل للسياق المُنشَأ حديثًا لأغراض العرض. يجب ان يكون تنسيق الأصل مثل URL، ولكن فقط مع المخطَط، والمضيف، والمَنفذ (إذا لزم الأمر)، مثل قيمة الخاصية url.origin لكائن URL. والاهم من ذلك، يجب حذف الشرطة المائلة اللاحقة، إذ إنها تشير إلى مسار. القيمة الافتراضية: ''.
    • contextCodeGeneration القيمة المُعادة <Object>.
      • strings من النوع <boolean> إذا ضُبط على false سيُطلِق أي استدعاء إلى eval أو لمنشئات الدالة (Function و GeneratorFunction، الخ) خطأ EvalError. القيمة الافتراضية: true.
      • wasm من نوع <boolean>، إذا ضُبط على false ستُطلِق أي محاولة لترجمة وحدة WebAssembly الخطأ WebAssembly.CompileError. القيمة الافتراضية: true.

يضع أولا كائن sandbox المعطى في السياق، ثم ينفذ الشيفرة البرمجية المترجمة الواردة في كائن vm.Script الوارد في كائن sandbox المُنشَأ، وإعادة النتيجة. ليس لدى الشيفرة الجاري تشغيلها الحق في الوصول إلى النطاق المحلي.

يُترجم المثال التالي الشيفرة البرمجية التي تضبط قيمة متغيرٍ عام، ثم يُنفذ التعليمات البرمجية عده مرات في عدة سياقات. تُضبط المتغيرات العامة وترِد ضمن كل sandbox فردي.

const util = require('util');
const vm = require('vm');

const script = new vm.Script('globalVar = "set"');

const sandboxes = [{}, {}, {}];
sandboxes.forEach((sandbox) => {
  script.runInNewContext(sandbox);
});

console.log(util.inspect(sandboxes));

// [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }]

script.runInThisContext([options])‎ [المصدر]

أضيف مع الإصدار: v0.3.1.

  • options من النوع <Object>.
    • filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
    • lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
    • timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق Error.

يُنفذ هذا التابع الشيفرة البرمجية المترجمة المضمنة في vm.Script ضمن سياق الكائن global الحالي. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي ولكن لديها حق الوصول إلى الكائن global الحالي.

يُترجم المثال التالي الشيفرة البرمجية التي تُزيد متغير global، ثم يُنفذ التعليمات البرمجية عدة مرات:

const vm = require('vm');

global.globalVar = 0;

const script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' });

for (let i = 0; i < 1000; ++i) {
  script.runInThisContext();
}

console.log(globalVar);

// 1000

vm.compileFunction(code[, params[, options]])‎ [المصدر]

أُضيف مع الإصدار: v10.10.0.

  • code من النوع <string> وهو متن الدالة المراد ترجمتها.
  • params من النوع <string[]‎> وهو مصفوفة من السلاسل النصية التي تحتوي على جميع المعاملات للدالة.
  • options من النوع <Object>.
    • filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت. القيمة الافتراضية: ''.
    • lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت. القيمة الافترضية: 0.
    • columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت. القيمة الافتراضية: 0.
    • cachedData من النوع <Buffer> وهو يوفرBuffer اختياري مع بيانات مؤقتة لشيفرة V8 للمصدر المُعطى.
    • producecacheddata من النوع<boolean>، وهو يحدد ما إذا كان ستُنتَج بيانات مؤقتة جديدة. القيمة الافتراضية: false.
    • parsingContext من النوع <boolean> وهو sandbox/السياق الذي يجب ترجمة الدالة المعنية فيه.
    • contextExtensions من النوع <Object[]‎> وهو مصفوفة تحتوي علي مجموعة من ملحقات السياق (كائنات تلتف حول النطاق الحالي) لتطبيقها أثناء الترجمة. القيمة الافتراضية: [].

ترجمة الشيفرة البرمجية المعطاة إلى السياق/sanbox المتوفر (إذا لم يتوفر أي سياق، يستخدم السياق الحالي)، ويقوم بإعادتها ملفوفَا داخل دالة مع params المُعطي.

vm.createContext([sandbox[, options]])[المصدر]

سجل التغييرات

الإصدار التغييرات
v10.0.0 لا يمكن أن يكون الخيار sandbox دالة بعد الآن.
v10.0.0 بداية دعم codeGeneration.
v0.3.1 أضيف مع الإصدار: v0.3.1
  • sandbox من النوع <boolean>.
  • options من النوع <boolean>.
    • name من النوع <string> وهو اسم قابل للقراءة للسياق المُنشَأ حديثًا. القيمة الافتراضية: 'VM Context i'، حيث i هو مؤشر تصاعدي عددي للسياق المُنشَأ.
    • origin من النوع <string> وهو الأصل Origin المقابل للسياق المُنشَأ حديثًا لأغراض العرض. يجب ان يكون تنسيق الأصل مثل URL، ولكن فقط مع المخطَط، والمضيف، والمَنفذ (إذا لزم الأمر)، مثل قيمة الخاصية url.origin لكائن URL. والاهم من ذلك، يجب حذف الشرطة المائلة اللاحقة، إذ إنها تشير إلى مسار. القيمة الافتراضية: ''.
    • codeGeneration من النوع <Object>.
      • strings من النوع <boolean> إذا ضُبط على false سيُطلِق أي استدعاء إلى eval أو لمنشئات الدالة (Function و GeneratorFunction، الخ) خطأ EvalError. القيمة الافتراضية: true.
      • wasm من نوع <boolean> إذا ضُبط على false ستُطلِق أي محاولة لترجمة وحدة WebAssembly الخطأ WebAssembly.CompileError. القيمة الافتراضية: true.

إذا أُعطي كائن sandbox، سيُحضِـر التابع vm.createContext()‎ كائن sandbox هذا بحيث يمكن استخدامه في استدعاء vm.runInContext()‎ أو script.runInContext()‎. داخل مثل هذه السكريبتات، سيكون كائن sandbox هو الكائن العام، محتفظًا بكافة خصائصه الموجودة ولكنه يمتلك أيضا الكائنات المضمنة والدوال التي يمتلكها أي كائن عام قياسي. فيما عدا السكريبتات التي تُنفَّذ بواسطة الوحدة vm، ستبقي المتغيرات العامة دون تغيير.

const util = require('util');
const vm = require('vm');

global.globalVar = 3;

const sandbox = { globalVar: 1 };
vm.createContext(sandbox);

vm.runInContext('globalVar *= 2;', sandbox);

console.log(util.inspect(sandbox)); // { globalVar: 2 }

console.log(util.inspect(globalVar)); // 3

إذا حُذِف sandbox (أو مُرِر بشكل صريح كـ undefined)، سيعاد كائن sandbox جديد فارغ موضوع في السياق.

ويفيد التابع vm.createContext()‎ في المقام الأول في إنشاء sandbox منفرد والذي يمكن استخدامه لتشغيل عدة سكريبتات. علي سبيل المثال، في حالة محاكاة متصفح ويب، يمكن استخدام التابع لإنشاء sandbox منفرد يمثل كائن عام للإطار، ثم لتشغيل كافة وسوم <script> معا ضمن سياق كائن sandbox هذا.

ويُجعَل name و origin السياق المتوفرَين مرئيـيَن من خلال مفتش API.

vm.isContext(sandbox)‎ [المصدر]

أضيف مع الإصدار: v 0.11.7.

  • sandbox من النوع <Object>.
  • القيمة المُعادة: من النوع <boolean>.

يُعيد true إذا وُضِع كائن sandbox المُعطي في السياق باستخدام vm. createcontext()‎‎.

vm.runInContext(code, contextifiedSandbox[, options])‎ [المصدر]

  • code من النوع <string> وهو شيفرة JavaScript المراد ترجمتها وتنفيذها.
  • contextifiedSandbox من النوع <Object>، وهو الكائن الموضوع في السياق المستخدام كمتغير global عند ترجمة code وتشغيله.
  • options من النوع ‎<Object> | <string>‎.
    • filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
    • lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • displayErrors من النوع <number>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
    • timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق Error.

يترجم التابع vm.runInContext()‎ الشيفرة code، وينفذها ضمن سياق vm contextifiedSandbox، ثم يعيد النتيجة. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي. يجب أن يكون كائن contextifiedSandbox موضوعا مسبقا في السياق باستخدام التابع vm.createcontext()‎‎.

إذا كانت قيمة options سلسلة نصية، ثم تحدد اسم الملف.

يُترجم المثال التالي سكريبتات مختلفة وينفذها باستخدام كائن منفرد موضوع في السياق.

const util = require('util');
const vm = require('vm');

const sandbox = { globalVar: 1 };
vm.createContext(sandbox);

for (let i = 0; i < 10; ++i) {
  vm.runInContext('globalVar *= 2;', sandbox);
}
console.log(util.inspect(sandbox));

// { globalVar: 1024 }

vm.runInNewContext(code[, sandbox[, options]])‎ [المصدر]

أضيف مع الإصدار: v0.3.1.

  • code من النوع <string> وهو شيفرة JavaScript المراد ترجمتها وتنفيذها.
  • sandbox من النوع <Object> وهو الكائن المراد وضعه في السياق. إذا كان undefined، سينشأ كائن جديد.
  • options من النوع ‎<Object> | <string>‎.
    • filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
    • lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
    • timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق Error.
    • contextName من النوع <string> وهو اسم قابل للقراءة للسياق المُنشَأ حديثًا. القيمة الافتراضية: 'VM Context i'، حيث i هو مؤشر تصاعدي عددي للسياق المُنشَأ.
    • contextOrigin من النوع <string> وهو الأصل المقابل للسياق المُنشَأ حديثًا لأغراض العرض. يجب ان يكون تنسيق الأصل مثل URL، ولكن فقط مع المخطَط، والمضيف، والمنفذ (إذا لزم الأمر)، مثل قيمة الخاصية url.origin لكائن URL. والاهم من ذلك، يجب حذف الشرطة المائلة اللاحقة، إذ إنها تشير إلى مسار. القيمة الافتراضية: ''.

يضع التابع vm.runInNewContext()‎ أولا كائنَ sandbox المُعطى في السياق (أو ينشئ sandbox جديد إذا مُرر كـ undefined)، ويترجم code، وينفذه ضمن سياق السياق المُنشَأ، ثم يعيد النتيجة. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي.

إذا كانت قيمة options سلسلة نصية، ستُحدِد اسم الملف.

يُترجم المثال التالي شيفرة وينفذها والتي تُزيد متغيرًا عامًا وتضبط واحدًا جديدًا. المتغيرات العامة مضمنة في الكائن sandbox.

const util = require('util');
const vm = require('vm');

const sandbox = {
  animal: 'cat',
  count: 2
};

vm.runInNewContext('count += 1; name = "kitty"', sandbox);
console.log(util.inspect(sandbox));

// { animal: 'cat', count: 3, name: 'kitty' }

vm.runInThisContext(code[, options])‎ [المصدر]

أضيف مع الإصدار: v0.3.1.

  • code من النوع <string> وهو شيفرة JavaScript المراد ترجمتها وتنفيذها.
  • options من النوع ‎<Object> | <string>‎.
    • filename من النوع <string> وهو يحدد اسم الملف المستخدم في تتبعات المكدس المُنتَجة بواسطة هذا السكريبت.
    • lineOffset من النوع <number> وهو يحدد إزاحة رقم السطر المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • columnOffset من النوع <number> وهو يحدد إزاحة رقم العمود المعروض في تتبعات المكدس التي ينتجها هذا السكريبت.
    • displayErrors من النوع <boolean>، عندما يكون true، إذا حدث خطأ Error أثناء ترجمة code، يُرفق السطر من الشيفرة البرمجية الذي يسبب الخطأ إلى تتبع المكدس.
    • timeout من النوع <number> وهو يحدد عدد المللي ثانية اللازمة لتنفيذ code قبل إنهاء التنفيذ. إذا انتهى التنفيذ، سينطلق Error.

يترجم التابع vm.runInThisContext()‎ الشيفرة code، وينفذها ضمن سياق global الحالي، ثم يعيد النتيجة. ليس لدى الشيفرة الجاري تنفيذها الحق في الوصول إلى النطاق المحلي ولكن لديها حق الوصول إلى الكائن global الحالي.

إذا كانت قيمة options سلسلة نصية، ستُحدِد اسم الملف.

يوضح المثال التالي استخدام كل من vm.runInThisContext()‎ ودالة eval()‎ من JavaScript لتنفيذ نفس الشيفرة:

const vm = require('vm');
let localVar = 'initial value';

const vmResult = vm.runInThisContext('localVar = "vm";');
console.log('vmResult:', vmResult);
console.log('localVar:', localVar);

const evalResult = eval('localVar = "eval";');
console.log('evalResult:', evalResult);
console.log('localVar:', localVar);

// vmResult: 'vm', localVar: 'initial value'
// evalResult: 'eval', localVar: 'eval'

لا تتغير localVar، لأنه ليس لدى vm.runInThisContext()‎ الحق في الوصول إلى النطاق المحلي. في المقابل، لدى eval()‎‎ حق الوصول إلى النطاق المحلي، فتتغير قيمة localVar. بهذه الطريقة يصبح التابع vm.runInThisContext()‎‎ مشابه إلى حد كبير بالاستدعاء غير المباشر للدالة eval()‎، علي سبيل المثال، ‎(0,eval)('code')‎.

أمثلة: تشغيل خادم HTTP ضمن VM.

عند استخدام إما script.runInThisContext()‎ أو vm.runInThisContext()‎‎، تُنفـَذ الشيفرة البرمجية داخل سياق V8 العام الحالي. سيكون للشيفرة البرمجية الممررة إلى سياق VM نطاقها المعزول الخاص.

من أجل تشغيل خادم ويب بسيط باستخدام وحدة http، يجب أن تستدعي الشيفرةُ البرمجية التي مُرِرت إلى السياقِ التابعَ require('http')‎ على نفسه، أو أن يكون له مرجع إلى الوحدة http يمرر إليه. على سبيل المثال:

'use strict';
const vm = require('vm');

const code = `
((require) => {
  const http = require('http');

  http.createServer((request, response) => {
    response.writeHead(200, { 'Content-Type': 'text/plain' });
    response.end('Hello World\\n');
  }).listen(8124);

  console.log('Server running at http://127.0.0.1:8124/');
})`;

vm.runInThisContext(code)(require);

يشارك التابع require()‎ في الحالة السابقة الحالة مع السياق الذي مُرِر منه. وهذا قد يفرض المخاطر عند تنفيذ شيفرة برمجية غير موثوق بها، علي سبيل المثال تغيير الكائنات في السياق بطرق غير مرغوب فيها.

ماذا يعني أن يوضع كائن في السياق؟

جميع شيفرات JavaScript المنفذة داخل Node.js تعمل ضمن نطاق "السياق". فوفقًا لدليل V8 Embedder:

في V8، يكون السياق هو بيئة تنفيذ والتي تسمح لتطبيقات JavaScript المنفصلة، غير المترابطة أن تعمل في مثيل واحد من V8. يجب تحديد السياق المراد تشغيل أي شيفرات JavaScript فيه بشكل صريح.

عند استدعاء التابع vm.createContext()‎، يقترن كائن sandbox الذي مُرِر فيه (أو كائن مُنشَأ حديثًا إذا كان sandbox قيمته undefined) داخليا مع مثيل جديد من سياق V8. يوفر سياق V8 هذا تشغيل code باستخدام توابع الوحدة vm مع بيئة عامة معزولة والتي يمكن أن تعمل فيها. عملية إنشاء سياق V8 واقترانه مع الكائن sandbox هو ما تشير إليه هذه الوثيقة بأنه "الوضع في السياق" لكائن sandbox.

مصادر

صفحة الوحدة VM (تنفيذ JavaScript) في توثيق Node.js الرسمي.