Initial commit

This commit is contained in:
2025-12-08 12:12:07 +07:00
commit 0b2e8c4c16
1238 changed files with 160253 additions and 0 deletions

5
server/node_modules/buildcheck/.eslintrc.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
'use strict';
module.exports = {
extends: '@mscdex/eslint-config',
};

View File

@@ -0,0 +1,88 @@
name: CI
on:
pull_request:
push:
branches: [ master ]
jobs:
tests-linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x, 22.x, 24.x]
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Check Node.js version
run: node -pe process.versions
- name: Install module
run: npm install
- name: Run tests
run: npm test
tests-macos-intel:
runs-on: macos-15-intel
strategy:
fail-fast: false
matrix:
node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x, 22.x, 24.x]
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Check Node.js version
run: node -pe process.versions
- name: Install module
run: npm install
- name: Run tests
run: npm test
tests-macos-arm:
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
node-version: [16.x, 18.x, 20.x, 22.x, 24.x]
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Check Node.js version
run: node -pe process.versions
- name: Install module
run: npm install
- name: Run tests
run: npm test
tests-windows-2022:
runs-on: windows-2022
strategy:
fail-fast: false
matrix:
node-version: [24.x]
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Check Node.js version
run: node -pe process.versions
- name: Install module
run: npm install
- name: Run tests
run: npm test

View File

@@ -0,0 +1,27 @@
name: lint
on:
pull_request:
push:
branches: [ master ]
env:
NODE_VERSION: 22.x
jobs:
lint-js:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Use Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Check Node.js version
run: node -pe process.versions
- name: Install ESLint + ESLint configs/plugins
run: npm install --only=dev
- name: Lint files
run: npm run lint

3
server/node_modules/buildcheck/.npmignore generated vendored Normal file
View File

@@ -0,0 +1,3 @@
.eslintcache
**/node_modules/**
/package-lock.json

19
server/node_modules/buildcheck/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright Brian White. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

106
server/node_modules/buildcheck/README.md generated vendored Normal file
View File

@@ -0,0 +1,106 @@
# Description
Build environment checking for [node.js](http://nodejs.org/).
This allows for autoconf-like functionality for node addons/build scripts.
**Note:** Obsolete and/or exotic build environments or platforms not supported
by node.js are not supported.
## Requirements
* [node.js](http://nodejs.org/) -- v10.0.0 or newer
* Supported compilers:
* gcc
* clang
* MSVC 2013+ and Windows SDK 8.1+
## Installation
npm install buildcheck
## Examples
### Check if a C function exists
```js
'use strict';
const BuildEnvironment = require('buildcheck');
const buildEnv = new BuildEnvironment();
console.log(buildEnv.checkFunction('c', 'preadv2'));
```
### Check if a C header is usable
```js
'use strict';
const BuildEnvironment = require('buildcheck');
const buildEnv = new BuildEnvironment();
console.log(buildEnv.checkHeader('c', 'linux/io_uring.h'));
```
### Try to compile some C code
```js
'use strict';
const BuildEnvironment = require('buildcheck');
const buildEnv = new BuildEnvironment();
// Should be a successful compile
console.log(buildEnv.tryCompile('c', 'int main() { return 0; }'));
// Should be a failed compile
console.log(buildEnv.tryCompile('c', 'int main() { return z; }'));
```
## API
### Exports
The exported value is `BuildEnvironment`, the main class for dealing with a build environment.
### BuildEnvironment
#### Methods
* **(constructor)**([< _object_ >config]) - Creates and returns a new BuildEnvironment instance. `config` may contain:
* **compilerC** - _string_ - C compiler command to use. *Note: this is ignored on Windows.* **Default:** `process.env.CC` or `'cc'`
* **compilerCXX** - _string_ - C++ compiler command to use. *Note: this is ignored on Windows.* **Default:** `process.env.CXX` or `'c++'`
* **msvs_version** - _mixed_ - A string or number containing the year of the Visual Studio compiler to use. *Note: this is for Windows only.* **Default:** newest version installed
* **checkDeclared**(< _string_ >lang, < _string_ >symbolName[, < _object_ >options]) - _boolean_ - Checks if a symbol `symbolName` is declared where `lang` is either `'c'` or `'c++'`. Returns `true` if symbol exists, `false` otherwise. `options` may contain:
* **headers** - _array_ - A list of headers to try when checking if the symbol is declared. `checkFunction()` will always first try without a library. If not supplied, a default list of common (platform-specific) headers will be used.
* **searchLibs** - _array_ - A list of library names (without the `'-l'` prefix) to try when checking if the symbol is declared. `checkDeclared()` will always first try without a library.
* **checkFunction**(< _string_ >lang, < _string_ >functionName[, < _object_ >options]) - _boolean_ - Checks if a function `functionName` exists and is linkable where `lang` is either `'c'` or `'c++'`. Returns `true` if function exists, `false` otherwise. `options` may contain:
* **searchLibs** - _array_ - A list of library names (without the `'-l'` prefix) to try when checking for this function. `checkFunction()` will always first try without a library.
* **checkFeature**(< _string_ >featureName) - _mixed_ - Executes a special test for a "feature" and returns the result. Supported values for `featureName`:
* `'strerror_r'` - Returns an object containing:
* `declared` - _boolean_ - Whether `strerror_r()` is declared
* `returnsCharPtr` - _boolean_ - If `strerror_r()` is declared, whether it returns `char*` (a GNU extension) or not.
* **checkHeader**(< _string_ >lang, < _string_ >headerName) - _boolean_ - Checks if the header `headerName` exists and is usable where `lang` is either `'c'` or `'c++'`. Returns `true` if the header exists and is usable, `false` otherwise.
* **defines**([< _string_ >lang[, < _boolean_ >rendered]]) - _array_ - Returns a list of features, functions, headers, and symbols known to be defined by this build environment instance. `lang` is either `'c'` or `'c++'` If `lang` is not set, defines for both `'c'` and `'c++'` will be returned. If `rendered` is `true` (defaults to `false`), autoconf-style defines (e.g. "HAVE_FOO=1") will be returned instead. Defines coming from features utilize base strings/names from autoconf for better compatibility.
* **libs**([< _string_ >lang]) - _array_ - Returns a list of (`'-l'`-prefixed) libraries known to be required for features and functions defined by this build environment instance. `lang` is either `'c'` or `'c++'` If `lang` is not set, defines for both `'c'` and `'c++'` will be returned.
* **tryCompile**(< _string_ >lang, < _string_ >code[, < _array_ >compilerParams]) - _mixed_ - Attempts to compile `code` where `lang` is either `'c'` or `'c++'`. `compilerParams` is an optional array of compiler/linker flags to include. Returns `true` on successful compilation, or an _Error_ instance with an `output` property containing the compiler error output.

View File

@@ -0,0 +1,250 @@
// Copyright 2017 - Refael Ackermann
// Distributed under MIT style license
// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf
// Usage:
// powershell -ExecutionPolicy Unrestricted -Command "Add-Type -Path Find-VisualStudio.cs; [VisualStudioConfiguration.Main]::PrintJson()"
// This script needs to be compatible with PowerShell v2 to run on Windows 2008R2 and Windows 7.
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections.Generic;
namespace VisualStudioConfiguration
{
[Flags]
public enum InstanceState : uint
{
None = 0,
Local = 1,
Registered = 2,
NoRebootRequired = 4,
NoErrors = 8,
Complete = 4294967295,
}
[Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface IEnumSetupInstances
{
void Next([MarshalAs(UnmanagedType.U4), In] int celt,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt,
[MarshalAs(UnmanagedType.U4)] out int pceltFetched);
void Skip([MarshalAs(UnmanagedType.U4), In] int celt);
void Reset();
[return: MarshalAs(UnmanagedType.Interface)]
IEnumSetupInstances Clone();
}
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface ISetupConfiguration
{
}
[Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface ISetupConfiguration2 : ISetupConfiguration
{
[return: MarshalAs(UnmanagedType.Interface)]
IEnumSetupInstances EnumInstances();
[return: MarshalAs(UnmanagedType.Interface)]
ISetupInstance GetInstanceForCurrentProcess();
[return: MarshalAs(UnmanagedType.Interface)]
ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path);
[return: MarshalAs(UnmanagedType.Interface)]
IEnumSetupInstances EnumAllInstances();
}
[Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface ISetupInstance
{
}
[Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface ISetupInstance2 : ISetupInstance
{
[return: MarshalAs(UnmanagedType.BStr)]
string GetInstanceId();
[return: MarshalAs(UnmanagedType.Struct)]
System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate();
[return: MarshalAs(UnmanagedType.BStr)]
string GetInstallationName();
[return: MarshalAs(UnmanagedType.BStr)]
string GetInstallationPath();
[return: MarshalAs(UnmanagedType.BStr)]
string GetInstallationVersion();
[return: MarshalAs(UnmanagedType.BStr)]
string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid);
[return: MarshalAs(UnmanagedType.BStr)]
string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid);
[return: MarshalAs(UnmanagedType.BStr)]
string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath);
[return: MarshalAs(UnmanagedType.U4)]
InstanceState GetState();
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
ISetupPackageReference[] GetPackages();
ISetupPackageReference GetProduct();
[return: MarshalAs(UnmanagedType.BStr)]
string GetProductPath();
[return: MarshalAs(UnmanagedType.VariantBool)]
bool IsLaunchable();
[return: MarshalAs(UnmanagedType.VariantBool)]
bool IsComplete();
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
ISetupPropertyStore GetProperties();
[return: MarshalAs(UnmanagedType.BStr)]
string GetEnginePath();
}
[Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface ISetupPackageReference
{
[return: MarshalAs(UnmanagedType.BStr)]
string GetId();
[return: MarshalAs(UnmanagedType.BStr)]
string GetVersion();
[return: MarshalAs(UnmanagedType.BStr)]
string GetChip();
[return: MarshalAs(UnmanagedType.BStr)]
string GetLanguage();
[return: MarshalAs(UnmanagedType.BStr)]
string GetBranch();
[return: MarshalAs(UnmanagedType.BStr)]
string GetType();
[return: MarshalAs(UnmanagedType.BStr)]
string GetUniqueId();
[return: MarshalAs(UnmanagedType.VariantBool)]
bool GetIsExtension();
}
[Guid("c601c175-a3be-44bc-91f6-4568d230fc83")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
public interface ISetupPropertyStore
{
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
string[] GetNames();
object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName);
}
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
[CoClass(typeof(SetupConfigurationClass))]
[ComImport]
public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration
{
}
[Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
[ClassInterface(ClassInterfaceType.None)]
[ComImport]
public class SetupConfigurationClass
{
}
public static class Main
{
public static void PrintJson()
{
ISetupConfiguration query = new SetupConfiguration();
ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
IEnumSetupInstances e = query2.EnumAllInstances();
int pceltFetched;
ISetupInstance2[] rgelt = new ISetupInstance2[1];
List<string> instances = new List<string>();
while (true)
{
e.Next(1, rgelt, out pceltFetched);
if (pceltFetched <= 0)
{
Console.WriteLine(String.Format("[{0}]", string.Join(",", instances.ToArray())));
return;
}
try
{
instances.Add(InstanceJson(rgelt[0]));
}
catch (COMException)
{
// Ignore instances that can't be queried.
}
}
}
private static string JsonString(string s)
{
return "\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
}
private static string InstanceJson(ISetupInstance2 setupInstance2)
{
// Visual Studio component directory:
// https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids
StringBuilder json = new StringBuilder();
json.Append("{");
string path = JsonString(setupInstance2.GetInstallationPath());
json.Append(String.Format("\"path\":{0},", path));
string version = JsonString(setupInstance2.GetInstallationVersion());
json.Append(String.Format("\"version\":{0},", version));
List<string> packages = new List<string>();
foreach (ISetupPackageReference package in setupInstance2.GetPackages())
{
string id = JsonString(package.GetId());
packages.Add(id);
}
json.Append(String.Format("\"packages\":[{0}]", string.Join(",", packages.ToArray())));
json.Append("}");
return json.ToString();
}
}
}

361
server/node_modules/buildcheck/lib/findvs.js generated vendored Normal file
View File

@@ -0,0 +1,361 @@
'use strict';
const { execFileSync } = require('child_process');
const { readFileSync, statSync } = require('fs');
const { win32: path } = require('path');
const modernMSBuildPath = (() => {
let arch;
switch (process.arch) {
case 'x64':
arch = 'amd64';
break;
case 'arm64':
arch = process.arch;
break;
default:
arch = '';
}
return path.join('MSBuild', 'Current', 'Bin', arch, 'MSBuild.exe');
})();
const VS_VERSIONS_MODERN = new Map([
[15, {
year: 2017,
msbuild: path.join('MSBuild', '15.0', 'Bin', 'MSBuild.exe'),
toolset: 'v141',
}],
[16, {
year: 2019,
msbuild: path.join('MSBuild', 'Current', 'Bin', 'MSBuild.exe'),
toolset: 'v142',
}],
[17, {
year: 2022,
msbuild: modernMSBuildPath,
toolset: 'v143',
}],
[18, {
year: 2026,
msbuild: modernMSBuildPath,
toolset: 'v145',
}],
]);
const PACKAGES = {
msbuild: /^Microsoft[.]VisualStudio[.]VC[.]MSBuild[.](?:v\d+[.])?Base$/i,
vctools: /^Microsoft[.]VisualStudio[.]Component[.]VC[.]Tools[.](x86[.]x64|ARM64)$/i,
express: /^Microsoft[.]VisualStudio[.]WDExpress$/i,
winsdk:
/^Microsoft[.]VisualStudio[.]Component[.]Windows(81|10|11)SDK(?:[.](\d+)(?:[.]Desktop.*)?)?$/,
};
const SDK_REG = 'HKLM\\Software\\Microsoft\\Microsoft SDKs\\Windows';
const SDK32_REG =
'HKLM\\Software\\Wow6432Node\\Microsoft\\Microsoft SDKs\\Windows';
function checkRequiredPackages(packages) {
if (!Array.isArray(packages))
return false;
let foundMSBuild = false;
let foundVCTools = false;
let foundExpress = false;
for (const pkg of packages) {
if (!foundMSBuild && PACKAGES.msbuild.test(pkg))
foundMSBuild = true;
else if (!foundVCTools && PACKAGES.vctools.test(pkg))
foundVCTools = true;
else if (!foundExpress && PACKAGES.express.test(pkg))
foundExpress = true;
if (foundMSBuild && (foundVCTools || foundExpress))
return true;
}
}
// Sorts newest to oldest
function versionStringCompare(a, b) {
const splitA = a.split('.');
const splitB = b.split('.');
const len = Math.min(splitA.length, splitB.length);
for (let i = 0; i < len; ++i) {
const nA = parseInt(splitA[i], 10);
const nB = parseInt(splitB[i], 10);
if (nA > nB)
return -1;
if (nA < nB)
return 1;
}
if (splitA.length > splitB.length)
return -1;
else if (splitA.length < splitB.length)
return 1;
return 0;
}
function sdkVersionCompare(a, b) {
return versionStringCompare(a.fullVersion, b.fullVersion);
}
function getSDKPaths(fullVer) {
if (typeof fullVer !== 'string' || !fullVer)
return;
try {
const arch = (process.arch === 'ia32' ? 'x86' : process.arch);
const shortVer = `v${/^\d+[.]\d+/.exec(fullVer)[0]}`;
let verPath = getRegValue(`${SDK_REG}\\${shortVer}`, 'InstallationFolder');
if (!verPath)
verPath = getRegValue(`${SDK32_REG}\\${shortVer}`, 'InstallationFolder');
if (!verPath)
return;
// Includes
const includePaths = [];
for (const type of ['shared', 'um', 'ucrt']) {
const testPath = path.resolve(verPath, 'Include', fullVer, type);
statSync(testPath);
includePaths.push(testPath);
}
// Libraries
const libPaths = [];
for (const type of ['um', 'ucrt']) {
const testPath = path.resolve(verPath, 'Lib', fullVer, type, arch);
statSync(testPath);
libPaths.push(testPath);
}
return { includePaths, libPaths };
} catch {}
}
const execOpts = {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
windowsHide: true,
};
function findModernVS() {
const versions = [];
const ps = path.join(
process.env.SystemRoot,
'System32',
'WindowsPowerShell',
'v1.0',
'powershell.exe'
);
const cs = path.resolve(__dirname, '..', 'deps', 'Find-VisualStudio.cs');
const args = [
'-ExecutionPolicy',
'Unrestricted',
'-NoProfile',
'-Command',
`&{Add-Type -Path '${cs}';[VisualStudioConfiguration.Main]::PrintJson()}`
];
try {
const out = execFileSync(ps, args, execOpts);
const info = JSON.parse(out);
if (Array.isArray(info)) {
for (const vs of info) {
const vsPath = path.resolve(vs.path);
let vsVer = /^(?<major>\d+)[.](?<minor>\d+)[.]/.exec(vs.version);
if (!vsVer)
continue;
vsVer = {
full: vs.version,
major: +vsVer.groups.major,
minor: +vsVer.groups.minor,
};
const verInfo = VS_VERSIONS_MODERN.get(vsVer.major);
if (verInfo === undefined)
continue;
if (!checkRequiredPackages(vs.packages))
continue;
const vsSDKs = [];
for (const pkg of vs.packages) {
let fullVersion;
let version;
const m = PACKAGES.winsdk.exec(pkg);
if (!m)
continue;
const sdk = m[1];
switch (sdk) {
case '81':
fullVersion = version = '8.1';
break;
case '10':
case '11': {
if (m[2] === undefined)
continue;
const sdkVer = parseInt(m[2], 10);
if (!isFinite(sdkVer) || sdkVer < 0)
continue;
fullVersion = `10.0.${sdkVer}.0`;
version = '10.0';
break;
}
}
const paths = getSDKPaths(fullVersion);
if (!paths)
continue;
vsSDKs.push({
version,
fullVersion,
...paths,
});
}
if (vsSDKs.length === 0)
continue;
let clPath;
const includePaths = [];
const libPaths = [];
try {
let vcVerFile;
let clVer;
try {
vcVerFile = path.join(
vsPath,
'VC',
'Auxiliary',
'Build',
`Microsoft.VCToolsVersion.${verInfo.toolset}.default.txt`
);
clVer = readFileSync(vcVerFile, { encoding: 'utf8' }).trim();
} catch {}
if (!clVer) {
vcVerFile = path.join(
vsPath,
'VC',
'Auxiliary',
'Build',
'Microsoft.VCToolsVersion.default.txt'
);
clVer = readFileSync(vcVerFile, { encoding: 'utf8' }).trim();
}
const arch = (process.arch === 'ia32' ? 'x86' : process.arch);
let testPath = path.join(
vsPath,
'VC',
'Tools',
'MSVC',
clVer,
'bin',
`Host${arch}`,
arch,
'cl.exe'
);
statSync(testPath);
clPath = testPath;
testPath = path.join(
vsPath,
'VC',
'Tools',
'MSVC',
clVer,
'include'
);
statSync(testPath);
includePaths.push(testPath);
testPath = path.join(
vsPath,
'VC',
'Tools',
'MSVC',
clVer,
'lib',
arch
);
statSync(testPath);
libPaths.push(testPath);
} catch {
continue;
}
vsSDKs.sort(sdkVersionCompare);
versions.push({
path: vsPath,
version: vsVer,
sdks: vsSDKs,
...verInfo,
msbuild: path.join(vsPath, verInfo.msbuild),
cl: clPath,
includePaths,
libPaths,
});
}
}
} catch {}
return versions;
}
const VS_VERSIONS_OLDER = [
{
version: { full: '12.0', major: 12, minor: 0 },
year: 2013,
toolset: 'v120',
},
{
version: { full: '14.0', major: 14, minor: 0 },
year: 2015,
toolset: 'v140',
},
];
const VC_REG = 'HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7';
const VC32_REG =
'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7';
const MSBUILD_REG = 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions';
function getRegValue(key, value, use32) {
const extraArgs = (use32 ? [ '/reg:32' ] : []);
const regexp = new RegExp(`^\\s+${value}\\s+REG_\\w+\\s+(\\S.*)$`, 'im');
const reg = path.join(process.env.SystemRoot, 'System32', 'reg.exe');
const args = [ 'query', key, '/v', value, ...extraArgs ];
try {
const out = execFileSync(reg, args, execOpts);
const m = regexp.exec(out);
if (m)
return m[1];
} catch {}
}
function findOlderVS() {
const versions = [];
try {
for (const vs of VS_VERSIONS_OLDER) {
let vsPath = getRegValue(VC_REG, vs.version.full);
if (!vsPath)
vsPath = getRegValue(VC32_REG, vs.version.full);
if (!vsPath)
continue;
vsPath = path.resolve(vsPath, '..');
const msbuildPath = getRegValue(
`${MSBUILD_REG}\\${vs.version.full}`,
'MSBuildToolsPath',
(process.arch === 'ia32')
);
if (!msbuildPath)
continue;
versions.push({
path: vsPath,
...vs,
msbuild: path.join(msbuildPath, 'MSBuild.exe'),
cl: path.join(vsPath, 'VC', 'bin', 'cl.exe'),
includePaths: [path.join(vsPath, 'VC', 'include')],
libPaths: [path.join(vsPath, 'VC', 'lib')],
sdks: [],
});
}
} catch {}
return versions;
}
module.exports = () => {
const versions = findModernVS().concat(findOlderVS());
// Sorts newest to oldest
versions.sort((a, b) => {
return versionStringCompare(a.version.full, b.version.full);
});
return versions;
};

738
server/node_modules/buildcheck/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,738 @@
'use strict';
// TODO: take `compilerParams`, headers into account in cache for all cached
// results
// TODO: debug output
const { spawnSync } = require('child_process');
const { unlinkSync, writeFileSync } = require('fs');
const { tmpdir } = require('os');
const { win32: path } = require('path');
const { inspect } = require('util');
const isWindows = (process.platform === 'win32');
const findVS = require('./findvs.js');
const RE_HEADER_DECORATED = /^(?:"(.+)")|(?:<(.+)>)$/;
const genWinTmpFilenames = (() => {
let instance = 1;
return () => {
const base =
path.resolve(tmpdir(), `_buildcheck-${process.pid}-${instance++}`);
return {
input: `${base}.in.tmp`,
object: `${base}.out.obj`,
output: `${base}.out.tmp`,
};
};
})();
function getKind(prop) {
const spawnOpts = {
encoding: 'utf8',
stdio: 'pipe',
windowsHide: true,
};
const lang = (prop === '_cc' ? 'c' : 'c++');
if (isWindows) {
spawnOpts.stdio = [ 'ignore', 'pipe', 'pipe' ];
writeFileSync(this._tmpInFile, [
'_MSC_VER',
].join(' '));
const result = spawnSync(
this[prop],
[ '-EP', `-T${lang === 'c' ? 'c' : 'p'}`, this._tmpInFile],
spawnOpts
);
unlinkSync(this._tmpInFile);
if (result.status === 0) {
const values = result.stdout.trim().split(' ');
if (values.length === 1 && /^\d+$/.test(values[0])) {
this[`${prop}Kind`] = 'msvc';
this[`${prop}Version`] = values[0];
this[`${prop}SpawnOpts`] = spawnOpts;
this._debug(
`>>> Detected MSVC ${values[0]} for ${lang.toUpperCase()} language`
);
return;
}
}
} else {
const result = spawnSync(
this[prop],
[ '-E', '-P', '-x', lang, '-' ],
{
...spawnOpts,
input: [
'__clang__',
'__GNUC__',
'__GNUC_MINOR__',
'__GNUC_PATCHLEVEL__',
'__clang_major__',
'__clang_minor__',
'__clang_patchlevel__',
].join(' '),
}
);
if (result.status === 0) {
const values = result.stdout.trim().split(' ');
if (values.length === 7) {
let kind;
let version;
if (values[0] === '1') {
kind = 'clang';
version = values.slice(4).map((v) => +v);
} else {
kind = 'gnu';
version = values.slice(1, 4).map((v) => +v);
}
let good = true;
for (const part of version) {
if (!isFinite(part) || part < 0) {
good = false;
break;
}
}
if (good) {
this[`${prop}Kind`] = kind;
this[`${prop}Version`] = version;
this[`${prop}SpawnOpts`] = spawnOpts;
const verStr = version.join('.');
this._debug(
`>>> Detected ${kind} ${verStr} for ${lang.toUpperCase()} language`
);
return;
}
}
}
}
throw new Error('Unable to detect compiler type');
}
class BuildEnvironment {
constructor(cfg) {
if (typeof cfg !== 'object' || cfg === null)
cfg = {};
this._debug = (typeof cfg.debug === 'function' ? cfg.debug : () => {});
let cc;
let cxx;
if (isWindows) {
const versions = findVS();
this._debug(
`>>> Detected MSVS installations: ${inspect(versions, false, 10)}`
);
if (versions.length === 0)
throw new Error('Unable to detect compiler type');
let selected_msvs;
if (cfg.msvs_version
&& (typeof cfg.msvs_version === 'string'
|| typeof cfg.msvs_version === 'number')) {
this._debug(`>>> Explicit MSVS requested: ${cfg.msvs_version}`);
// Try to select compiler by year
const msvs_version = cfg.msvs_version.toString();
for (const vs of versions) {
if (vs.year.toString() === msvs_version) {
selected_msvs = vs;
break;
}
}
if (selected_msvs === undefined)
throw new Error(`Unable to find MSVS with year '${msvs_version}'`);
} else {
selected_msvs = versions[0]; // Use newest
}
this._debug(`>>> Using MSVS: ${selected_msvs.year}`);
cc = selected_msvs.cl;
cxx = cc;
this._includePaths = selected_msvs.includePaths;
this._libPaths = selected_msvs.libPaths;
// Add (newest) SDK paths if we have them
for (const sdk of selected_msvs.sdks) {
this._debug(`>>> Using Windows SDK: ${sdk.fullVersion}`);
this._includePaths = this._includePaths.concat(sdk.includePaths);
this._libPaths = this._libPaths.concat(sdk.libPaths);
break;
}
const { input, object, output } = genWinTmpFilenames();
this._tmpInFile = input;
this._tmpObjFile = object;
this._tmpOutFile = output;
} else {
cc = ((typeof cfg.compilerC === 'string' && cfg.compilerC)
|| process.env.CC
|| 'cc');
cxx = ((typeof cfg.compilerCXX === 'string' && cfg.compilerCXX)
|| process.env.CXX
|| 'c++');
this._debug(`>>> Using C compiler: ${cc}`);
this._debug(`>>> Using C++ compiler: ${cxx}`);
}
this._cc = cc;
this._ccKind = undefined;
this._ccVersion = undefined;
this._ccSpawnOpts = undefined;
this._cxx = cxx;
this._cxxKind = undefined;
this._cxxVersion = undefined;
this._cxxSpawnOpts = undefined;
if (cfg.cache !== false) {
this._cache = new Map(Object.entries({
c: new Map(),
cxx: new Map(),
}));
} else {
this._cache = null;
}
}
checkDeclared(type, symbolName, opts) {
validateType(type);
if (typeof symbolName !== 'string' || !symbolName)
throw new Error(`Invalid symbol name: ${inspect(symbolName)}`);
const cached = getCachedValue(type, this._cache, 'declared', symbolName);
if (cached !== undefined) {
this._debug(
`>>> Checking if '${symbolName}' is declared... ${cached} (cached)`
);
return cached;
}
if (typeof opts !== 'object' || opts === null)
opts = {};
const { headers, searchLibs } = opts;
const headersList = renderHeaders(Array.isArray(headers)
? headers
: getDefaultHeaders(this, type));
const declName = symbolName.replace(/ *\(.*/, '');
const declUse = symbolName.replace(/\(/, '((')
.replace(/\)/, ') 0)')
.replace(/,/g, ') 0, (');
const libs = [
'',
...(Array.isArray(searchLibs) ? searchLibs : [])
];
for (let lib of libs) {
if (typeof lib !== 'string')
continue;
lib = lib.trim();
const code = `
${headersList}
int
main ()
{
#ifndef ${declName}
#ifdef __cplusplus
(void) ${declUse};
#else
(void) ${declName};
#endif
#endif
;
return 0;
}`;
const compilerParams = (lib ? [`-l${lib}`] : []);
const result = this.tryCompile(type, code, compilerParams);
this._debug(
`>>> Checking if '${symbolName}' is declared `
+ `(using ${lib ? `'${lib}'` : 'no'} library)... ${result === true}`
);
if (result !== true) {
this._debug('... check failed with compiler output:');
this._debug(result.output);
}
if (result === true) {
setCachedValue(
type,
this._cache,
'declared',
symbolName,
(result === true)
);
return true;
}
}
return false;
}
checkFeature(name) {
const cached = getCachedValue('features', this._cache, null, name);
if (cached !== undefined) {
if (typeof cached === 'object'
&& cached !== null
&& typeof cached.val !== undefined) {
return cached.val;
}
return cached;
}
const feature = features.get(name);
if (feature === undefined)
throw new Error(`Invalid feature: ${name}`);
let result = feature(this);
if (result === undefined)
result = null;
setCachedValue('features', this._cache, null, name, result);
if (typeof result === 'object'
&& result !== null
&& typeof result.val !== undefined) {
return result.val;
}
return result;
}
checkFunction(type, funcName, opts) {
validateType(type);
if (typeof funcName !== 'string' || !funcName)
throw new Error(`Invalid function name: ${inspect(funcName)}`);
const cached = getCachedValue(type, this._cache, 'functions', funcName);
if (cached !== undefined) {
this._debug(
`>>> Checking if function '${funcName}' exists... true (cached)`
);
return true;
}
if (typeof opts !== 'object' || opts === null)
opts = {};
const { searchLibs } = opts;
const libs = [
'',
...(Array.isArray(searchLibs) ? searchLibs : [])
];
for (let lib of libs) {
if (typeof lib !== 'string')
continue;
lib = lib.trim();
const code = `
/* Define ${funcName} to an innocuous variant, in case <limits.h> declares
${funcName}.
For example, HP-UX 11i <limits.h> declares gettimeofday. */
#define ${funcName} innocuous_${funcName}
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char ${funcName} (); below. */
#include <limits.h>
#undef ${funcName}
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char ${funcName} ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined __stub_${funcName} || defined __stub___${funcName}
choke me
#endif
int
main ()
{
return ${funcName} ();
;
return 0;
}`;
const compilerParams = (lib ? [`-l${lib}`] : []);
const result = this.tryCompile(type, code, compilerParams);
this._debug(
`>>> Checking if function '${funcName}' exists `
+ `(using ${lib ? `'${lib}'` : 'no'} library)... ${result === true}`
);
if (result !== true) {
this._debug('... check failed with compiler output:');
this._debug(result.output);
}
if (result === true) {
setCachedValue(
type,
this._cache,
'functions',
funcName,
compilerParams
);
return true;
}
}
return false;
}
checkHeader(type, header) {
validateType(type);
const cached = getCachedValue(
type,
this._cache,
'headers',
normalizeHeader(header)
);
if (cached !== undefined) {
this._debug(
`>>> Checking if header '${header}' exists... ${cached} (cached)`
);
return cached;
}
const headersList = renderHeaders([header]);
const code = `
${headersList}
int
main ()
{
return 0;
}`;
const result = this.tryCompile(type, code);
setCachedValue(
type,
this._cache,
'headers',
normalizeHeader(header),
(result === true)
);
this._debug(
`>>> Checking if header '${header}' exists... ${result === true}`
);
if (result !== true) {
this._debug('... check failed with compiler output:');
this._debug(result.output);
}
return (result === true);
}
defines(type, rendered) {
if (this._cache === null)
return [];
const defines = new Map();
let types;
if (!['c', 'c++'].includes(type))
types = ['c', 'c++'];
else
types = [type];
for (const t of types) {
const typeCache = this._cache.get(t);
if (!typeCache)
continue;
for (const [subtype, entries] of typeCache) {
for (let name of entries.keys()) {
if (subtype === 'headers')
name = name.replace(RE_HEADER_DECORATED, '$1$2');
defines.set(makeDefine(name, rendered), 1);
}
}
}
{
const featuresCache = this._cache.get('features');
if (featuresCache) {
for (const result of featuresCache.values()) {
if (typeof result === 'object'
&& result !== null
&& Array.isArray(result.defines)) {
for (const define of result.defines)
defines.set(makeDefine(define, rendered), 1);
}
}
}
}
return Array.from(defines.keys());
}
libs(type) {
if (this._cache === null)
return [];
const libs = new Map();
let types;
if (!['c', 'c++'].includes(type))
types = ['c', 'c++'];
else
types = [type];
for (const t of types) {
const typeCache = this._cache.get(t);
if (!typeCache)
continue;
const functionsCache = typeCache.get('functions');
if (!functionsCache)
continue;
for (const compilerParams of functionsCache.values()) {
for (const param of compilerParams)
libs.set(param, 1);
}
}
{
const featuresCache = this._cache.get('features');
if (featuresCache) {
for (const result of featuresCache.values()) {
if (typeof result === 'object'
&& result !== null
&& Array.isArray(result.libs)) {
for (const lib of result.libs)
libs.set(lib, 1);
}
}
}
}
return Array.from(libs.keys());
}
tryCompile(type, code, compilerParams) {
validateType(type);
if (typeof code !== 'string')
throw new TypeError('Invalid code argument');
type = (type === 'c' ? 'c' : 'c++');
const prop = (type === 'c' ? '_cc' : '_cxx');
if (this[`${prop}Kind`] === undefined)
getKind.call(this, prop);
if (!Array.isArray(compilerParams))
compilerParams = [];
let result;
if (this[`${prop}Kind`] === 'msvc') {
const cmpOpts = [`-Fo${this._tmpObjFile}`];
for (const includePath of this._includePaths)
cmpOpts.push('-I', includePath);
const lnkOpts = [];
for (const libPath of this._libPaths)
lnkOpts.push(`-LIBPATH:${libPath}`);
for (const opt of compilerParams) {
let m;
if (m = /^[-/]l(.+)$/.exec(opt))
lnkOpts.push(m[1]);
else
cmpOpts.push(opt);
}
try {
writeFileSync(this._tmpInFile, code);
const args = [
...cmpOpts,
`-T${prop === '_cc' ? 'c' : 'p'}`,
this._tmpInFile,
'-link',
`-out:${this._tmpOutFile}`,
...lnkOpts,
];
result = spawnSync(
this[prop],
args,
this[`${prop}SpawnOpts`]
);
unlinkSync(this._tmpInFile);
// Overwrite stderr with stdout because MSVC seems to print
// errors to stdout instead for some reason
result.stderr = result.stdout;
} catch (ex) {
// We had trouble writing or deleting a temp file, fake
// the result
result = { status: Infinity, stderr: ex.stack };
}
try { unlinkSync(this._tmpObjFile); } catch {}
try { unlinkSync(this._tmpOutFile); } catch {}
} else {
result = spawnSync(
this[prop],
[
'-x', type,
'-o', '/dev/null',
'-',
...compilerParams,
],
{
...this[`${prop}SpawnOpts`],
input: code,
}
);
}
if (result.status === 0)
return true;
const err = new Error('Compilation failed');
err.output = result.stderr;
return err;
}
}
function validateType(type) {
if (!['c', 'c++'].includes(type))
throw new Error('Invalid type argument');
}
function getCachedValue(type, cache, subtype, key) {
if (cache === null)
return;
const typeCache = cache.get(type);
if (!typeCache)
return;
const subtypeCache = (typeof subtype !== 'string'
? typeCache
: typeCache.get(subtype));
if (!subtypeCache)
return;
return subtypeCache.get(key);
}
function setCachedValue(type, cache, subtype, key, value) {
if (cache === null)
return;
let typeCache = cache.get(type);
if (!typeCache)
cache.set(type, typeCache = new Map());
let subtypeCache = (typeof subtype !== 'string'
? typeCache
: typeCache.get(subtype));
if (!subtypeCache)
typeCache.set(subtype, subtypeCache = new Map());
subtypeCache.set(key, value);
}
function renderHeaders(headers) {
let ret = '';
if (Array.isArray(headers)) {
for (const header of headers) {
if (typeof header !== 'string' || !header)
throw new Error(`Invalid header: ${inspect(header)}`);
ret += `#include ${normalizeHeader(header)}\n`;
}
}
return ret;
}
function normalizeHeader(header) {
if (!RE_HEADER_DECORATED.test(header))
header = `<${header}>`;
return header;
}
const DEFAULT_HEADERS_POSIX = [
'stdio.h',
'sys/types.h',
'sys/stat.h',
'stdlib.h',
'stddef.h',
'memory.h',
'string.h',
'strings.h',
'inttypes.h',
'stdint.h',
'unistd.h'
];
const DEFAULT_HEADERS_MSVC = [
'windows.h',
];
function getDefaultHeaders(be, type) {
const prop = (type === 'c' ? '_cc' : '_cxx');
if (be[`${prop}Kind`] === undefined)
getKind.call(be, prop);
let headers;
if (be[`${prop}Kind`] === 'msvc')
headers = DEFAULT_HEADERS_MSVC;
else
headers = DEFAULT_HEADERS_POSIX;
return headers.filter((hdr) => be.checkHeader(type, hdr));
}
const features = new Map(Object.entries({
'strerror_r': (be) => {
const defines = [];
let returnsCharPtr = false;
const declared = be.checkDeclared('c', 'strerror_r');
if (declared) {
const code = `
${renderHeaders(getDefaultHeaders(be, 'c'))}
int
main ()
{
char buf[100];
char x = *strerror_r (0, buf, sizeof buf);
char *p = strerror_r (0, buf, sizeof buf);
return !p || x;
;
return 0;
}`;
returnsCharPtr = (be.tryCompile('c', code) === true);
if (returnsCharPtr)
defines.push('STRERROR_R_CHAR_P');
}
return {
defines,
val: { declared, returnsCharPtr }
};
},
}));
function makeDefine(name, rendered) {
name = name.replace(/[*]/g, 'P')
.replace(/[^_A-Za-z0-9]/g, '_')
.toUpperCase();
return (rendered ? `HAVE_${name}=1` : name);
}
module.exports = BuildEnvironment;

36
server/node_modules/buildcheck/package.json generated vendored Normal file
View File

@@ -0,0 +1,36 @@
{
"name": "buildcheck",
"version": "0.0.7",
"author": "Brian White <mscdex@mscdex.net>",
"description": "Build environment checking (a la autoconf) for node.js",
"main": "./lib/index.js",
"engines": {
"node": ">=10.0.0"
},
"devDependencies": {
"@mscdex/eslint-config": "^1.1.0",
"eslint": "^7.0.0"
},
"scripts": {
"test": "node test/test.js",
"lint": "eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib",
"lint:fix": "npm run lint -- --fix"
},
"keywords": [
"build",
"autoconf",
"addons",
"compiler",
"environment"
],
"licenses": [
{
"type": "MIT",
"url": "http://github.com/mscdex/buildcheck/raw/master/LICENSE"
}
],
"repository": {
"type": "git",
"url": "http://github.com/mscdex/buildcheck.git"
}
}

8
server/node_modules/buildcheck/test/test.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
'use strict';
const BE = require('..');
{
// Test compiler detection
new BE({ debug: console.log });
}