diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index e580beed..5f01d805 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -20,8 +20,8 @@ jobs:
matrix:
backends: [ V8, JavaScriptCore, QuickJs, Lua ]
steps:
- - uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - uses: actions/checkout@v4.1.7
+ - uses: actions/cache@v4.0.2
with:
key: ScriptX-UnitTests-Depedencies-${{ hashFiles('test/cmake/**') }}
path: |
diff --git a/.github/workflows/sync_to_tencent_code.yml b/.github/workflows/sync_to_tencent_code.yml
index a18ad9c3..7002ec66 100644
--- a/.github/workflows/sync_to_tencent_code.yml
+++ b/.github/workflows/sync_to_tencent_code.yml
@@ -9,7 +9,7 @@ jobs:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4.1.7
with:
fetch-depth: 0
- name: mirror-repository
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
index 0ede8b4f..a093bd33 100644
--- a/.github/workflows/unit_tests.yml
+++ b/.github/workflows/unit_tests.yml
@@ -24,8 +24,8 @@ jobs:
# mac runner seems to be slow and rear
# - Release
steps:
- - uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - uses: actions/checkout@v4.1.7
+ - uses: actions/cache@v4.0.2
with:
key: ScriptX-UnitTests-Depedencies-${{ hashFiles('test/cmake/**') }}
path: |
@@ -61,15 +61,15 @@ jobs:
- Debug
- Release
steps:
- - uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - uses: actions/checkout@v4.1.7
+ - uses: actions/cache@v4.0.2
with:
key: ScriptX-UnitTests-Depedencies-${{ hashFiles('test/cmake/**') }}
path: |
build/ScriptXTestLibs
build/googletest-src
- name: Add MSBuild to PATH
- uses: microsoft/setup-msbuild@v1.0.2
+ uses: microsoft/setup-msbuild@v2
- name: Configure cmake X64
if: matrix.backends != 'JavaScriptCore'
shell: powershell
@@ -112,8 +112,8 @@ jobs:
- Debug
- Release
steps:
- - uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - uses: actions/checkout@v4.1.7
+ - uses: actions/cache@v4.0.2
with:
key: ScriptX-UnitTests-Depedencies-${{ hashFiles('test/cmake/**') }}
path: |
@@ -138,6 +138,29 @@ jobs:
cd build
./UnitTests
+ ubuntu-v8-versions-build:
+ timeout-minutes: 60
+ runs-on: ubuntu-20.04
+ strategy:
+ fail-fast: false
+ matrix:
+ # format index{0 .. index-1}/concurrency
+ job_split: [ 0/8, 1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8 ]
+ steps:
+ - uses: actions/checkout@v4.1.7
+ - uses: actions/cache@v4.0.2
+ with:
+ key: ScriptX-UnitTests-Depedencies-${{ hashFiles('test/cmake/**') }}
+ path: |
+ build/ScriptXTestLibs
+ - name: Test build v8 on supported versions
+ env:
+ SCRIPTX_TEST_FORCE_UPDATE_DEPS: ON
+ SCRIPTX_TEST_V8_JOB_SPLIT_CONFIG: ${{ matrix.job_split }}
+ run: |
+ mkdir -p build && cd build
+ ../test/cmake/test_v8_compiles.sh continue
+
android-clang-build:
# disable for now
# 1. we don't have android libraries
@@ -153,8 +176,8 @@ jobs:
- Debug
- Release
steps:
- - uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - uses: actions/checkout@v4.1.7
+ - uses: actions/cache@v4.0.2
with:
key: ScriptX-UnitTests-Depedencies-${{ hashFiles('test/cmake/**') }}
path: |
@@ -185,9 +208,9 @@ jobs:
matrix:
node-version: [ 14.x, 15.x, 16.x, 18.x ] # 19.x
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4.1.7
- name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4.0.4
with:
node-version: ${{ matrix.node-version }}
- name: Prepare npm
@@ -209,20 +232,20 @@ jobs:
matrix:
emscripten-version: [ '3.0.0', '3.1.33' ]
steps:
- - uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - uses: actions/checkout@v4.1.7
+ - uses: actions/cache@v4.0.2
with:
key: ScriptX-UnitTests-Depedencies-${{ hashFiles('test/cmake/**') }}
path: |
build/ScriptXTestLibs
build/googletest-src
- name: Setup Emscripten
- uses: mymindstorm/setup-emsdk@v11
+ uses: mymindstorm/setup-emsdk@v14
with:
version: ${{ matrix.emscripten-version }}
actions-cache-folder: emsdk-cache-${{ matrix.emscripten-version }}
- name: Setup Node.js
- uses: actions/setup-node@v1
+ uses: actions/setup-node@v4.0.4
with:
node-version: '19.3.0' # insteadof '>= 14', use fixed version
- name: Configure Webassembly backend
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1da39c5e..cc0ecb41 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+Version 3.6.0 (2024-09):
+1. `[V8]` add test infrastructure to test on multiple v8 versions
+2. `[V8]` add support to v8 versions through 7.4~13.0
+
Version 3.5.0 (2023-05):
1. `[QuickJs]` add support for QuickJs 2024-01-13
@@ -83,4 +87,4 @@ A Template backend which has no implementation.
---
Version 0.0 (2019-10):
-Project started.
\ No newline at end of file
+Project started.
diff --git a/README-zh.md b/README-zh.md
index 7dc7e6e6..84d297f3 100644
--- a/README-zh.md
+++ b/README-zh.md
@@ -20,7 +20,7 @@ ScriptX的术语中,"前端"指对外的C++ API,"后端"则指不同的底
| 后端 | 语言 | 版本 | 状态 |
| :----: | :----: | :----: | :----: |
-| V8 | JavaScript | 7.4+ | done |
+| V8 | JavaScript | 7.4+
([tested versions][tested_v8_versions]) | done |
| JavaScriptCore | JavaScript | 7604.1.38.0.7+
(iOS 10+/macOS10.12+) | done |
| Node.js | JavaScript | 14.x+ | done |
| QuickJs | JavaScript | 2024-01-13 | done |
@@ -30,6 +30,7 @@ ScriptX的术语中,"前端"指对外的C++ API,"后端"则指不同的底
| YARV | Ruby | | todo |
| Mono | C# | | todo |
+[tested_v8_versions]: https://github.com/LanderlYoung/ScriptXTestLibs/blob/main/v8/supported_versions.txt
# 简介
diff --git a/README.md b/README.md
index 1c46d88a..ba3df45f 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ In ScriptX terminology, "front-end" refers to the external C++ API, and "back-en
| backend | language | version | states |
| :----: | :----: | :----: | :----: |
-| V8 | JavaScript | 7.4+ | done |
+| V8 | JavaScript | 7.4+
([tested versions][tested_v8_versions]) | done |
| JavaScriptCore | JavaScript | 7604.1.38.0.7+
(iOS 10+/macOS10.12+) | done |
| Node.js | JavaScript | 14.x+ | done |
| QuickJs | JavaScript | 2024-01-13 | done |
@@ -29,6 +29,8 @@ In ScriptX terminology, "front-end" refers to the external C++ API, and "back-en
| YARV | Ruby | | todo |
| Mono | C# | | todo |
+[tested_v8_versions]: https://github.com/LanderlYoung/ScriptXTestLibs/blob/main/v8/supported_versions.txt
+
# Introduction
The interface of ScriptX uses modern C++ features. And to be 100% in line with the C++ standard, completely cross-platform.
diff --git a/VERSION b/VERSION
index e5b82034..40c341bd 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.5.0
\ No newline at end of file
+3.6.0
diff --git a/backend/V8/V8Engine.cc b/backend/V8/V8Engine.cc
index 11306559..5043d2df 100644
--- a/backend/V8/V8Engine.cc
+++ b/backend/V8/V8Engine.cc
@@ -158,8 +158,9 @@ Local V8Engine::eval(const Local& script, const Local& sou
throw Exception("can't eval script");
}
v8::ScriptOrigin origin(
-#if SCRIPTX_V8_VERSION_AT_LEAST(9, 0)
+#if SCRIPTX_V8_VERSION_BETWEEN(9, 0, 12, 0)
// V8 9.0 add isolate param for external API
+ // V8 12.1 deprecated the isolate version, and introduced the one without isolation
isolate_,
#endif
sourceFile.isNull() || !sourceFile.isString() ? v8::Local()
@@ -180,17 +181,18 @@ Local V8Engine::eval(const Local& script) { return eval(script, {
void V8Engine::registerNativeClassStatic(v8::Local funcT,
const internal::StaticDefine* staticDefine) {
for (auto& prop : staticDefine->properties) {
+ using PropDefPtr = internal::StaticDefine::PropertyDefine*;
+
StackFrameScope stack;
auto name = String::newString(prop.name);
- v8::AccessorGetterCallback getter = nullptr;
- v8::AccessorSetterCallback setter = nullptr;
+ v8::AccessorNameGetterCallback getter = nullptr;
+ v8::AccessorNameSetterCallback setter = nullptr;
if (prop.getter) {
- getter = [](v8::Local /*property*/,
+ getter = [](v8::Local /*property*/,
const v8::PropertyCallbackInfo& info) {
- auto ptr = static_cast(
- info.Data().As()->Value());
+ auto ptr = static_cast(info.Data().As()->Value());
Tracer trace(EngineScope::currentEngine(), ptr->traceName);
Local ret = ptr->getter();
try {
@@ -202,10 +204,9 @@ void V8Engine::registerNativeClassStatic(v8::Local funcT,
}
if (prop.setter) {
- setter = [](v8::Local /*property*/, v8::Local value,
+ setter = [](v8::Local /*property*/, v8::Local value,
const v8::PropertyCallbackInfo& info) {
- auto ptr = static_cast(
- info.Data().As()->Value());
+ auto ptr = static_cast(info.Data().As()->Value());
Tracer trace(EngineScope::currentEngine(), ptr->traceName);
try {
ptr->setter(make>(value));
@@ -216,25 +217,26 @@ void V8Engine::registerNativeClassStatic(v8::Local funcT,
} else {
// v8 requires setter to be present, otherwise, a real js set code with create a new
// property...
- setter = [](v8::Local property, v8::Local value,
+ setter = [](v8::Local property, v8::Local value,
const v8::PropertyCallbackInfo& info) {};
}
- funcT->SetNativeDataProperty(
- toV8(isolate_, name), getter, setter,
- v8::External::New(isolate_, const_cast(&prop)),
- v8::PropertyAttribute::DontDelete);
+ // SetNativeDataProperty with Local and AccessControl is deprecated
+ funcT->SetNativeDataProperty(toV8(isolate_, name).As(), getter, setter,
+ v8::External::New(isolate_, const_cast(&prop)),
+ v8::PropertyAttribute::DontDelete);
}
for (auto& func : staticDefine->functions) {
+ using FuncDefPtr = internal::StaticDefine::FunctionDefine*;
+
StackFrameScope stack;
auto name = String::newString(func.name);
auto fn = v8::FunctionTemplate::New(
isolate_,
[](const v8::FunctionCallbackInfo& info) {
- auto funcDef = reinterpret_cast(
- info.Data().As()->Value());
+ auto funcDef = reinterpret_cast(info.Data().As()->Value());
auto engine = v8_backend::currentEngine();
Tracer trace(engine, funcDef->traceName);
@@ -245,8 +247,8 @@ void V8Engine::registerNativeClassStatic(v8::Local funcT,
v8_backend::rethrowException(e);
}
},
- v8::External::New(isolate_, const_cast(&func)), {},
- 0, v8::ConstructorBehavior::kThrow);
+ v8::External::New(isolate_, const_cast(&func)), {}, 0,
+ v8::ConstructorBehavior::kThrow);
if (!fn.IsEmpty()) {
funcT->Set(toV8(isolate_, name), fn, v8::PropertyAttribute::DontDelete);
} else {
@@ -453,67 +455,67 @@ void V8Engine::registerNativeClassInstance(v8::Local funcT
// instance
auto instanceT = funcT->PrototypeTemplate();
auto signature = v8::Signature::New(isolate_, funcT);
+
for (auto& prop : classDefine->instanceDefine.properties) {
+ // Template::SetAccessor is removed in 12.8
+ // using Template::SetAccessorProperty is recommended
+
+ using PropDefPtr = typename internal::InstanceDefine::PropertyDefine*;
StackFrameScope stack;
auto name = String::newString(prop.name);
-
- v8::AccessorGetterCallback getter = nullptr;
- v8::AccessorSetterCallback setter = nullptr;
+ auto data = v8::External::New(isolate_, const_cast(&prop));
+ v8::Local getter;
+ v8::Local setter;
if (prop.getter) {
- getter = [](v8::Local property, const v8::PropertyCallbackInfo& info) {
- auto ptr = static_cast(info.Data().As()->Value());
- auto thiz = static_cast(info.This()->GetAlignedPointerFromInternalField(
- kInstanceObjectAlignedPointer_PolymorphicPointer));
- auto scriptClass =
- static_cast(info.This()->GetAlignedPointerFromInternalField(
- kInstanceObjectAlignedPointer_ScriptClass));
- auto& getter = ptr->getter;
-
- Tracer trace(scriptClass->getScriptEngine(), ptr->traceName);
-
- Local ret = (getter)(thiz);
- try {
- info.GetReturnValue().Set(toV8(info.GetIsolate(), ret));
- } catch (const Exception& e) {
- v8_backend::rethrowException(e);
- }
- };
+ getter = v8::FunctionTemplate::New(
+ isolate_,
+ [](const v8::FunctionCallbackInfo& info) {
+ auto ptr = static_cast(info.Data().As()->Value());
+ auto thiz = static_cast(info.This()->GetAlignedPointerFromInternalField(
+ kInstanceObjectAlignedPointer_PolymorphicPointer));
+ auto scriptClass =
+ static_cast(info.This()->GetAlignedPointerFromInternalField(
+ kInstanceObjectAlignedPointer_ScriptClass));
+ auto& getter = ptr->getter;
+
+ Tracer trace(scriptClass->getScriptEngine(), ptr->traceName);
+
+ Local ret = (getter)(thiz);
+ try {
+ info.GetReturnValue().Set(toV8(info.GetIsolate(), ret));
+ } catch (const Exception& e) {
+ v8_backend::rethrowException(e);
+ }
+ },
+ data, signature);
}
if (prop.setter) {
- setter = [](v8::Local property, v8::Local value,
- const v8::PropertyCallbackInfo& info) {
- auto ptr = static_cast(info.Data().As()->Value());
- auto thiz = static_cast(info.This()->GetAlignedPointerFromInternalField(
- kInstanceObjectAlignedPointer_PolymorphicPointer));
- auto scriptClass =
- static_cast(info.This()->GetAlignedPointerFromInternalField(
- kInstanceObjectAlignedPointer_ScriptClass));
- auto& setter = ptr->setter;
-
- Tracer trace(scriptClass->getScriptEngine(), ptr->traceName);
-
- try {
- (setter)(thiz, make>(value));
- } catch (const Exception& e) {
- v8_backend::rethrowException(e);
- }
- };
+ setter = v8::FunctionTemplate::New(
+ isolate_,
+ [](const v8::FunctionCallbackInfo& info) {
+ auto ptr = static_cast(info.Data().As()->Value());
+ auto thiz = static_cast(info.This()->GetAlignedPointerFromInternalField(
+ kInstanceObjectAlignedPointer_PolymorphicPointer));
+ auto scriptClass =
+ static_cast(info.This()->GetAlignedPointerFromInternalField(
+ kInstanceObjectAlignedPointer_ScriptClass));
+ auto& setter = ptr->setter;
+
+ Tracer trace(scriptClass->getScriptEngine(), ptr->traceName);
+
+ try {
+ (setter)(thiz, make>(info[0]));
+ } catch (const Exception& e) {
+ v8_backend::rethrowException(e);
+ }
+ },
+ data, signature);
}
- auto v8Name = toV8(isolate_, name);
- auto data = v8::External::New(
- isolate_, const_cast(&prop));
-
-#if SCRIPTX_V8_VERSION_AT_MOST(10, 1) // SetAccessor AccessorSignature deprecated in 10.2 a8beac
- auto accessSignature = v8::AccessorSignature::New(isolate_, funcT);
- instanceT->SetAccessor(v8Name, getter, setter, data, v8::AccessControl::DEFAULT,
- v8::PropertyAttribute::DontDelete, accessSignature);
-#else
- instanceT->SetAccessor(v8Name, getter, setter, data, v8::AccessControl::DEFAULT,
- v8::PropertyAttribute::DontDelete);
-#endif
+ instanceT->SetAccessorProperty(toV8(isolate_, name).As(), getter, setter,
+ v8::PropertyAttribute::DontDelete);
}
for (auto& func : classDefine->instanceDefine.functions) {
@@ -541,7 +543,7 @@ void V8Engine::registerNativeClassInstance(v8::Local funcT
},
v8::External::New(isolate_, const_cast(&func)), signature);
if (!fn.IsEmpty()) {
- funcT->PrototypeTemplate()->Set(toV8(isolate_, name), fn, v8::PropertyAttribute::DontDelete);
+ instanceT->Set(toV8(isolate_, name), fn, v8::PropertyAttribute::DontDelete);
} else {
throw Exception("can't create function for instance");
}
diff --git a/backend/V8/V8Helper.h b/backend/V8/V8Helper.h
index f03f73d3..7bed27cd 100644
--- a/backend/V8/V8Helper.h
+++ b/backend/V8/V8Helper.h
@@ -37,17 +37,16 @@ SCRIPTX_END_INCLUDE_LIBRARY
// V8 version check helper
// V8_version >= version
-#define SCRIPTX_V8_VERSION_AT_LEAST(major, minor) \
+#define SCRIPTX_V8_VERSION_GE(major, minor) \
(V8_MAJOR_VERSION > (major) || (V8_MAJOR_VERSION == (major) && V8_MINOR_VERSION >= (minor)))
// V8_version <= version
-#define SCRIPTX_V8_VERSION_AT_MOST(major, minor) \
+#define SCRIPTX_V8_VERSION_LE(major, minor) \
(V8_MAJOR_VERSION < (major) || (V8_MAJOR_VERSION == (major) && V8_MINOR_VERSION <= (minor)))
// old_version <= V8_version <= new_version
#define SCRIPTX_V8_VERSION_BETWEEN(old_major, old_minor, new_major, new_minor) \
- SCRIPTX_V8_VERSION_AT_LEAST(old_major, old_minor) && \
- SCRIPTX_V8_VERSION_AT_MOST(new_major, new_minor)
+ SCRIPTX_V8_VERSION_GE(old_major, old_minor) && SCRIPTX_V8_VERSION_LE(new_major, new_minor)
namespace script::v8_backend {
@@ -73,4 +72,4 @@ void rethrowException(const Exception& exception);
namespace script {
struct v8_interop;
-}
\ No newline at end of file
+}
diff --git a/backend/V8/V8Platform.cc b/backend/V8/V8Platform.cc
index 06c1df22..f8bd974f 100644
--- a/backend/V8/V8Platform.cc
+++ b/backend/V8/V8Platform.cc
@@ -16,8 +16,9 @@
*/
#include "V8Platform.h"
-#include
+#include
#include
+#include
#include "../../src/Utils.h"
#include "V8Engine.h"
#include "V8Helper.hpp"
@@ -26,14 +27,9 @@ namespace script::v8_backend {
class MessageQueueTaskRunner : public v8::TaskRunner {
private:
- V8Platform* platform_{};
v8::Isolate* isolate_{};
- std::shared_ptr defaultTaskRunner_{};
-
V8Engine* engine_{};
- std::atomic_bool isPumpScheduled_{false};
-
public:
MessageQueueTaskRunner() = default;
@@ -41,69 +37,81 @@ class MessageQueueTaskRunner : public v8::TaskRunner {
~MessageQueueTaskRunner() override = default;
- bool hasRunner() const { return defaultTaskRunner_ != nullptr; }
+ bool inited() const { return isolate_ != nullptr; }
- void setQueue(V8Platform* platform, v8::Isolate* isolate,
- std::shared_ptr defaultTaskRunner) {
- platform_ = platform;
- isolate_ = isolate;
- defaultTaskRunner_ = std::move(defaultTaskRunner);
- }
+ void setQueue(v8::Isolate* isolate) { isolate_ = isolate; }
void setEngine(V8Engine* engine) { engine_ = engine; }
- void PostTask(std::unique_ptr task) override {
- defaultTaskRunner_->PostTask(std::move(task));
- schedulePump();
+#if SCRIPTX_V8_VERSION_GE(12, 4) // changed to PostTaskImpl
+ void PostTaskImpl(std::unique_ptr task, const v8::SourceLocation& location) override {
+ scheduleTask(std::move(task));
+ }
+
+ void PostDelayedTaskImpl(std::unique_ptr task, double delay_in_seconds,
+ const v8::SourceLocation& location) override {
+ scheduleTask(std::move(task), delay_in_seconds);
+ }
+
+ void PostIdleTaskImpl(std::unique_ptr task,
+ const v8::SourceLocation& location) override {
+ ::abort();
}
+ void PostNonNestableTaskImpl(std::unique_ptr task,
+ const v8::SourceLocation& location) override {
+ scheduleTask(std::move(task));
+ }
+
+ void PostNonNestableDelayedTaskImpl(std::unique_ptr task, double delay_in_seconds,
+ const v8::SourceLocation& location) override {
+ scheduleTask(std::move(task), delay_in_seconds);
+ }
+
+#else
+ void PostTask(std::unique_ptr task) override { scheduleTask(std::move(task)); }
+
void PostDelayedTask(std::unique_ptr task, double delay_in_seconds) override {
- defaultTaskRunner_->PostDelayedTask(std::move(task), delay_in_seconds);
- schedulePump();
+ scheduleTask(std::move(task), delay_in_seconds);
}
void PostIdleTask(std::unique_ptr task) override {
- defaultTaskRunner_->PostIdleTask(std::move(task));
- schedulePump();
+ // not supported
+ ::abort();
}
- bool IdleTasksEnabled() override { return defaultTaskRunner_->IdleTasksEnabled(); }
+ void PostNonNestableTask(std::unique_ptr task) override {
+ scheduleTask(std::move(task));
+ }
+#endif
+
+ bool IdleTasksEnabled() override { return false; }
- void PostNonNestableTask(std::unique_ptr task) override { PostTask(std::move(task)); }
+ bool NonNestableTasksEnabled() const override { return true; }
+#if SCRIPTX_V8_VERSION_BETWEEN(7, 5, 12, 4)
void PostNonNestableDelayedTask(std::unique_ptr task,
double delay_in_seconds) override {
- PostDelayedTask(std::move(task), delay_in_seconds);
+ scheduleTask(std::move(task), delay_in_seconds);
}
+#endif
- bool NonNestableTasksEnabled() const override { return true; }
-
+#if SCRIPTX_V8_VERSION_GE(7, 5)
bool NonNestableDelayedTasksEnabled() const override { return true; }
+#endif
private:
- void schedulePump() {
- bool expected = false;
- if (engine_ && isPumpScheduled_.compare_exchange_strong(expected, true)) {
- script::utils::Message s(
- [](auto& msg) {
- static_cast(msg.ptr0)->isPumpScheduled_ = false;
- auto platform = static_cast(msg.ptr1);
- auto isolate = static_cast(msg.ptr2);
-
- while (platform->pumpMessageQueue(isolate)) {
- // loop until no more message to pump
- }
- },
- nullptr);
-
- s.name = "SchedulePump";
- s.ptr0 = this;
- s.ptr1 = platform_;
- s.ptr2 = isolate_;
- s.tag = engine_;
-
- engine_->messageQueue()->postMessage(s);
- }
+ void scheduleTask(std::unique_ptr task, double delay_in_seconds = 0) {
+ script::utils::Message s([](auto& msg) { static_cast(msg.ptr0)->Run(); },
+ [](auto& msg) {
+ using deleter = std::unique_ptr::deleter_type;
+ deleter{}(static_cast(msg.ptr0));
+ });
+ s.name = "SchedulePump";
+ s.ptr0 = task.release();
+ s.tag = engine_;
+
+ engine_->messageQueue()->postMessage(s, std::chrono::duration(delay_in_seconds));
}
};
@@ -162,7 +170,7 @@ V8Platform::~V8Platform() {
std::lock_guard lock(lock_);
v8::V8::Dispose();
-#if SCRIPTX_V8_VERSION_AT_LEAST(10, 0)
+#if SCRIPTX_V8_VERSION_GE(10, 0)
v8::V8::DisposePlatform();
#else
// DEPRECATED in 10.0 36707481ffa
@@ -170,29 +178,29 @@ V8Platform::~V8Platform() {
#endif
}
+#if SCRIPTX_V8_VERSION_GE(11, 7)
+std::shared_ptr V8Platform::GetForegroundTaskRunner(v8::Isolate* isolate,
+ v8::TaskPriority priority) {
+#else
std::shared_ptr V8Platform::GetForegroundTaskRunner(v8::Isolate* isolate) {
+#endif
std::lock_guard lock(lock_);
auto queueRunner = engineMap_[isolate].messageQueueRunner;
- if (!queueRunner->hasRunner()) {
+ if (!queueRunner->inited()) {
// this method may be called during creating Isolate...
// set anything we now ASAP
- queueRunner->setQueue(this, isolate, defaultPlatform_->GetForegroundTaskRunner(isolate));
+ queueRunner->setQueue(isolate);
}
return queueRunner;
}
-bool V8Platform::pumpMessageQueue(v8::Isolate* isolate) {
- v8::Locker locker(isolate);
- return v8::platform::PumpMessageLoop(defaultPlatform_.get(), isolate);
-}
-
void V8Platform::OnCriticalMemoryPressure() {
Logger() << "V8Platform::OnCriticalMemoryPressure()";
return defaultPlatform_->OnCriticalMemoryPressure();
}
-#if SCRIPTX_V8_VERSION_AT_MOST(10, 6)
+#if SCRIPTX_V8_VERSION_LE(10, 6)
bool V8Platform::OnCriticalMemoryPressure(size_t length) {
Logger() << "V8Platform::OnCriticalMemoryPressure(" << length << ")";
return defaultPlatform_->OnCriticalMemoryPressure(length);
diff --git a/backend/V8/V8Platform.h b/backend/V8/V8Platform.h
index 8db71957..cada9d89 100644
--- a/backend/V8/V8Platform.h
+++ b/backend/V8/V8Platform.h
@@ -15,6 +15,8 @@
* limitations under the License.
*/
+// for all v8 api changes, refer to https://github.com/LanderlYoung/ScriptXTestLibs/blob/main/v8/
+
#pragma once
#include
@@ -23,6 +25,7 @@
#include "../../src/foundation.h"
SCRIPTX_BEGIN_INCLUDE_LIBRARY
+#include
#include
SCRIPTX_END_INCLUDE_LIBRARY
@@ -43,24 +46,28 @@ class V8Platform : public v8::Platform {
SCRIPTX_DISALLOW_COPY_AND_MOVE(V8Platform);
public:
- // this method is used in v8 internally, we should handle it properly, since V8 7.1.1
+#if SCRIPTX_V8_VERSION_GE(11, 7)
+ // V7.1: added 1-param one
+ // V11.7: added 2-param overload one, 1-param one delegate to 2-param one
+ // V13.0: made 1-param overload one non-virtual
+ std::shared_ptr GetForegroundTaskRunner(v8::Isolate* isolate,
+ v8::TaskPriority priority) override;
+#else
std::shared_ptr GetForegroundTaskRunner(v8::Isolate* isolate) override;
-
- // call in V8Engine
- bool pumpMessageQueue(v8::Isolate* isolate);
+#endif
void OnCriticalMemoryPressure() override;
-#if SCRIPTX_V8_VERSION_AT_MOST(10, 6)
+#if SCRIPTX_V8_VERSION_LE(10, 6)
// DEPRECATED in 10.7 - 24cf9b
// REMOVED in 10.8 - 8b8703
bool OnCriticalMemoryPressure(size_t length) override;
#endif
- public:
// directly delegate to default platform
int NumberOfWorkerThreads() override { return defaultPlatform_->NumberOfWorkerThreads(); }
+#if SCRIPTX_V8_VERSION_LE(11, 3) // added default impl to call PostTaskOnWorkerThreadImpl in 11.4
void CallOnWorkerThread(std::unique_ptr task) override {
return defaultPlatform_->CallOnWorkerThread(std::move(task));
}
@@ -68,6 +75,7 @@ class V8Platform : public v8::Platform {
void CallDelayedOnWorkerThread(std::unique_ptr task, double delay_in_seconds) override {
return defaultPlatform_->CallDelayedOnWorkerThread(std::move(task), delay_in_seconds);
}
+#endif
double MonotonicallyIncreasingTime() override {
return defaultPlatform_->MonotonicallyIncreasingTime();
@@ -86,29 +94,65 @@ class V8Platform : public v8::Platform {
// NOTE: not available in node 14.x (node.js modified v8 code...)
// https://nodejs.org/en/download/releases/
// and node 15.x uses v8 8.6+
-#if defined(BUILDING_NODE_EXTENSION) ? SCRIPTX_V8_VERSION_AT_LEAST(8, 6) \
- : SCRIPTX_V8_VERSION_AT_LEAST(8, 4)
-
+ // V8 8.6 made it pure virtual
+ // V8 10.5 add default impl to CreateJob
+ // V12.2 make it none-virtual by delegate to CreateJobImpl
+#if defined(BUILDING_NODE_EXTENSION) ? SCRIPTX_V8_VERSION_BETWEEN(8, 6, 12, 1) \
+ : SCRIPTX_V8_VERSION_BETWEEN(8, 4, 12, 1)
virtual std::unique_ptr PostJob(v8::TaskPriority priority,
std::unique_ptr job_task) override {
return defaultPlatform_->PostJob(priority, std::move(job_task));
}
-
#endif
-#if SCRIPTX_V8_VERSION_AT_LEAST(10, 5) // added in 10.5 1e0d18
+#if SCRIPTX_V8_VERSION_BETWEEN(10, 5, 11, 3)
+ // V10.5 added pure-virtual
+ // V11.4 added default impl to CreateJobImpl
+ // V12.2 make it none-virtual by delegate to CreateJobImpl
std::unique_ptr CreateJob(v8::TaskPriority priority,
std::unique_ptr job_task) override {
return defaultPlatform_->CreateJob(priority, std::move(job_task));
}
#endif
-#if !SCRIPTX_V8_VERSION_AT_LEAST(8, 0)
- // v8 8.0 added default impl
- // v8 8.1 removed those function
- // so we won't override them since v8 8.0
- // https://github.com/v8/v8/commit/95aba36b52eecdec56752956a7960b916f986a39
+#if SCRIPTX_V8_VERSION_GE(11, 4)
+ protected:
+ // V11.4 added
+ // V12.2 made pure virtual
+ virtual std::unique_ptr CreateJobImpl(
+ v8::TaskPriority priority, std::unique_ptr job_task,
+ const v8::SourceLocation& location) override {
+ return defaultPlatform_->CreateJob(priority, std::move(job_task));
+ }
+
+ // V11.4 added
+ // V12.2 made pure virtual
+ virtual void PostTaskOnWorkerThreadImpl(v8::TaskPriority priority, std::unique_ptr task,
+ const v8::SourceLocation& location) override {
+#if SCRIPTX_V8_VERSION_GE(12, 2)
+ defaultPlatform_->CallOnWorkerThread(std::move(task), location);
+#else
+ defaultPlatform_->CallOnWorkerThread(std::move(task));
+#endif
+ }
+
+ // V11.4 added
+ // V12.2 made pure virtual
+ virtual void PostDelayedTaskOnWorkerThreadImpl(v8::TaskPriority priority,
+ std::unique_ptr task,
+ double delay_in_seconds,
+ const v8::SourceLocation& location) override {
+#if SCRIPTX_V8_VERSION_GE(12, 2)
+ defaultPlatform_->CallDelayedOnWorkerThread(std::move(task), delay_in_seconds, location);
+#else
+ defaultPlatform_->CallDelayedOnWorkerThread(std::move(task), delay_in_seconds);
+#endif
+ }
+ public:
+#endif
+
+#if SCRIPTX_V8_VERSION_LE(8, 0) // removed in 8.1
void CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) override {
return GetForegroundTaskRunner(isolate)->PostTask(std::unique_ptr(task));
}
@@ -120,6 +164,15 @@ class V8Platform : public v8::Platform {
}
#endif
+ bool IdleTasksEnabled(v8::Isolate* isolate) override { return false; }
+
+#if SCRIPTX_V8_VERSION_GE(11, 3)
+ virtual std::unique_ptr CreateBlockingScope(
+ v8::BlockingType blocking_type) override {
+ return defaultPlatform_->CreateBlockingScope(blocking_type);
+ }
+#endif
+
public:
~V8Platform() override;
diff --git a/backend/V8/V8Reference.hpp b/backend/V8/V8Reference.hpp
index 2ffc5106..7d78d827 100644
--- a/backend/V8/V8Reference.hpp
+++ b/backend/V8/V8Reference.hpp
@@ -32,8 +32,11 @@ namespace script {
namespace v8_backend {
template
+
GlobalRefState::GlobalRefState(V8Engine* scriptEngine, const GlobalRefState::V8Global& v8Global)
- : engine_(scriptEngine), ref_(v8Global) {}
+ : engine_(scriptEngine),
+ // v8::Global don't support copy
+ ref_{engine_->isolate_, v8Global} {}
template
GlobalRefState::GlobalRefState(V8Engine* scriptEngine, const Local& localReference)
diff --git a/backend/V8/V8Value.cc b/backend/V8/V8Value.cc
index 3d738a1b..05013f81 100644
--- a/backend/V8/V8Value.cc
+++ b/backend/V8/V8Value.cc
@@ -176,9 +176,9 @@ Local ByteBuffer::newByteBuffer(void* nativeBuffer, si
return ret;
}
-#if V8_MAJOR_VERSION >= 8
+#if SCRIPTX_V8_VERSION_GE(8, 1)
-// v8 8.0 introduced new api for this
+// v8 8.1 introduced new api for this
// https://docs.google.com/document/d/1sTc_jRL87Fu175Holm5SV0kajkseGl2r8ifGY76G35k/edit
Local ByteBuffer::newByteBuffer(std::shared_ptr buffer, size_t size) {
diff --git a/backend/V8/trait/TraitReference.h b/backend/V8/trait/TraitReference.h
index 1389dc40..cdd1f00d 100644
--- a/backend/V8/trait/TraitReference.h
+++ b/backend/V8/trait/TraitReference.h
@@ -56,8 +56,9 @@ TypeMap(::script::Unsupported, v8::Value);
template
class GlobalRefState {
private:
- using V8Global =
- typename ::v8::CopyablePersistentTraits>::CopyablePersistent;
+ // v8::CopyablePersistentTraits deprecated in 10.5, removed in 12.5
+ // always use v8::Global
+ using V8Global = v8::Global>;
public:
V8Engine* engine_ = nullptr;
@@ -70,7 +71,17 @@ class GlobalRefState {
GlobalRefState(V8Engine* scriptEngine, const V8Global& v8Global);
- GlobalRefState(const GlobalRefState& copy) : engine_(copy.engine_), ref_(copy.ref_) {}
+ // v8::Global don't support copy
+ GlobalRefState(const GlobalRefState& copy)
+ : engine_(copy.engine_), ref_{currentEngineIsolateChecked(), copy.ref_} {}
+
+ GlobalRefState& operator=(const GlobalRefState& assign) {
+ if (this != &assign) {
+ engine_ = assign.engine_;
+ ref_ = V8Global(currentEngineIsolateChecked(), assign.ref_);
+ }
+ return *this;
+ }
GlobalRefState(GlobalRefState&& move) noexcept
: engine_(move.engine_), ref_(std::move(move.ref_)) {
@@ -80,14 +91,6 @@ class GlobalRefState {
move.engine_ = nullptr;
}
- GlobalRefState& operator=(const GlobalRefState& assign) {
- if (this != &assign) {
- engine_ = assign.engine_;
- ref_ = assign.ref_;
- }
- return *this;
- }
-
GlobalRefState& operator=(GlobalRefState&& assign) noexcept {
if (this != &assign) {
engine_ = assign.engine_;
diff --git a/src/version.h b/src/version.h
index 6797668c..b1109c5e 100644
--- a/src/version.h
+++ b/src/version.h
@@ -19,9 +19,9 @@
// ScriptX version config files
// auto generated from the file VERSION
-#define SCRIPTX_VERSION_STRING "3.5.0"
+#define SCRIPTX_VERSION_STRING "3.6.0"
#define SCRIPTX_VERSION_MAJOR 3
-#define SCRIPTX_VERSION_MINOR 5
+#define SCRIPTX_VERSION_MINOR 6
#define SCRIPTX_VERSION_PATCH 0
namespace script {
diff --git a/test/cmake/TestEnv.cmake b/test/cmake/TestEnv.cmake
index 1d582f2a..badcec24 100644
--- a/test/cmake/TestEnv.cmake
+++ b/test/cmake/TestEnv.cmake
@@ -52,9 +52,15 @@ include(${CMAKE_CURRENT_LIST_DIR}/test_libs/CMakeLists.txt)
if (${SCRIPTX_BACKEND} STREQUAL V8)
if (SCRIPTX_TEST_BUILD_ONLY)
+ if ("${SCRIPTX_V8_INCLUDES}" STREQUAL "")
set(DEVOPS_LIBS_INCLUDE
- "${SCRIPTX_TEST_LIBS}/v8/mac/include"
- CACHE STRING "" FORCE)
+ "${SCRIPTX_TEST_LIBS}/v8/mac/include"
+ CACHE STRING "" FORCE)
+ else()
+ set(DEVOPS_LIBS_INCLUDE
+ "${SCRIPTX_V8_INCLUDES}"
+ CACHE STRING "" FORCE)
+ endif()
elseif (APPLE)
if (CMAKE_SYSTEM_PROCESSOR STREQUAL arm64)
set(DEVOPS_LIBS_INCLUDE
diff --git a/test/cmake/test_v8_compiles.sh b/test/cmake/test_v8_compiles.sh
new file mode 100755
index 00000000..829ab2d0
--- /dev/null
+++ b/test/cmake/test_v8_compiles.sh
@@ -0,0 +1,92 @@
+#! /bin/bash
+
+# USAGE:
+#