Skip to content

V8

Source Code: lib/v8.js

يعرض الوحدة النمطية node:v8 واجهات برمجة تطبيقات خاصة بإصدار V8 المُدمج في ملف Node.js الثنائي. ويمكن الوصول إليه باستخدام:

js
const v8 = require('node:v8')

v8.cachedDataVersionTag()

مضاف في: v8.0.0

يُعيد عددًا صحيحًا يمثل علامة إصدار مُشتقة من إصدار V8، وأعلام سطر الأوامر، وميزات وحدة المعالجة المركزية المُكتشفة. وهذا مفيد لتحديد ما إذا كان المخزن المؤقت cachedData لـ vm.Script متوافقًا مع مثيل V8 هذا.

js
console.log(v8.cachedDataVersionTag()) // 3947234607
// القيمة التي تُعاد بواسطة v8.cachedDataVersionTag() مُشتقة من إصدار V8، وأعلام سطر الأوامر، وميزات وحدة المعالجة المركزية المُكتشفة. اختبر أن القيمة
// يتم تحديثها بالفعل عند تبديل الأعلام.
v8.setFlagsFromString('--allow_natives_syntax')
console.log(v8.cachedDataVersionTag()) // 183726201

v8.getHeapCodeStatistics()

مضاف في: v12.8.0

الحصول على إحصائيات حول التعليمات البرمجية وبيانات التعريف الخاصة بها في الكومة، راجع واجهة برمجة تطبيقات V8 GetHeapCodeAndMetadataStatistics. يُعيد كائنًا يحتوي على الخصائص التالية:

js
{
  code_and_metadata_size: 212208,
  bytecode_and_metadata_size: 161368,
  external_script_source_size: 1410794,
  cpu_profiler_metadata_size: 0,
}

v8.getHeapSnapshot([options])

[History]

الإصدارالتغييرات
v19.1.0دعم خيارات تكوين لقطة كومة الذاكرة.
v11.13.0تمت الإضافة في: v11.13.0
  • options <Object>

    • exposeInternals <boolean> إذا كان صحيحًا، فقم بعرض الأجزاء الداخلية في لقطة كومة الذاكرة. الافتراضي: false.
    • exposeNumericValues <boolean> إذا كان صحيحًا، فقم بعرض القيم العددية في الحقول الاصطناعية. الافتراضي: false.
  • المُرجَع: <stream.Readable> تيار قابل للقراءة يحتوي على لقطة كومة V8.

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

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

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

js
// طباعة لقطة كومة الذاكرة على وحدة التحكم
const v8 = require('node:v8')
const stream = v8.getHeapSnapshot()
stream.pipe(process.stdout)

v8.getHeapSpaceStatistics()

[History]

الإصدارالتغييرات
v7.5.0دعم القيم التي تتجاوز نطاق عدد صحيح بدون إشارة 32 بت.
v6.0.0تمت الإضافة في: v6.0.0

يرجع إحصائيات حول مسافات كومة V8، أي الأجزاء التي تشكل كومة V8. لا يمكن ضمان ترتيب مسافات الكومة، ولا توافر مساحة كومة، نظرًا لأن الإحصائيات يتم توفيرها عبر دالة V8 GetHeapSpaceStatistics وقد تتغير من إصدار V8 إلى التالي.

القيمة المُرجعة هي مصفوفة من الكائنات التي تحتوي على الخصائص التالية:

json
[
  {
    "space_name": "new_space",
    "space_size": 2063872,
    "space_used_size": 951112,
    "space_available_size": 80824,
    "physical_space_size": 2063872
  },
  {
    "space_name": "old_space",
    "space_size": 3090560,
    "space_used_size": 2493792,
    "space_available_size": 0,
    "physical_space_size": 3090560
  },
  {
    "space_name": "code_space",
    "space_size": 1260160,
    "space_used_size": 644256,
    "space_available_size": 960,
    "physical_space_size": 1260160
  },
  {
    "space_name": "map_space",
    "space_size": 1094160,
    "space_used_size": 201608,
    "space_available_size": 0,
    "physical_space_size": 1094160
  },
  {
    "space_name": "large_object_space",
    "space_size": 0,
    "space_used_size": 0,
    "space_available_size": 1490980608,
    "physical_space_size": 0
  }
]

v8.getHeapStatistics()

[السجل]

الإصدارالتغييرات
v7.5.0دعم القيم التي تتجاوز نطاق عدد صحيح بدون إشارة 32 بت.
v7.2.0تمت إضافة malloced_memory و peak_malloced_memory و does_zap_garbage.
v1.0.0تمت الإضافة في: v1.0.0

يرجع كائنًا يحتوي على الخصائص التالية:

total_heap_size قيمة total_heap_size هي عدد البايتات التي خصصها V8 للكومة. يمكن أن تنمو إذا احتاجت used_heap إلى مزيد من الذاكرة.

total_heap_size_executable قيمة total_heap_size_executable هي جزء من الكومة الذي يمكن أن يحتوي على شفرة قابلة للتنفيذ، بالبايت. وهذا يشمل الذاكرة المستخدمة بواسطة الشفرة المُجمعة بواسطة JIT وأي ذاكرة يجب الاحتفاظ بها قابلة للتنفيذ.

total_physical_size قيمة total_physical_size هي الذاكرة الفعلية المستخدمة بواسطة كومة V8، بالبايت. هذه هي كمية الذاكرة المُلتزمة (أو قيد الاستخدام) بدلاً من المحجوزة.

total_available_size قيمة total_available_size هي عدد بايتات الذاكرة المتاحة لكومة V8. تمثل هذه القيمة مقدار الذاكرة الإضافية التي يمكن أن يستخدمها V8 قبل تجاوز حد الكومة.

used_heap_size قيمة used_heap_size هي عدد البايتات التي يستخدمها حاليًا كائنات JavaScript الخاصة بـ V8. هذه هي الذاكرة الفعلية قيد الاستخدام ولا تتضمن الذاكرة التي تم تخصيصها ولكن لم يتم استخدامها بعد.

heap_size_limit قيمة heap_size_limit هي الحجم الأقصى لكومة V8، بالبايت (إما الحد الافتراضي، المُحدد بواسطة موارد النظام، أو القيمة المُمررة إلى خيار --max_old_space_size).

malloced_memory قيمة malloced_memory هي عدد البايتات المُخصصة من خلال malloc بواسطة V8.

peak_malloced_memory قيمة peak_malloced_memory هي ذروة عدد البايتات المُخصصة من خلال malloc بواسطة V8 خلال عمر العملية.

does_zap_garbage هو قيمة منطقية 0/1، والتي تُشير إلى ما إذا كان خيار --zap_code_space مُمكّنًا أم لا. هذا يجعل V8 يُعيد كتابة القمامة في الكومة بنمط بت. تصبح بصمة RSS (حجم المجموعة المُقيمة) أكبر لأنها تلمس باستمرار جميع صفحات الكومة وهذا يجعلها أقل عرضة للتبديل بواسطة نظام التشغيل.

number_of_native_contexts قيمة native_context هي عدد السياقات العليا النشطة حاليًا. يشير زيادة هذا العدد بمرور الوقت إلى تسرب للذاكرة.

number_of_detached_contexts قيمة detached_context هي عدد السياقات التي تم فصلها ولم يتم جمعها كقمامة بعد. يشير هذا العدد غير الصفري إلى تسرب محتمل للذاكرة.

total_global_handles_size قيمة total_global_handles_size هي الحجم الإجمالي للذاكرة لمقابض V8 العالمية.

used_global_handles_size قيمة used_global_handles_size هي حجم الذاكرة المُستخدمة لمقابض V8 العالمية.

external_memory قيمة external_memory هي حجم ذاكرة مُخازن الصفيف والسلاسل الخارجية.

js
{
  total_heap_size: 7326976,
  total_heap_size_executable: 4194304,
  total_physical_size: 7326976,
  total_available_size: 1152656,
  used_heap_size: 3476208,
  heap_size_limit: 1535115264,
  malloced_memory: 16384,
  peak_malloced_memory: 1127496,
  does_zap_garbage: 0,
  number_of_native_contexts: 1,
  number_of_detached_contexts: 0,
  total_global_handles_size: 8192,
  used_global_handles_size: 3296,
  external_memory: 318824
}

v8.queryObjects(ctor[, options])

مضاف في: v22.0.0، v20.13.0

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

مستقر: 1 استقرار: 1.1 - تطوير نشط

  • ctor <Function> مُنشئ يمكن استخدامه للبحث في سلسلة النموذج الأولي من أجل تصفية الكائنات الهدف في الذاكرة.

  • options <undefined> | <Object>

    • format <string> إذا كان 'count'، يتم إرجاع عدد الكائنات المتطابقة. إذا كان 'summary'، يتم إرجاع مصفوفة تحتوي على سلاسل مُلخص للكائنات المتطابقة.
  • مُخرجات: {number|Array

يشبه هذا واجهة برمجة التطبيقات [queryObjects()`](https://developer.chrome.com/docs/devtools/console/utilities#queryObjects-function) لوحدة تحكم Chrome DevTools. يمكن استخدامه للبحث عن الكائنات التي تحتوي على المُنشئ المطابق في سلسلة النموذج الأولي في الذاكرة بعد عملية جمع القمامة الكاملة، والتي يمكن أن تكون مفيدة لاختبارات انحدار تسرب الذاكرة. لتجنب النتائج المُفاجئة، يجب على المستخدمين تجنب استخدام واجهة برمجة التطبيقات هذه على المُنشئات التي لا يتحكمون في تنفيذها، أو على المُنشئات التي يمكن استدعائها من قبل أطراف أخرى في التطبيق.

لتجنب التسريبات العرضية، لا تُعيد واجهة برمجة التطبيقات هذه مراجع خام للكائنات الموجودة. بشكل افتراضي، تُعيد عدد الكائنات الموجودة. إذا كانت options.format هي 'summary'، فإنها تُعيد مصفوفة تحتوي على تمثيلات سلسلة مُوجزة لكل كائن. تشبه الرؤية المُقدمة في واجهة برمجة التطبيقات هذه ما تقدمه لقطة الذاكرة، بينما يمكن للمستخدمين توفير تكلفة التسلسل والتحليل وإجراء تصفية مباشرة للكائنات الهدف أثناء البحث.

لا يتم تضمين الكائنات المُنشأة فقط في سياق التنفيذ الحالي في النتائج.

js
const { queryObjects } = require('node:v8')
class A {
  foo = 'bar'
}
console.log(queryObjects(A)) // 0
const a = new A()
console.log(queryObjects(A)) // 1
// [ "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))

class B extends A {
  bar = 'qux'
}
const b = new B()
console.log(queryObjects(B)) // 1
// [ "B { foo: 'bar', bar: 'qux' }" ]
console.log(queryObjects(B, { format: 'summary' }))

// لاحظ أنه عندما تكون هناك فئات فرعية ترث من مُنشئ،
// يظهر المُنشئ أيضًا في سلسلة النموذج الأولي للنموذج الأولي للفئات الفرعية، لذلك سيتم تضمين النموذج الأولي للفئات الفرعية أيضًا في النتيجة.
console.log(queryObjects(A)) // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))
js
import { queryObjects } from 'node:v8'
class A {
  foo = 'bar'
}
console.log(queryObjects(A)) // 0
const a = new A()
console.log(queryObjects(A)) // 1
// [ "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))

class B extends A {
  bar = 'qux'
}
const b = new B()
console.log(queryObjects(B)) // 1
// [ "B { foo: 'bar', bar: 'qux' }" ]
console.log(queryObjects(B, { format: 'summary' }))

// لاحظ أنه عندما تكون هناك فئات فرعية ترث من مُنشئ،
// يظهر المُنشئ أيضًا في سلسلة النموذج الأولي للنموذج الأولي للفئات الفرعية، لذلك سيتم تضمين النموذج الأولي للفئات الفرعية أيضًا في النتيجة.
console.log(queryObjects(A)) // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }))

v8.setFlagsFromString(flags)

مضاف في: v1.0.0

يمكن استخدام طريقة v8.setFlagsFromString() لضبط علميات سطر أوامر V8 برمجيًا. يجب استخدام هذه الطريقة بحذر. قد يؤدي تغيير الإعدادات بعد بدء تشغيل الجهاز الظاهري إلى سلوك غير متوقع، بما في ذلك التعطل وفقدان البيانات؛ أو قد لا تفعل شيئًا على الإطلاق.

يمكن تحديد خيارات V8 المتاحة لإصدار من Node.js عن طريق تشغيل node --v8-options.

الاستخدام:

js
// طباعة أحداث GC إلى stdout لمدة دقيقة واحدة.
const v8 = require('node:v8')
v8.setFlagsFromString('--trace_gc')
setTimeout(() => {
  v8.setFlagsFromString('--notrace_gc')
}, 60e3)

v8.stopCoverage()

مضاف في: v15.1.0، v14.18.0، v12.22.0

تتيح طريقة v8.stopCoverage() للمستخدم إيقاف جمع تغطية البيانات التي بدأت بواسطة NODE_V8_COVERAGE، بحيث يمكن لـ V8 إصدار سجلات عدادات التنفيذ وتحسين التعليمات البرمجية. يمكن استخدام هذا بالتزامن مع v8.takeCoverage() إذا أراد المستخدم جمع التغطية عند الطلب.

v8.takeCoverage()

مضاف في: v15.1.0، v14.18.0، v12.22.0

تتيح طريقة v8.takeCoverage() للمستخدم كتابة التغطية التي بدأت بواسطة NODE_V8_COVERAGE على القرص عند الطلب. يمكن استدعاء هذه الطريقة عدة مرات خلال عمر العملية. في كل مرة سيتم إعادة تعيين عداد التنفيذ وسيتم كتابة تقرير تغطية جديد إلى الدليل المحدد بواسطة NODE_V8_COVERAGE.

عندما تكون العملية على وشك الخروج، سيتم كتابة تغطية أخيرة على القرص ما لم يتم استدعاء v8.stopCoverage() قبل خروج العملية.

v8.writeHeapSnapshot([filename[,options]])

[السجل]

الإصدارالتغييرات
v19.1.0دعم خيارات تكوين لقطة كومة البيانات.
v18.0.0سيتم الآن إلقاء استثناء إذا تعذر كتابة الملف.
v18.0.0جعل رموز الخطأ المُرتجعة متسقة عبر جميع الأنظمة الأساسية.
v11.13.0مضاف في: v11.13.0
  • filename <string> مسار الملف الذي سيتم حفظ لقطة كومة V8 فيه. إذا لم يتم تحديده، فسيتم إنشاء اسم ملف بنمط 'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'، حيث سيكون {pid} هو PID لعملية Node.js، و سيكون {thread_id} هو 0 عند استدعاء writeHeapSnapshot() من مؤشر ترابط Node.js الرئيسي أو معرف مؤشر ترابط عامل.

  • options <Object>

    • exposeInternals <boolean> إذا كان صحيحًا، فقم بكشف الأجزاء الداخلية في لقطة كومة البيانات. افتراضيًا: false.
    • exposeNumericValues <boolean> إذا كان صحيحًا، فقم بكشف القيم العددية في الحقول الاصطناعية. افتراضيًا: false.
  • المُرتجع: <string> اسم الملف الذي تم حفظ اللقطة فيه.

يولد لقطة من كومة V8 الحالية ويكتبها إلى ملف JSON. يهدف هذا الملف إلى استخدامه مع أدوات مثل Chrome DevTools. مخطط JSON غير موثق وهو خاص بمحرك V8، وقد يتغير من إصدار V8 إلى آخر.

تكون لقطة كومة البيانات خاصة بمعزل V8 واحد. عند استخدام خيوط العامل، لن تحتوي لقطة كومة البيانات التي تم إنشاؤها من المؤشر الترابط الرئيسي على أي معلومات حول العمال، والعكس صحيح.

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

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

js
const { writeHeapSnapshot } = require('node:v8')
const { Worker, isMainThread, parentPort } = require('node:worker_threads')

if (isMainThread) {
  const worker = new Worker(__filename)

  worker.once('message', filename => {
    console.log(`worker heapdump: ${filename}`)
    // الآن الحصول على heapdump للمؤشر الترابط الرئيسي.
    console.log(`main thread heapdump: ${writeHeapSnapshot()}`)
  })

  // أخبر العامل بإنشاء heapdump.
  worker.postMessage('heapdump')
} else {
  parentPort.once('message', message => {
    if (message === 'heapdump') {
      // توليد heapdump للعامل
      // وإرجاع اسم الملف إلى الأصل.
      parentPort.postMessage(writeHeapSnapshot())
    }
  })
}

v8.setHeapSnapshotNearHeapLimit(limit)

تم الإضافة في: v18.10.0، v16.18.0

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

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

واجهة برمجة التطبيقات هي عملية لا تعمل إذا تم تعيين --heapsnapshot-near-heap-limit بالفعل من سطر الأوامر أو تم استدعاء واجهة برمجة التطبيقات أكثر من مرة. يجب أن يكون limit عددًا صحيحًا موجبًا. راجع --heapsnapshot-near-heap-limit لمزيد من المعلومات.

واجهة برمجة تسلسل البيانات

توفر واجهة برمجة تسلسل البيانات وسائل لتسلسل قيم JavaScript بطريقة تتوافق مع خوارزمية الاستنساخ المُبنيّة HTML.

النسق متوافق مع الإصدارات السابقة (أي آمن لحفظه على القرص). قد تؤدي قيم JavaScript المتساوية إلى نتائج مُسلسلة مختلفة.

v8.serialize(value)

تم الإضافة في: v8.0.0

يستخدم DefaultSerializer لتسلسل value إلى مُخزن مؤقت.

سيتم طرح ERR_BUFFER_TOO_LARGE عند محاولة تسلسل كائن ضخم يتطلب مُخزنًا مؤقتًا أكبر من buffer.constants.MAX_LENGTH.

v8.deserialize(buffer)

تم الإضافة في: v8.0.0

يستخدم DefaultDeserializer مع الخيارات الافتراضية لقراءة قيمة JS من مُخزن مؤقت.

الصنف: v8.Serializer

مضاف في: v8.0.0

new Serializer()

يُنشئ كائن Serializer جديدًا.

serializer.writeHeader()

يكتب رأسًا، والذي يتضمن إصدار تنسيق التسلسل.

serializer.writeValue(value)

يُسلسل قيمة JavaScript ويضيف التمثيل المُسلسل إلى المخزن المؤقت الداخلي.

يُلقي هذا خطأ إذا تعذر تسلسل value.

serializer.releaseBuffer()

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

serializer.transferArrayBuffer(id, arrayBuffer)

يُشير إلى أن ArrayBuffer لديه محتوياته المُنقلّة خارج النطاق. مرّر ArrayBuffer المُقابِل في سياق إلغاء التسلسل إلى deserializer.transferArrayBuffer().

serializer.writeUint32(value)

اكتب عددًا صحيحًا بدون إشارة 32 بت. للاستخدام داخل مُخصص serializer._writeHostObject().

serializer.writeUint64(hi, lo)

اكتب عددًا صحيحًا بدون إشارة 64 بت، مُقسّمًا إلى أجزاء عالية ومنخفضة 32 بت. للاستخدام داخل مُخصص serializer._writeHostObject().

serializer.writeDouble(value)

كتابة قيمة عددية من نوع JS. للاستخدام داخل مُهيئ مخصص serializer._writeHostObject().

serializer.writeRawBytes(buffer)

كتابة بايت خام في المخزن المؤقت الداخلي للمُهيئ. سيحتاج المُحلل إلى طريقة لحساب طول المخزن المؤقت. للاستخدام داخل مُهيئ مخصص serializer._writeHostObject().

serializer._writeHostObject(object)

يتم استدعاء هذه الطريقة لكتابة نوع من كائنات المضيف، أي كائن تم إنشاؤه بواسطة ارتباطات C++ الأصلية. إذا لم يكن من الممكن مُهيئة object، فيجب إطلاق استثناء مناسب.

هذه الطريقة غير موجودة في فئة Serializer نفسها ولكن يمكن توفيرها بواسطة الفئات الفرعية.

serializer._getDataCloneError(message)

يتم استدعاء هذه الطريقة لإنشاء كائنات خطأ سيتم إلقاؤها عندما لا يمكن استنساخ كائن ما.

تُرجع هذه الطريقة افتراضيًا مُنشئ Error ويمكن تجاوزها في الفئات الفرعية.

serializer._getSharedArrayBufferId(sharedArrayBuffer)

يتم استدعاء هذه الطريقة عندما يقوم المُهيئ بتهيئة كائن SharedArrayBuffer. يجب أن تُرجع معرفًا صحيحًا مكونًا من 32 بت بدون إشارة للكائن، باستخدام نفس المعرف إذا تم تهيئة هذا SharedArrayBuffer بالفعل. عند إلغاء التهيئة، سيتم تمرير هذا المعرف إلى deserializer.transferArrayBuffer().

إذا تعذر تهيئة الكائن، فيجب إطلاق استثناء.

هذه الطريقة غير موجودة في فئة Serializer نفسها ولكن يمكن توفيرها بواسطة الفئات الفرعية.

serializer._setTreatArrayBufferViewsAsHostObjects(flag)

يشير إلى ما إذا كان سيتم التعامل مع كائنات TypedArray و DataView كائنات مضيفة، أي تمريرها إلى serializer._writeHostObject().

الصف: v8.Deserializer

مضاف في: v8.0.0

new Deserializer(buffer)

يُنشئ كائن Deserializer جديدًا.

deserializer.readHeader()

يقوم بقراءة و التحقق من صحة الرأس (بما في ذلك إصدار التنسيق). قد، على سبيل المثال، يرفض تنسيق سلكي غير صالح أو غير مدعوم. في هذه الحالة، يتم طرح Error.

deserializer.readValue()

يُزيل تسلسل قيمة JavaScript من العازل ويرجعها.

deserializer.transferArrayBuffer(id, arrayBuffer)

يُشير إلى أن ArrayBuffer يحتوي على محتوياته التي تم نقلها خارج النطاق. قم بتمرير ArrayBuffer المقابل في سياق التسلسل إلى serializer.transferArrayBuffer() (أو قم بإرجاع id من serializer._getSharedArrayBufferId() في حالة SharedArrayBuffers).

deserializer.getWireFormatVersion()

يقوم بقراءة إصدار تنسيق السلك الأساسي. من المحتمل أن يكون مفيدًا في الغالب للكود القديم الذي يقرأ إصدارات تنسيق سلك قديمة. قد لا يتم استدعاء هذه الدالة قبل .readHeader().

deserializer.readUint32()

يقوم بقراءة عدد صحيح بدون إشارة 32 بت خام وإعادته. للاستخدام داخل مُخصص deserializer._readHostObject().

deserializer.readUint64()

يقوم بقراءة عدد صحيح بدون إشارة 64 بت خام وإعادته كمصفوفة [hi, lo] مع مُدخلين صحيحين بدون إشارة 32 بت. للاستخدام داخل مُخصص deserializer._readHostObject().

deserializer.readDouble()

يقوم بقراءة قيمة number من JS. للاستخدام داخل مُخصص deserializer._readHostObject().

deserializer.readRawBytes(length)

يقوم بقراءة البايت الخام من المخزن المؤقت الداخلي لـ deserializer. يجب أن يتوافق مُعامل length مع طول المخزن المؤقت الذي تم تمريره إلى serializer.writeRawBytes(). للاستخدام داخل مُخصص deserializer._readHostObject().

deserializer._readHostObject()

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

هذه الطريقة غير موجودة في فئة Deserializer نفسها، ولكن يمكن توفيرها بواسطة الفئات الفرعية.

صنف: v8.DefaultSerializer

مضاف في: v8.0.0

صنف فرعي من Serializer يقوم بتسلسل كائنات TypedArray (خاصةً Buffer) و DataView كائنات مضيفة، ويخزن فقط الجزء من ArrayBuffer الأساسية التي تشير إليها.

صنف: v8.DefaultDeserializer

مضاف في: v8.0.0

صنف فرعي من Deserializer يتوافق مع التنسيق الذي كتبه DefaultSerializer.

خطافات الوعود

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

js
import { promiseHooks } from 'node:v8'

// هناك أربعة أحداث لدورة الحياة تنتجها الوعود:

// يمثل حدث `init` إنشاء وعد. يمكن أن يكون هذا إنشاءً مباشرًا كما هو الحال مع `new Promise(...)` أو متابعة مثل `then()` أو `catch()`. يحدث أيضًا كلما تم استدعاء دالة غير متزامنة أو قامت بـ `await`. إذا تم إنشاء وعد متابعة، فسيكون `parent` هو الوعد الذي هو متابعة منه.
function init(promise, parent) {
  console.log('تم إنشاء وعد', { promise, parent })
}

// يحدث حدث `settled` عندما يتلقى وعد قيمة حل أو رفض. قد يحدث هذا بشكل متزامن مثل عند استخدام `Promise.resolve()` على إدخال غير وعد.
function settled(promise) {
  console.log('تم حل وعد أو رفضه', { promise })
}

// يتم تشغيل حدث `before` مباشرةً قبل تشغيل مُعالِج `then()` أو `catch()` أو استئناف تنفيذ `await`.
function before(promise) {
  console.log('على وشك أن يستدعي وعد مُعالِج then', { promise })
}

// يتم تشغيل حدث `after` مباشرةً بعد تشغيل مُعالِج `then()` أو عندما يبدأ `await` بعد الاستئناف من آخر.
function after(promise) {
  console.log('انتهى وعد من استدعاء مُعالِج then', { promise })
}

// يمكن بدء خطافات دورة الحياة وإيقافها بشكل فردي
const stopWatchingInits = promiseHooks.onInit(init)
const stopWatchingSettleds = promiseHooks.onSettled(settled)
const stopWatchingBefores = promiseHooks.onBefore(before)
const stopWatchingAfters = promiseHooks.onAfter(after)

// أو يمكن بدءها وإيقافها في مجموعات
const stopHookSet = promiseHooks.createHook({
  init,
  settled,
  before,
  after,
})

// لإيقاف خطاف، اتصل بالدالة التي تم إرجاعها عند إنشائها.
stopWatchingInits()
stopWatchingSettleds()
stopWatchingBefores()
stopWatchingAfters()
stopHookSet()

promiseHooks.onInit(init)

أضيف في: v17.1.0، v16.14.0

  • init <Function> دالة الاستدعاء init التي تُستدعى عند إنشاء وعد.
  • الإرجاع: <Function> استدعاء لإيقاف الخطاف.

يجب أن تكون دالة الخطاف init دالة عادية. سيؤدي توفير دالة غير متزامنة إلى إلقاء استثناء لأنها ستنتج حلقة مُهام صغيرة لانهائية.

js
import { promiseHooks } from 'node:v8'

const stop = promiseHooks.onInit((promise, parent) => {})
js
const { promiseHooks } = require('node:v8')

const stop = promiseHooks.onInit((promise, parent) => {})

promiseHooks.onSettled(settled)

أضيف في: v17.1.0، v16.14.0

  • settled <Function> دالة الاستدعاء settled التي تُستدعى عند حل أو رفض وعد.
  • الإرجاع: <Function> استدعاء لإيقاف الخطاف.

يجب أن تكون دالة الخطاف settled دالة عادية. سيؤدي توفير دالة غير متزامنة إلى إلقاء استثناء لأنها ستنتج حلقة مُهام صغيرة لانهائية.

js
import { promiseHooks } from 'node:v8'

const stop = promiseHooks.onSettled(promise => {})
js
const { promiseHooks } = require('node:v8')

const stop = promiseHooks.onSettled(promise => {})

promiseHooks.onBefore(before)

أضيف في: v17.1.0، v16.14.0

  • before <Function> دالة الاستدعاء before التي تُستدعى قبل تنفيذ استمرار وعد.
  • الإرجاع: <Function> استدعاء لإيقاف الخطاف.

يجب أن تكون دالة الخطاف before دالة عادية. سيؤدي توفير دالة غير متزامنة إلى إلقاء استثناء لأنها ستنتج حلقة مُهام صغيرة لانهائية.

js
import { promiseHooks } from 'node:v8'

const stop = promiseHooks.onBefore(promise => {})
js
const { promiseHooks } = require('node:v8')

const stop = promiseHooks.onBefore(promise => {})

promiseHooks.onAfter(after)

تم الإضافة في: v17.1.0، v16.14.0

  • after <Function> دالة الاستدعاء after التي سيتم استدعاؤها بعد تنفيذ استمرار الوعد.
  • الإرجاع: <Function> دعوة لإيقاف الخطاف.

يجب أن تكون دالة الخطاف after دالة عادية. إنشاء دالة غير متزامنة سيرمي خطأ لأنه سيؤدي إلى حلقة مايكروتاسك لانهائية.

js
import { promiseHooks } from 'node:v8'

const stop = promiseHooks.onAfter(promise => {})
js
const { promiseHooks } = require('node:v8')

const stop = promiseHooks.onAfter(promise => {})

promiseHooks.createHook(callbacks)

تم الإضافة في: v17.1.0، v16.14.0

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

تسجل الدوال التي سيتم استدعاؤها لأحداث عمر مختلفة لكل وعد.

يتم استدعاء استدعاءات الدوال init()/before()/after()/settled() للأحداث ذات الصلة خلال دورة حياة الوعد.

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

js
import { promiseHooks } from 'node:v8'

const stopAll = promiseHooks.createHook({
  init(promise, parent) {},
})
js
const { promiseHooks } = require('node:v8')

const stopAll = promiseHooks.createHook({
  init(promise, parent) {},
})

تعليقات هوك

تم تصنيف الأحداث الرئيسية في دورة حياة الوعد إلى أربعة مجالات: إنشاء وعد، قبل/بعد استدعاء مُعالِج الاستمرار أو حول انتظار، وعندما يُحلّ أو يُرفض الوعد.

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

نظرًا لأن الوعود عبارة عن موارد غير متزامنة يتم تتبع دورة حياتها عبر آلية تعليقات الوعد، يجب ألا تكون عمليات استدعاء init() و before() و after() و settled() وظائف غير متزامنة لأنها تُنشئ المزيد من الوعود التي من شأنها أن تُنتج حلقة لانهائية.

في حين يتم استخدام هذا الواجهة البرمجية لتغذية أحداث الوعد في async_hooks، فإن الترتيب بين الاثنين غير محدد. كلا الواجهتين البرمجيتين متعددة المستأجرين، وبالتالي يمكنهما إنتاج أحداث بأي ترتيب بالنسبة لبعضهما البعض.

init(promise, parent)

  • promise <Promise> الوعد الذي يتم إنشاؤه.
  • parent <Promise> الوعد الذي تم الاستمرار منه، إذا كان ذلك ينطبق.

يتم استدعاء هذه الوظيفة عند إنشاء وعد. هذا لا يعني أن أحداث before/after المقابلة ستحدث، بل فقط أن الاحتمال موجود. سيحدث هذا إذا تم إنشاء وعد دون الحصول على استمرار على الإطلاق.

before(promise)

يتم استدعاء هذه الوظيفة قبل تنفيذ استمرار الوعد. يمكن أن يكون هذا في شكل مُعالِجات then() أو catch() أو finally() أو استئناف await.

سيتم استدعاء مُعالِج before من 0 إلى N مرة. سيتم عادةً استدعاء مُعالِج before 0 مرة إذا لم يتم إجراء أي استمرار للوعد على الإطلاق. قد يتم استدعاء مُعالِج before عدة مرات في حالة إجراء العديد من الاستمرارات من نفس الوعد.

after(promise)

يطلق مباشرة بعد تنفيذ استمرار الوعد. قد يكون هذا بعد مُعالِج then() أو catch() أو finally() أو قبل await بعد await آخر.

settled(promise)

يطلق عندما يتلقى الوعد قيمة حل أو رفض. قد يحدث هذا بشكل متزامن في حالة Promise.resolve() أو Promise.reject().

واجهة برمجة تطبيقات لقطة بدء التشغيل

مضاف في: v18.6.0، v16.17.0

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

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

يمكن استخدام واجهة v8.startupSnapshot لإضافة خطافات تسلسل وتسلسل عكسي للقطات بدء التشغيل المخصصة.

bash
$ node --snapshot-blob snapshot.blob --build-snapshot entry.js
# هذا يطلق عملية مع اللقطة {#this-launches-a-process-with-the-snapshot}
$ node --snapshot-blob snapshot.blob

في المثال أعلاه، يمكن لـ entry.js استخدام طرق من واجهة v8.startupSnapshot لتحديد كيفية حفظ المعلومات للكائنات المخصصة في اللقطة أثناء التسلسل وكيف يمكن استخدام المعلومات لمزامنة هذه الكائنات أثناء إلغاء تسلسل اللقطة. على سبيل المثال، إذا كان entry.js يحتوي على البرنامج النصي التالي:

js
'use strict'

const fs = require('node:fs')
const zlib = require('node:zlib')
const path = require('node:path')
const assert = require('node:assert')

const v8 = require('node:v8')

class BookShelf {
  storage = new Map()

  // قراءة سلسلة من الملفات من الدليل وتخزينها في التخزين.
  constructor(directory, books) {
    for (const book of books) {
      this.storage.set(book, fs.readFileSync(path.join(directory, book)))
    }
  }

  static compressAll(shelf) {
    for (const [book, content] of shelf.storage) {
      shelf.storage.set(book, zlib.gzipSync(content))
    }
  }

  static decompressAll(shelf) {
    for (const [book, content] of shelf.storage) {
      shelf.storage.set(book, zlib.gunzipSync(content))
    }
  }
}

// __dirname هنا هو المكان الذي يتم وضع البرنامج النصي للقطة فيه
// أثناء وقت بناء اللقطة.
const shelf = new BookShelf(__dirname, ['book1.en_US.txt', 'book1.es_ES.txt', 'book2.zh_CN.txt'])

assert(v8.startupSnapshot.isBuildingSnapshot())
// عند تسلسل اللقطة، قم بضغط الكتب لتقليل الحجم.
v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf)
// عند إلغاء تسلسل اللقطة، قم بفك ضغط الكتب.
v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf)
v8.startupSnapshot.setDeserializeMainFunction(shelf => {
  // يتم تحديث process.env و process.argv أثناء إلغاء تسلسل اللقطة.
  const lang = process.env.BOOK_LANG || 'en_US'
  const book = process.argv[1]
  const name = `${book}.${lang}.txt`
  console.log(shelf.storage.get(name))
}, shelf)

سيقوم الثنائي الناتج بطباعة البيانات التي تم إلغاء تسلسلها من اللقطة أثناء بدء التشغيل، باستخدام process.env و process.argv المُحدّثين للعملية التي تم إطلاقها:

bash
$ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
# يطبع محتوى book1.es_ES.txt الذي تم إلغاء تسلسله من اللقطة. {#prints-content-of-book1es_estxt-deserialized-from-the-snapshot}

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

v8.startupSnapshot.addSerializeCallback(callback[, data])

تم الإضافة في: v18.6.0، v16.17.0

  • callback <Function> دالة مُستدعاة قبل التسلسل.
  • data <any> بيانات اختيارية سيتم تمريرها إلى callback عند استدعائها.

إضافة دالة مُستدعاة سيتم استدعاؤها عندما تكون مثيل Node.js على وشك أن يتم تسلسله إلى لقطة والخروج. يمكن استخدام هذا لإطلاق الموارد التي لا ينبغي أو لا يمكن تسلسلها أو لتحويل بيانات المستخدم إلى شكل أكثر ملاءمة للتسلسل.

يتم تشغيل الدوال المُستدعاة بالترتيب الذي تمت إضافتها به.

v8.startupSnapshot.addDeserializeCallback(callback[, data])

تم الإضافة في: v18.6.0، v16.17.0

  • callback <Function> دالة مُستدعاة بعد فك تسلسل اللقطة.
  • data <any> بيانات اختيارية سيتم تمريرها إلى callback عند استدعائها.

إضافة دالة مُستدعاة سيتم استدعاؤها عندما يتم فك تسلسل مثيل Node.js من لقطة. سيتم تسلسل callback و data (إذا تم توفيره) إلى اللقطة، ويمكن استخدامهما لإعادة تهيئة حالة التطبيق أو لإعادة الحصول على الموارد التي يحتاجها التطبيق عند إعادة تشغيل التطبيق من اللقطة.

يتم تشغيل الدوال المُستدعاة بالترتيب الذي تمت إضافتها به.

v8.startupSnapshot.setDeserializeMainFunction(callback[, data])

تم الإضافة في: v18.6.0، v16.17.0

  • callback <Function> دالة مُستدعاة كنقطة دخول بعد فك تسلسل اللقطة.
  • data <any> بيانات اختيارية سيتم تمريرها إلى callback عند استدعائها.

هذا يحدد نقطة دخول تطبيق Node.js عندما يتم فك تسلسله من لقطة. يمكن استدعاء هذا مرة واحدة فقط في برنامج إنشاء اللقطة. إذا تم استدعاؤه، فلن يحتاج التطبيق المُفكك تسلسله إلى برنامج نقطة دخول إضافي للبدء وسوف يقوم ببساطة باستدعاء الدالة المُستدعاة بالإضافة إلى البيانات المُفككة تسلسله (إذا تم توفيرها)، وإلا فلا يزال يتعين توفير برنامج نقطة دخول للتطبيق المُفكك تسلسله.

v8.startupSnapshot.isBuildingSnapshot()

أضيف في: v18.6.0، v16.17.0

ترجع true إذا تم تشغيل مثيل Node.js لإنشاء لقطة.

الصنف: v8.GCProfiler

أضيف في: v19.6.0، v18.15.0

يُجمع هذا الـ API بيانات GC في مؤشر ترابط حالي.

new v8.GCProfiler()

أضيف في: v19.6.0، v18.15.0

إنشاء مثيل جديد من فئة v8.GCProfiler.

profiler.start()

أضيف في: v19.6.0، v18.15.0

بدء جمع بيانات GC.

profiler.stop()

أضيف في: v19.6.0، v18.15.0

إيقاف جمع بيانات GC وإرجاع كائن. محتوى الكائن كما يلي.

json
{
  "version": 1,
  "startTime": 1674059033862,
  "statistics": [
    {
      "gcType": "Scavenge",
      "beforeGC": {
        "heapStatistics": {
          "totalHeapSize": 5005312,
          "totalHeapSizeExecutable": 524288,
          "totalPhysicalSize": 5226496,
          "totalAvailableSize": 4341325216,
          "totalGlobalHandlesSize": 8192,
          "usedGlobalHandlesSize": 2112,
          "usedHeapSize": 4883840,
          "heapSizeLimit": 4345298944,
          "mallocedMemory": 254128,
          "externalMemory": 225138,
          "peakMallocedMemory": 181760
        },
        "heapSpaceStatistics": [
          {
            "spaceName": "read_only_space",
            "spaceSize": 0,
            "spaceUsedSize": 0,
            "spaceAvailableSize": 0,
            "physicalSpaceSize": 0
          }
        ]
      },
      "cost": 1574.14,
      "afterGC": {
        "heapStatistics": {
          "totalHeapSize": 6053888,
          "totalHeapSizeExecutable": 524288,
          "totalPhysicalSize": 5500928,
          "totalAvailableSize": 4341101384,
          "totalGlobalHandlesSize": 8192,
          "usedGlobalHandlesSize": 2112,
          "usedHeapSize": 4059096,
          "heapSizeLimit": 4345298944,
          "mallocedMemory": 254128,
          "externalMemory": 225138,
          "peakMallocedMemory": 181760
        },
        "heapSpaceStatistics": [
          {
            "spaceName": "read_only_space",
            "spaceSize": 0,
            "spaceUsedSize": 0,
            "spaceAvailableSize": 0,
            "physicalSpaceSize": 0
          }
        ]
      }
    }
  ],
  "endTime": 1674059036865
}

فيما يلي مثال.

js
const { GCProfiler } = require('node:v8')
const profiler = new GCProfiler()
profiler.start()
setTimeout(() => {
  console.log(profiler.stop())
}, 1000)