278 lines
8.0 KiB
JavaScript
278 lines
8.0 KiB
JavaScript
/**
|
|
* Preload for `brittle-node` / Node-based booter tests:
|
|
* - `bare-type/binding.js` uses Bare-only `require.addon()`.
|
|
* - `bare-dns/binding.js` uses Bare-only `require.addon()` (transitive via holesail / DHT).
|
|
* - `bare-inspect` pulls the same; brittle → bare-assert → bare-inspect.
|
|
*
|
|
* Usage: node --require ./scripts/bare-node-test-shim.cjs …
|
|
*/
|
|
'use strict'
|
|
|
|
/** `bare-path` and some Holepunch modules expect a global `Bare` (Pear/Bare runtime). */
|
|
if (typeof globalThis.Bare === 'undefined') {
|
|
globalThis.Bare = {
|
|
platform: process.platform,
|
|
on(event, fn) {
|
|
if (event === 'exit' && typeof fn === 'function' && process.on) {
|
|
process.on('exit', fn)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const path = require('path')
|
|
const Module = require('module')
|
|
const { types } = require('node:util')
|
|
|
|
const constants = {
|
|
UNDEFINED: 0,
|
|
NULL: 1,
|
|
BOOLEAN: 2,
|
|
NUMBER: 3,
|
|
STRING: 4,
|
|
SYMBOL: 5,
|
|
OBJECT: 6,
|
|
FUNCTION: 7,
|
|
EXTERNAL: 8,
|
|
BIGINT: 9,
|
|
INT32: 256,
|
|
UINT32: 512,
|
|
ARRAY: 256,
|
|
ARGUMENTS: 512,
|
|
DATE: 768,
|
|
REGEXP: 1024,
|
|
ERROR: 1280,
|
|
PROMISE: 1536,
|
|
PROXY: 1792,
|
|
GENERATOR: 2048,
|
|
MAP: 2304,
|
|
SET: 2560,
|
|
WEAK_MAP: 2816,
|
|
WEAK_SET: 3072,
|
|
WEAK_REF: 3328,
|
|
ARRAYBUFFER: 3584,
|
|
SHAREDARRAYBUFFER: 3840,
|
|
TYPEDARRAY: 4096,
|
|
DATAVIEW: 4352,
|
|
MODULE_NAMESPACE: 4608,
|
|
INT8ARRAY: 65536,
|
|
UINT8ARRAY: 131072,
|
|
UINT8CLAMPEDARRAY: 196608,
|
|
INT16ARRAY: 262144,
|
|
UINT16ARRAY: 327680,
|
|
INT32ARRAY: 393216,
|
|
UINT32ARRAY: 458752,
|
|
FLOAT16ARRAY: 786432,
|
|
FLOAT32ARRAY: 524288,
|
|
FLOAT64ARRAY: 589824,
|
|
BIGINT64ARRAY: 655360,
|
|
BIGUINT64ARRAY: 720896,
|
|
ASYNC_FUNCTION: 256,
|
|
GENERATOR_FUNCTION: 512
|
|
}
|
|
|
|
const t = constants
|
|
|
|
function typeNumber(value) {
|
|
let ty = t.NUMBER
|
|
if (Number.isSafeInteger(value)) {
|
|
if (value >= -0x80000000 && value <= 0x7fffffff && (value | 0) === value) {
|
|
ty |= t.INT32
|
|
} else if (value >= 0 && value <= 0xffffffff && (value >>> 0) === value) {
|
|
ty |= t.UINT32
|
|
}
|
|
}
|
|
return ty
|
|
}
|
|
|
|
function typeObject(value) {
|
|
if (value === null) return t.NULL
|
|
if (Array.isArray(value)) return t.OBJECT | t.ARRAY
|
|
if (types.isArgumentsObject(value)) return t.OBJECT | t.ARGUMENTS
|
|
if (value instanceof Date) return t.OBJECT | t.DATE
|
|
if (value instanceof RegExp) return t.OBJECT | t.REGEXP
|
|
if (types.isNativeError(value)) return t.OBJECT | t.ERROR
|
|
if (value instanceof Promise) return t.OBJECT | t.PROMISE
|
|
if (types.isProxy(value)) return t.OBJECT | t.PROXY
|
|
if (types.isGeneratorObject(value)) return t.OBJECT | t.GENERATOR
|
|
if (value instanceof Map) return t.OBJECT | t.MAP
|
|
if (value instanceof Set) return t.OBJECT | t.SET
|
|
if (value instanceof WeakMap) return t.OBJECT | t.WEAK_MAP
|
|
if (value instanceof WeakSet) return t.OBJECT | t.WEAK_SET
|
|
if (value instanceof WeakRef) return t.OBJECT | t.WEAK_REF
|
|
if (value instanceof ArrayBuffer) return t.OBJECT | t.ARRAYBUFFER
|
|
if (value instanceof SharedArrayBuffer) return t.OBJECT | t.SHAREDARRAYBUFFER
|
|
if (ArrayBuffer.isView(value) && !(value instanceof DataView)) {
|
|
let ta = t.OBJECT | t.TYPEDARRAY
|
|
if (value instanceof Int8Array) ta |= t.INT8ARRAY
|
|
else if (value instanceof Uint8Array) ta |= t.UINT8ARRAY
|
|
else if (value instanceof Uint8ClampedArray) ta |= t.UINT8CLAMPEDARRAY
|
|
else if (value instanceof Int16Array) ta |= t.INT16ARRAY
|
|
else if (value instanceof Uint16Array) ta |= t.UINT16ARRAY
|
|
else if (value instanceof Int32Array) ta |= t.INT32ARRAY
|
|
else if (value instanceof Uint32Array) ta |= t.UINT32ARRAY
|
|
else if (typeof Float16Array !== 'undefined' && value instanceof Float16Array)
|
|
ta |= t.FLOAT16ARRAY
|
|
else if (value instanceof Float32Array) ta |= t.FLOAT32ARRAY
|
|
else if (value instanceof Float64Array) ta |= t.FLOAT64ARRAY
|
|
else if (value instanceof BigInt64Array) ta |= t.BIGINT64ARRAY
|
|
else if (value instanceof BigUint64Array) ta |= t.BIGUINT64ARRAY
|
|
return ta
|
|
}
|
|
if (value instanceof DataView) return t.OBJECT | t.DATAVIEW
|
|
if (types.isModuleNamespaceObject(value)) return t.OBJECT | t.MODULE_NAMESPACE
|
|
return t.OBJECT
|
|
}
|
|
|
|
function typeFunction(fn) {
|
|
let ty = t.FUNCTION
|
|
if (types.isAsyncFunction(fn)) ty |= t.ASYNC_FUNCTION
|
|
if (types.isGeneratorFunction(fn)) ty |= t.GENERATOR_FUNCTION
|
|
return ty
|
|
}
|
|
|
|
function bareType(value) {
|
|
switch (typeof value) {
|
|
case 'undefined':
|
|
return t.UNDEFINED
|
|
case 'boolean':
|
|
return t.BOOLEAN
|
|
case 'number':
|
|
return typeNumber(value)
|
|
case 'string':
|
|
return t.STRING
|
|
case 'symbol':
|
|
return t.SYMBOL
|
|
case 'object':
|
|
return typeObject(value)
|
|
case 'function':
|
|
return typeFunction(value)
|
|
case 'bigint':
|
|
return t.BIGINT
|
|
default:
|
|
return t.UNDEFINED
|
|
}
|
|
}
|
|
|
|
const bareTypeBinding = {
|
|
constants,
|
|
type: bareType,
|
|
addTag() {},
|
|
checkTag() {
|
|
return false
|
|
}
|
|
}
|
|
|
|
/** @param {string} filename */
|
|
function isBareInspectIndex(filename) {
|
|
const n = filename.replace(/\\/g, '/')
|
|
return n.includes('/bare-inspect/') && n.endsWith('/index.js')
|
|
}
|
|
|
|
const BARE_INSPECT_NODE_SOURCE = `'use strict'
|
|
const util = require('util')
|
|
module.exports = function inspect(value, opts = {}) {
|
|
return util.inspect(value, {
|
|
depth: opts.depth,
|
|
colors: !!opts.colors,
|
|
breakLength: opts.breakLength,
|
|
maxArrayLength: opts.maxArrayLength,
|
|
maxStringLength: opts.maxStringLength
|
|
})
|
|
}
|
|
module.exports.styles = {}
|
|
`
|
|
|
|
/** Minimal stub so `require('bare-dns')` loads under Node (no native addon). */
|
|
const bareDnsBindingStub = {
|
|
initResolver() {
|
|
return 0
|
|
},
|
|
destroyResolver() {},
|
|
resolveTxt(_handle, _hostname, cb) {
|
|
if (typeof cb === 'function') {
|
|
process.nextTick(() => cb(new Error('bare-dns: stub binding in Node tests')))
|
|
}
|
|
},
|
|
lookup(_hostname, _family, _all, _req, callback) {
|
|
if (typeof callback === 'function') {
|
|
process.nextTick(() => callback(new Error('bare-dns: stub binding in Node tests'), null))
|
|
}
|
|
return null
|
|
}
|
|
}
|
|
|
|
const origLoad = Module._load
|
|
Module._load = function (request, parent, isMain) {
|
|
if (
|
|
request === './binding' &&
|
|
parent &&
|
|
typeof parent.filename === 'string' &&
|
|
parent.filename.includes(`${path.sep}bare-type${path.sep}`) &&
|
|
parent.filename.endsWith(`${path.sep}index.js`)
|
|
) {
|
|
return bareTypeBinding
|
|
}
|
|
if (
|
|
request === './binding' &&
|
|
parent &&
|
|
typeof parent.filename === 'string' &&
|
|
parent.filename.includes(`${path.sep}bare-dns${path.sep}`) &&
|
|
parent.filename.endsWith(`${path.sep}index.js`)
|
|
) {
|
|
return bareDnsBindingStub
|
|
}
|
|
return origLoad.apply(this, arguments)
|
|
}
|
|
|
|
const ADDON_STUB_PREFIX =
|
|
'if (typeof require.addon !== "function") {\n' +
|
|
' require.addon = function bareOsNodeTestAddon() {\n' +
|
|
' return new Proxy({}, {\n' +
|
|
' get() {\n' +
|
|
' return function () { return {} }\n' +
|
|
' }\n' +
|
|
' })\n' +
|
|
' }\n' +
|
|
'}\n'
|
|
|
|
function isBareOsBindingFile(filename) {
|
|
if (typeof filename !== 'string') return false
|
|
const n = filename.replace(/\\/g, '/')
|
|
return n.endsWith('/bare-os/binding.js')
|
|
}
|
|
|
|
function isBareAddonBindingFile(filename, src) {
|
|
if (typeof filename !== 'string') return false
|
|
if (isBareOsBindingFile(filename)) return false
|
|
if (!filename.includes(`${path.sep}node_modules${path.sep}`)) return false
|
|
if (!filename.endsWith(`${path.sep}binding.js`)) return false
|
|
const s = String(src || '')
|
|
.replace(/\/\/[^\n]*/g, '')
|
|
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
.trim()
|
|
return /^\s*module\.exports\s*=\s*require\.addon\s*\(\s*\)\s*;?\s*$/.test(s)
|
|
}
|
|
|
|
const bareOsBindingNodeShimPath = path.join(
|
|
__dirname,
|
|
'bare-os-binding-node-shim.cjs'
|
|
)
|
|
|
|
const origCompile = Module.prototype._compile
|
|
Module.prototype._compile = function (content, filename) {
|
|
if (typeof filename === 'string' && isBareInspectIndex(filename)) {
|
|
return origCompile.call(this, BARE_INSPECT_NODE_SOURCE, filename)
|
|
}
|
|
if (isBareOsBindingFile(filename)) {
|
|
const src = `module.exports = require(${JSON.stringify(
|
|
bareOsBindingNodeShimPath
|
|
)})\n`
|
|
return origCompile.call(this, src, filename)
|
|
}
|
|
if (isBareAddonBindingFile(filename, content)) {
|
|
return origCompile.call(this, ADDON_STUB_PREFIX + content, filename)
|
|
}
|
|
return origCompile.call(this, content, filename)
|
|
}
|