diff --git a/build-capnp.bat b/build-capnp.bat index b585a30..dd7eee9 100755 --- a/build-capnp.bat +++ b/build-capnp.bat @@ -27,11 +27,13 @@ IF NOT EXIST %BUILD_DIR% MKDIR %BUILD_DIR% PUSHD %BUILD_DIR% +SET CAPNP_FILENAME=capnproto-c++-1.1.0.tar.gz + :: Download and unzip the capnproto source. It's pretty small (1.6 MiB), so this should be fast. :: curl.exe and tar.exe come pre-installed from Windows 10 onwards. -curl.exe -O https://capnproto.org/capnproto-c++-win32-0.10.3.zip || EXIT /B %ERRORLEVEL% -tar.exe --strip-components=1 -xf capnproto-c++-win32-0.10.3.zip || EXIT /B %ERRORLEVEL% -DEL capnproto-c++-win32-0.10.3.zip || EXIT /B %ERRORLEVEL% +curl.exe -O https://capnproto.org/%CAPNP_FILENAME% || EXIT /B %ERRORLEVEL% +tar.exe --strip-components=1 -xf %CAPNP_FILENAME% || EXIT /B %ERRORLEVEL% +DEL %CAPNP_FILENAME% || EXIT /B %ERRORLEVEL% :: Build the library, making sure that the MSVC runtime library is statically linked. Note that :: cmake won't respect that setting unless we also enable policy CMP0091. diff --git a/build-capnp.sh b/build-capnp.sh index 96bba53..634a866 100755 --- a/build-capnp.sh +++ b/build-capnp.sh @@ -32,7 +32,7 @@ here=$(cd "$(dirname "$BASH_SOURCE")"; \ # We store all of our build artefacts in a subdirectory. If that directory already exists, remove # it so that we can cleanly restart from scratch. Preserve the capnproto source distribution if # it's present, so that we don't need to redownload it. -capnp_filename="capnproto-c++-0.10.3.tar.gz" +capnp_filename="capnproto-c++-1.1.0.tar.gz" build_dir="${here}/build-capnp" if [[ -f "${build_dir}/${capnp_filename}" ]]; then @@ -51,7 +51,7 @@ pushd ${build_dir} # Download the capnproto source, if we don't already have it, and then unpack it. It's pretty small # (1.6 MiB), so the download should be fast. if [[ ! -f "${capnp_filename}" ]]; then - curl -O https://capnproto.org/capnproto-c++-0.10.3.tar.gz + curl -O "https://capnproto.org/${capnp_filename}" fi tar --strip-components=1 -zxf "${capnp_filename}" @@ -63,7 +63,7 @@ if [[ $1 == "linux" ]]; then CC="clang" \ CXX="clang++" \ CFLAGS="-fPIC" \ - CXXFLAGS="-std=c++17 -fPIC" \ + CXXFLAGS="-std=c++20 -fPIC" \ ./configure --disable-shared make -j make install-data DESTDIR=capnp-root diff --git a/build.js b/build.js index 8425194..4f62d27 100755 --- a/build.js +++ b/build.js @@ -126,6 +126,9 @@ function buildCapnp() { buildCapnpResult = childProcess.spawnSync("build-capnp.bat", [], { stdio: "inherit", + // shell: true is required on Windows since node v20.12.2: + // https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2 + shell: true }); } else { throw new Error( @@ -172,7 +175,7 @@ if (process.platform === "linux" && args.targetPlatform === "linux") { buildEnvironment.CC = "clang"; buildEnvironment.CXX = "clang++"; buildEnvironment.CFLAGS = "-I" + capnpIncPath; - buildEnvironment.CXXFLAGS = buildEnvironment.CFLAGS; + buildEnvironment.CXXFLAGS = buildEnvironment.CFLAGS + " -std=c++20"; buildEnvironment.LDFLAGS = "-L" + capnpLibPath; } @@ -190,7 +193,7 @@ if (process.platform === "linux" && args.targetPlatform === "darwin") { } buildEnvironment.CFLAGS = - "-mmacosx-version-min=10.7 -std=c++17 " + + "-mmacosx-version-min=10.7 -std=c++20 " + "-stdlib=libc++ -I" + capnpIncPath; buildEnvironment.CXXFLAGS = buildEnvironment.CFLAGS; @@ -259,10 +262,18 @@ function build(buildEnvironment) { `Executing ${command} with the following arguments:\n${commandArgs}` ); - const nodeGypResult = childProcess.spawnSync(command, commandArgs, { + const spawnSyncOptions = { stdio: "inherit", env: buildEnvironment, - }); + }; + + if (process.platform === "win32") { + // shell: true is required on Windows since node v20.12.2: + // https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2 + spawnSyncOptions.shell = true; + } + + const nodeGypResult = childProcess.spawnSync(command, commandArgs, spawnSyncOptions); if (nodeGypResult.error) { throw nodeGypResult.error; @@ -335,7 +346,7 @@ function moveBuildResult(builtPath, buildEnvironment) { * @param target - The target binary to be modified */ function patchLibs(patchTool, patchPath, target) { - var libVersion = "0.10.3"; + var libVersion = "1.1.0"; var libExt = "so"; var libs = ["libkj", "libkj-async", "libcapnp", "libcapnpc", "libcapnp-rpc"]; diff --git a/package.json b/package.json index 73c50c3..7dfb4c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "capnp", - "version": "0.5.7", + "version": "0.6.0", "description": "A wrapper for the C++ Cap'n Proto library", "keywords": [ "capnproto", @@ -21,7 +21,7 @@ "main": "src/node-capnp/capnp.js", "types": "src/node-capnp/capnp.d.ts", "scripts": { - "install": "node ./build.js --dist-url=https://electronjs.org/headers --target=20.3.3", + "install": "node ./build.js --dist-url=https://electronjs.org/headers --target=35.1.2", "test": "electron src/node-capnp/capnp-test.js" }, "dependencies": { @@ -29,8 +29,8 @@ "yargs": "^17.6.2" }, "devDependencies": { - "electron": "^20.3.3", - "node-gyp": "^9.1.0" + "electron": "^35.1.2", + "node-gyp": "^11.2.0" }, "repository": { "type": "git", diff --git a/prebuilt/win32-x64/capnp.node b/prebuilt/win32-x64/capnp.node index 2ab3e53..c92d21d 100755 Binary files a/prebuilt/win32-x64/capnp.node and b/prebuilt/win32-x64/capnp.node differ diff --git a/src/node-capnp/capnp.cc b/src/node-capnp/capnp.cc index 9f47fb6..56c789d 100644 --- a/src/node-capnp/capnp.cc +++ b/src/node-capnp/capnp.cc @@ -1272,16 +1272,15 @@ kj::Maybe> unwrapBuffer(v8::Local value) { kj::ArrayPtr& name = KJ_ASSERT_NONNULL(name##_maybe) template -void deleteArray(char*, void* hint) { - delete reinterpret_cast*>(hint); -} - -template -v8::Local wrapBuffer(kj::Array&& array) { +v8::Local copyToNodeBuffer(kj::Array&& array) { char* data = reinterpret_cast(array.begin()); size_t size = array.size() * sizeof(T); - return check(node::Buffer::New(v8::Isolate::GetCurrent(), data, size, &deleteArray, - new kj::Array(kj::mv(array)))); + // We need to copy the data into a V8 ArrayBuffer as since version 21 Electron + // does not allow externally allocated pointers to be passed to JavaScript. + // See https://www.electronjs.org/blog/v8-memory-cage + v8::Local ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), size); + memcpy(ab->Data(), data, size); + return check(node::Buffer::New(v8::Isolate::GetCurrent(), ab, 0, size)); } // ======================================================================================= @@ -2037,7 +2036,7 @@ v8::Local valueToJs(CapnpContext& context, capnp::DynamicValue::Reade } else { capnp::MallocMessageBuilder message; message.setRoot(value.as()); - return scope.Escape(wrapBuffer(capnp::messageToFlatArray(message))); + return scope.Escape(copyToNodeBuffer(capnp::messageToFlatArray(message))); } } } @@ -2255,17 +2254,17 @@ void toBytes(const v8::FunctionCallbackInfo& args) { kj::VectorOutputStream output; capnp::_::PackedOutputStream packer(output); packer.write(words.asBytes().begin(), words.asBytes().size()); - return wrapBuffer(kj::heapArray(output.getArray())); + return copyToNodeBuffer(kj::heapArray(output.getArray())); } else { - return wrapBuffer(kj::mv(words)); + return copyToNodeBuffer(kj::mv(words)); } } else if (packed) { kj::VectorOutputStream output; capnp::writePackedMessage(output, builder.message); auto packedMessage = heapArray(output.getArray()); - return wrapBuffer(kj::mv(packedMessage)); + return copyToNodeBuffer(kj::mv(packedMessage)); } else { - return wrapBuffer(capnp::messageToFlatArray(builder.message)); + return copyToNodeBuffer(capnp::messageToFlatArray(builder.message)); } }); }