This is an automated email from the ASF dual-hosted git repository.

xiazcy pushed a commit to branch 3.7-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/3.7-dev by this push:
     new b75f82cab5 backport gremlin-js node 22+ compatibility changes from 3.8 
to 3.7 (#3333)
b75f82cab5 is described below

commit b75f82cab5324be22568cd87feb99dcad75d0ac0
Author: Yang Xia <[email protected]>
AuthorDate: Mon Mar 23 10:05:00 2026 -0700

    backport gremlin-js node 22+ compatibility changes from 3.8 to 3.7 (#3333)
---
 .github/workflows/build-test.yml                   | 74 +++++++++++++++++-----
 CHANGELOG.asciidoc                                 |  1 +
 docs/src/reference/gremlin-variants.asciidoc       |  2 +-
 gremlin-javascript/pom.xml                         |  1 +
 .../gremlin-javascript/docker-compose.yml          |  2 +-
 .../gremlin-javascript/lib/driver/connection.js    |  9 ++-
 .../test/integration/client-behavior-tests.js      |  2 +-
 .../test/integration/socket-connection-tests.js    |  3 +-
 pom.xml                                            |  2 +
 9 files changed, 73 insertions(+), 23 deletions(-)

diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index 6c9cc99678..350b36e253 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -238,16 +238,65 @@ jobs:
         run: |
           mvn clean install -pl 
-:gremlin-javascript,-gremlin-dotnet,-:gremlin-dotnet-source,-:gremlin-dotnet-tests,-:gremlint
 -q -DskipTests -Dci
           mvn verify -pl gremlin-driver -DskipIntegrationTests=false
-  javascript:
-    name: javascript
+  javascript-node20:
+    name: javascript-all-node20
     timeout-minutes: 15
     needs: cache-gremlin-server-docker-image
-    runs-on: ${{ matrix.os }}
-    strategy:
-      matrix:
-        # Windows Disabled until Linux containers are supported on Windows 
runners: https://github.com/actions/virtual-environments/issues/252
-        # os: [ubuntu-latest, windows-latest]
-        os: [ubuntu-latest]
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v6
+      - name: Set up JDK 11
+        uses: actions/setup-java@v5
+        with:
+          java-version: '11'
+          distribution: 'temurin'
+      - name: Get Cached Server Base Image
+        uses: actions/cache@v5
+        id: gremlin-server-test-docker-image
+        with:
+          path: |
+            ./gremlin-server/*
+            ~/.m2/repository/org/apache/tinkerpop/*
+          key: ${{ github.sha }}
+      - name: Load Docker Image
+        working-directory: ./gremlin-server
+        run: docker load --input gremlin-server.tar
+      - name: Build with Maven
+        run: |
+          mvn clean install -pl 
-:gremlin-python,-gremlin-dotnet,-:gremlin-dotnet-source,-:gremlin-dotnet-tests 
-q -DskipTests -Dci
+          mvn verify -pl :gremlin-javascript,:gremlint -Dnode.test.version=20
+  javascript-node22:
+    name: javascript-glv-node22
+    timeout-minutes: 15
+    needs: cache-gremlin-server-docker-image
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v6
+      - name: Set up JDK 11
+        uses: actions/setup-java@v5
+        with:
+          java-version: '11'
+          distribution: 'temurin'
+      - name: Get Cached Server Base Image
+        uses: actions/cache@v5
+        id: gremlin-server-test-docker-image
+        with:
+          path: |
+            ./gremlin-server/*
+            ~/.m2/repository/org/apache/tinkerpop/*
+          key: ${{ github.sha }}
+      - name: Load Docker Image
+        working-directory: ./gremlin-server
+        run: docker load --input gremlin-server.tar
+      - name: Build with Maven
+        run: |
+          mvn clean install -pl 
-:gremlin-python,-gremlin-dotnet,-:gremlin-dotnet-source,-:gremlin-dotnet-tests 
-q -DskipTests -Dci
+          mvn verify -pl :gremlin-javascript -Dnode.test.version=22
+  javascript-node24:
+    name: javascript-glv-node24
+    timeout-minutes: 15
+    needs: cache-gremlin-server-docker-image
+    runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v6
       - name: Set up JDK 11
@@ -256,7 +305,6 @@ jobs:
           java-version: '11'
           distribution: 'temurin'
       - name: Get Cached Server Base Image
-        if: matrix.os == 'ubuntu-latest'
         uses: actions/cache@v5
         id: gremlin-server-test-docker-image
         with:
@@ -264,19 +312,13 @@ jobs:
             ./gremlin-server/*
             ~/.m2/repository/org/apache/tinkerpop/*
           key: ${{ github.sha }}
-#      - name: Download Server Base Image
-#        if: matrix.os == 'windows-latest'
-#        uses: actions/download-artifact@v3
-#        with:
-#          name: ${{ github.sha }}
-#          path: ./gremlin-server
       - name: Load Docker Image
         working-directory: ./gremlin-server
         run: docker load --input gremlin-server.tar
       - name: Build with Maven
         run: |
           mvn clean install -pl 
-:gremlin-python,-gremlin-dotnet,-:gremlin-dotnet-source,-:gremlin-dotnet-tests 
-q -DskipTests -Dci
-          mvn verify -pl :gremlin-javascript,:gremlint
+          mvn verify -pl :gremlin-javascript -Dnode.test.version=24
   python:
     name: python
     timeout-minutes: 20
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index dd9c116ab6..26c33cbc84 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -33,6 +33,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 * Added `closeSessionPostGraphOp` to the Gremlin Server settings to indicate 
that the `Session` should be closed on either a successful commit or rollback.
 * Added `SessionedChildClient` that borrows connections from a different 
`Client` for use with `Sessions`.
 * Added `reuseConnectionsForSessions` to Java GLV settings to decide whether 
to use `SessionedChildClient` for remote transactions.
+* Added support for Node 22 and 24 alongside Node 20.
 
 [[release-3-7-5]]
 === TinkerPop 3.7.5 (Release Date: November 12, 2025)
diff --git a/docs/src/reference/gremlin-variants.asciidoc 
b/docs/src/reference/gremlin-variants.asciidoc
index 97b99ae5dc..413c9243b6 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -1375,7 +1375,7 @@ java -cp target/run-examples-shaded.jar 
examples.ModernTraversals
 == Gremlin-JavaScript
 
 image:gremlin-js.png[width=130,float=right] Apache TinkerPop's 
Gremlin-JavaScript implements Gremlin within the
-JavaScript language. It targets Node.js runtime and can be used on different 
operating systems on any Node.js 6 or
+JavaScript language. It targets Node.js runtime and can be used on different 
operating systems on any Node.js 20 or
 above. Since the JavaScript naming conventions are very similar to that of 
Java, it should be very easy to switch
 between Gremlin-Java and Gremlin-JavaScript.
 
diff --git a/gremlin-javascript/pom.xml b/gremlin-javascript/pom.xml
index f8c5aee24a..15d8000fbc 100644
--- a/gremlin-javascript/pom.xml
+++ b/gremlin-javascript/pom.xml
@@ -262,6 +262,7 @@ limitations under the License.
                                         
<ABS_PROJECT_HOME>${project.basedir}/../</ABS_PROJECT_HOME>
                                         <!-- setting this env variable is 
needed to be cross-platform compatible -->
                                         <HOME>${user.home}</HOME>
+                                        
<NODE_VERSION>${node.test.version}</NODE_VERSION>
                                     </environmentVariables>
                                     <executable>docker</executable>
                                     <arguments>
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/docker-compose.yml 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/docker-compose.yml
index 0345237422..1a98258307 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/docker-compose.yml
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/docker-compose.yml
@@ -43,7 +43,7 @@ services:
 
   gremlin-js-integration-tests:
     container_name: gremlin-js-integration-tests
-    image: node:20
+    image: node:${NODE_VERSION:-20}
     volumes:
       - .:/js_app
       - 
../../../../../gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features:/gremlin-test
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
index 5bfe5b366f..1386c04759 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
@@ -135,9 +135,12 @@ class Connection extends EventEmitter {
       'perMessageDeflate',
     ]);
     // Check if any `ws` specific options are provided and are non-null / 
non-undefined
-    const hasWsSpecificOptions = Object.entries(this.options).some(
-      ([key, value]) => wsSpecificOptions.has(key) && ![null, 
undefined].includes(value),
-    );
+    const hasWsSpecificOptions =
+      Object.entries(this.options).some(
+        ([key, value]) => wsSpecificOptions.has(key) && ![null, 
undefined].includes(value),
+      ) ||
+      this._enableCompression || // we need to check the presence of this 
variable and pass this into ws
+      this._enableUserAgentOnConnect; // global websocket will send "node" as 
user agent by default which doesn't comply with Gremlin
     // Only use the global websocket if we don't have any unsupported options
     const useGlobalWebSocket = !hasWsSpecificOptions && globalThis.WebSocket;
     const WebSocket = useGlobalWebSocket || (await import('ws')).default;
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-behavior-tests.js
 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-behavior-tests.js
index 528d4414aa..782b7c1e92 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-behavior-tests.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-behavior-tests.js
@@ -59,7 +59,7 @@ describe('Client', function () {
             let result = await noUserAgentClient.submit('1', null,
                 {requestId: settings.USER_AGENT_REQUEST_ID});
 
-            assert.strictEqual(result.first(), "");
+            assert.ok(result.first() === "" || result.first() === "node"); // 
The default node websocket library may use a default user-agent of "node" if 
none is specified
 
             await noUserAgentClient.close();
         });
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/socket-connection-tests.js
 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/socket-connection-tests.js
index ec4820cbb7..66ada86897 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/socket-connection-tests.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/socket-connection-tests.js
@@ -78,7 +78,8 @@ describe('Connection', function () {
       globalThis.WebSocket = function () {
         globalWebsocketCalls++;
       };
-      const connection = 
helper.getDriverRemoteConnection(`ws://localhost:${testServerPort}/401`);
+      const connection = 
helper.getDriverRemoteConnection(`ws://localhost:${testServerPort}/401`,
+          {enableCompression: false, enableUserAgentOnConnect: false}); // 
Global WebSocket is not compatible with customized compression and user agent 
headers
       return connection
         .open()
         .catch(() => {})
diff --git a/pom.xml b/pom.xml
index 3e182451dd..4312297c22 100644
--- a/pom.xml
+++ b/pom.xml
@@ -222,6 +222,8 @@ limitations under the License.
             --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED
             --add-opens=java.base/java.net=ALL-UNNAMED
         </jdk17JvmArgs>
+
+        <node.test.version>20</node.test.version>
     </properties>
     <build>
         <directory>${basedir}/target</directory>

Reply via email to