Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: use WeakRef instead of weak-napi for GC tests + chore: add debugging configuration for VsCode #631

Merged
merged 5 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"llvm-vs-code-extensions.vscode-clangd",
"xadillax.gyp",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
"esbenp.prettier-vscode",
"vadimcn.vscode-lldb"
]
}
46 changes: 46 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"configurations": [
{
"name": "JS-Attach",
"type": "node",
"request": "attach",
"port": 9229,
"continueOnAttach": true,
"autoAttachChildProcesses": true,
"resolveSourceMapLocations": [
"!**/node_modules/**",
"!**/.vscode/extensions/hbenl.vscode-mocha-test-adapter-*/**"
],
"skipFiles": [
"<node_internals>/**"
],
},
{
"type": "lldb",
"request": "launch",
"name": "Native-Launch",
"preLaunchTask": "clean_build_debug",
"program": "node",
"suppressMultipleSessionWarning": true,
"sourceLanguages": [
"cpp"
],
"args": [
"--inspect-brk=9229",
"--expose-gc",
"-r",
"ts-node/register",
"${workspaceFolder}/test/debug.ts"
],
}
],
"compounds": [
{
"name": "Node-Launch",
"configurations": [
"Native-Launch",
"JS-Attach",
]
}
]
}
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"mochaExplorer.parallel": true,
"mochaExplorer.globImplementation": "vscode"
"mochaExplorer.globImplementation": "vscode",
"mochaExplorer.nodeArgv": [
"--expose-gc"
],
"mochaExplorer.debuggerConfig": "JS-Attach"
}
10 changes: 10 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "clean_build_debug",
"type": "shell",
"command": "pnpm clean.release && pnpm build.debug",
}
]
}
10 changes: 0 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,3 @@ tool similar to Cmake. GYP was originally created to generate native IDE project
files (Visual Studio, Xcode) for building Chromium.

The `.gyp` file is structured as a Python dictionary.

## Weak-napi

https://www.npmjs.com/package/weak-napi On certain rarer occasions, you run into
the need to be notified when a JavaScript object is going to be garbage
collected. This feature is exposed to V8's C++ API, but not to JavaScript.

That's where weak-napi comes in! This module exports the JS engine's GC tracking
functionality to JavaScript. This allows you to create weak references, and
optionally attach a callback function to any arbitrary JS object.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"scripts": {
"install": "(shx test -f ./script/build.js || run-s build.js) && cross-env npm_config_build_from_source=true aminya-node-gyp-build",
"clean": "shx rm -rf ./build ./lib/ ./prebuilds ./script/*.js ./script/*.js.map ./script/*.d.ts ./script/*.tsbuildinfo",
"clean.release": "shx rm -rf ./build/Release",
"clean.temp": "shx rm -rf ./tmp && shx mkdir -p ./tmp",
"build.library": "tsc -p ./src/tsconfig.json",
"build.script": "tsc -p ./script/tsconfig.json && tsc -p ./script/tsconfig.esm.json",
Expand All @@ -95,10 +96,9 @@
"build.native.debug": "node-gyp configure --debug && node-gyp configure --debug -- -f compile_commands_json && cross-env CMAKE_BUILD_TYPE=Debug node-gyp build --debug",
"build": "run-s build.js build.native",
"build.debug": "run-s build.js build.native.debug",
"test.deps": "cd test && pnpm install && cd ..",
"test": "run-s clean.temp test.deps build && mocha",
"test.skip_gc_tests": "run-s clean.temp test.deps build.debug && cross-env SKIP_GC_TESTS=true mocha",
"test.electron.main": "run-s clean.temp test.deps build && electron-mocha",
"test": "run-s clean.temp build && mocha",
"test.skip_gc_tests": "run-s clean.temp build.debug && cross-env SKIP_GC_TESTS=true mocha",
"test.electron.main": "run-s clean.temp build && electron-mocha",
"format": "prettier --write .",
"test.electron.renderer": "run-s build && electron-mocha --renderer",
"lint.clang-format": "clang-format -i -style=file ./src/*.cc ./src/*.h ./src/util/*.h",
Expand Down
26 changes: 26 additions & 0 deletions test/debug.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as zmq from "../src"

import {getGcOrSkipTest} from "./unit/helpers"

async function main() {
const gc = getGcOrSkipTest()

let weakRef: undefined | WeakRef<zmq.Context>
const task = async () => {
const context: zmq.Context | undefined = new zmq.Context()
const dealer = new zmq.Dealer({context, linger: 0})
weakRef = new WeakRef(context)

// dealer.close()
}

await task()
await gc()

console.log(weakRef?.deref())
}

main().catch(err => {
console.error(err)
process.exit(1)
})
6 changes: 0 additions & 6 deletions test/package.json

This file was deleted.

81 changes: 0 additions & 81 deletions test/pnpm-lock.yaml

This file was deleted.

4 changes: 3 additions & 1 deletion test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"extends": "../tsconfig.json",
"include": ["**/*.ts"]
"include": [
"**/*.ts"
]
}
40 changes: 40 additions & 0 deletions test/unit/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,43 @@ export async function captureEventsUntil(

return events
}

// REAL typings for global.gc per
// https://github.com/nodejs/node/blob/v20.0.0/deps/v8/src/extensions/gc-extension.cc
interface GCFunction {
(options: {
execution?: "sync"
flavor?: "regular" | "last-resort"
type?: "major-snapshot" | "major" | "minor"
filename?: string
}): void
(options: {
execution?: "async"
flavor?: "regular" | "last-resort"
type?: "major-snapshot" | "major" | "minor"
filename?: string
}): Promise<void>
(options: {
execution?: "async" | "sync"
flavor?: "regular" | "last-resort"
type?: "major-snapshot" | "major" | "minor"
filename?: string
}): void | Promise<void>
}

export function getGcOrSkipTest(test?: Mocha.Context) {
if (process.env.SKIP_GC_TESTS === "true") {
test?.skip()
}

const gc = global.gc as undefined | GCFunction
if (typeof gc !== "function") {
throw new Error(
"Garbage collection is not exposed. It may be enabled by the node --expose-gc flag or v8-expose-gc flag in Mocha. To skip GC tests, set the environment variable `SKIP_GC_TESTS`",
)
}
// https://github.com/nodejs/node/blob/v20.0.0/deps/v8/src/extensions/gc-extension.h
// per docs, we we're using use case 2 (Test that certain objects indeed are reclaimed)
const asyncMajorGc = () => gc({type: "major", execution: "async"})
return asyncMajorGc
}
Loading
Loading