git: 3129dbeb5a4e - main - devel/cbang: databases/postgresql-plv8js: Chase v8 upgrade
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 02 Oct 2026 06:09:36 UTC
The branch main has been updated by delphij:
URL: https://cgit.FreeBSD.org/ports/commit/?id=3129dbeb5a4e0ebfcc9997501f3852f22df40b60
commit 3129dbeb5a4e0ebfcc9997501f3852f22df40b60
Author: Xin LI <delphij@FreeBSD.org>
AuthorDate: 2026-10-02 06:07:47 +0000
Commit: Xin LI <delphij@FreeBSD.org>
CommitDate: 2026-10-02 06:09:12 +0000
devel/cbang: databases/postgresql-plv8js: Chase v8 upgrade
V8 15.4 headers refuse to compile ("Non-CppGC MicrotaskQueue definition
is not supported") unless the embedder defines V8_CPPGC_MICROTASK_QUEUE,
matching how lang/v8 itself is built.
databases/postgresql-plv8js: pass the define in CXXFLAGS.
devel/cbang: define it in the v8 scons config before the v8.h header
check, which otherwise fails and silently disables V8 support, breaking
packaging. Also record it in cbang/config.h for consumers.
---
cad/camotics/Makefile | 5 +-
databases/postgresql-plv8js/Makefile | 4 +-
databases/postgresql-plv8js/files/patch-Makefile | 14 +-
databases/postgresql-plv8js/files/patch-plv8.cc | 60 +++++++
databases/postgresql-plv8js/files/patch-plv8.h | 44 ++++++
.../files/patch-plv8__allocator.cc | 10 ++
.../files/patch-plv8__allocator.h | 11 ++
.../postgresql-plv8js/files/patch-plv8__func.cc | 175 +++++++++++++++++++++
.../postgresql-plv8js/files/patch-plv8__type.cc | 20 +++
databases/postgresql-plv8js/pkg-plist | 2 +
devel/cbang/Makefile | 8 +-
devel/cbang/files/patch-config_v8_____init____.py | 21 +++
.../cbang/files/patch-src_cbang_js_v8_Context.cpp | 14 ++
devel/cbang/files/patch-src_cbang_js_v8_V8.h | 9 ++
devel/cbang/files/patch-src_cbang_js_v8_Value.cpp | 20 +++
devel/cbang/files/patch-src_cbang_js_v8_Value.h | 11 ++
devel/cbang/files/patch-src_cbang_net_URI.cpp | 65 ++++++++
17 files changed, 482 insertions(+), 11 deletions(-)
diff --git a/cad/camotics/Makefile b/cad/camotics/Makefile
index b6019f6b4329..e42946f7e196 100644
--- a/cad/camotics/Makefile
+++ b/cad/camotics/Makefile
@@ -60,7 +60,7 @@ PORTEXAMPLES= *
MAKE_ARGS+= cc="${CC}" \
cxx="${CXX}" \
- cxxstd="c++17" \
+ cxxstd="c++20" \
ccflags="${CCFLAGS}" \
cxxflags="${CXXFLAGS} ${QT5_INC}" \
linkflags="${LDFLAGS} ${QT5_LIBS}" \
@@ -71,7 +71,8 @@ MAKE_ARGS+= cc="${CC}" \
compiler="${CHOSEN_COMPILER_TYPE:C/gcc/gnu/}" \
disable_local="zlib bzip2 lz4 sqlite3 expat libevent re2 libyaml"
MAKE_ENV+= QT5DIR="${LOCALBASE}" \
- CBANG_HOME="${WRKDIR}/cbang"
+ CBANG_HOME="${WRKDIR}/cbang" \
+ V8_INCLUDE="${LOCALBASE}/include"
.if defined(WITH_DEBUG)
MAKE_ARGS+= debug=1 strict=0
.endif
diff --git a/databases/postgresql-plv8js/Makefile b/databases/postgresql-plv8js/Makefile
index 89095e267cf6..a308ca5995ce 100644
--- a/databases/postgresql-plv8js/Makefile
+++ b/databases/postgresql-plv8js/Makefile
@@ -14,13 +14,13 @@ LICENSE= PostgreSQL
BUILD_DEPENDS= bash:shells/bash
LIB_DEPENDS= libv8.so:lang/v8
-USES= compiler:c++17-lang gmake pgsql
+USES= compiler:c++20-lang gmake pgsql
USE_GITHUB= yes
PLIST_SUB= PORTVERSION="${PORTVERSION}"
.include <bsd.port.options.mk>
-CXXFLAGS+= -std=c++17 -fno-rtti
+CXXFLAGS+= -std=c++20 -fno-rtti -DV8_CPPGC_MICROTASK_QUEUE=1
# Only for 64-bit architectures
.if ${ARCH} != armv6 && ${ARCH} != armv7 && ${ARCH} != i386 && ${ARCH} != powerpc && ${ARCH} != powerpcspe
CXXFLAGS+= -DV8_COMPRESS_POINTERS=1 -DV8_31BIT_SMIS_ON_64BIT_ARCH=1
diff --git a/databases/postgresql-plv8js/files/patch-Makefile b/databases/postgresql-plv8js/files/patch-Makefile
index 04eaa72f4057..8199929511b5 100644
--- a/databases/postgresql-plv8js/files/patch-Makefile
+++ b/databases/postgresql-plv8js/files/patch-Makefile
@@ -1,6 +1,6 @@
--- Makefile.orig 2025-07-05 17:44:26 UTC
+++ Makefile
-@@ -37,20 +37,8 @@ SHLIB_LINK += -Ldeps/v8-cmake/build
+@@ -37,24 +37,12 @@ SHLIB_LINK += -Ldeps/v8-cmake/build
SHLIB_LINK += -Ldeps/v8-cmake/build
@@ -22,12 +22,20 @@
# enable direct jsonb conversion by default
CCFLAGS += -DJSONB_DIRECT_CONVERSION
-@@ -76,7 +64,7 @@ endif
+-CCFLAGS += -Ideps/v8-cmake/v8/include -std=c++17
++CCFLAGS += -Ideps/v8-cmake/v8/include -std=c++20
+
+ ifdef EXECUTION_TIMEOUT
+ CCFLAGS += -DEXECUTION_TIMEOUT
+@@ -76,9 +64,9 @@ endif
REGRESS += bigint_graceful
endif
-SHLIB_LINK += -lv8_base_without_compiler -lv8_compiler -lv8_snapshot -lv8_inspector -lv8_libplatform -lv8_base_without_compiler -lv8_libsampler -lv8_torque_generated -lv8_libbase
+SHLIB_LINK += -lv8_libbase -lv8 -lv8_libplatform
- OPTFLAGS = -std=c++17 -fno-rtti -O2
+-OPTFLAGS = -std=c++17 -fno-rtti -O2
++OPTFLAGS = -std=c++20 -fno-rtti -O2
CCFLAGS += -Wall $(OPTFLAGS)
+
+ generate_upgrades:
diff --git a/databases/postgresql-plv8js/files/patch-plv8.cc b/databases/postgresql-plv8js/files/patch-plv8.cc
new file mode 100644
index 000000000000..4b8bf3f61a1b
--- /dev/null
+++ b/databases/postgresql-plv8js/files/patch-plv8.cc
@@ -0,0 +1,60 @@
+--- plv8.cc.orig 2025-07-05 17:44:26 UTC
++++ plv8.cc
+@@ -232,10 +232,10 @@ void PromiseRejectCB(PromiseRejectMessage rejection) {
+
+ void PromiseRejectCB(PromiseRejectMessage rejection) {
+ auto event = rejection.GetEvent();
+- if (event == kPromiseRejectAfterResolved || event == kPromiseResolveAfterResolved)
++ if (event == kDeprecatedPromiseRejectAfterResolved || event == kDeprecatedPromiseResolveAfterResolved)
+ return;
+ auto promise = rejection.GetPromise();
+- auto isolate = promise->GetIsolate();
++ auto isolate = v8::Isolate::GetCurrent();
+
+ if (rejection.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
+ if (current_context->ignore_unhandled_promises) return;
+@@ -753,7 +753,7 @@ DoCall(Local<Context> ctx, Handle<Function> fn, Handle
+ DoCall(Local<Context> ctx, Handle<Function> fn, Handle<Object> receiver,
+ int nargs, Handle<v8::Value> args[], bool nonatomic)
+ {
+- Isolate *isolate = ctx->GetIsolate();
++ Isolate *isolate = Isolate::GetCurrent();
+ TryCatch try_catch(isolate);
+
+ if (isolate->IsExecutionTerminating() || current_context->interrupted) {
+@@ -897,7 +897,7 @@ CallFunction(PG_FUNCTION_ARGS, plv8_exec_env *xenv,
+
+ Local<Object> recv = Local<Object>::New(xenv->isolate, xenv->recv);
+ Local<Function> fn =
+- Local<Function>::Cast(recv->GetInternalField(0));
++ Local<Function>::Cast(recv->GetInternalField(0).As<v8::Value>());
+
+ Local<v8::Value> result =
+ DoCall(context, fn, recv, nargs, args, nonatomic);
+@@ -1014,7 +1014,7 @@ CallSRFunction(PG_FUNCTION_ARGS, plv8_exec_env *xenv,
+
+ Local<Object> recv = Local<Object>::New(xenv->isolate, xenv->recv);
+ Local<Function> fn =
+- Local<Function>::Cast(recv->GetInternalField(0));
++ Local<Function>::Cast(recv->GetInternalField(0).As<v8::Value>());
+
+ Handle<v8::Value> result = DoCall(context, fn, recv, nargs, args, nonatomic);
+
+@@ -1148,7 +1148,7 @@ CallTrigger(PG_FUNCTION_ARGS, plv8_exec_env *xenv)
+ TryCatch try_catch(xenv->isolate);
+ Local<Object> recv = Local<Object>::New(xenv->isolate, xenv->recv);
+ Local<Function> fn =
+- Local<Function>::Cast(recv->GetInternalField(0));
++ Local<Function>::Cast(recv->GetInternalField(0).As<v8::Value>());
+ Handle<v8::Value> newtup =
+ DoCall(context, fn, recv, lengthof(args), args, nonatomic);
+
+@@ -1547,7 +1547,7 @@ CompileFunction(
+ Local<Context> context = Local<Context>::New(isolate, global_context->context);
+ Context::Scope context_scope(context);
+ TryCatch try_catch(isolate);
+- v8::ScriptOrigin origin(isolate, name);
++ v8::ScriptOrigin origin(name);
+
+ // set up the signal handlers
+ if (int_handler == NULL) {
diff --git a/databases/postgresql-plv8js/files/patch-plv8.h b/databases/postgresql-plv8js/files/patch-plv8.h
new file mode 100644
index 000000000000..8c3c7edfcb78
--- /dev/null
+++ b/databases/postgresql-plv8js/files/patch-plv8.h
@@ -0,0 +1,44 @@
+--- plv8.h.orig 2026-06-01 05:04:31 UTC
++++ plv8.h
+@@ -217,15 +217,15 @@ class WindowFunctionSupport (public)
+ {
+ m_plv8obj = v8::Handle<v8::Object>::Cast(
+ context->Global()->Get(context, v8::String::NewFromUtf8Literal(
+- context->GetIsolate(),
++ v8::Isolate::GetCurrent(),
+ "plv8",
+ v8::NewStringType::kInternalized)).ToLocalChecked());
+ if (m_plv8obj.IsEmpty())
+ throw js_error("plv8 object not found");
+ /* Stash the current item, just in case of nested call */
+- m_prev_fcinfo = m_plv8obj->GetInternalField(PLV8_INTNL_FCINFO);
++ m_prev_fcinfo = m_plv8obj->GetInternalField(PLV8_INTNL_FCINFO).As<v8::Value>();
+ m_plv8obj->SetInternalField(PLV8_INTNL_FCINFO,
+- v8::External::New(context->GetIsolate(), fcinfo));
++ v8::External::New(v8::Isolate::GetCurrent(), fcinfo, v8::kExternalPointerTypeTagDefault));
+ }
+ }
+ bool IsWindowCall() { return WindowObjectIsValid(m_winobj); }
+@@ -257,17 +257,17 @@ class SRFSupport (public)
+ {
+ v8::Local<v8::Value> m_val;
+ if (!context->Global()->Get(context, v8::String::NewFromUtf8Literal(
+- context->GetIsolate(),
++ v8::Isolate::GetCurrent(),
+ "plv8",
+ v8::NewStringType::kInternalized)).ToLocal(&m_val))
+ throw js_error("plv8 object not found");
+ m_plv8obj = v8::Handle<v8::Object>::Cast(m_val);
+- m_prev_conv = m_plv8obj->GetInternalField(PLV8_INTNL_CONV);
+- m_prev_tupstore = m_plv8obj->GetInternalField(PLV8_INTNL_TUPSTORE);
++ m_prev_conv = m_plv8obj->GetInternalField(PLV8_INTNL_CONV).As<v8::Value>();
++ m_prev_tupstore = m_plv8obj->GetInternalField(PLV8_INTNL_TUPSTORE).As<v8::Value>();
+ m_plv8obj->SetInternalField(PLV8_INTNL_CONV,
+- v8::External::New(context->GetIsolate(), conv));
++ v8::External::New(v8::Isolate::GetCurrent(), conv, v8::kExternalPointerTypeTagDefault));
+ m_plv8obj->SetInternalField(PLV8_INTNL_TUPSTORE,
+- v8::External::New(context->GetIsolate(), tupstore));
++ v8::External::New(v8::Isolate::GetCurrent(), tupstore, v8::kExternalPointerTypeTagDefault));
+ }
+ ~SRFSupport()
+ {
diff --git a/databases/postgresql-plv8js/files/patch-plv8__allocator.cc b/databases/postgresql-plv8js/files/patch-plv8__allocator.cc
new file mode 100644
index 000000000000..da60dc19b02a
--- /dev/null
+++ b/databases/postgresql-plv8js/files/patch-plv8__allocator.cc
@@ -0,0 +1,10 @@
+--- plv8_allocator.cc.orig 2026-06-01 05:04:31 UTC
++++ plv8_allocator.cc
+@@ -67,5 +67,6 @@ void* ArrayAllocator::Reallocate(void *data, size_t ol
+ return nullptr;
+ }
+ }
+- return this->allocator->Reallocate(data, old_length, new_length);
++ allocated += delta;
++ return std::realloc(data, new_length);
+ }
diff --git a/databases/postgresql-plv8js/files/patch-plv8__allocator.h b/databases/postgresql-plv8js/files/patch-plv8__allocator.h
new file mode 100644
index 000000000000..6bc6e1763e67
--- /dev/null
+++ b/databases/postgresql-plv8js/files/patch-plv8__allocator.h
@@ -0,0 +1,11 @@
+--- plv8_allocator.h.orig 2026-06-01 05:04:31 UTC
++++ plv8_allocator.h
+@@ -22,7 +22,7 @@ class ArrayAllocator : public v8::ArrayBuffer::Allocat
+ void* Allocate(size_t length) final;
+ void* AllocateUninitialized(size_t length) final;
+ void Free(void* data, size_t length) final;
+- void* Reallocate(void *data, size_t old_length, size_t new_length) final;
++ void* Reallocate(void *data, size_t old_length, size_t new_length);
+ };
+
+ #endif //PLV8_PLV8_ALLOCATOR_H
diff --git a/databases/postgresql-plv8js/files/patch-plv8__func.cc b/databases/postgresql-plv8js/files/patch-plv8__func.cc
new file mode 100644
index 000000000000..3c9d9be135ce
--- /dev/null
+++ b/databases/postgresql-plv8js/files/patch-plv8__func.cc
@@ -0,0 +1,175 @@
+--- plv8_func.cc.orig 2026-06-01 05:04:31 UTC
++++ plv8_func.cc
+@@ -71,14 +71,15 @@ WrapCallback(FunctionCallback func)
+ Isolate* isolate = Isolate::GetCurrent();
+ return External::New(isolate,
+ reinterpret_cast<void *>(
+- reinterpret_cast<uintptr_t>(func)));
++ reinterpret_cast<uintptr_t>(func)),
++ v8::kExternalPointerTypeTagDefault);
+ }
+
+ static inline FunctionCallback
+ UnwrapCallback(Handle<v8::Value> value)
+ {
+ return reinterpret_cast<FunctionCallback>(
+- reinterpret_cast<uintptr_t>(External::Cast(*value)->Value()));
++ reinterpret_cast<uintptr_t>(External::Cast(*value)->Value(v8::kExternalPointerTypeTagDefault)));
+ }
+
+ static inline void
+@@ -645,8 +646,8 @@ plv8_Prepare(const FunctionCallbackInfo<v8::Value> &ar
+ Local<ObjectTemplate> templ = Local<ObjectTemplate>::New(isolate, current_context->plan_template);
+
+ Local<v8::Object> result = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
+- result->SetInternalField(0, External::New(isolate, saved));
+- result->SetInternalField(1, External::New(isolate, parstate));
++ result->SetInternalField(0, External::New(isolate, saved, v8::kExternalPointerTypeTagDefault));
++ result->SetInternalField(1, External::New(isolate, parstate, v8::kExternalPointerTypeTagDefault));
+
+ args.GetReturnValue().Set(result);
+ }
+@@ -669,7 +670,7 @@ plv8_PlanCursor(const FunctionCallbackInfo<v8::Value>
+ plv8_param_state *parstate = NULL;
+
+ plan = static_cast<SPIPlanPtr>(
+- Handle<External>::Cast(self->GetInternalField(0))->Value());
++ Handle<External>::Cast(self->GetInternalField(0))->Value(v8::kExternalPointerTypeTagDefault));
+
+ if (plan == NULL) {
+ StringInfoData buf;
+@@ -694,7 +695,7 @@ plv8_PlanCursor(const FunctionCallbackInfo<v8::Value>
+ * If the plan has the variable param info, use it.
+ */
+ parstate = static_cast<plv8_param_state *>(
+- Handle<External>::Cast(self->GetInternalField(1))->Value());
++ Handle<External>::Cast(self->GetInternalField(1))->Value(v8::kExternalPointerTypeTagDefault));
+
+ if (parstate)
+ argcount = parstate->numParams;
+@@ -777,7 +778,7 @@ plv8_PlanExecute(const FunctionCallbackInfo<v8::Value>
+
+
+ plan = static_cast<SPIPlanPtr>(
+- Handle<External>::Cast(self->GetInternalField(0))->Value());
++ Handle<External>::Cast(self->GetInternalField(0))->Value(v8::kExternalPointerTypeTagDefault));
+ /* XXX: Add plan validation */
+
+ if (args.Length() > 0)
+@@ -793,7 +794,7 @@ plv8_PlanExecute(const FunctionCallbackInfo<v8::Value>
+ * If the plan has the variable param info, use it.
+ */
+ parstate = static_cast<plv8_param_state *>(
+- Handle<External>::Cast(self->GetInternalField(1))->Value());
++ Handle<External>::Cast(self->GetInternalField(1))->Value(v8::kExternalPointerTypeTagDefault));
+
+ if (parstate)
+ argcount = parstate->numParams;
+@@ -868,19 +869,19 @@ plv8_PlanFree(const FunctionCallbackInfo<v8::Value> &a
+ int status = 0;
+
+ plan = static_cast<SPIPlanPtr>(
+- Handle<External>::Cast(self->GetInternalField(0))->Value());
++ Handle<External>::Cast(self->GetInternalField(0))->Value(v8::kExternalPointerTypeTagDefault));
+
+ if (plan)
+ status = SPI_freeplan(plan);
+
+- self->SetInternalField(0, External::New(isolate, 0));
++ self->SetInternalField(0, External::New(isolate, nullptr, v8::kExternalPointerTypeTagDefault));
+
+ parstate = static_cast<plv8_param_state *>(
+- Handle<External>::Cast(self->GetInternalField(1))->Value());
++ Handle<External>::Cast(self->GetInternalField(1))->Value(v8::kExternalPointerTypeTagDefault));
+
+ if (parstate)
+ pfree(parstate);
+- self->SetInternalField(1, External::New(isolate, 0));
++ self->SetInternalField(1, External::New(isolate, nullptr, v8::kExternalPointerTypeTagDefault));
+
+ args.GetReturnValue().Set(Int32::New(isolate, status));
+ }
+@@ -899,7 +900,7 @@ plv8_CursorFetch(const FunctionCallbackInfo<v8::Value>
+ throw js_error("cannot find cursor");
+ }
+
+- CString cname(self->GetInternalField(0));
++ CString cname(self->GetInternalField(0).As<v8::Value>());
+ Portal cursor = SPI_cursor_find(cname);
+ int nfetch = 1;
+ bool forward = true, wantarray = false;
+@@ -965,7 +966,7 @@ plv8_CursorMove(const FunctionCallbackInfo<v8::Value>&
+ {
+ Isolate* isolate = args.GetIsolate();
+ Handle<v8::Object> self = args.This();
+- CString cname(self->GetInternalField(0));
++ CString cname(self->GetInternalField(0).As<v8::Value>());
+ Portal cursor = SPI_cursor_find(cname);
+ int nmove = 1;
+ bool forward = true;
+@@ -1007,7 +1008,7 @@ plv8_CursorClose(const FunctionCallbackInfo<v8::Value>
+ plv8_CursorClose(const FunctionCallbackInfo<v8::Value> &args)
+ {
+ Handle<v8::Object> self = args.This();
+- CString cname(self->GetInternalField(0));
++ CString cname(self->GetInternalField(0).As<v8::Value>());
+ Portal cursor = SPI_cursor_find(cname);
+
+ if (!cursor)
+@@ -1035,17 +1036,17 @@ plv8_ReturnNext(const FunctionCallbackInfo<v8::Value>&
+ plv8_ReturnNext(const FunctionCallbackInfo<v8::Value>& args)
+ {
+ Handle<v8::Object> self = args.This();
+- Handle<v8::Value> conv_value = self->GetInternalField(PLV8_INTNL_CONV);
++ Handle<v8::Value> conv_value = self->GetInternalField(PLV8_INTNL_CONV).As<v8::Value>();
+
+ if (!conv_value->IsExternal())
+ throw js_error("return_next called in context that cannot accept a set");
+
+ Converter *conv = static_cast<Converter *>(
+- Handle<External>::Cast(conv_value)->Value());
++ Handle<External>::Cast(conv_value)->Value(v8::kExternalPointerTypeTagDefault));
+
+ Tuplestorestate *tupstore = static_cast<Tuplestorestate *>(
+ Handle<External>::Cast(
+- self->GetInternalField(PLV8_INTNL_TUPSTORE))->Value());
++ self->GetInternalField(PLV8_INTNL_TUPSTORE).As<v8::Value>())->Value(v8::kExternalPointerTypeTagDefault));
+
+ conv->ToDatum(args[0], tupstore);
+
+@@ -1158,7 +1159,7 @@ plv8_GetWindowObject(const FunctionCallbackInfo<v8::Va
+ Isolate* isolate = args.GetIsolate();
+ Handle<v8::Object> self = args.This();
+ Handle<v8::Value> fcinfo_value =
+- self->GetInternalField(PLV8_INTNL_FCINFO);
++ self->GetInternalField(PLV8_INTNL_FCINFO).As<v8::Value>();
+
+ if (!fcinfo_value->IsExternal())
+ throw js_error("get_window_object called in wrong context");
+@@ -1179,7 +1180,7 @@ plv8_MyWindowObject(const FunctionCallbackInfo<v8::Val
+ Handle<v8::Object> self = args.This();
+ /* fcinfo is embedded in the internal field. See plv8_GetWindowObject() */
+ FunctionCallInfo fcinfo = static_cast<FunctionCallInfo>(
+- Handle<External>::Cast(self->GetInternalField(0))->Value());
++ Handle<External>::Cast(self->GetInternalField(0))->Value(v8::kExternalPointerTypeTagDefault));
+
+ if (fcinfo == NULL)
+ throw js_error("window function api called with wrong object");
+@@ -1201,7 +1202,7 @@ plv8_MyArgType(const FunctionCallbackInfo<v8::Value>&
+ {
+ Handle<v8::Object> self = args.This();
+ FunctionCallInfo fcinfo = static_cast<FunctionCallInfo>(
+- Handle<External>::Cast(self->GetInternalField(0))->Value());
++ Handle<External>::Cast(self->GetInternalField(0))->Value(v8::kExternalPointerTypeTagDefault));
+
+ if (fcinfo == NULL)
+ throw js_error("window function api called with wrong object");
+@@ -1636,7 +1637,7 @@ void GetMemoryInfo(v8::Local<v8::Object> obj) {
+
+ void GetMemoryInfo(v8::Local<v8::Object> obj) {
+ HeapStatistics v8_heap_stats;
+- Isolate *isolate = obj->GetIsolate();
++ Isolate *isolate = Isolate::GetCurrent();
+ Handle<Context> context = isolate->GetCurrentContext();
+
+ isolate->GetHeapStatistics(&v8_heap_stats);
diff --git a/databases/postgresql-plv8js/files/patch-plv8__type.cc b/databases/postgresql-plv8js/files/patch-plv8__type.cc
new file mode 100644
index 000000000000..db8dd5e2d994
--- /dev/null
+++ b/databases/postgresql-plv8js/files/patch-plv8__type.cc
@@ -0,0 +1,20 @@
+--- plv8_type.cc.orig 2026-06-01 05:04:31 UTC
++++ plv8_type.cc
+@@ -575,7 +575,7 @@ CreateExternalArray(void *data, plv8_external_array_ty
+ default:
+ throw js_error("unexpected array type");
+ }
+- array->SetInternalField(0, External::New(isolate, DatumGetPointer(datum)));
++ array->SetInternalField(0, External::New(isolate, DatumGetPointer(datum), v8::kExternalPointerTypeTagDefault));
+
+ // needs to be a copy, as the data could go away
+ memcpy(buffer->GetBackingStore()->Data(), data, byte_size);
+@@ -593,7 +593,7 @@ ExtractExternalArrayDatum(Handle<v8::Value> value)
+ if (value->IsTypedArray())
+ {
+ Handle<Object> object = Handle<Object>::Cast(value);
+- return Handle<External>::Cast(object->GetInternalField(0))->Value();
++ return Handle<External>::Cast(object->GetInternalField(0).As<v8::Value>())->Value(v8::kExternalPointerTypeTagDefault);
+ }
+
+ return NULL;
diff --git a/databases/postgresql-plv8js/pkg-plist b/databases/postgresql-plv8js/pkg-plist
index dcd63abeb425..c51f360b84a7 100644
--- a/databases/postgresql-plv8js/pkg-plist
+++ b/databases/postgresql-plv8js/pkg-plist
@@ -41,5 +41,7 @@ share/postgresql/extension/plv8--3.1.7--%%PORTVERSION%%.sql
share/postgresql/extension/plv8--3.1.8--%%PORTVERSION%%.sql
share/postgresql/extension/plv8--3.2.0--%%PORTVERSION%%.sql
share/postgresql/extension/plv8--3.2.1--%%PORTVERSION%%.sql
+share/postgresql/extension/plv8--3.2.2--%%PORTVERSION%%.sql
+share/postgresql/extension/plv8--3.2.3--%%PORTVERSION%%.sql
share/postgresql/extension/plv8--%%PORTVERSION%%.sql
share/postgresql/extension/plv8.control
diff --git a/devel/cbang/Makefile b/devel/cbang/Makefile
index 63cdff4d0a96..934c81544ea8 100644
--- a/devel/cbang/Makefile
+++ b/devel/cbang/Makefile
@@ -1,6 +1,6 @@
PORTNAME= cbang
PORTVERSION= 1.8.0
-PORTREVISION= 2
+PORTREVISION= 3
CATEGORIES= devel
MAINTAINER= thierry@FreeBSD.org
@@ -23,10 +23,10 @@ LIB_DEPENDS= libv8.so:lang/v8 \
USE_GITHUB= yes
GH_ACCOUNT= CauldronDevelopmentLLC
-USES= compiler:c++17-lang cpe localbase mysql:client python:test scons \
+USES= compiler:c++20-lang cpe localbase mysql:client python:test scons \
sqlite ssl
CPE_VENDOR= cauldrondevelopment
-USE_CXXSTD= gnu++17
+USE_CXXSTD= gnu++20
USE_LDCONFIG= yes
OPTIONS_DEFINE= DEBUG DOCS
@@ -37,7 +37,7 @@ MAKE_ARGS+= cc="${CC}" \
cxx="${CXX}" \
ccflags="${CCFLAGS}" \
cxxflags="${CXXFLAGS}" \
- cxxstd="c++17" \
+ cxxstd="c++20" \
libpath="/lib" \
sharedlib=1 \
prefix="${STAGEDIR}${PREFIX}" \
diff --git a/devel/cbang/files/patch-config_v8_____init____.py b/devel/cbang/files/patch-config_v8_____init____.py
new file mode 100644
index 000000000000..25afb89f5467
--- /dev/null
+++ b/devel/cbang/files/patch-config_v8_____init____.py
@@ -0,0 +1,21 @@
+--- config/v8/__init__.py.orig 2023-03-09 16:36:47 UTC
++++ config/v8/__init__.py
+@@ -8,13 +8,17 @@ def configure(conf):
+ else: lib_suffix.append('/build/Debug/lib')
+
+ if not 'V8_INCLUDE' in os.environ and not 'V8_HOME' in os.environ:
+- os.environ['V8_INCLUDE'] = '/usr/include/v8'
++ os.environ['V8_INCLUDE'] = '/usr/local/include'
+
+ conf.CBCheckHome('v8', lib_suffix = lib_suffix)
+
+ if conf.env['PLATFORM'] == 'win32' or int(conf.env.get('cross_mingw', 0)):
+ conf.CBRequireLib('winmm')
+ conf.CBCheckLib('dbghelp')
++
++ # V8 >= 15.4 refuses to compile unless the embedder defines this
++ conf.env.AppendUnique(CPPDEFINES = ['V8_CPPGC_MICROTASK_QUEUE=1'])
++ conf.env.CBConfigDef('V8_CPPGC_MICROTASK_QUEUE=1')
+
+ conf.CBRequireCXXHeader('v8.h')
+ conf.CBRequireCXXHeader('libplatform/libplatform.h')
diff --git a/devel/cbang/files/patch-src_cbang_js_v8_Context.cpp b/devel/cbang/files/patch-src_cbang_js_v8_Context.cpp
new file mode 100644
index 000000000000..b6d09c885038
--- /dev/null
+++ b/devel/cbang/files/patch-src_cbang_js_v8_Context.cpp
@@ -0,0 +1,14 @@
+--- src/cbang/js/v8/Context.cpp.orig 2026-06-01 05:31:12 UTC
++++ src/cbang/js/v8/Context.cpp
+@@ -51,11 +51,7 @@ Value Context::eval(const InputSource &src) {
+ string filename = src.getName();
+ if (!filename.empty()) origin = Value::createString(filename);
+
+-#if V8_MAJOR_VERSION < 10
+ v8::ScriptOrigin sOrigin(origin);
+-#else
+- v8::ScriptOrigin sOrigin(Value::getIso(), origin);
+-#endif
+
+ // Get script source
+ auto source = Value::createString(src.toString());
diff --git a/devel/cbang/files/patch-src_cbang_js_v8_V8.h b/devel/cbang/files/patch-src_cbang_js_v8_V8.h
new file mode 100644
index 000000000000..28f383eb8dba
--- /dev/null
+++ b/devel/cbang/files/patch-src_cbang_js_v8_V8.h
@@ -0,0 +1,9 @@
+--- src/cbang/js/v8/V8.h.orig 2026-06-01 05:31:12 UTC
++++ src/cbang/js/v8/V8.h
+@@ -40,6 +40,4 @@
+ #include <stdio.h>
+ #define V8STDINT_H_
+
+-#define V8_ENABLE_CHECKS
+-
+ #include <v8.h>
diff --git a/devel/cbang/files/patch-src_cbang_js_v8_Value.cpp b/devel/cbang/files/patch-src_cbang_js_v8_Value.cpp
new file mode 100644
index 000000000000..0a17ce81bf8a
--- /dev/null
+++ b/devel/cbang/files/patch-src_cbang_js_v8_Value.cpp
@@ -0,0 +1,20 @@
+--- src/cbang/js/v8/Value.cpp.orig 2026-06-01 05:31:12 UTC
++++ src/cbang/js/v8/Value.cpp
+@@ -47,7 +47,7 @@ namespace {
+ namespace {
+ void _callback(const v8::FunctionCallbackInfo<v8::Value> &info) {
+ js::Callback &cb =
+- *static_cast<js::Callback *>(v8::External::Cast(*info.Data())->Value());
++ *static_cast<js::Callback *>(v8::External::Cast(*info.Data())->Value(v8::kExternalPointerTypeTagDefault));
+
+ try {
+ // Convert args
+@@ -87,7 +87,7 @@ Value::Value(const js::Function &func) {
+ JSImpl::current().add(cb);
+
+ v8::Handle<v8::Value> data =
+- v8::External::New(getIso(), (void *)cb.get());
++ v8::External::New(getIso(), (void *)cb.get(), v8::kExternalPointerTypeTagDefault);
+ v8::Handle<v8::FunctionTemplate> tmpl =
+ v8::FunctionTemplate::New(getIso(), &_callback, data);
+ value = tmpl->GetFunction(getCtx()).ToLocalChecked();
diff --git a/devel/cbang/files/patch-src_cbang_js_v8_Value.h b/devel/cbang/files/patch-src_cbang_js_v8_Value.h
new file mode 100644
index 000000000000..ad11c8bdcf95
--- /dev/null
+++ b/devel/cbang/files/patch-src_cbang_js_v8_Value.h
@@ -0,0 +1,11 @@
+--- src/cbang/js/v8/Value.h.orig 2026-06-01 05:31:12 UTC
++++ src/cbang/js/v8/Value.h
+@@ -135,7 +135,7 @@ namespace cb {
+ std::string toString() const;
+
+ int utf8Length() const {
+- return v8::String::Cast(*value)->Utf8Length(getIso());
++ return v8::String::Cast(*value)->Utf8LengthV2(getIso());
+ }
+
+ // Object
diff --git a/devel/cbang/files/patch-src_cbang_net_URI.cpp b/devel/cbang/files/patch-src_cbang_net_URI.cpp
new file mode 100644
index 000000000000..f127525b5b1f
--- /dev/null
+++ b/devel/cbang/files/patch-src_cbang_net_URI.cpp
@@ -0,0 +1,65 @@
+--- src/cbang/net/URI.cpp.orig 2026-06-01 04:53:38 UTC
++++ src/cbang/net/URI.cpp
+@@ -282,7 +282,7 @@ string URI::encode(const string &s, const char *unesca
+ string result;
+
+ for (unsigned i = 0; i < s.length(); i++)
+- if (contains(unescaped, s[i])) result.append(1, s[i]);
++ if (::contains(unescaped, s[i])) result.append(1, s[i]);
+ else result.append(String::printf("%%%02x", (unsigned)s[i]));
+
+ return result;
+@@ -331,7 +331,7 @@ void URI::parsePathSegment(const char *&s) {
+ string seg;
+
+ while (true)
+- if (contains(PATH_SEGMENT_CHARS, *s)) seg.append(1, *s++);
++ if (::contains(PATH_SEGMENT_CHARS, *s)) seg.append(1, *s++);
+ else if (*s == '%') seg.append(1, parseEscape(s));
+ else break;
+
+@@ -343,7 +343,7 @@ void URI::parseScheme(const char *&s) {
+ if (!isalpha(*s)) THROW("Expected alpha at start of scheme");
+
+ while (true)
+- if (contains(SCHEME_CHARS, *s)) scheme.append(1, *s++);
++ if (::contains(SCHEME_CHARS, *s)) scheme.append(1, *s++);
+ else break;
+
+ match(s, ':');
+@@ -378,7 +378,7 @@ string URI::parseUserPass(const char *&s) {
+ string result;
+
+ while (true)
+- if (contains(USER_PASS_CHARS, *s)) result.append(1, *s++);
++ if (::contains(USER_PASS_CHARS, *s)) result.append(1, *s++);
+ else if (*s == '%') result.append(1, parseEscape(s));
+ else break;
+
+@@ -394,7 +394,7 @@ void URI::parseHost(const char *&s) {
+
+ void URI::parseHost(const char *&s) {
+ while (true)
+- if (contains(HOST_CHARS, *s)) host.append(1, *s++);
++ if (::contains(HOST_CHARS, *s)) host.append(1, *s++);
+ else break;
+
+ if (host.empty()) THROW("Expected host character");
+@@ -429,7 +429,7 @@ string URI::parseName(const char *&s) {
+ string result;
+
+ while (true)
+- if (contains(NAME_CHARS, *s)) result.append(1, *s++);
++ if (::contains(NAME_CHARS, *s)) result.append(1, *s++);
+ else if (*s == '%') result.append(1, parseEscape(s));
+ else break;
+
+@@ -443,7 +443,7 @@ string URI::parseValue(const char *&s) {
+ string result;
+
+ while (true)
+- if (contains(VALUE_CHARS, *s)) result.append(1, *s++);
++ if (::contains(VALUE_CHARS, *s)) result.append(1, *s++);
+ else if (*s == '%') result.append(1, parseEscape(s));
+ else break;
+