diff --git a/.eslintrc b/.eslintrc index cea2e6c9..1254442e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,6 +5,7 @@ "@typescript-eslint/quotes": ["error", "double"], "require-await": "off", "@typescript-eslint/strict-boolean-expressions": "off", + "@typescript-eslint/no-extraneous-class": "off", "@typescript-eslint/no-explicit-any": "off", "no-await-in-loop": "off", "class-methods-use-this": "off" diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 22b8a100..34b18a3b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -175,7 +175,19 @@ jobs: timeout_minutes: 5 max_attempts: 1 command: | - pnpm run test + pnpm run clean.temp + pnpm run test.unit + continue-on-error: true + + - name: Test Compatibility + if: ${{ !matrix.docker }} + uses: nick-fields/retry@v3 + with: + timeout_minutes: 5 + max_attempts: 1 + command: | + pnpm run clean.temp + pnpm run test.unit.compat continue-on-error: true - name: Test Electron (Main) diff --git a/.mocharc.js b/.mocharc.js index 1411e927..3cc6d952 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -3,13 +3,14 @@ */ const config = { require: ["ts-node/register"], - spec: ["test/unit/*-test.ts", "test/unit/compat/*-test.js"], "expose-gc": true, "v8-expose-gc": true, exit: true, parallel: true, - timeout: 10000, - retries: 3, + timeout: 5000, + retries: 1, + fullTrace: true, + bail: false, } module.exports = config diff --git a/.vscode/settings.json b/.vscode/settings.json index 350f941b..c0a09f4b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,10 +13,13 @@ }, "mochaExplorer.parallel": true, "mochaExplorer.globImplementation": "vscode", - "mochaExplorer.nodeArgv": [ - "--expose-gc" - ], + "mochaExplorer.nodeArgv": ["--expose-gc"], "mochaExplorer.debuggerConfig": "JS-Attach", + "mochaExplorer.env": { + "INCLUDE_COMPAT_TESTS": "true" + }, + "mochaExplorer.files": "test/unit/**/*-test.ts", + "mochaExplorer.mochaPath": "./node_modules/mocha", "files.exclude": { "**/.DS_Store": true, "**/Thumbs.db": true, diff --git a/package.json b/package.json index f1f2c06f..c4975a9d 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@types/which": "^3.0.4", "benchmark": "^2.1.4", "chai": "^4", + "cross-env": "^7.0.3", "deasync": "^0.1.30", "downlevel-dts": "^0.11.0", "electron-mocha": "^13.0.0", @@ -97,9 +98,11 @@ "build.native.debug": "cmake-ts dev-os-only", "build": "run-p build.js build.native", "build.debug": "run-s build.js build.native.debug", - "test": "run-s clean.temp build && mocha", + "test": "run-s test.unit", + "test.unit": "run-s clean.temp build && cross-env INCLUDE_COMPAT_TESTS=false mocha ./test/unit/*-test.ts", + "test.unit.compat": "run-s clean.temp build && cross-env INCLUDE_COMPAT_TESTS=true mocha ./test/unit/compat/*-test.ts", "test.smoke": "bash ./script/smoke-test.bash", - "test.skip_gc_tests": "run-s clean.temp build.debug && cross-env SKIP_GC_TESTS=true mocha", + "test.skip_gc_tests": "run-s clean.temp build && cross-env SKIP_GC_TESTS=true mocha", "test.electron.main": "run-s clean.temp build && electron-mocha", "format": "run-s format.prettier format.clang-format", "format.prettier": "prettier -l --cache --cache-location ./.cache/prettier --write .", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9246484d..de10f953 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -58,6 +58,9 @@ importers: chai: specifier: ^4 version: 4.5.0 + cross-env: + specifier: ^7.0.3 + version: 7.0.3 deasync: specifier: ^0.1.30 version: 0.1.30 @@ -953,6 +956,11 @@ packages: create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -4462,6 +4470,10 @@ snapshots: create-require@1.1.1: {} + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.3 + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 diff --git a/src/compat.ts b/src/compat.ts index 59174423..7314439d 100644 --- a/src/compat.ts +++ b/src/compat.ts @@ -6,6 +6,9 @@ import {EventEmitter} from "events" import * as zmq from "." import {FullError} from "./errors" +import * as longOptions from "./compat/long-options" +import * as pollStates from "./compat/poll-states" +import * as sendOptions from "./compat/send-options" type AnySocket = | zmq.Pair @@ -22,99 +25,6 @@ type AnySocket = | zmq.Stream let count = 1 -const types = { - ZMQ_PAIR: 0, - ZMQ_PUB: 1, - ZMQ_SUB: 2, - ZMQ_REQ: 3, - ZMQ_REP: 4, - ZMQ_DEALER: 5, - ZMQ_XREQ: 5, - ZMQ_ROUTER: 6, - ZMQ_XREP: 6, - ZMQ_PULL: 7, - ZMQ_PUSH: 8, - ZMQ_XPUB: 9, - ZMQ_XSUB: 10, - ZMQ_STREAM: 11, -} - -const longOptions = { - ZMQ_AFFINITY: 4, - ZMQ_IDENTITY: 5, - ZMQ_SUBSCRIBE: 6, - ZMQ_UNSUBSCRIBE: 7, - ZMQ_RATE: 8, - ZMQ_RECOVERY_IVL: 9, - ZMQ_RECOVERY_IVL_MSEC: 9, - ZMQ_SNDBUF: 11, - ZMQ_RCVBUF: 12, - ZMQ_RCVMORE: 13, - ZMQ_FD: 14, - ZMQ_EVENTS: 15, - ZMQ_TYPE: 16, - ZMQ_LINGER: 17, - ZMQ_RECONNECT_IVL: 18, - ZMQ_BACKLOG: 19, - ZMQ_RECONNECT_IVL_MAX: 21, - ZMQ_MAXMSGSIZE: 22, - ZMQ_SNDHWM: 23, - ZMQ_RCVHWM: 24, - ZMQ_MULTICAST_HOPS: 25, - ZMQ_RCVTIMEO: 27, - ZMQ_SNDTIMEO: 28, - ZMQ_IPV4ONLY: 31, - ZMQ_LAST_ENDPOINT: 32, - ZMQ_ROUTER_MANDATORY: 33, - ZMQ_TCP_KEEPALIVE: 34, - ZMQ_TCP_KEEPALIVE_CNT: 35, - ZMQ_TCP_KEEPALIVE_IDLE: 36, - ZMQ_TCP_KEEPALIVE_INTVL: 37, - ZMQ_TCP_ACCEPT_FILTER: 38, - ZMQ_DELAY_ATTACH_ON_CONNECT: 39, - ZMQ_XPUB_VERBOSE: 40, - ZMQ_ROUTER_RAW: 41, - ZMQ_IPV6: 42, - ZMQ_MECHANISM: 43, - ZMQ_PLAIN_SERVER: 44, - ZMQ_PLAIN_USERNAME: 45, - ZMQ_PLAIN_PASSWORD: 46, - ZMQ_CURVE_SERVER: 47, - ZMQ_CURVE_PUBLICKEY: 48, - ZMQ_CURVE_SECRETKEY: 49, - ZMQ_CURVE_SERVERKEY: 50, - ZMQ_ZAP_DOMAIN: 55, - ZMQ_HEARTBEAT_IVL: 75, - ZMQ_HEARTBEAT_TTL: 76, - ZMQ_HEARTBEAT_TIMEOUT: 77, - ZMQ_CONNECT_TIMEOUT: 79, - ZMQ_IO_THREADS: 1, - ZMQ_MAX_SOCKETS: 2, - ZMQ_ROUTER_HANDOVER: 56, -} - -const pollStates = { - ZMQ_POLLIN: 1, - ZMQ_POLLOUT: 2, - ZMQ_POLLERR: 4, -} - -const sendOptions = { - ZMQ_SNDMORE: 2, -} - -const capabilities = { - ZMQ_CAN_MONITOR: 1, - ZMQ_CAN_DISCONNECT: 1, - ZMQ_CAN_UNBIND: 1, - ZMQ_CAN_SET_CTX: 1, -} - -const socketStates = { - STATE_READY: 0, - STATE_BUSY: 1, - STATE_CLOSED: 2, -} const shortOptions = { _fd: longOptions.ZMQ_FD, @@ -241,9 +151,11 @@ class Socket extends EventEmitter { case "stream": this._socket = new zmq.Stream() break + default: + throw new Error(`Invalid socket type: ${type}`) } - const recv = async () => { + const recv = () => { this.once("_flushRecv", async () => { while (!this._socket.closed && !this._paused) { await this._recv() @@ -347,7 +259,7 @@ class Socket extends EventEmitter { .catch(err => { process.nextTick(() => { if (cb) { - cb(err) + cb(err as Error) } else { this.emit("error", err) } @@ -371,7 +283,7 @@ class Socket extends EventEmitter { .catch(err => { process.nextTick(() => { if (cb) { - cb(err) + cb(err as Error) } else { this.emit("error", err) } @@ -391,8 +303,12 @@ class Socket extends EventEmitter { return this } - send(message: zmq.MessageLike[], flags = 0, cb?: Callback) { - flags = flags | 0 + send( + message: zmq.MessageLike[] | zmq.MessageLike, + givenFlags: number | undefined | null = 0, + cb: Callback | undefined = undefined, + ) { + const flags = (givenFlags ?? 0) | 0 this._msg = this._msg.concat(message) if ((flags & sendOptions.ZMQ_SNDMORE) === 0) { this._sendQueue.push([this._msg, cb]) @@ -460,7 +376,7 @@ class Socket extends EventEmitter { return this._socket.closed } - monitor(interval: number, num: number) { + monitor(interval?: number, num?: number) { this._count = count++ /* eslint-disable-next-line no-unused-expressions */ @@ -560,8 +476,9 @@ class Socket extends EventEmitter { } } - setsockopt(option: number | keyof typeof shortOptions, value: any) { - option = typeof option !== "number" ? shortOptions[option] : option + setsockopt(givenOption: number | keyof typeof shortOptions, value: any) { + const option = + typeof givenOption === "number" ? givenOption : shortOptions[givenOption] switch (option) { case longOptions.ZMQ_AFFINITY: @@ -699,8 +616,9 @@ class Socket extends EventEmitter { return this } - getsockopt(option: number | keyof typeof shortOptions) { - option = typeof option !== "number" ? shortOptions[option] : option + getsockopt(givenOption: number | keyof typeof shortOptions) { + const option = + typeof givenOption !== "number" ? shortOptions[givenOption] : givenOption switch (option) { case longOptions.ZMQ_AFFINITY: @@ -822,10 +740,9 @@ for (const key in shortOptions) { get(this: Socket) { return this.getsockopt(shortOptions[key as keyof typeof shortOptions]) }, - set(this: Socket, val: string | Buffer) { - if ("string" === typeof val) { - val = Buffer.from(val, "utf8") - } + set(this: Socket, givenVal: string | Buffer) { + const val = + typeof givenVal === "string" ? Buffer.from(givenVal, "utf8") : givenVal return this.setsockopt( shortOptions[key as keyof typeof shortOptions], val, @@ -909,11 +826,9 @@ export { shortOptions as options, } -/* Unfortunately there is no easy way to include these in the resulting - TS definitions. */ -Object.assign(module.exports, longOptions) -Object.assign(module.exports, types) -Object.assign(module.exports, pollStates) -Object.assign(module.exports, sendOptions) -Object.assign(module.exports, socketStates) -Object.assign(module.exports, capabilities) +export * from "./compat/long-options" +export * from "./compat/types" +export * from "./compat/poll-states" +export * from "./compat/send-options" +export * from "./compat/capabilities" +export * from "./compat/socket-states" diff --git a/src/compat/capabilities.ts b/src/compat/capabilities.ts new file mode 100644 index 00000000..a7b8a4e0 --- /dev/null +++ b/src/compat/capabilities.ts @@ -0,0 +1,4 @@ +export const ZMQ_CAN_MONITOR = 1 +export const ZMQ_CAN_DISCONNECT = 1 +export const ZMQ_CAN_UNBIND = 1 +export const ZMQ_CAN_SET_CTX = 1 diff --git a/src/compat/long-options.ts b/src/compat/long-options.ts new file mode 100644 index 00000000..80d74404 --- /dev/null +++ b/src/compat/long-options.ts @@ -0,0 +1,51 @@ +export const ZMQ_AFFINITY = 4 +export const ZMQ_IDENTITY = 5 +export const ZMQ_SUBSCRIBE = 6 +export const ZMQ_UNSUBSCRIBE = 7 +export const ZMQ_RATE = 8 +export const ZMQ_RECOVERY_IVL = 9 +export const ZMQ_RECOVERY_IVL_MSEC = 9 +export const ZMQ_SNDBUF = 11 +export const ZMQ_RCVBUF = 12 +export const ZMQ_RCVMORE = 13 +export const ZMQ_FD = 14 +export const ZMQ_EVENTS = 15 +export const ZMQ_TYPE = 16 +export const ZMQ_LINGER = 17 +export const ZMQ_RECONNECT_IVL = 18 +export const ZMQ_BACKLOG = 19 +export const ZMQ_RECONNECT_IVL_MAX = 21 +export const ZMQ_MAXMSGSIZE = 22 +export const ZMQ_SNDHWM = 23 +export const ZMQ_RCVHWM = 24 +export const ZMQ_MULTICAST_HOPS = 25 +export const ZMQ_RCVTIMEO = 27 +export const ZMQ_SNDTIMEO = 28 +export const ZMQ_IPV4ONLY = 31 +export const ZMQ_LAST_ENDPOINT = 32 +export const ZMQ_ROUTER_MANDATORY = 33 +export const ZMQ_TCP_KEEPALIVE = 34 +export const ZMQ_TCP_KEEPALIVE_CNT = 35 +export const ZMQ_TCP_KEEPALIVE_IDLE = 36 +export const ZMQ_TCP_KEEPALIVE_INTVL = 37 +export const ZMQ_TCP_ACCEPT_FILTER = 38 +export const ZMQ_DELAY_ATTACH_ON_CONNECT = 39 +export const ZMQ_XPUB_VERBOSE = 40 +export const ZMQ_ROUTER_RAW = 41 +export const ZMQ_IPV6 = 42 +export const ZMQ_MECHANISM = 43 +export const ZMQ_PLAIN_SERVER = 44 +export const ZMQ_PLAIN_USERNAME = 45 +export const ZMQ_PLAIN_PASSWORD = 46 +export const ZMQ_CURVE_SERVER = 47 +export const ZMQ_CURVE_PUBLICKEY = 48 +export const ZMQ_CURVE_SECRETKEY = 49 +export const ZMQ_CURVE_SERVERKEY = 50 +export const ZMQ_ZAP_DOMAIN = 55 +export const ZMQ_HEARTBEAT_IVL = 75 +export const ZMQ_HEARTBEAT_TTL = 76 +export const ZMQ_HEARTBEAT_TIMEOUT = 77 +export const ZMQ_CONNECT_TIMEOUT = 79 +export const ZMQ_IO_THREADS = 1 +export const ZMQ_MAX_SOCKETS = 2 +export const ZMQ_ROUTER_HANDOVER = 56 diff --git a/src/compat/poll-states.ts b/src/compat/poll-states.ts new file mode 100644 index 00000000..47bae768 --- /dev/null +++ b/src/compat/poll-states.ts @@ -0,0 +1,3 @@ +export const ZMQ_POLLIN = 1 +export const ZMQ_POLLOUT = 2 +export const ZMQ_POLLERR = 4 diff --git a/src/compat/send-options.ts b/src/compat/send-options.ts new file mode 100644 index 00000000..e826e8b1 --- /dev/null +++ b/src/compat/send-options.ts @@ -0,0 +1 @@ +export const ZMQ_SNDMORE = 2 diff --git a/src/compat/socket-states.ts b/src/compat/socket-states.ts new file mode 100644 index 00000000..c24a8e31 --- /dev/null +++ b/src/compat/socket-states.ts @@ -0,0 +1,3 @@ +export const STATE_READY = 0 +export const STATE_BUSY = 1 +export const STATE_CLOSED = 2 diff --git a/src/compat/types.ts b/src/compat/types.ts new file mode 100644 index 00000000..80a51d07 --- /dev/null +++ b/src/compat/types.ts @@ -0,0 +1,14 @@ +export const ZMQ_PAIR = 0 +export const ZMQ_PUB = 1 +export const ZMQ_SUB = 2 +export const ZMQ_REQ = 3 +export const ZMQ_REP = 4 +export const ZMQ_DEALER = 5 +export const ZMQ_XREQ = 5 +export const ZMQ_ROUTER = 6 +export const ZMQ_XREP = 6 +export const ZMQ_PULL = 7 +export const ZMQ_PUSH = 8 +export const ZMQ_XPUB = 9 +export const ZMQ_XSUB = 10 +export const ZMQ_STREAM = 11 diff --git a/src/index.ts b/src/index.ts index 5a2c219d..548f7a41 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,6 +45,7 @@ export type MessageLike = | ArrayBuffer /* Backing buffer of TypedArrays. */ | SharedArrayBuffer | string + | number | null /** diff --git a/test/tsconfig.json b/test/tsconfig.json index b5bce5fa..d9a119c0 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -1,12 +1,8 @@ { "extends": "../tsconfig.json", - "include": ["**/*.ts"], + "include": ["./unit/**/*.ts", "./*.ts"], "compilerOptions": { - "skipLibCheck": true, - "lib": [ - "ES2020", - // only used in tests - "ES2021.WeakRef" - ] - } + "skipLibCheck": true + }, + "compileOnSave": false } diff --git a/test/unit/compat/README.md b/test/unit/compat/README.md index 79babeb9..0b71a6c7 100644 --- a/test/unit/compat/README.md +++ b/test/unit/compat/README.md @@ -1,5 +1,6 @@ -The tests in this directory have been copied from the original ZeroMQ.js version -(up to 5.x) for which the license and copyright notice is reproduced below. +The tests in this directory have been modified from the original ZeroMQ.js +version (up to 5.x) for which the license and copyright notice is reproduced +below. Copyright (c) 2011 TJ Holowaychuk Copyright (c) 2010, 2011 Justin Tulloss diff --git a/test/unit/compat/context-test.js b/test/unit/compat/context-test.ts similarity index 80% rename from test/unit/compat/context-test.js rename to test/unit/compat/context-test.ts index 741e5320..a460deb6 100644 --- a/test/unit/compat/context-test.js +++ b/test/unit/compat/context-test.ts @@ -1,7 +1,7 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { describe("compat context", function () { it("should support setting max io threads", function () { zmq.Context.setMaxThreads(3) diff --git a/test/unit/compat/exports-test.js b/test/unit/compat/exports-test.js deleted file mode 100644 index ff2eefe6..00000000 --- a/test/unit/compat/exports-test.js +++ /dev/null @@ -1,101 +0,0 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const semver = require("semver") - const {assert} = require("chai") - - describe("compat exports", function () { - it("should export a valid version", function () { - assert.ok(semver.valid(zmq.version)) - }) - - it("should generate valid curve keypair", function () { - if (!zmq.capability.curve) { - this.skip() - } - - const curve = zmq.curveKeypair() - assert.typeOf(curve.public, "string") - assert.typeOf(curve.secret, "string") - assert.equal(curve.public.length, 40) - assert.equal(curve.secret.length, 40) - }) - - it("should export socket types and options", function () { - const constants = [ - "PUB", - "SUB", - "REQ", - "XREQ", - "REP", - "XREP", - "DEALER", - "ROUTER", - "PUSH", - "PULL", - "PAIR", - "AFFINITY", - "IDENTITY", - "SUBSCRIBE", - "UNSUBSCRIBE", - "RCVTIMEO", - "SNDTIMEO", - "RATE", - "RECOVERY_IVL", - "SNDBUF", - "RCVBUF", - "RCVMORE", - "FD", - "EVENTS", - "TYPE", - "LINGER", - "RECONNECT_IVL", - "RECONNECT_IVL_MAX", - "BACKLOG", - "POLLIN", - "POLLOUT", - "POLLERR", - "SNDMORE", - "XPUB", - "XSUB", - "SNDHWM", - "RCVHWM", - "MAXMSGSIZE", - "MULTICAST_HOPS", - "TCP_KEEPALIVE", - "TCP_KEEPALIVE_CNT", - "TCP_KEEPALIVE_IDLE", - "TCP_KEEPALIVE_INTVL", - "IPV4ONLY", - "DELAY_ATTACH_ON_CONNECT", - "ROUTER_MANDATORY", - "XPUB_VERBOSE", - "TCP_KEEPALIVE", - "TCP_KEEPALIVE_IDLE", - "TCP_KEEPALIVE_CNT", - "TCP_KEEPALIVE_INTVL", - "TCP_ACCEPT_FILTER", - "LAST_ENDPOINT", - "ROUTER_RAW", - ] - - constants.forEach(function (typeOrProp) { - assert.typeOf(zmq[`ZMQ_${typeOrProp}`], "number") - }) - }) - - it("should export states", function () { - ;["STATE_READY", "STATE_BUSY", "STATE_CLOSED"].forEach(function (state) { - assert.typeOf(zmq[state], "number") - }) - }) - - it("should export constructors", function () { - assert.typeOf(zmq.Context, "function") - assert.typeOf(zmq.Socket, "function") - }) - - it("should export methods", function () { - assert.typeOf(zmq.socket, "function") - }) - }) -} diff --git a/test/unit/compat/exports-test.ts b/test/unit/compat/exports-test.ts new file mode 100644 index 00000000..893314a1 --- /dev/null +++ b/test/unit/compat/exports-test.ts @@ -0,0 +1,92 @@ +import * as zmq from "../../../v5-compat" +import {capability} from "../../../src" +import {assert} from "chai" +import semver from "semver" + +if (process.env.INCLUDE_COMPAT_TESTS === "true") { + describe("compat exports", function () { + it("should export a valid version", function () { + assert.ok(semver.valid(zmq.version)) + }) + + it("should generate valid curve keypair", function () { + if (!capability.curve) { + this.skip() + } + + const curve = zmq.curveKeypair() + assert.typeOf(curve.public, "string") + assert.typeOf(curve.secret, "string") + assert.equal(curve.public.length, 40) + assert.equal(curve.secret.length, 40) + }) + + it("should export socket types and options", function () { + assert.typeOf(zmq.ZMQ_PUB, "number") + assert.typeOf(zmq.ZMQ_SUB, "number") + assert.typeOf(zmq.ZMQ_REQ, "number") + assert.typeOf(zmq.ZMQ_XREQ, "number") + assert.typeOf(zmq.ZMQ_REP, "number") + assert.typeOf(zmq.ZMQ_XREP, "number") + assert.typeOf(zmq.ZMQ_DEALER, "number") + assert.typeOf(zmq.ZMQ_ROUTER, "number") + assert.typeOf(zmq.ZMQ_PUSH, "number") + assert.typeOf(zmq.ZMQ_PULL, "number") + assert.typeOf(zmq.ZMQ_PAIR, "number") + assert.typeOf(zmq.ZMQ_AFFINITY, "number") + assert.typeOf(zmq.ZMQ_IDENTITY, "number") + assert.typeOf(zmq.ZMQ_SUBSCRIBE, "number") + assert.typeOf(zmq.ZMQ_UNSUBSCRIBE, "number") + assert.typeOf(zmq.ZMQ_RCVTIMEO, "number") + assert.typeOf(zmq.ZMQ_SNDTIMEO, "number") + assert.typeOf(zmq.ZMQ_RATE, "number") + assert.typeOf(zmq.ZMQ_RECOVERY_IVL, "number") + assert.typeOf(zmq.ZMQ_SNDBUF, "number") + assert.typeOf(zmq.ZMQ_RCVBUF, "number") + assert.typeOf(zmq.ZMQ_RCVMORE, "number") + assert.typeOf(zmq.ZMQ_FD, "number") + assert.typeOf(zmq.ZMQ_EVENTS, "number") + assert.typeOf(zmq.ZMQ_TYPE, "number") + assert.typeOf(zmq.ZMQ_LINGER, "number") + assert.typeOf(zmq.ZMQ_RECONNECT_IVL, "number") + assert.typeOf(zmq.ZMQ_RECONNECT_IVL_MAX, "number") + assert.typeOf(zmq.ZMQ_BACKLOG, "number") + assert.typeOf(zmq.ZMQ_POLLIN, "number") + assert.typeOf(zmq.ZMQ_POLLOUT, "number") + assert.typeOf(zmq.ZMQ_POLLERR, "number") + assert.typeOf(zmq.ZMQ_SNDMORE, "number") + assert.typeOf(zmq.ZMQ_XPUB, "number") + assert.typeOf(zmq.ZMQ_XSUB, "number") + assert.typeOf(zmq.ZMQ_SNDHWM, "number") + assert.typeOf(zmq.ZMQ_RCVHWM, "number") + assert.typeOf(zmq.ZMQ_MAXMSGSIZE, "number") + assert.typeOf(zmq.ZMQ_MULTICAST_HOPS, "number") + assert.typeOf(zmq.ZMQ_TCP_KEEPALIVE, "number") + assert.typeOf(zmq.ZMQ_TCP_KEEPALIVE_CNT, "number") + assert.typeOf(zmq.ZMQ_TCP_KEEPALIVE_IDLE, "number") + assert.typeOf(zmq.ZMQ_TCP_KEEPALIVE_INTVL, "number") + assert.typeOf(zmq.ZMQ_IPV4ONLY, "number") + assert.typeOf(zmq.ZMQ_DELAY_ATTACH_ON_CONNECT, "number") + assert.typeOf(zmq.ZMQ_ROUTER_MANDATORY, "number") + assert.typeOf(zmq.ZMQ_XPUB_VERBOSE, "number") + assert.typeOf(zmq.ZMQ_TCP_ACCEPT_FILTER, "number") + assert.typeOf(zmq.ZMQ_LAST_ENDPOINT, "number") + assert.typeOf(zmq.ZMQ_ROUTER_RAW, "number") + }) + + it("should export states", function () { + assert.typeOf(zmq.STATE_READY, "number") + assert.typeOf(zmq.STATE_BUSY, "number") + assert.typeOf(zmq.STATE_CLOSED, "number") + }) + + it("should export constructors", function () { + assert.typeOf(zmq.Context, "function") + assert.typeOf(zmq.Socket, "function") + }) + + it("should export methods", function () { + assert.typeOf(zmq.socket, "function") + }) + }) +} diff --git a/test/unit/compat/gc-test.js b/test/unit/compat/gc-test.ts similarity index 83% rename from test/unit/compat/gc-test.js rename to test/unit/compat/gc-test.ts index a742b630..54fbe41b 100644 --- a/test/unit/compat/gc-test.js +++ b/test/unit/compat/gc-test.ts @@ -1,10 +1,15 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp", "inproc")) { describe(`compat socket with ${proto}`, function () { + let address: string + beforeEach(async () => { + address = await uniqAddress(proto) + }) + it("should cooperate with gc", function (done) { const sockA = zmq.socket("dealer") const sockB = zmq.socket("dealer") @@ -28,7 +33,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { let bound = false - const address = uniqAddress(proto) sockA.bind(address, err => { if (err) { clearInterval(interval) diff --git a/test/unit/compat/load.js b/test/unit/compat/load.js deleted file mode 100644 index 64c26e6d..00000000 --- a/test/unit/compat/load.js +++ /dev/null @@ -1,10 +0,0 @@ -const path = require("path") - -module.exports = require( - process.env.ZMQ_COMPAT_PATH - ? path.resolve(process.cwd(), process.env.ZMQ_COMPAT_PATH) - : "../../../src/compat", -) - -/* Copy capabilities from regular module. */ -module.exports.capability = require("../../../src").capability diff --git a/test/unit/compat/socket-error-callback-test.js b/test/unit/compat/socket-error-callback-test.ts similarity index 66% rename from test/unit/compat/socket-error-callback-test.js rename to test/unit/compat/socket-error-callback-test.ts index d3c95fd0..4ced29c2 100644 --- a/test/unit/compat/socket-error-callback-test.js +++ b/test/unit/compat/socket-error-callback-test.ts @@ -1,9 +1,11 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") +import * as zmq from "../../../v5-compat" +import type {Socket} from "../../../v5-compat" +import {isFullError} from "../../../src/errors" +import {assert} from "chai" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { describe("compat socket error callback", function () { - let sock + let sock: Socket beforeEach(function () { sock = zmq.socket("router") @@ -20,9 +22,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { it("should callback with error when not connected", function (done) { sock.send(["foo", "bar"], null, err => { - if (!isFullError(err)) { - throw err - } + assert.isUndefined(err) sock.close() done() }) diff --git a/test/unit/compat/socket-events-test.js b/test/unit/compat/socket-events-test.ts similarity index 75% rename from test/unit/compat/socket-events-test.js rename to test/unit/compat/socket-events-test.ts index edae1e85..0e0bd8e0 100644 --- a/test/unit/compat/socket-events-test.js +++ b/test/unit/compat/socket-events-test.ts @@ -1,16 +1,19 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp", "inproc")) { describe(`compat socket with ${proto} events`, function () { + let address: string + beforeEach(async () => { + address = await uniqAddress(proto) + }) + it("should support events", function (done) { const rep = zmq.socket("rep") const req = zmq.socket("req") - const address = uniqAddress(proto) - rep.on("message", function (msg) { assert.instanceOf(msg, Buffer) assert.equal(msg.toString(), "hello") diff --git a/test/unit/compat/socket-messages-test.js b/test/unit/compat/socket-messages-test.ts similarity index 87% rename from test/unit/compat/socket-messages-test.js rename to test/unit/compat/socket-messages-test.ts index 996069f8..c5173da1 100644 --- a/test/unit/compat/socket-messages-test.js +++ b/test/unit/compat/socket-messages-test.ts @@ -1,21 +1,21 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" - for (const proto of testProtos("tcp", "inproc")) { +if (process.env.INCLUDE_COMPAT_TESTS === "true") { + for (const proto of testProtos( "inproc")) { describe(`compat socket with ${proto} messages`, function () { - let push - let pull + let push: zmq.Socket + let pull: zmq.Socket + let address: string - beforeEach(function () { + beforeEach(async function () { push = zmq.socket("push") pull = zmq.socket("pull") + address = await uniqAddress(proto) }) it("should support messages", function (done) { - const address = uniqAddress(proto) - let n = 0 pull.on("message", function (msg) { @@ -44,8 +44,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should support multipart messages", function (done) { - const address = uniqAddress(proto) - pull.on("message", function (msg1, msg2, msg3) { assert.equal(msg1.toString(), "string") assert.equal(msg2.toString(), "15.99") @@ -61,8 +59,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should support sndmore", function (done) { - const address = uniqAddress(proto) - pull.on("message", function (a, b, c, d, e) { assert.equal(a.toString(), "tobi") assert.equal(b.toString(), "loki") @@ -83,7 +79,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { if (proto != "inproc") { it("should handle late connect", function (done) { - const address = uniqAddress(proto) let n = 0 pull.on("message", function (msg) { @@ -116,7 +111,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { } it("should call send callbacks", function (done) { - const address = uniqAddress(proto) let received = 0 let callbacks = 0 diff --git a/test/unit/compat/socket-monitor-test.js b/test/unit/compat/socket-monitor-test.ts similarity index 86% rename from test/unit/compat/socket-monitor-test.js rename to test/unit/compat/socket-monitor-test.ts index 4df0e03d..19971f7e 100644 --- a/test/unit/compat/socket-monitor-test.js +++ b/test/unit/compat/socket-monitor-test.ts @@ -1,13 +1,18 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const semver = require("semver") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") - const {isFullError} = require("../../src/errors") +import * as zmq from "../../../v5-compat" +import semver from "semver" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +import {isFullError} from "../../../src/errors" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { /* This test case only seems to work reliably with TCP. */ for (const proto of testProtos("tcp")) { describe(`compat socket with ${proto} monitor`, function () { + let address: string + beforeEach(async () => { + address = await uniqAddress(proto) + }) + beforeEach(function () { /* ZMQ < 4.2 occasionally fails with assertion errors. */ if (semver.satisfies(zmq.version, "< 4.2")) { @@ -28,8 +33,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { const rep = zmq.socket("rep") const req = zmq.socket("req") - const address = uniqAddress(proto) - rep.on("message", function (msg) { assert.instanceOf(msg, Buffer) assert.equal(msg.toString(), "hello") diff --git a/test/unit/compat/socket-pair-test.js b/test/unit/compat/socket-pair-test.ts similarity index 82% rename from test/unit/compat/socket-pair-test.js rename to test/unit/compat/socket-pair-test.ts index 0e314418..c6077364 100644 --- a/test/unit/compat/socket-pair-test.js +++ b/test/unit/compat/socket-pair-test.ts @@ -1,16 +1,19 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp")) { describe(`compat socket with ${proto} pair`, function () { + let address: string + beforeEach(async () => { + address = await uniqAddress(proto) + }) + it("should support pair-pair", function (done) { const pairA = zmq.socket("pair") const pairB = zmq.socket("pair") - const address = uniqAddress(proto) - let n = 0 pairA.monitor() pairB.monitor() diff --git a/test/unit/compat/socket-pub-sub-test.js b/test/unit/compat/socket-pub-sub-test.ts similarity index 91% rename from test/unit/compat/socket-pub-sub-test.js rename to test/unit/compat/socket-pub-sub-test.ts index 60467ba1..34ba0a87 100644 --- a/test/unit/compat/socket-pub-sub-test.js +++ b/test/unit/compat/socket-pub-sub-test.ts @@ -1,20 +1,20 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp", "inproc")) { describe(`compat socket with ${proto} pub-sub`, function () { - let pub - let sub - - beforeEach(function () { + let pub: zmq.Socket + let sub: zmq.Socket + let address: string + beforeEach(async function () { pub = zmq.socket("pub") sub = zmq.socket("sub") + address = await uniqAddress(proto) }) it("should support pub-sub", function (done) { - const address = uniqAddress(proto) let n = 0 sub.subscribe("") @@ -60,7 +60,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should support pub-sub filter", function (done) { - const address = uniqAddress(proto) let n = 0 sub.subscribe("js") @@ -113,12 +112,11 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should continue to deliver messages in message handler", function (done) { - let error + let error: Error process.once("uncaughtException", err => { error = err }) - const address = uniqAddress(proto) let n = 0 sub.subscribe("") diff --git a/test/unit/compat/socket-push-pull-test.js b/test/unit/compat/socket-push-pull-test.ts similarity index 89% rename from test/unit/compat/socket-push-pull-test.js rename to test/unit/compat/socket-push-pull-test.ts index c589bf8d..789ff382 100644 --- a/test/unit/compat/socket-push-pull-test.js +++ b/test/unit/compat/socket-push-pull-test.ts @@ -1,16 +1,19 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp", "inproc")) { describe(`compat socket with ${proto} push-pull`, function () { + let address: string + beforeEach(async () => { + address = await uniqAddress(proto) + }) + it("should support push-pull", function (done) { const push = zmq.socket("push") const pull = zmq.socket("pull") - const address = uniqAddress(proto) - let n = 0 pull.on("message", function (msg) { assert.instanceOf(msg, Buffer) @@ -46,8 +49,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { const push = zmq.socket("push") const pull = zmq.socket("pull") - const address = uniqAddress(proto) - let n = 0 pull.on("message", function (msg) { @@ -81,8 +82,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { const push = zmq.socket("push") const pull = zmq.socket("pull") - const address = uniqAddress(proto) - const messages = ["bar", "foo"] pull.bind(address, err => { if (err) { @@ -112,15 +111,13 @@ if (process.env.INCLUDE_COMPAT_TESTS) { const push = zmq.socket("push") const pull = zmq.socket("pull") - const address = uniqAddress(proto) - let n = 0 - function checkNoMessages(msg) { + function checkNoMessages(msg: string) { assert.equal(msg, undefined) } - function checkMessages(msg) { + function checkMessages(msg: string) { assert.instanceOf(msg, Buffer) switch (n++) { case 0: diff --git a/test/unit/compat/socket-req-rep-test.js b/test/unit/compat/socket-req-rep-test.ts similarity index 79% rename from test/unit/compat/socket-req-rep-test.js rename to test/unit/compat/socket-req-rep-test.ts index d83168e0..8086de05 100644 --- a/test/unit/compat/socket-req-rep-test.js +++ b/test/unit/compat/socket-req-rep-test.ts @@ -1,17 +1,20 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp", "inproc")) { describe(`compat socket with ${proto} req-rep`, function () { + let address: string + beforeEach(async () => { + address = await uniqAddress(proto) + }) + it("should support req-rep", function (done) { const rep = zmq.socket("rep") const req = zmq.socket("req") - const address = uniqAddress(proto) - - rep.on("message", function (msg) { + rep.on("message", function (msg: string) { assert.instanceOf(msg, Buffer) assert.equal(msg.toString(), "hello") rep.send("world") @@ -33,15 +36,15 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) }) - it("should support multiple", function (done) { - const n = 5 - - for (let i = 0; i < n; i++) { - ;(function (n) { + it("should support multiple", function () { + return new Promise(async resolve => { + const n = 5 + for (let i = 0; i < n; i++) { + let n = i const rep = zmq.socket("rep") const req = zmq.socket("req") - const address = uniqAddress(proto) + const address = await uniqAddress(proto) rep.on("message", function (msg) { assert.instanceOf(msg, Buffer) @@ -61,20 +64,18 @@ if (process.env.INCLUDE_COMPAT_TESTS) { req.close() rep.close() if (!--n) { - done() + resolve() } }) }) - })(i) - } + } + }) }) it("should support a burst", function (done) { const rep = zmq.socket("rep") const req = zmq.socket("req") - const address = uniqAddress(proto) - const n = 10 rep.on("message", function (msg) { diff --git a/test/unit/compat/socket-router-test.js b/test/unit/compat/socket-router-test.ts similarity index 87% rename from test/unit/compat/socket-router-test.js rename to test/unit/compat/socket-router-test.ts index 8413ffb8..bbfe167c 100644 --- a/test/unit/compat/socket-router-test.js +++ b/test/unit/compat/socket-router-test.ts @@ -1,10 +1,15 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp", "inproc")) { describe(`compat socket with ${proto} router`, function () { + let address: string + beforeEach(async () => { + address = await uniqAddress(proto) + }) + it("should handle unroutable messages", function (done) { let complete = 0 @@ -16,7 +21,10 @@ if (process.env.INCLUDE_COMPAT_TESTS) { errMsgs.push("Resource temporarily unavailable") errMsgs.push("Host unreachable") - function assertRouteError(err) { + function assertRouteError(err: Error | undefined) { + if (err === undefined) { + throw new Error("No error was emitted") + } if (errMsgs.indexOf(err.message) === -1) { throw new Error(err.message) } @@ -72,15 +80,12 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should handle router-dealer message bursts", function (done) { - this.slow(150) // tests https://github.com/JustinTulloss/zeromq.node/issues/523 // based on https://gist.github.com/messa/862638ab44ca65f712fe4d6ef79aeb67 const router = zmq.socket("router") const dealer = zmq.socket("dealer") - const address = uniqAddress(proto) - const expected = 1000 let counted = 0 diff --git a/test/unit/compat/socket-stream-test.js b/test/unit/compat/socket-stream-test.ts similarity index 78% rename from test/unit/compat/socket-stream-test.js rename to test/unit/compat/socket-stream-test.ts index 6dcb4ace..399380bc 100644 --- a/test/unit/compat/socket-stream-test.js +++ b/test/unit/compat/socket-stream-test.ts @@ -1,15 +1,19 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") - const http = require("http") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {uniqAddress} from "../helpers" +import http from "http" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { describe("compat socket stream", function () { + let address: string + beforeEach(async () => { + address = await uniqAddress("tcp") + }) + it("should support a stream socket type", function (done) { const stream = zmq.socket("stream") - const address = uniqAddress("tcp") - stream.on("message", function (id, msg) { + stream.on("message", function (id: string, msg: string) { assert.instanceOf(msg, Buffer) if (msg.length == 0) { return @@ -37,7 +41,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { stream.send([id, httpProtocolString]) }) - stream.bind(address, err => { + stream.bind(address, (err: Error | undefined) => { if (err) { throw err } @@ -46,9 +50,10 @@ if (process.env.INCLUDE_COMPAT_TESTS) { http.get( `${address.replace("tcp:", "http:")}/aRandomRequestPath`, function (httpMsg) { + // @ts-expect-error assert.equal(httpMsg.socket._readableState.reading, false) - httpMsg.on("data", function (msg) { + httpMsg.on("data", function (msg: string) { assert.instanceOf(msg, Buffer) assert.equal( msg.toString(), diff --git a/test/unit/compat/socket-test.js b/test/unit/compat/socket-test.ts similarity index 90% rename from test/unit/compat/socket-test.js rename to test/unit/compat/socket-test.ts index bf8d178f..e8813636 100644 --- a/test/unit/compat/socket-test.js +++ b/test/unit/compat/socket-test.ts @@ -1,9 +1,9 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") +import * as zmq from "../../../v5-compat" +import { assert } from "chai" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { describe("compat socket", function () { - let sock + let sock: zmq.Socket beforeEach(function () { sock = zmq.socket("req") diff --git a/test/unit/compat/socket-unbind-test.js b/test/unit/compat/socket-unbind-test.ts similarity index 73% rename from test/unit/compat/socket-unbind-test.js rename to test/unit/compat/socket-unbind-test.ts index dfb72bb8..612c337e 100644 --- a/test/unit/compat/socket-unbind-test.js +++ b/test/unit/compat/socket-unbind-test.ts @@ -1,14 +1,14 @@ /* This test is very unreliable in practice, especially in CI. It is disabled by default. */ +import * as zmq from "../../../v5-compat" +import semver from "semver" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" + if ( - process.env.INCLUDE_COMPAT_TESTS && + process.env.INCLUDE_COMPAT_TESTS === "true" && process.env.INCLUDE_COMPAT_UNBIND_TEST ) { - const zmq = require("./load") - const semver = require("semver") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") - for (const proto of testProtos("tcp")) { describe(`compat socket with ${proto} unbind`, function () { beforeEach(function () { @@ -18,14 +18,18 @@ if ( } }) - let sockA - let sockB - let sockC + let sockA: zmq.Socket + let sockB: zmq.Socket + let sockC: zmq.Socket + let address1: string + let address2: string - beforeEach(function () { + beforeEach(async function () { sockA = zmq.socket("dealer", {linger: 0}) sockB = zmq.socket("dealer", {linger: 0}) sockC = zmq.socket("dealer", {linger: 0}) + address1 = await uniqAddress(proto) + address2 = await uniqAddress(proto) }) afterEach(function () { @@ -35,14 +39,11 @@ if ( }) it("should be able to unbind", function (done) { - const address1 = uniqAddress(proto) - const address2 = uniqAddress(proto) - let msgCount = 0 sockA.bindSync(address1) sockA.bindSync(address2) - sockA.on("unbind", async function (addr) { + sockA.on("unbind", async function (addr: string) { if (addr === address1) { sockB.send("Error from sockB.") sockC.send("Messsage from sockC.") @@ -50,7 +51,7 @@ if ( } }) - sockA.on("message", async function (msg) { + sockA.on("message", async function (msg: {toString: () => string}) { msgCount++ if (msg.toString() === "Hello from sockB.") { sockA.unbindSync(address1) diff --git a/test/unit/compat/socket-xpub-xsub-test.js b/test/unit/compat/socket-xpub-xsub-test.ts similarity index 88% rename from test/unit/compat/socket-xpub-xsub-test.js rename to test/unit/compat/socket-xpub-xsub-test.ts index f101a94c..3828af9c 100644 --- a/test/unit/compat/socket-xpub-xsub-test.js +++ b/test/unit/compat/socket-xpub-xsub-test.ts @@ -1,9 +1,17 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp", "inproc")) { + let address1: string + let address2: string + + beforeEach(async function () { + address1 = await uniqAddress(proto) + address2 = await uniqAddress(proto) + }) + describe(`compat socket with ${proto} xpub-xsub`, function () { it("should support pub-sub tracing and filtering", function (done) { let n = 0 @@ -13,9 +21,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { const xpub = zmq.socket("xpub") const xsub = zmq.socket("xsub") - const address1 = uniqAddress(proto) - const address2 = uniqAddress(proto) - pub.bind(address1, err => { if (err) { throw err diff --git a/test/unit/compat/socket-zap-test.js b/test/unit/compat/socket-zap-test.ts similarity index 82% rename from test/unit/compat/socket-zap-test.js rename to test/unit/compat/socket-zap-test.ts index 583e5b89..cc9a16ce 100644 --- a/test/unit/compat/socket-zap-test.js +++ b/test/unit/compat/socket-zap-test.ts @@ -1,9 +1,10 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const semver = require("semver") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {capability} from "../../../src" +import semver from "semver" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { function start() { const zap = zmq.socket("router") @@ -49,7 +50,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { ) }) - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { zap.bind("inproc://zeromq.zap.01", err => { if (err) { return reject(err) @@ -61,9 +62,10 @@ if (process.env.INCLUDE_COMPAT_TESTS) { for (const proto of testProtos("tcp", "inproc")) { describe(`compat socket with ${proto} zap`, function () { - let zapSocket - let rep - let req + let zapSocket: zmq.Socket + let rep: zmq.Socket + let req: zmq.Socket + let address: string before(async function () { zapSocket = await start() @@ -76,7 +78,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) }) - beforeEach(function () { + beforeEach(async function () { /* Since ZAP uses inproc transport, it does not work reliably. */ if (semver.satisfies(zmq.version, "< 4.2")) { this.skip() @@ -84,6 +86,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { rep = zmq.socket("rep") req = zmq.socket("req") + address = await uniqAddress(proto) }) afterEach(function () { @@ -92,11 +95,10 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should support curve", function (done) { - if (!zmq.capability.curve) { + if (!capability.curve) { this.skip() } - const address = uniqAddress(proto) const serverPublicKey = Buffer.from( "7f188e5244b02bf497b86de417515cf4d4053ce4eb977aee91a55354655ec33a", "hex", @@ -114,7 +116,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { "hex", ) - rep.on("message", function (msg) { + rep.on("message", function (msg: unknown) { assert.instanceOf(msg, Buffer) assert.equal(msg.toString(), "hello") rep.send("world") @@ -125,7 +127,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { rep.curve_secretkey = serverPrivateKey assert.equal(rep.mechanism, 2) - rep.bind(address, err => { + rep.bind(address, (err: any) => { if (err) { throw err } @@ -136,7 +138,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { req.connect(address) req.send("hello") - req.on("message", function (msg) { + req.on("message", function (msg: unknown) { assert.instanceOf(msg, Buffer) assert.equal(msg.toString(), "world") done() @@ -145,9 +147,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should support null", function (done) { - const address = uniqAddress(proto) - - rep.on("message", function (msg) { + rep.on("message", function (msg: unknown) { assert.instanceOf(msg, Buffer) assert.equal(msg.toString(), "hello") rep.send("world") @@ -156,14 +156,14 @@ if (process.env.INCLUDE_COMPAT_TESTS) { rep.zap_domain = "test" assert.equal(rep.mechanism, 0) - rep.bind(address, err => { + rep.bind(address, (err: any) => { if (err) { throw err } assert.equal(req.mechanism, 0) req.connect(address) req.send("hello") - req.on("message", function (msg) { + req.on("message", function (msg: unknown) { assert.instanceOf(msg, Buffer) assert.equal(msg.toString(), "world") done() @@ -172,9 +172,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should support plain", function (done) { - const address = uniqAddress(proto) - - rep.on("message", function (msg) { + rep.on("message", function (msg: unknown) { assert.instanceOf(msg, Buffer) assert.equal(msg.toString(), "hello") rep.send("world") @@ -184,7 +182,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { rep.plain_server = 1 assert.equal(rep.mechanism, 1) - rep.bind(address, err => { + rep.bind(address, (err: any) => { if (err) { throw err } @@ -194,7 +192,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { req.connect(address) req.send("hello") - req.on("message", function (msg) { + req.on("message", function (msg: unknown) { assert.instanceOf(msg, Buffer) assert.equal(msg.toString(), "world") done() diff --git a/test/unit/compat/zmq-proxy-push-pull-test.js b/test/unit/compat/zmq-proxy-push-pull-test.ts similarity index 82% rename from test/unit/compat/zmq-proxy-push-pull-test.js rename to test/unit/compat/zmq-proxy-push-pull-test.ts index 41837694..e4606608 100644 --- a/test/unit/compat/zmq-proxy-push-pull-test.js +++ b/test/unit/compat/zmq-proxy-push-pull-test.ts @@ -1,22 +1,28 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp")) { describe(`compat proxy with ${proto} push-pull`, function () { - const sockets = [] + const sockets: zmq.Socket[] = [] + let frontendAddr: string + let backendAddr: string + let captureAddr: string + + beforeEach(async function () { + frontendAddr = await uniqAddress(proto) + backendAddr = await uniqAddress(proto) + captureAddr = await uniqAddress(proto) + }) afterEach(function () { - while (sockets.length) { - sockets.pop().close() + if (sockets.length) { + sockets.pop()?.close() } }) it("should proxy push-pull connected to pull-push", function (done) { - const frontendAddr = uniqAddress(proto) - const backendAddr = uniqAddress(proto) - const frontend = zmq.socket("pull") const backend = zmq.socket("push") @@ -48,10 +54,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should proxy pull-push connected to push-pull with capture", function (done) { - const frontendAddr = uniqAddress(proto) - const backendAddr = uniqAddress(proto) - const captureAddr = uniqAddress(proto) - const frontend = zmq.socket("push") const backend = zmq.socket("pull") diff --git a/test/unit/compat/zmq-proxy-router-dealer-test.js b/test/unit/compat/zmq-proxy-router-dealer-test.ts similarity index 84% rename from test/unit/compat/zmq-proxy-router-dealer-test.js rename to test/unit/compat/zmq-proxy-router-dealer-test.ts index 148412dd..d5ee4e5f 100644 --- a/test/unit/compat/zmq-proxy-router-dealer-test.js +++ b/test/unit/compat/zmq-proxy-router-dealer-test.ts @@ -1,22 +1,28 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp")) { describe(`compat proxy with ${proto} router-dealer`, function () { - const sockets = [] + const sockets: zmq.Socket[] = [] + let frontendAddr: string + let backendAddr: string + let captureAddr: string + + beforeEach(async function () { + frontendAddr = await uniqAddress(proto) + backendAddr = await uniqAddress(proto) + captureAddr = await uniqAddress(proto) + }) afterEach(function () { while (sockets.length) { - sockets.pop().close() + sockets.pop()?.close() } }) it("should proxy req-rep connected over router-dealer", function (done) { - const frontendAddr = uniqAddress(proto) - const backendAddr = uniqAddress(proto) - const frontend = zmq.socket("router") const backend = zmq.socket("dealer") @@ -53,10 +59,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should proxy rep-req connections with capture", function (done) { - const frontendAddr = uniqAddress(proto) - const backendAddr = uniqAddress(proto) - const captureAddr = uniqAddress(proto) - const frontend = zmq.socket("router") const backend = zmq.socket("dealer") diff --git a/test/unit/compat/zmq-proxy-test.js b/test/unit/compat/zmq-proxy-test.ts similarity index 58% rename from test/unit/compat/zmq-proxy-test.js rename to test/unit/compat/zmq-proxy-test.ts index 8146a89f..40b1ffed 100644 --- a/test/unit/compat/zmq-proxy-test.js +++ b/test/unit/compat/zmq-proxy-test.ts @@ -1,7 +1,7 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { describe("compat proxy", function () { it("should be a function off the module namespace", function () { assert.typeOf(zmq.proxy, "function") diff --git a/test/unit/compat/zmq-proxy-xpub-xsub-test.js b/test/unit/compat/zmq-proxy-xpub-xsub-test.ts similarity index 83% rename from test/unit/compat/zmq-proxy-xpub-xsub-test.js rename to test/unit/compat/zmq-proxy-xpub-xsub-test.ts index c0580fca..e0eb2a6b 100644 --- a/test/unit/compat/zmq-proxy-xpub-xsub-test.js +++ b/test/unit/compat/zmq-proxy-xpub-xsub-test.ts @@ -1,22 +1,30 @@ -if (process.env.INCLUDE_COMPAT_TESTS) { - const zmq = require("./load") - const {assert} = require("chai") - const {testProtos, uniqAddress} = require("../helpers") +import * as zmq from "../../../v5-compat" +import {assert} from "chai" +import {testProtos, uniqAddress} from "../helpers" +import {isFullError} from "../../../src/errors" +if (process.env.INCLUDE_COMPAT_TESTS === "true") { for (const proto of testProtos("tcp")) { describe(`compat proxy with ${proto} xpub-xsub`, function () { - const sockets = [] + const sockets: zmq.Socket[] = [] + + let frontendAddr: string + let backendAddr: string + let captureAddr: string + + beforeEach(async function () { + frontendAddr = await uniqAddress(proto) + backendAddr = await uniqAddress(proto) + captureAddr = await uniqAddress(proto) + }) afterEach(function () { while (sockets.length) { - sockets.pop().close() + sockets.pop()?.close() } }) it("should proxy pub-sub connected to xpub-xsub", function (done) { - const frontendAddr = uniqAddress(proto) - const backendAddr = uniqAddress(proto) - const frontend = zmq.socket("xpub") const backend = zmq.socket("xsub") @@ -50,10 +58,6 @@ if (process.env.INCLUDE_COMPAT_TESTS) { }) it("should proxy connections with capture", function (done) { - const frontendAddr = uniqAddress(proto) - const backendAddr = uniqAddress(proto) - const captureAddr = uniqAddress(proto) - const frontend = zmq.socket("xpub") const backend = zmq.socket("xsub") @@ -119,6 +123,7 @@ if (process.env.INCLUDE_COMPAT_TESTS) { try { zmq.proxy(backend, frontend) } catch (err) { + assert(isFullError(err)) assert.include( [ "wrong socket order to proxy", diff --git a/test/unit/context-process-exit-test.ts b/test/unit/context-process-exit-test.ts index 9aeda4fe..c5f9ae79 100644 --- a/test/unit/context-process-exit-test.ts +++ b/test/unit/context-process-exit-test.ts @@ -7,7 +7,6 @@ import {createProcess} from "./helpers" describe("context process exit", function () { describe("with default context", function () { it("should occur when sockets are closed", async function () { - this.slow(200) const {code} = await createProcess(() => { const socket1 = new zmq.Dealer() socket1.close() @@ -19,7 +18,6 @@ describe("context process exit", function () { }) it("should occur when sockets are not closed", async function () { - this.slow(200) const {code} = await createProcess(() => { const socket1 = new zmq.Dealer() const socket2 = new zmq.Router() @@ -29,7 +27,6 @@ describe("context process exit", function () { }) it("should not occur when sockets are open and polling", async function () { - this.slow(1000) const {code, isTimeout} = await createProcess(() => { const socket1 = new zmq.Dealer() socket1.connect("inproc://foo") @@ -43,7 +40,6 @@ describe("context process exit", function () { }) it("should produce warning when messages are queued with blocky", async function () { - this.slow(2000) const {stderr} = await createProcess(() => { zmq.context.blocky = true const socket1 = new zmq.Dealer({linger: 1000}) @@ -67,7 +63,6 @@ describe("context process exit", function () { }) it("should produce warning when messages are queued without blocky", async function () { - this.slow(2000) const {stderr} = await createProcess(() => { zmq.context.blocky = false const socket1 = new zmq.Dealer({linger: 1000}) @@ -84,7 +79,6 @@ describe("context process exit", function () { }) it("should not produce warning when messages are queued for a short time", async function () { - this.slow(1000) const {stderr} = await createProcess(() => { zmq.context.blocky = true const socket1 = new zmq.Dealer({linger: 50}) @@ -100,7 +94,6 @@ describe("context process exit", function () { describe("with custom context", function () { it("should occur when sockets are closed", async function () { - this.slow(200) const {code} = await createProcess(() => { const context = new zmq.Context() const socket1 = new zmq.Dealer({context}) @@ -113,7 +106,6 @@ describe("context process exit", function () { }) it("should occur when sockets are closed and context is gced", async function () { - this.slow(200) const {code} = await createProcess(() => { function run() { const context = new zmq.Context() @@ -131,7 +123,6 @@ describe("context process exit", function () { }) it("should occur when sockets are not closed", async function () { - this.slow(200) const {code} = await createProcess(() => { const context = new zmq.Context() const socket1 = new zmq.Dealer({context}) @@ -142,7 +133,6 @@ describe("context process exit", function () { }) it("should not occur when sockets are open and polling", async function () { - this.slow(1000) const {code, isTimeout} = await createProcess(() => { const context = new zmq.Context() const socket1 = new zmq.Dealer({context}) diff --git a/test/unit/context-thread-test.ts b/test/unit/context-thread-test.ts index 3d44a206..0d4b0208 100644 --- a/test/unit/context-thread-test.ts +++ b/test/unit/context-thread-test.ts @@ -5,9 +5,6 @@ import {assert} from "chai" import {createWorker} from "./helpers" describe("context in thread", function () { - this.slow(2000) - this.timeout(5000) - beforeEach(function () { /* Node.js worker support introduced in version 10.5. */ if (semver.satisfies(process.versions.node, "< 10.5")) { diff --git a/test/unit/helpers.ts b/test/unit/helpers.ts index 5186f8de..005f50ec 100644 --- a/test/unit/helpers.ts +++ b/test/unit/helpers.ts @@ -19,7 +19,7 @@ if (semver.satisfies(zmq.version, ">= 4.2")) { */ let idFallback = 5000 async function getUniqueId() { - const idPath = path.resolve(__dirname, "../../tmp/id") + const idPath = path.resolve(__dirname, "../../tmp/port-id.lock") await fs.promises.mkdir(path.dirname(idPath), {recursive: true}) try { diff --git a/test/unit/proxy-router-dealer-test.ts b/test/unit/proxy-router-dealer-test.ts index f5d9a67f..51e3d945 100644 --- a/test/unit/proxy-router-dealer-test.ts +++ b/test/unit/proxy-router-dealer-test.ts @@ -89,13 +89,16 @@ for (const proto of testProtos("tcp", "ipc", "inproc")) { rep.close() } - console.log("waiting for messages") + console.log( + `waiting for messages for proxy with ${proto} router/dealer...`, + ) await Promise.all([echo(), send()]) assert.deepEqual(received, messages) proxy.terminate() await done + console.log(`Done proxying with ${proto} router/dealer`) }) }) }) diff --git a/test/unit/socket-close-test.ts b/test/unit/socket-close-test.ts index 83f145b5..3e92fab2 100644 --- a/test/unit/socket-close-test.ts +++ b/test/unit/socket-close-test.ts @@ -108,7 +108,6 @@ for (const proto of testProtos("tcp", "ipc", "inproc")) { it("should release reference to context", async function () { const gc = getGcOrSkipTest(this) - this.slow(200) let weakRef: undefined | WeakRef @@ -138,7 +137,7 @@ for (const proto of testProtos("tcp", "ipc", "inproc")) { // if (process.env.SKIP_GC_FINALIZER_TESTS) { // this.skip() // } - // this.slow(200) + // // let weakRef: undefined | WeakRef // const task = async () => { diff --git a/test/unit/socket-events-test.ts b/test/unit/socket-events-test.ts index bf294a60..bef10ebd 100644 --- a/test/unit/socket-events-test.ts +++ b/test/unit/socket-events-test.ts @@ -54,7 +54,6 @@ for (const proto of testProtos("tcp", "ipc", "inproc")) { }) it("should receive connect events", async function () { - this.slow(250) const address = await uniqAddress(proto) const [event] = await Promise.all([ diff --git a/test/unit/socket-process-exit-test.ts b/test/unit/socket-process-exit-test.ts index 2d3392fb..22a4c9be 100644 --- a/test/unit/socket-process-exit-test.ts +++ b/test/unit/socket-process-exit-test.ts @@ -6,7 +6,6 @@ import {createProcess} from "./helpers" describe("socket process exit", function () { /* Reported: https://github.com/nodejs/node-addon-api/issues/591 */ it.skip("should occur cleanly when sending in exit hook", async function () { - this.slow(200) const {code} = await createProcess(async () => { const sockA = new zmq.Pair() const sockB = new zmq.Pair() @@ -24,7 +23,6 @@ describe("socket process exit", function () { }) it("should occur cleanly when sending on unbound socket", async function () { - this.slow(200) const {code} = await createProcess(async () => { const sock = new zmq.Publisher() await sock.send("test") @@ -34,7 +32,6 @@ describe("socket process exit", function () { }) it("should not occur when sending and blocked on unbound socket", async function () { - this.slow(1000) const {code} = await createProcess(async () => { const sock = new zmq.Dealer() await sock.send("test") @@ -44,7 +41,6 @@ describe("socket process exit", function () { }) it("should occur cleanly on socket close when reading events", async function () { - this.slow(200) const {code} = await createProcess(() => { const sock = new zmq.Dealer() @@ -63,7 +59,6 @@ describe("socket process exit", function () { }) it("should not occur while reading events", async function () { - this.slow(1000) const {code} = await createProcess(async () => { const sock = new zmq.Dealer() diff --git a/test/unit/socket-send-receive-test.ts b/test/unit/socket-send-receive-test.ts index bdd22871..508fab57 100644 --- a/test/unit/socket-send-receive-test.ts +++ b/test/unit/socket-send-receive-test.ts @@ -265,8 +265,6 @@ for (const proto of testProtos("tcp", "ipc", "inproc")) { }) it("should poll simultaneously", async function () { - this.timeout(5000) - const sendReceiveA = async () => { const [msg1] = await Promise.all([ sockA.receive(), @@ -426,8 +424,6 @@ for (const proto of testProtos("tcp", "ipc", "inproc")) { } it("should not starve event loop", async function () { - this.slow(250) - sockA.sendHighWaterMark = 5000 sockB.receiveHighWaterMark = 5000 diff --git a/test/unit/socket-thread-test.ts b/test/unit/socket-thread-test.ts index 290847b3..9d581780 100644 --- a/test/unit/socket-thread-test.ts +++ b/test/unit/socket-thread-test.ts @@ -6,9 +6,6 @@ import {createWorker, testProtos, uniqAddress} from "./helpers" for (const proto of testProtos("tcp", "ipc", "inproc")) { describe(`socket with ${proto} in thread`, function () { - this.slow(2000) - this.timeout(5000) - beforeEach(function () { /* Node.js worker support introduced in version 10.5. */ if (semver.satisfies(process.versions.node, "< 10.5")) { diff --git a/test/unit/socket-zap-test.ts b/test/unit/socket-zap-test.ts index 113c23f4..53fa9fbc 100644 --- a/test/unit/socket-zap-test.ts +++ b/test/unit/socket-zap-test.ts @@ -167,8 +167,6 @@ for (const proto of testProtos("tcp", "ipc")) { this.skip() } - this.slow(250) - sockA.plainServer = true sockB.curveServer = true diff --git a/test/unit/typings-compatibility-test.ts b/test/unit/typings-compatibility-test.ts index 86af58d1..1c2ee070 100644 --- a/test/unit/typings-compatibility-test.ts +++ b/test/unit/typings-compatibility-test.ts @@ -100,7 +100,6 @@ describe("compatibility of typings for typescript versions", async function () { let execCmd: string before(async function () { - this.timeout(10000) if (/^true$/.test(process.env.EXCLUDE_TYPINGS_COMPAT_TESTS as string)) { this.skip() } @@ -110,7 +109,6 @@ describe("compatibility of typings for typescript versions", async function () { for (const tsVer of tsVersions) { // must increase timeout for allowing `npm install`'ing the version of // the typescript package to complete - this.timeout(30000) const tscTargetPath = path.resolve( tscTestBasePath, diff --git a/tsconfig.json b/tsconfig.json index 5f6b4dde..e21bbb36 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,6 +19,11 @@ "incremental": true, "sourceMap": true, "esModuleInterop": true, - "lib": ["ES2020"] - } + "lib": [ + "ES2020", + // only used in tests + "ES2021.WeakRef" + ] + }, + "compileOnSave": true }