يازما يازمىغىلى بىر يىلغا يېقىن ۋاقىت بوپتۇ، مۇددىتىمنى ئۇزارتىپ قوياي 😁
سوئال: V8 دىگەن نىمە؟
جاۋاب: V8 بولسا گۇگۇل Chrome تور كۆرگۈچ ئەترىتى C++ بىلەن يېزىپ چىققان دۇنيادىكى ئىجرا بولۇش سۈرئىتى ئەڭ تىز ئوچۇق كودلۇق JavaScript ماتورى بولۇپ Google chrome, Microsoft edge (chromium based), Node.js, Deno, MongoDB, Electron ۋە باشقا يادىمغا كېلىپ بولالمىغان تۈر ۋە مەھسۇلاتلاردا ئىشلىتىلىۋاتىدۇ،
سوئال: بۇنىڭ بىلەن نىمە قىلالايمىز؟ نېمىشقا بۇنداق قىلىمىز؟
جاۋاب: بىزمۇ ئۆزىمىزنىڭ پروگراممىسىغا V8 نى سىڭدۈرۈپ ئىشلىتىش ئارقىلىق پروگراممىمىزنى JavaScript نى ئىجرا قىلىش ئىمكانىيىتىگە ئىگە قىلالايمىز،
مەسىلەن ئۈچ ئۆلچەملىك لاھىيە يۇمشاق دېتاللىرى، چوڭ تىپتىكى يۇمشاق دېتاللار ھەممىسى دىگۈدەك JavaScript, Python غا ئوخشاش سىكرىپىت (قوليازما) تىللار ئارقىلىق قىستۇرما ۋە كىڭەيتمە يېزىشنى قوللايدۇ،
- مەسىلەن Adobe شىركىتىنىڭ Photoshop, After effects, Illustrator ۋە باشقا يۇمشاق دېتاللىرى ھەممىسى JavaScript بىلەن قىستۇرما ئېچىشنى قوللايدۇ،
- Blender بولسا ئوچۇق كودلۇق ھەقسىز ئۈچ ئۆلچەملىك لاھىيە يۇمشاق دېتالى بولۇپ Python بىلەن قىستۇرما ئېچىشنى قوللايدۇ
- Houdini بولسا ئۈچ ئۆلچەملىك VFX ۋە ئالاھىدە ئۈنۈم تەقلىدلەش، پروگراممىلاشتۇرۇلغان ئۈچ ئۆلچەملىك مودىل ھاسىللاش (Simulation, Procedural modeling) Vex ۋە Python بىلەن Attribute wrangler غا پروگرامما يېزىش ۋە Node لارنىڭ خاسلىقىنى Python, Vex ئىپادىسى (Expression) بىلەن قىممەت بېرىشنى قوللايدۇ،
- Autodesk Maya, Autodesk 3Ds Max قاتارلىقلار كەسپىي ئۈچ ئۆلچەملىك لاھىيە يۇمشاق دېتاللىرى بولۇپ كىنو-فىلىم، كارتون فىلىم، ئويۇن قاتارلىقلارنى ئىشلەشكە ئىشلىتىلىدۇ، بۇلارمۇ Python بىلەن قىستۇرما، كىڭەيتمە ئېچىشنى قوللايدۇ.
- Visual studio code بولسا JavaScript, TypeScript ئارقىلىق قىستۇرما ئېچىشنى قوللايدۇ،
ئەلۋەتتە سىزمۇ V8 كە C, C++, Rust قاتارلىق تۆۋەن قاتلام تىللىرىدا تۇرۇپ مەشغۇلات سىستېمىسىنىڭ مۇناسىۋەتلىك api لىرىنى JavaScript تەرەپكە چىقىرىش ئارقىلىق سىزمۇ Node.js, Bun, Deno قاتارلىقلاردەك ئۆزىڭىزنىڭ JavaScript runtime سىنى ياسىيالايسىز،
ۋە ياكى بىخەتەرلىك ئۈچۈن Node.js, deno قاتارلىقلارنىڭ ئەسلى كودىنى ئۆزگەرتىپ ئۆزىڭىزنىڭ مەخپىيلەشتۈرۈلگەن پروگرامما كودى يۈكلەش مىخانىزىمنى ياساپ چىقسىڭىزمۇ بولىدۇ.
مەسىلەن تۆۋەندىكىسى Node.js نىڭ ئىچكى قۇرۇلمىسى:
نۆۋەتتە Github دا V8 نىڭ نۇرغۇن پروگرامما تىللىرىغا ماسلاشتۇرغان بولاق ۋە كود ئامبارلىرى بار بولۇپ ئەمما بىز بۇ يازمىدا C++ بىلەن بۇ جەرياننى تاماملايمىز.
سوئال: قانداق قىلىمىز؟
ھازىر قىلىمىز 😁
كىتەرلىك شارائىتلار:
- بارلىق جەريان C++ دا تاماملىنىدىغان بولغاچ پروگراممىرنىڭ يىتەرلىك دەرىجىدە C++ ئاساس ۋە ئىچكى ساقلىغۇچ باشقۇرۇش قاتارلىقلاردىن ئاساسى بولىشى كىرەك
- Linux, macOS, Windows قاتارلىقلاردىن خالىغان بىرى بولۇش، ھەمدە C++ ئىجرا مۇھىتلىرى تولۇق قاچىلانغان بولۇش (C++ Compiler, Cmake, Ninja قاتارلىقلار، قالغىنىغا ئۆزىڭىزنىڭ ئەمەلىي مۇھىتىڭىزغا قاراپ باشقا كىرەكلىك نەرسىلەر ئوخشىمايدۇ، مەسىلەن Windows بولسا Visual studio ئەگەر macOS بولسا xcode دىگەندەك)، بۇ يازمىدىكى مەزمۇن Linux مۇھىتىدا تاماملىنىدۇ.
- v8 shared/static library
مەشغۇلات سىستېمىڭىزدا C++ پروگراممىرلىق مۇھىتى ھازىرلىنىپ بولغاندىن كىيىن (This includes compiler, cmake, ninja build system has been installed.) v8 نىڭ static ياكى dynamic ھالەتتىكى pre build binaries قا ئىھتىياجلىق بولىمىز،
ئەگەر شارائىتىڭىز بولسا v8 نى Github دىكى ئەسلى كودىدىن چۈشۈرۈپ ئۆزىڭىز تەرجىمىلىسىڭىزمۇ بولىدۇ،
ئىگە تەرەپ تور ئادېرسى: https://v8.dev/
Github پروجىكىت باش بېتى: https://github.com/v8/v8
ئەمما بىز تۇرۇشلۇق رايۇننىڭ تور مۇھىتى چەكلىمىسى سەۋەبلىك v8 نى تەرجىمىلەشكە كېتىدىغان باشقا تايانمىلارنى (dependencies) چۈشۈرۈشكە مۇمكىن بولمىغانلىقى ئۈچۈن github دىن باشقىلار تەرجىمىلەپ قويغان ئەڭ يېڭى نەشىردىكى v8 static library نى تېپىپ ئىشلەتتىم،
Github بەت ئادېرسى: مەۋەدىن ياكى ئۇ بوممىسا مەۋەدىن
ئاچقاندىن كىيىن Release بېتىدىن ئۆزىڭىز لازىملىق بولغان مەشغۇلات سىستېمىسىنىڭكىنى چۈشۈرۈڭ، مەسىلەن تۆۋەندىكى رەسىمدىكى.
ئاندىن Cmake بىلەن بىر C++ پروجىكىت قۇرۇڭ، ئاندىن ئۆزىڭىز ياقتۇرغان C++ كود تەھرىرلىگۈچى بىلەن ئېچىڭ. ئاندىن توردىن چۈشۈرىۋالغان ياكى ئۆزىڭىز تەييارلىغان v8 shared or static library نى پروجىكىت ئىچىگە ئەكىرىڭ.
تۆۋەندىكىسى مېنىڭ CmakeLists.txt
ھۆججىتىمنىڭ مەزمۇنى.
project("HelloV8")
cmake_minimum_required(VERSION 3.20)
set(
SOURCE_CODE
"src/main.cpp"
)
add_executable(HelloV8 "${SOURCE_CODE}")
target_include_directories(HelloV8 PRIVATE "libs/v8/include")
target_link_libraries(HelloV8 PRIVATE "${CMAKE_SOURCE_DIR}/libs/v8/libv8_monolith.a")
بۇ بولسا پروجىكىت مۇندەرىجىسى: (مەزمۇن بەك كۆپ بولغاچقا كۆپ چىكىت بىلەن نۇرغۇن ھۆججەت تىزىملىكلىرى قىسقارتىلدى.)
.
├── CMakeLists.txt
├── js
│ └── file.js
├── libs
│ └── v8
│ ├── gn-args_Linux.txt
│ ├── include
│ │ ├── APIDesign.md
│ │ ├── cppgc
│ │ │ ├── allocation.h
│ │ │ ├── common.h
│ │ │ ├── cross-thread-persistent.h
│ │ │ ├── .............................
│ │ │ ├── internal
│ │ │ │ ├── api-constants.h
│ │ │ │ ├── atomic-entry-flag.h
│ │ │ │ ├── base-page-handle.h
│ │ │ │ ├── .........................
│ │ │ ├── liveness-broker.h
│ │ │ ├── macros.h
│ │ │ ├── member.h
│ │ │ ├── .............................
│ │ ├── DEPS
│ │ ├── DIR_METADATA
│ │ ├── js_protocol-1.2.json
│ │ ├── js_protocol-1.3.json
│ │ ├── js_protocol.pdl
│ │ ├── libplatform
│ │ │ ├── DEPS
│ │ │ ├── libplatform-export.h
│ │ │ ├── libplatform.h
│ │ │ └── v8-tracing.h
│ │ ├── OWNERS
│ │ ├── v8-array-buffer.h
│ │ ├── v8-container.h
│ │ ├── .....................................
│ │ ├── v8-wasm-trap-handler-posix.h
│ │ ├── v8-wasm-trap-handler-win.h
│ │ └── v8-weak-callback-info.h
│ └── libv8_monolith.a
└── src
└── main.cpp
ئاددىي بىر Example يېزىپ باقايلى، تۆەندىكى كودلارنى مەن ChatGpt نىڭ ياردىمى ۋە github دىكى مەنبەلەرگە ئاساسەن يېزىپ چىقتىم.
v8 دىكى مەن ئىگىلىگەن ئۇقۇملارنى ئاددىي چۈشەندۈرۈپ ئۆتەي:
v8 نى ئاۋال initialize قىلىش كىرەك، initialize قىلىش ئۈچۈن تۆۋەندىكى فۇنكىسىيەلەر چوقۇم توغرا تەرتىپ بىلەن بولىشى كىرەك:
v8::V8::InitializeICU();
v8::V8::InitializeExternalStartupData("");
//دىققەت، بۇ يەردىن قايتقان
///platform ئۆزگەرگۈچى مىقدار چوقۇم پۈتكۈل پروگرامما دائىرىسىدە مەۋجۇت بولىشى كىرەك، ئۇنداق بولمىسا shared_ptr ئۆزىنىڭ تەسىر دائىرىسىدىن چىقىپ كەتكەندە platform نىڭ ئىچكى ساقلىغۇچتىن ئۆچۈرۈلۈشىنى كەلتۈرۈپ چىقىرىدۇ.
///Isolate قۇرىدىغاندا خاتالىق چىقىدۇ.
auto platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
Isolate ،Isolate دىگىنىمىز v8 دىكى JavaScript ماتورىنىڭ instance سى دەپ قاراشقا بولىدۇ، بىرلا ۋاقىتتا كۆپ Isolate instance بولسا بولىدۇ، ھەر قايسى instance لەر ئۆز-ئارا تەسىر قىلىشمايدۇ، ھەر قايسى isolate instance لەر ئوخشىمىغان لىنيەدە پاراللىل ئىجرا قىلىنسا بولىدۇ، چوقۇم ئەڭ ئاز بولغاندا بىر تال isolate بولىشى كىرەك،
v8 دە تەقسىملىنىدىغان JavaScript تەرەپتىكى Stack, Heap ئىچكى ساقلىغۇچلار دەل Isolate تەرىپىدىن تەقسىملىنىدۇ ۋە باشقۇرىلىدۇ، بىر نەچچە Isolate نىڭ ئۆزلىرىنىڭ Stack, Heap ئىچكى ساقلىغۇچ رايۇنى ۋە ئۆزلىرىنىڭ Garbage collector سى بولىدۇ، ئۆزىنىڭ Event loop سى بولىدۇ، v8 دە JavaScript تەرەپكە بارىدىغان ۋە كېلىدىغان ھەمدە GC تەرىپىدىن باشقۇرىلىدىغان ھەر قانداق بىر ئوبىتكىت Isolate بىلەن باغلىنىدۇ،
v8::Isolate::CreateParams params;
params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
auto isolate = v8::Isolate::New(params);
Context, Context بولسا نۆۋەتتىكى JavaScript پروگراممىسى ئىجرا بولىدىغان ئۆزىنىڭ مۇھىتىنىڭ باش ئاخىرىنى كۆرسىتىدۇ، ھەر بىر Isolate ئىچىدە كۆپ دانە Context بولسا بولىدۇ، ھەمدە ھەر بىر Context نىڭ ئۆزىنىڭ JavaScript تەرەپتە مۇستەقىل global ئوبىيكىتى بولىدۇ، شۇڭا ئوخشاش بىر Isolate ئۈستىدىكى ئوخشىمىغان Context لارنىڭ ئىچكى ساقلىغۇچنى زىيارەت قىلىش دائىرىسى ۋە global ئوبىتكىتى يەنىلا ئايرىم بولىدۇ، ھەر بىر isolate ئىچىدە بىر قىتىمدا چوقۇم پەقەت بىرلا context مەۋجۇت بولىشى كىرەك، بىرلا ۋاقىتتا كۆپ لىنيەدە بىر isolate ئۈستىدىكى كۆپ context لار مۆلچەرلەشكە بولمايدىغان ئىچكى ساقلىغۇچ خاتالىقىنى كەلتۈرۈپ چىقىرىدۇ،
auto context = v8::Context::New(isolate);
ئىچكى ساقلىغۇچ چوقۇم HandleScope ئىچىدە تەقسىملىنىشى كىرەك:
ھەر قانداق v8 GC تەرىپىدىن باشقۇرىلىدىغان JavaScript ئوبىيكىتلىرىنى C++ تەرەپتە ئېنىقلىغاندا چوقۇم بۇ يەر HandleScope نىڭ تەسىر قىلىش دائىرىسى بولىشى كىرەك، HandleScope ئۆزىنىڭ تەسىر قىلىش دائىرىسىدىن چىقىپ كەتكەندە destructor سى تەرىپىدىن ئۆزىنىڭ ئىچىدە ئىنىقلىغان بارلىق Local<T> JavaScript قىممەتلىرىنى V8 نىڭ باشقۇرۇشى ئۈچۈن بوشىتىپ بېرىدۇ، ئەگەر بۇ يەر HandleScope نىڭ دائىرىسى بولمىسا Local<T> نى تەقسىملىگىلى بولمايدۇ.
v8::HandleScope handleScope(isolate);
ھەمدە ChatGpt نىڭ دىيىشىچە بۇ يەردە IsolateScope بولسا ئايرىم HandleScope بولمىسىمۇ بولىدىكەن.
Local<T>, ھەر قانداق v8 GC تەرىپىدىن باشقۇرىلىدىغان ئوبىيكىتلارنى C++ تەرەپتە ئىشلەتكەندە v8 دىكى GC بەلكىم C++ دا ئىشلىتىۋاتقان بۇ ئوبىيكىتلارنى ئىچكى ساقلىغۇچتا يۆتكىشى ۋە ياكى ئەخلەت ئوبىيكىت سۈپىتىدە يىغىۋېلىشى مۇمكىن، ئەگەر C++ دا ئىشلىتىۋاتقان بۇ ئوبىيكىتنى v8 GC يىغىۋالسا بۇ ئىچكى ساقلىغۇچ خاتالىقى كەلتۈرۈپ چىقىرىدۇ، شۇڭا ئامال قىلىپ v8 GC غا نۆۋەتتىكى ئوبىيكىتنىڭ ئىشلىتىۋاتقىنىنى بىلدۈرۈش كىرەك، مانا بۇ نېمىشقا Local<T> نىڭ مەۋجۇتلۇقىنىڭ سەۋەبى، Local<T> بولسا v8 GC ئىگىدارلىقىدىكى ھەر قانداق ئوبىيكىتنى C++ دا زىيارەت قىلغاندا ئىشلىتىدىغان Template class ھەمدە Smart pointer بولۇپ ئەگەر v8 GC ئىگىدارلىقىدىكى مەلۇم بىر ئوبىيكىت C++ تەرەپتە Local<T> تەرىپىدىن ئىشلىتىۋاتقان بولسا v8 بۇ ئوبىيكىتنىڭ Local<T> سى مەۋجۇت بولغان ئەھۋالدا ئىچكى ساقلىغۇچتىن ئۆچۈرۈلمەسلىكىگە كاپالەتلىك قىلىدۇ،
شۇڭا C++ تەرەپتە v8 دائىرىسىدىكى JavaScript ئوبىيكىتلىرىنى زىيارەت قىلغاندا Local<T> ئارقىلىق v8 GC غا نۆۋەتتىكى JavaScript ئوبىيكىتىنىڭ C++ تەرەپتە ئىشلىتىۋاتقانلىقىنى بىلدۈرىمىز،
{
auto cppFunction = v8::FunctionTemplate::New(isolate, printInCpp);
auto jsFunction = cppFunction->GetFunction(context).ToLocalChecked();
auto succeed = context->Global()->Set(context, v8::String::NewFromUtf8(isolate, "print").ToLocalChecked(), jsFunction).ToChecked();
}
{
std::ifstream file("js/file.js", std::ios_base::in);
std::stringstream stringBuffer;
stringBuffer << file.rdbuf();
auto sourceCode = v8::String::NewFromUtf8(isolate, stringBuffer.str().c_str()).ToLocalChecked();
auto compiled = v8::Script::Compile(context, sourceCode).ToLocalChecked();
auto result = compiled->Run(context).ToLocalChecked();
}
مەسىلەن v8::Local<v8::Object> ياكى v8::Local<v8::String> قاتارلىقلار،
C++ تەرەپتە JavaScript ئوبىيكىتلىرىنى قۇرغاندا چوقۇم نۆۋەتتىكى دائىرىدە ئەڭ ئاز بولغاندا بىر دانە HandleScope مەۋجۇت بولىشى كىرەك.
Isolate بىلەن Context نىڭ پەرقى: Process بىلەن Thread نىڭ پەرقىگە ئوخشايدۇ، (ئەمما Context بىرلا ۋاقىتتا پەقەت بىرسىلا ئىجرا بولالايدۇ) يەنى كۆپ دانە Context لار مەلۇم بىر Isolate تەرىپىدىن باشقۇرىلىدۇ، ھەر بىر Context نى پەقەت بىر دانە ئوخشاش JavaScript ماتورى ئۈستىدىكى قۇم ساندۇقى (sandbox) دەپ قاراشقا بولىدۇ،
isolate نىڭ ئۆزىنىڭ event loop, ئۆزىنىڭ heap, stack ئىچكى ساقلىغۇچى، ئۆزىنىڭ handle scope سى، ئۆزىنىڭ gc سى بولىدۇ، ئەمما context بولسا isolate گە قارىغاندا يەڭگىل ئۇقۇم بولۇپ پەقەت Isolate ئۈستىدىكى قاچا (Container) دەپ قاراشقا بولىدۇ، پەقەت ئۆزىنىڭ ئىچكى ساقلىغۇچ رايۇنى ۋە global ئوبىيكىتى بولىدۇ.
تېخىمۇ كۆپ ياردەم ئۈچۈن:
- [https://v8.dev/docs/embed](ئىگە تەرەپ v8 پروگراممىرلار قوللانمىسى) دىن ياردەمگە ئىرىشىڭ،
- ChatGPT
يازمىدىكى مىسال پروجىكىت ئەسلى كودى Gitlab قا چىقىرىلدى، بۇ يەردىن كۆرۈڭ: https://dev.subat.cn/Ug-Projekt/hello_v8_cpp_version