ONLY_FOR_ARCHS =	amd64 aarch64 i386 powerpc64 riscv64
DPB_PROPERTIES =	parallel

USE_WXNEEDED =		Yes

COMMENT = JavaScript runtime built on Chrome's V8 JavaScript engine

NODE_VERSION =		24.18.0

DIST_TUPLE+=		github nodejs node v${NODE_VERSION} .
DIST_TUPLE+=		github qbit node-pledge 1.1.3 \
				deps/npm/node_modules/node-pledge

DISTFILES.node =	node-v${NODE_VERSION}-headers.tar.gz
SITES.node =		${HOMEPAGE}dist/v${NODE_VERSION}/

# make v8-deps
# https://raw.githubusercontent.com/nodejs/node/v24.18.0/deps/v8/DEPS
BUILD_V=		451ef881d77fff0b7a8bbfa61934f5e4a35b4c96
BUILDTOOLS_V=		6f359296daa889aa726f3d05046b9f37be241169
ICU_V=			c9fb4b3a6fb54aa8c20a03bbcaa0a4a985ffd34b
PROTOBUF_V=		b714f7890b8b6ad3ff3471d3148b28c2c7bbff90
FUZZTEST_V=		df29ed1355d06c486e17fc421767ff01af050ca4
FUZZTEST_SRC_V=		3c7bc855a4938c5d0d1d07303aa0697c88d33e6c
GOOGLETEST_V=		52204f78f94d7512df1f0f3bea1d47437a2c3a58
JSONCPP_V=		42e892d96e47b1f6e29844cc705e148ec4856448
RE2_V=			c84a140c93352cdabbfb547c531be34515b12228
ZLIB_V=			788cb3c270e8700b425c7bdca1f9ce6b0c1400a9
LIBCXX_V=		449310fe2e37834a7e62972d2a690cade2ef596b
LIBCXXABI_V=		94c5d7a8edc09f0680aee57548c0b5d400c2840d
# wasm archives checked by tools/make-v8.sh
WASM_JS_H=		8a69e14a26326662093099426eff78db6d409761
WASM_SPEC_H=		e8f855c3f80301e3f127eaf18ba426dd6208c4bb

# chromium.googlesource.com/chromium/
# build: Chromium build configuration and scripts; BSD-3-Clause
# buildtools: Common build tooling for Chromium; BSD-3-Clause
# protobuf: Protocol Buffers data serialization; BSD-3-Clause
# icu: International Components for Unicode; Unicode-3.0
# fuzztest: Chromium mirror metadata for FuzzTest; BSD-3-Clause
# zlib: A massively spiffy yet delicately unobtrusive compression library; Zlib
SITES.chromium = 	https://chromium.googlesource.com/chromium/
TEMPLATE_DISTFILES.chromium = \
	v8-<project>-{<account>/<project>/+archive/}<id>.tar.gz
DIST_TUPLE+= \
chromium src build ${BUILD_V} deps/v8/build \
chromium src buildtools ${BUILDTOOLS_V} deps/v8/buildtools \
chromium src/third_party protobuf ${PROTOBUF_V} deps/v8/third_party/protobuf \
chromium deps icu ${ICU_V} deps/v8/third_party/icu \
chromium src/third_party fuzztest ${FUZZTEST_V} deps/v8/third_party/fuzztest \
chromium src/third_party zlib ${ZLIB_V} deps/v8/third_party/zlib

# fuzztest-src: C++ framework for writing and running fuzz tests; Apache-2.0
# googletest: Google Test: Google's C++ Testing Framework; BSD-3-Clause
# jsoncpp: JSON parser and generator for C++; MIT
# re2: An efficient, principled regular expression library; BSD-3-Clause
DIST_TUPLE+= \
github google fuzztest ${FUZZTEST_SRC_V} deps/v8/third_party/fuzztest/src \
github google googletest ${GOOGLETEST_V} deps/v8/third_party/googletest/src \
github open-source-parsers jsoncpp ${JSONCPP_V} \
	deps/v8/third_party/jsoncpp/source \
github google re2 ${RE2_V} deps/v8/third_party/re2/src

# chromium.googlesource.com/external/github.com/
# libcxx: LLVM C++ standard library; Apache-2.0 WITH LLVM-exception
# libcxxabi: LLVM C++ low level support; Apache-2.0 WITH LLVM-exception
SITES.chromium-ext =	https://chromium.googlesource.com/external/github.com/
TEMPLATE_DISTFILES.chromium-ext = \
	v8-<project>-{llvm/llvm-project/<project>/+archive/}<id>.tar.gz
DIST_TUPLE+= \
chromium-ext _ libcxx ${LIBCXX_V} deps/v8/third_party/libc++/src \
chromium-ext _ libcxxabi ${LIBCXXABI_V} deps/v8/third_party/libc++abi/src

# storage.googleapis.com/v8-wasm-spec-tests
# wasm-js: WebAssembly JavaScript API tests; Apache-2.0/BSD-3-Clause
# wasm-spec-tests: WebAssembly specification tests; Apache-2.0
SITES.v8wasm =		https://storage.googleapis.com/v8-wasm-spec-tests/
DISTFILES.v8wasm = \
	v8-wasm-js-${WASM_JS_H}.tar.gz{${WASM_JS_H}} \
	v8-wasm-spec-tests-${WASM_SPEC_H}.tar.gz{${WASM_SPEC_H}}

DISTNAME =		node-${NODE_VERSION}
PKGNAME =		${DISTNAME:S/v//g}
EPOCH =			0

CATEGORIES =		lang devel

HOMEPAGE =		https://nodejs.org/

# MIT
PERMIT_PACKAGE =	Yes

MODULES =		lang/python
MODPY_RUNDEP =		No

COMPILER =		base-clang ports-gcc

USE_GMAKE =		Yes
ALL_TARGET =		v8

BUILD_DEPENDS =		devel/glib2 \
			sysutils/flock

CONFIGURE_STYLE =	simple
CONFIGURE_SCRIPT =	configure

CONFIGURE_ARGS =	--prefix=${PREFIX}

SUBST_VARS +=		DISTNAME
SUBST_VARS +=		WRKDIST
SUBST_VARS +=		NODE_VERSION

DEBUG_PACKAGES =	${BUILD_PACKAGES}

# Upstream marks test-v8 as the V8 CI job target.
TEST_TARGET =		test-v8
TEST_ENV =		${MAKE_ENV} HOME=${WRKSRC} CI=true
TEST_OPTIONS = \
	-j1 -t 30 --progress=verbose \
	--exit-after-n-failures=20 --total-timeout-sec=3600

ALL_PATCHFILES+=	${PATCHDIR}/chromium/patch-*
PATCH_CASES+=		${PATCHDIR}/chromium/patch-*) \
			    ${PATCH} ${PATCH_DIST_ARGS} \
			    -z .orig.chromium \
			    -d ${WRKSRC} <$$patchfile ;;

EXTRACT_CASES+=	v8-*)						\
	d=$$(basename $$archive .tar.gz | sed 's/^v8-//') ;	\
	case "$$archive" in					\
	v8-wasm-js-*)						\
		t=${WRKSRC}/deps/v8/test/wasm-js ;;		\
	v8-wasm-spec-tests-*)					\
		t=${WRKSRC}/deps/v8/test/wasm-spec-tests ;;	\
	*)							\
		t=${WRKDIR}/$$d ;;				\
	esac ;							\
	mkdir -p $$t ;						\
	${GZIP_CMD} -d <${FULLDISTDIR}/$$archive |		\
		${TAR} -xf - -C $$t ;;

post-extract:
	rm -rf ${WRKSRC}/deps/v8/third_party/googletest/src
	rm -rf ${WRKSRC}/deps/v8/third_party/zlib
	[ -d ${WRKSRC}/include ] || \
		mv ${WRKDIR}/node-v${NODE_VERSION}/include ${WRKSRC}

pre-configure:
	${SUBST_CMD} ${WRKDIST}/common.gypi \
		${WRKDIST}/deps/npm/node_modules/node-gyp/lib/install.js \
		${WRKDIST}/src/env.cc \
		${WRKDIST}/tools/test.py

pre-build:
	touch ${WRKSRC}/deps/v8/build/config/gclient_args.gni

do-test:
	cd ${WRKSRC} && \
	ulimit -n $$(ulimit -Hn) && \
	ulimit -d $$(ulimit -Hd) && \
	${SETENV} ${TEST_ENV} ${MAKE_PROGRAM} --ignore-errors \
		V8_EXTRA_TEST_OPTIONS="${TEST_OPTIONS}" ${TEST_TARGET}

# XXX extract node version, find matching chromium, find matching port's version
_CHROMIUM_PATCH_DATE=	20250515

_TMP=		/tmp/${DISTNAME}
_NODE_RAW=	https://raw.githubusercontent.com/nodejs/node/v${NODE_VERSION}
_DEPS_RAW=	${_NODE_RAW}/deps/v8/DEPS

v8-deps:
	# make v8-deps
	@set -e ;							\
	mkdir -p ${_TMP}/v8-deps ;					\
	cd ${_TMP}/v8-deps ;						\
	ftp -VMo DEPS ${_NODE_RAW}/deps/v8/DEPS ;			\
	dep_sha() {							\
		printf "%s=\t%s\n" "$$1" $$(grep -A3 "^  '$$2':"	\
		    DEPS | awk -F"'" '/@/ {print $$(NF - 1); exit}') ;	\
	} ;								\
	wasm_hash() {							\
		_h=$$(grep -A12 "'name': '$$2'" DEPS) ;			\
		_s=$$(printf "%s\n" "$$_h" |				\
			sed -n "s/.*'-s', '\([^']*\)'.*/\1/p") ;	\
		ftp -VMo "$$1.sha1" "${_NODE_RAW}/deps/v8/$$_s" ;	\
		printf "%s_H=\t%s\n" "$$1" $$(sed -n '1p' "$$1.sha1") ;	\
	} ;								\
	printf "# %s\n" "${_NODE_RAW}/deps/v8/DEPS" ;			\
	dep_sha BUILD_V build ;						\
	dep_sha BUILDTOOLS_V buildtools ;				\
	dep_sha ICU_V third_party/icu ;					\
	dep_sha PROTOBUF_V third_party/protobuf ;			\
	dep_sha FUZZTEST_V third_party/fuzztest ;			\
	dep_sha FUZZTEST_SRC_V third_party/fuzztest/src ;		\
	dep_sha GOOGLETEST_V third_party/googletest/src ;		\
	dep_sha JSONCPP_V third_party/jsoncpp/source ;			\
	dep_sha RE2_V third_party/re2/src ;				\
	dep_sha ZLIB_V third_party/zlib ;				\
	dep_sha LIBCXX_V third_party/libc++/src ;			\
	dep_sha LIBCXXABI_V third_party/libc++abi/src ;			\
	printf "# wasm archives checked by tools/make-v8.sh\n" ;	\
	wasm_hash WASM_JS wasm_js ;					\
	wasm_hash WASM_SPEC wasm_spec_tests

chromium-patches:
	make extract
	# cvs co -D ${_CHROMIUM_PATCH_DATE} -d chromium ports/www/chromium
	# remember to update _CHROMIUM_PATCH_DATE if you change targeted version
	if [ -d ${_TMP}/chromium ]; then \
		echo "${_TMP}/chromium exists, skip cvs co" ; \
	else \
		mkdir -p ${_TMP} && cd ${_TMP} && \
		cvs co -D ${_CHROMIUM_PATCH_DATE} -d chromium \
		    ports/www/chromium ; \
	fi
	# rebase chromium patches into node's deps/v8 tree
	rm -rf ${_TMP}/patches/chromium*
	mkdir -p ${_TMP}/patches/chromium{,.rej,.miss,.new,.tmp,.orig}
	for p in ${_TMP}/chromium/patches/patch-*; do \
		[ -f $${p} ] || continue ; \
		b=$$(basename $${p}) ; \
		orig=$$(grep -m1 'Index: ' $${p} | sed -e 's/.*: //') ; \
		pp=${_TMP}/patches/chromium.tmp/$${b} ; \
		case "$${orig}" in \
		v8/*) \
			f=deps/$${orig} ; \
			sed -e "s|^\(Index: \)|\1deps/|" \
			    -e "s|^\(--- \)|\1deps/|" \
			    -e "s|^\(+++ \)|\1deps/|" \
			    $${p} > $${pp} ;; \
		*) \
			f=deps/v8/$${orig} ; \
			sed -e "s|^\(Index: \)|\1deps/v8/|" \
			    -e "s|^\(--- \)|\1deps/v8/|" \
			    -e "s|^\(+++ \)|\1deps/v8/|" \
			    $${p} > $${pp} ;; \
		esac ; \
		if grep -q "@@ -0,0" $${pp}; then \
			cp $${pp} ${_TMP}/patches/chromium/ ; \
			cp $${pp} ${_TMP}/patches/chromium.new/ ; \
		elif [ -f "${WRKSRC}/$${f}" ]; then \
			${PATCH} ${PATCH_DIST_ARGS} -sfC -z .orig.chromium \
			    -d ${WRKSRC} < $${pp} >/dev/null 2>&1 && \
			cp $${pp} ${_TMP}/patches/chromium/ || \
			cp $${pp} ${_TMP}/patches/chromium.rej/ ; \
		else \
			echo "missing ${WRKSRC}/$${f}" ; \
			cp $${pp} ${_TMP}/patches/chromium.miss/ ; \
		fi ; \
	done
	for p in ${_TMP}/patches/chromium.rej/patch-*; do \
		[ -f $${p} ] || continue ; \
		b=$$(basename $${p}) ; \
		f=$$(grep -m1 'Index: ' $${p} | sed -e 's/.*: //') ; \
		ot=${_TMP}/patches/chromium.orig/$${b} ; \
		if [ -f "${WRKSRC}/$${f}.orig.chromium" ]; then \
			rm -rf $${ot} ; \
			mkdir -p $${ot}/$${f%/*} ; \
			cp "${WRKSRC}/$${f}.orig.chromium" $${ot}/$${f} ; \
			if ${PATCH} ${PATCH_DIST_ARGS} -sfC \
			    -d $${ot} < $${p} >/dev/null 2>&1; then \
				echo "valid on .orig* ${WRKSRC}/$${f}" ; \
				cp $${p} ${_TMP}/patches/chromium/ ; \
				rm -f $${p} ; \
			fi ; \
		fi ; \
	done
	@echo "rejected:"
	@ls ${_TMP}/patches/chromium.rej
	# if ok, copy ${_TMP}/patches/chromium into port && make clean

.include <bsd.port.mk>
