Skip to content

واجهة نظام WebAssembly (WASI)

[مستقر: 1 - تجريبي]

مستقر: 1 الثبات: 1 - تجريبي

لا يوفر مُعامل node:wasi حاليًا خصائص أمان نظام الملفات الشاملة التي توفرها بعض بيئات تشغيل WASI. قد يتم أو لا يتم تنفيذ الدعم الكامل لعزل نظام الملفات الآمن في المستقبل. في هذه الأثناء، لا تعتمد عليه لتشغيل التعليمات البرمجية غير الموثوقة.

رمز المصدر: lib/wasi.js

يوفر واجهة برمجة التطبيقات WASI تطبيقًا لمواصفات واجهة نظام WebAssembly. يمنح WASI تطبيقات WebAssembly حق الوصول إلى نظام التشغيل الأساسي عبر مجموعة من الوظائف الشبيهة بـ POSIX.

js
import { readFile } from 'node:fs/promises'
import { WASI } from 'node:wasi'
import { argv, env } from 'node:process'

const wasi = new WASI({
  version: 'preview1',
  args: argv,
  env,
  preopens: {
    '/local': '/some/real/path/that/wasm/can/access',
  },
})

const wasm = await WebAssembly.compile(await readFile(new URL('./demo.wasm', import.meta.url)))
const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject())

wasi.start(instance)
js
'use strict'
const { readFile } = require('node:fs/promises')
const { WASI } = require('node:wasi')
const { argv, env } = require('node:process')
const { join } = require('node:path')

const wasi = new WASI({
  version: 'preview1',
  args: argv,
  env,
  preopens: {
    '/local': '/some/real/path/that/wasm/can/access',
  },
})

;(async () => {
  const wasm = await WebAssembly.compile(await readFile(join(__dirname, 'demo.wasm')))
  const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject())

  wasi.start(instance)
})()

لتشغيل المثال أعلاه، أنشئ ملف تنسيق نص WebAssembly جديدًا باسم demo.wat:

text
(module
    ;; استيراد دالة fd_write WASI المطلوبة التي ستكتب متجهات الإدخال/الإخراج المعطاة إلى stdout
    ;; توقيع الدالة لـ fd_write هو:
    ;; (وصف الملف، *iovs، iovs_len، nwritten) ->  يرجع عدد البايت المكتوبة
    (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))

    (memory 1)
    (export "memory" (memory 0))

    ;; كتابة 'hello world\n' إلى الذاكرة عند إزاحة 8 بايت
    ;; لاحظ سطر جديد في النهاية وهو مطلوب لظهور النص
    (data (i32.const 8) "hello world\n")

    (func $main (export "_start")
        ;; إنشاء متجه إدخال/إخراج جديد داخل ذاكرة خطية
        (i32.store (i32.const 0) (i32.const 8))  ;; iov.iov_base - هذا مؤشر إلى بداية سلسلة 'hello world\n'
        (i32.store (i32.const 4) (i32.const 12))  ;; iov.iov_len - طول سلسلة 'hello world\n'

        (call $fd_write
            (i32.const 1) ;; file_descriptor - 1 لـ stdout
            (i32.const 0) ;; *iovs - المؤشر إلى مصفوفة iov، المخزنة في موقع الذاكرة 0
            (i32.const 1) ;; iovs_len - نقوم بطباعة سلسلة واحدة مخزنة في iov - لذا واحدة.
            (i32.const 20) ;; nwritten - مكان في الذاكرة لتخزين عدد البايت المكتوبة
        )
        drop ;; تجاهل عدد البايت المكتوبة من أعلى المكدس
    )
)

استخدم wabt لترجمة .wat إلى .wasm

bash
wat2wasm demo.wat

الأمان

[السجل]

الإصدارالتغييرات
v21.2.0, v20.11.0توضيح خصائص أمان WASI.
v21.2.0, v20.11.0تمت الإضافة في: v21.2.0, v20.11.0

يوفر WASI نموذجًا قائمًا على الإمكانيات، حيث يتم تزويد التطبيقات بإمكانيات مخصصة خاصة بها env, preopens, stdin, stdout, stderr, و exit.

لا يوفر نموذج التهديد الحالي لـ Node.js حماية آمنة كما هو موجود في بعض بيئات تشغيل WASI.

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

الفئة: WASI

تمت الإضافة في: v13.3.0, v12.16.0

توفر فئة WASI واجهة برمجة تطبيقات نظام WASI وطرق مساعدة إضافية للعمل مع التطبيقات القائمة على WASI. يمثل كل مثيل WASI بيئة مميزة.

new WASI([options])

[السجل]

الإصدارالتغييرات
v20.1.0تم تغيير القيمة الافتراضية لـ returnOnExit إلى true.
v20.0.0أصبح خيار الإصدار مطلوبًا الآن وليس له قيمة افتراضية.
v19.8.0تمت إضافة حقل الإصدار إلى الخيارات.
v13.3.0, v12.16.0تمت الإضافة في: v13.3.0, v12.16.0
  • options <Object>
    • args <Array> مصفوفة من السلاسل التي سيرى تطبيق WebAssembly أنها وسيطات سطر الأوامر. الوسيطة الأولى هي المسار الظاهري لأمر WASI نفسه. الافتراضي: [].
    • env <Object> كائن مشابه لـ process.env سيرى تطبيق WebAssembly أنه بيئته. الافتراضي: {}.
    • preopens <Object> يمثل هذا الكائن بنية الدليل المحلي لتطبيق WebAssembly. تُعامل مفاتيح السلسلة في preopens على أنها أدلة داخل نظام الملفات. القيم المقابلة في preopens هي المسارات الحقيقية لتلك الأدلة على جهاز المضيف.
    • returnOnExit <boolean> بشكل افتراضي، عندما تستدعي تطبيقات WASI __wasi_proc_exit()، ستعيد wasi.start() رمز الخروج المحدد بدلاً من إنهاء العملية. سيؤدي تعيين هذا الخيار إلى false إلى إنهاء عملية Node.js برمز الخروج المحدد بدلاً من ذلك. الافتراضي: true.
    • stdin <integer> مُعرّف الملف المستخدم كمدخل قياسي في تطبيق WebAssembly. الافتراضي: 0.
    • stdout <integer> مُعرّف الملف المستخدم كمخرج قياسي في تطبيق WebAssembly. الافتراضي: 1.
    • stderr <integer> مُعرّف الملف المستخدم كخطأ قياسي في تطبيق WebAssembly. الافتراضي: 2.
    • version <string> إصدار WASI المطلوب. الإصدارات المدعومة حاليًا هي unstable و preview1. هذا الخيار إلزامي.

wasi.getImportObject()

تم الإضافة في: v19.8.0

إرجاع كائن استيراد يمكن تمريره إلى WebAssembly.instantiate() إذا لم تكن هناك حاجة إلى استيرادات WASM أخرى بخلاف تلك التي يوفرها WASI.

إذا تم تمرير الإصدار unstable إلى المُنشئ، فسيتم إرجاع ما يلي:

json
{ wasi_unstable: wasi.wasiImport }

إذا تم تمرير الإصدار preview1 إلى المُنشئ أو لم يتم تحديد أي إصدار، فسيتم إرجاع ما يلي:

json
{ wasi_snapshot_preview1: wasi.wasiImport }

wasi.start(instance)

تم الإضافة في: v13.3.0، v12.16.0

محاولة بدء تنفيذ instance كأمر WASI من خلال استدعاء تصديره _start(). إذا لم يحتوي instance على تصدير _start()، أو إذا كان instance يحتوي على تصدير _initialize()، فسيتم طرح استثناء.

يتطلب start() أن يقوم instance بتصدير ذاكرة من نوع WebAssembly.Memory باسم memory. إذا لم يكن لدى instance تصدير memory، فسيتم طرح استثناء.

إذا تم استدعاء start() أكثر من مرة، فسيتم طرح استثناء.

wasi.initialize(instance)

تم الإضافة في: v14.6.0، v12.19.0

محاولة تهيئة instance كجهاز استقبال WASI من خلال استدعاء تصديره _initialize()، إذا كان موجودًا. إذا كان instance يحتوي على تصدير _start()، فسيتم طرح استثناء.

يتطلب initialize() أن يقوم instance بتصدير ذاكرة من نوع WebAssembly.Memory باسم memory. إذا لم يكن لدى instance تصدير memory، فسيتم طرح استثناء.

إذا تم استدعاء initialize() أكثر من مرة، فسيتم طرح استثناء.

wasi.wasiImport

تم الإضافة في: v13.3.0، v12.16.0

wasiImport هو كائن ينفذ واجهة برمجة تطبيقات نظام استدعاء WASI. يجب تمرير هذا الكائن كاستيراد wasi_snapshot_preview1 أثناء إنشاء مثيل WebAssembly.Instance.