diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e9388be..7efe3ef 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -13,6 +13,6 @@ Node-API Conformance Test Suite: A pure ECMAScript test suite for Node-API imple - **Process Isolation**: The built-in runner for Node.js, run each test in isolation to prevent crashes from aborting entire test suite. ## Development Focus -- Port existing tests from `nodejs/node/test/js-native-api` into `tests/engine/` and `nodejs/node/test/node-api` into `tests/runtime/`, removing dependencies on Node.js runtime APIs while preserving test coverage +- Port existing tests from `nodejs/node/test/js-native-api` into `tests/js-native-api/` and `nodejs/node/test/node-api` into `tests/node-api/`, removing dependencies on Node.js runtime APIs while preserving test coverage - Structure tests for easy integration by external implementors - Consider following patterns from [web-platform-tests](https://web-platform-tests.org/) and [WebGPU CTS](https://github.com/gpuweb/cts) projects where applicable. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c8f0957 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +/node/ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6db5959 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,47 @@ +{ + "name": "node-api-cts", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "node-api-cts", + "version": "0.1.0", + "devDependencies": { + "@types/node": "^24.10.1", + "typescript": "^5.9.3" + } + }, + "node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9dc3a14 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "node-api-cts", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "shallow-checkout-nodejs": "node ./tools/shallow-checkout-nodejs.ts" + }, + "devDependencies": { + "@types/node": "^24.10.1", + "typescript": "^5.9.3" + } +} diff --git a/tools/shallow-checkout-nodejs.ts b/tools/shallow-checkout-nodejs.ts new file mode 100644 index 0000000..ae4ef3f --- /dev/null +++ b/tools/shallow-checkout-nodejs.ts @@ -0,0 +1,95 @@ +#!/usr/bin/env node +import assert from "node:assert/strict"; +import { + spawnSync, + type SpawnSyncOptionsWithStringEncoding, +} from "node:child_process"; +import { cpSync, mkdtempSync, mkdirSync, rmSync } from "node:fs"; +import path from "node:path"; +import { tmpdir } from "node:os"; + +const PATHS = ["test/js-native-api", "test/node-api", "doc/api/n-api.md"]; +const NODE_REPO_URL = "https://github.com/nodejs/node.git"; +const ROOT_PATH = path.resolve(import.meta.dirname, ".."); +const NODE_ROOT_PATH = path.join(ROOT_PATH, "node"); + +function getOptionsFromArgs([ref = "main"]: string[]) { + return { ref }; +} + +function runGit( + args: string[], + options: Partial = {} +) { + const result = spawnSync("git", args, { + stdio: options.stdio ?? "inherit", + encoding: options.encoding ?? "utf8", + cwd: options.cwd, + }); + + assert(!result.error, result.error); + assert.equal( + result.status, + 0, + `git ${args.join(" ")} exited with ${result.status ?? "unknown"}` + ); + + return result; +} + +function ensureGitAvailable() { + return runGit(["--version"], { stdio: "pipe" }).stdout.trim(); +} + +function copyPath(source: string, destination: string) { + rmSync(destination, { recursive: true, force: true }); + + mkdirSync(path.dirname(destination), { recursive: true }); + cpSync(source, destination, { recursive: true }); +} + +function main() { + const { ref } = getOptionsFromArgs(process.argv.slice(2)); + mkdirSync(NODE_ROOT_PATH, { recursive: true }); + + const gitVersion = ensureGitAvailable(); + console.log(`Using ${gitVersion}`); + + const tempDir = mkdtempSync(path.join(tmpdir(), "node-tests-")); + console.log(`Cloning ${NODE_REPO_URL} @ ${ref} into ${tempDir}`); + + try { + runGit([ + "clone", + "--depth=1", + "--filter=blob:none", + "--sparse", + "--branch", + ref, + NODE_REPO_URL, + tempDir, + ]); + + runGit(["sparse-checkout", "set", "--no-cone", ...PATHS], { + cwd: tempDir, + }); + + for (const sourcePath of PATHS) { + const source = path.join(tempDir, sourcePath); + const destination = path.join(NODE_ROOT_PATH, sourcePath); + console.log(`Updating ${destination}`); + copyPath(source, destination); + } + } finally { + rmSync(tempDir, { recursive: true, force: true }); + } + + console.log("Node.js tests and docs checkout complete."); +} + +try { + main(); +} catch (error) { + console.error(error instanceof Error ? error.message : error); + process.exitCode = 1; +} diff --git a/tools/tsconfig.json b/tools/tsconfig.json new file mode 100644 index 0000000..9cb9d34 --- /dev/null +++ b/tools/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "types": ["node"], + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["**/*.ts"] +}