mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
feat(dns) resolveSrv (#1870)
* initial steps * in-progress resolveSrv support * fix memory leak and ZigGlobalObject * promise.resolve + fix priority and weight mistake * fix node dns export * little better test * add poll_ref to keep alive loop in callback for resolveSrv and lookup * add test for error case in resolveSrc * fix Bun.dns.resolveSrv type
This commit is contained in:
438
packages/bun-error/package-lock.json
generated
438
packages/bun-error/package-lock.json
generated
@@ -1,8 +1,444 @@
|
||||
{
|
||||
"name": "bun-error",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bun-error",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "latest",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^17.0.39"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "17.0.47",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.47.tgz",
|
||||
"integrity": "sha512-mk0BL8zBinf2ozNr3qPnlu1oyVTYq+4V7WA76RgxUAtf0Em/Wbid38KN6n4abEkvO4xMTBWmnP1FtQzgkEiJoA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/scheduler": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
||||
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz",
|
||||
"integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"esbuild-android-64": "0.14.48",
|
||||
"esbuild-android-arm64": "0.14.48",
|
||||
"esbuild-darwin-64": "0.14.48",
|
||||
"esbuild-darwin-arm64": "0.14.48",
|
||||
"esbuild-freebsd-64": "0.14.48",
|
||||
"esbuild-freebsd-arm64": "0.14.48",
|
||||
"esbuild-linux-32": "0.14.48",
|
||||
"esbuild-linux-64": "0.14.48",
|
||||
"esbuild-linux-arm": "0.14.48",
|
||||
"esbuild-linux-arm64": "0.14.48",
|
||||
"esbuild-linux-mips64le": "0.14.48",
|
||||
"esbuild-linux-ppc64le": "0.14.48",
|
||||
"esbuild-linux-riscv64": "0.14.48",
|
||||
"esbuild-linux-s390x": "0.14.48",
|
||||
"esbuild-netbsd-64": "0.14.48",
|
||||
"esbuild-openbsd-64": "0.14.48",
|
||||
"esbuild-sunos-64": "0.14.48",
|
||||
"esbuild-windows-32": "0.14.48",
|
||||
"esbuild-windows-64": "0.14.48",
|
||||
"esbuild-windows-arm64": "0.14.48"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-android-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz",
|
||||
"integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-android-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-darwin-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz",
|
||||
"integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-darwin-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-freebsd-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz",
|
||||
"integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-freebsd-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-32": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz",
|
||||
"integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz",
|
||||
"integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-arm": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz",
|
||||
"integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-mips64le": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz",
|
||||
"integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-ppc64le": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz",
|
||||
"integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-riscv64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz",
|
||||
"integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-s390x": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz",
|
||||
"integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-netbsd-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz",
|
||||
"integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-openbsd-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz",
|
||||
"integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-sunos-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz",
|
||||
"integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-32": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz",
|
||||
"integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz",
|
||||
"integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-arm64": {
|
||||
"version": "0.14.48",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz",
|
||||
"integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dependencies": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
|
||||
"integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||
"integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"scheduler": "^0.20.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "17.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
|
||||
"integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
|
||||
16
packages/bun-types/dns.d.ts
vendored
16
packages/bun-types/dns.d.ts
vendored
@@ -650,13 +650,13 @@ declare module "dns" {
|
||||
* ```
|
||||
* @since v0.1.27
|
||||
*/
|
||||
// export function resolveSrv(
|
||||
// hostname: string,
|
||||
// callback: (err: ErrnoException | null, addresses: SrvRecord[]) => void,
|
||||
// ): void;
|
||||
// export namespace resolveSrv {
|
||||
// function __promisify__(hostname: string): Promise<SrvRecord[]>;
|
||||
// }
|
||||
export function resolveSrv(
|
||||
hostname: string,
|
||||
callback: (err: ErrnoException | null, addresses: SrvRecord[]) => void,
|
||||
): void;
|
||||
export namespace resolveSrv {
|
||||
function __promisify__(hostname: string): Promise<SrvRecord[]>;
|
||||
}
|
||||
/**
|
||||
* Uses the DNS protocol to resolve text queries (`TXT` records) for the`hostname`. The `records` argument passed to the `callback` function is a
|
||||
* two-dimensional array of the text records available for `hostname` (e.g.`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of
|
||||
@@ -867,7 +867,7 @@ declare module "dns" {
|
||||
// resolveNs: typeof resolveNs;
|
||||
// resolvePtr: typeof resolvePtr;
|
||||
// resolveSoa: typeof resolveSoa;
|
||||
// resolveSrv: typeof resolveSrv;
|
||||
resolveSrv: typeof resolveSrv;
|
||||
// resolveTxt: typeof resolveTxt;
|
||||
// reverse: typeof reverse;
|
||||
/**
|
||||
|
||||
8
packages/bun-types/dns/promises.d.ts
vendored
8
packages/bun-types/dns/promises.d.ts
vendored
@@ -15,7 +15,7 @@ declare module "dns/promises" {
|
||||
// MxRecord,
|
||||
// NaptrRecord,
|
||||
// SoaRecord,
|
||||
// SrvRecord,
|
||||
SrvRecord,
|
||||
ResolveWithTtlOptions,
|
||||
RecordWithTtl,
|
||||
ResolveOptions,
|
||||
@@ -144,7 +144,7 @@ declare module "dns/promises" {
|
||||
// function resolve(hostname: string, rrtype: "NS"): Promise<string[]>;
|
||||
// function resolve(hostname: string, rrtype: "PTR"): Promise<string[]>;
|
||||
// function resolve(hostname: string, rrtype: "SOA"): Promise<SoaRecord>;
|
||||
// function resolve(hostname: string, rrtype: "SRV"): Promise<SrvRecord[]>;
|
||||
function resolveSrv(hostname: string): Promise<SrvRecord[]>;
|
||||
// function resolve(hostname: string, rrtype: "TXT"): Promise<string[][]>;
|
||||
// function resolve(
|
||||
// hostname: string,
|
||||
@@ -319,7 +319,7 @@ declare module "dns/promises" {
|
||||
* ```
|
||||
* @since v10.6.0
|
||||
*/
|
||||
// function resolveSrv(hostname: string): Promise<SrvRecord[]>;
|
||||
function resolveSrv(hostname: string): Promise<SrvRecord[]>;
|
||||
/**
|
||||
* Uses the DNS protocol to resolve text queries (`TXT` records) for the`hostname`. On success, the `Promise` is resolved with a two-dimensional array
|
||||
* of the text records available for `hostname` (e.g.`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of
|
||||
@@ -390,7 +390,7 @@ declare module "dns/promises" {
|
||||
// resolveNs: typeof resolveNs;
|
||||
// resolvePtr: typeof resolvePtr;
|
||||
// resolveSoa: typeof resolveSoa;
|
||||
// resolveSrv: typeof resolveSrv;
|
||||
resolveSrv: typeof resolveSrv;
|
||||
// resolveTxt: typeof resolveTxt;
|
||||
// reverse: typeof reverse;
|
||||
// setLocalAddress(ipv4?: string, ipv6?: string): void;
|
||||
|
||||
@@ -614,6 +614,111 @@ pub const GetAddrInfo = struct {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
pub const ResolveSrvInfoRequest = struct {
|
||||
const log = Output.scoped(.ResolveSrvInfoRequest, false);
|
||||
|
||||
resolver_for_caching: ?*DNSResolver = null,
|
||||
hash: u64 = 0,
|
||||
cache: ResolveSrvInfoRequest.CacheConfig = ResolveSrvInfoRequest.CacheConfig{},
|
||||
head: SrvLookup,
|
||||
tail: *SrvLookup = undefined,
|
||||
task: bun.ThreadPool.Task = undefined,
|
||||
|
||||
pub fn init(
|
||||
cache: DNSResolver.SrvCacheHit,
|
||||
resolver: ?*DNSResolver,
|
||||
name: [] const u8,
|
||||
globalThis: *JSC.JSGlobalObject,
|
||||
comptime cache_field: []const u8,
|
||||
) !*ResolveSrvInfoRequest {
|
||||
|
||||
var request = try globalThis.allocator().create(ResolveSrvInfoRequest);
|
||||
var hasher = std.hash.Wyhash.init(0);
|
||||
hasher.update(name);
|
||||
const hash = hasher.final();
|
||||
var poll_ref = JSC.PollRef.init();
|
||||
poll_ref.ref(globalThis.bunVM());
|
||||
request.* = .{
|
||||
.resolver_for_caching = resolver,
|
||||
.hash = hash,
|
||||
.head = .{
|
||||
.poll_ref = poll_ref,
|
||||
.globalThis = globalThis,
|
||||
.promise = JSC.JSPromise.Strong.init(globalThis),
|
||||
.allocated = false,
|
||||
},
|
||||
};
|
||||
request.tail = &request.head;
|
||||
if (cache == .new) {
|
||||
request.resolver_for_caching = resolver;
|
||||
request.cache = ResolveSrvInfoRequest.CacheConfig{
|
||||
.pending_cache = true,
|
||||
.entry_cache = false,
|
||||
.pos_in_pending = @truncate(u5, @field(resolver.?, cache_field).indexOf(cache.new).?),
|
||||
.name_len = @truncate(u9, name.len),
|
||||
};
|
||||
cache.new.lookup = request;
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
pub const Task = bun.JSC.WorkTask(ResolveSrvInfoRequest, false);
|
||||
|
||||
pub const CacheConfig = packed struct(u16) {
|
||||
pending_cache: bool = false,
|
||||
entry_cache: bool = false,
|
||||
pos_in_pending: u5 = 0,
|
||||
name_len: u9 = 0,
|
||||
};
|
||||
|
||||
pub const PendingCacheKey = struct {
|
||||
hash: u64,
|
||||
len: u16,
|
||||
lookup: *ResolveSrvInfoRequest = undefined,
|
||||
|
||||
pub fn append(this: *PendingCacheKey, srv_lookup: *SrvLookup) void {
|
||||
var tail = this.lookup.tail;
|
||||
tail.next = srv_lookup;
|
||||
this.lookup.tail = srv_lookup;
|
||||
}
|
||||
|
||||
pub fn init(name: []const u8) PendingCacheKey {
|
||||
var hasher = std.hash.Wyhash.init(0);
|
||||
hasher.update(name);
|
||||
const hash = hasher.final();
|
||||
return PendingCacheKey{
|
||||
.hash = hash,
|
||||
.len = @truncate(u16, name.len),
|
||||
.lookup = undefined,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn onCaresComplete(this: *ResolveSrvInfoRequest, err_: ?c_ares.Error, timeout: i32, result: ?*c_ares.struct_ares_srv_reply) void {
|
||||
if (this.resolver_for_caching) |resolver| {
|
||||
|
||||
if (this.cache.pending_cache) {
|
||||
resolver.drainPendingSrvCares(
|
||||
this.cache.pos_in_pending,
|
||||
err_,
|
||||
timeout,
|
||||
result,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var head = this.head;
|
||||
bun.default_allocator.destroy(this);
|
||||
|
||||
head.processResolveSrv(err_, timeout, result);
|
||||
}
|
||||
};
|
||||
|
||||
pub const GetAddrInfoRequest = struct {
|
||||
const log = Output.scoped(.GetAddrInfoRequest, false);
|
||||
|
||||
@@ -634,12 +739,15 @@ pub const GetAddrInfoRequest = struct {
|
||||
comptime cache_field: []const u8,
|
||||
) !*GetAddrInfoRequest {
|
||||
var request = try globalThis.allocator().create(GetAddrInfoRequest);
|
||||
var poll_ref = JSC.PollRef.init();
|
||||
poll_ref.ref(globalThis.bunVM());
|
||||
request.* = .{
|
||||
.backend = backend,
|
||||
.resolver_for_caching = resolver,
|
||||
.hash = query.hash(),
|
||||
.head = .{
|
||||
.globalThis = globalThis,
|
||||
.poll_ref = poll_ref,
|
||||
.promise = JSC.JSPromise.Strong.init(globalThis),
|
||||
.allocated = false,
|
||||
},
|
||||
@@ -832,6 +940,82 @@ pub const GetAddrInfoRequest = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const SrvLookup = struct {
|
||||
const log = Output.scoped(.SrvLookup, true);
|
||||
|
||||
globalThis: *JSC.JSGlobalObject = undefined,
|
||||
promise: JSC.JSPromise.Strong,
|
||||
poll_ref: JSC.PollRef,
|
||||
allocated: bool = false,
|
||||
next: ?*SrvLookup = null,
|
||||
|
||||
pub fn init(globalThis: *JSC.JSGlobalObject, allocator: std.mem.Allocator) !*SrvLookup {
|
||||
var this = try allocator.create(SrvLookup);
|
||||
var poll_ref = JSC.PollRef.init();
|
||||
poll_ref.ref(globalThis.bunVM());
|
||||
this.* = .{
|
||||
.globalThis = globalThis,
|
||||
.promise = JSC.JSPromise.Strong.init(globalThis),
|
||||
.poll_ref = poll_ref,
|
||||
.allocated = true,
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
pub fn processResolveSrv(this: *SrvLookup, err_: ?c_ares.Error, _: i32, result: ?*c_ares.struct_ares_srv_reply) void {
|
||||
if (err_) |err| {
|
||||
var promise = this.promise;
|
||||
var globalThis = this.globalThis;
|
||||
const error_value = globalThis.createErrorInstance("SRV lookup failed: {s}", .{err.label()});
|
||||
error_value.put(
|
||||
globalThis,
|
||||
JSC.ZigString.static("code"),
|
||||
JSC.ZigString.init(err.code()).toValueGC(globalThis),
|
||||
);
|
||||
|
||||
promise.reject(globalThis, error_value);
|
||||
this.deinit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == null or result.?.next == null) {
|
||||
var promise = this.promise;
|
||||
var globalThis = this.globalThis;
|
||||
const error_value = globalThis.createErrorInstance("SRV lookup failed: {s}", .{"No results"});
|
||||
error_value.put(
|
||||
globalThis,
|
||||
JSC.ZigString.static("code"),
|
||||
JSC.ZigString.init("EUNREACHABLE").toValueGC(globalThis),
|
||||
);
|
||||
|
||||
promise.reject(globalThis, error_value);
|
||||
this.deinit();
|
||||
return;
|
||||
}
|
||||
var node = result.?;
|
||||
const array = node.toJSArray(this.globalThis.allocator(), this.globalThis);
|
||||
this.onComplete(array);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn onComplete(this: *SrvLookup, result: JSC.JSValue) void {
|
||||
var promise = this.promise;
|
||||
var globalThis = this.globalThis;
|
||||
this.promise = .{};
|
||||
|
||||
promise.resolve(globalThis, result);
|
||||
this.deinit();
|
||||
}
|
||||
|
||||
pub fn deinit(this: *SrvLookup) void {
|
||||
this.poll_ref.unrefOnNextTick(this.globalThis.bunVM());
|
||||
|
||||
if (this.allocated)
|
||||
this.globalThis.allocator().destroy(this);
|
||||
}
|
||||
};
|
||||
pub const DNSLookup = struct {
|
||||
const log = Output.scoped(.DNSLookup, true);
|
||||
|
||||
@@ -839,11 +1023,16 @@ pub const DNSLookup = struct {
|
||||
promise: JSC.JSPromise.Strong,
|
||||
allocated: bool = false,
|
||||
next: ?*DNSLookup = null,
|
||||
poll_ref: JSC.PollRef,
|
||||
|
||||
pub fn init(globalThis: *JSC.JSGlobalObject, allocator: std.mem.Allocator) !*DNSLookup {
|
||||
var this = try allocator.create(DNSLookup);
|
||||
var poll_ref = JSC.PollRef.init();
|
||||
poll_ref.ref(globalThis.bunVM());
|
||||
|
||||
this.* = .{
|
||||
.globalThis = globalThis,
|
||||
.poll_ref = poll_ref,
|
||||
.promise = JSC.JSPromise.Strong.init(globalThis),
|
||||
.allocated = true,
|
||||
};
|
||||
@@ -893,9 +1082,8 @@ pub const DNSLookup = struct {
|
||||
JSC.ZigString.init(err.code()).toValueGC(globalThis),
|
||||
);
|
||||
|
||||
this.deinit();
|
||||
|
||||
promise.reject(globalThis, error_value);
|
||||
this.deinit();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -909,8 +1097,8 @@ pub const DNSLookup = struct {
|
||||
JSC.ZigString.init("EUNREACHABLE").toValueGC(globalThis),
|
||||
);
|
||||
|
||||
this.deinit();
|
||||
promise.reject(globalThis, error_value);
|
||||
this.deinit();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -927,11 +1115,12 @@ pub const DNSLookup = struct {
|
||||
var globalThis = this.globalThis;
|
||||
this.promise = .{};
|
||||
|
||||
promise.resolve(globalThis, result);
|
||||
this.deinit();
|
||||
promise.resolveOnNextTick(globalThis, result);
|
||||
}
|
||||
|
||||
pub fn deinit(this: *DNSLookup) void {
|
||||
this.poll_ref.unrefOnNextTick(this.globalThis.bunVM());
|
||||
if (this.allocated)
|
||||
this.globalThis.allocator().destroy(this);
|
||||
}
|
||||
@@ -961,10 +1150,12 @@ pub const DNSResolver = struct {
|
||||
polls: std.AutoArrayHashMap(i32, ?*JSC.FilePoll) = undefined,
|
||||
|
||||
pending_host_cache_cares: PendingCache = PendingCache.init(),
|
||||
pending_srv_cache_cares: SrvPendingCache = SrvPendingCache.init(),
|
||||
pending_host_cache_native: PendingCache = PendingCache.init(),
|
||||
// entry_host_cache: std.BoundedArray(128)
|
||||
|
||||
const PendingCache = bun.HiveArray(GetAddrInfoRequest.PendingCacheKey, 32);
|
||||
const SrvPendingCache = bun.HiveArray(ResolveSrvInfoRequest.PendingCacheKey, 32);
|
||||
|
||||
fn getKey(this: *DNSResolver, index: u8, comptime cache_name: []const u8) GetAddrInfoRequest.PendingCacheKey {
|
||||
var cache: *PendingCache = &@field(this, cache_name);
|
||||
@@ -978,6 +1169,60 @@ pub const DNSResolver = struct {
|
||||
|
||||
return entry;
|
||||
}
|
||||
fn getSrvKey(this: *DNSResolver, index: u8, comptime cache_name: []const u8) ResolveSrvInfoRequest.PendingCacheKey {
|
||||
var cache: *SrvPendingCache = &@field(this, cache_name);
|
||||
std.debug.assert(!cache.available.isSet(index));
|
||||
const entry = cache.buffer[index];
|
||||
cache.buffer[index] = undefined;
|
||||
|
||||
var available = cache.available;
|
||||
available.set(index);
|
||||
cache.available = available;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
pub fn drainPendingSrvCares(this: *DNSResolver, index: u8, err: ?c_ares.Error, timeout: i32, result: ?*c_ares.struct_ares_srv_reply) void {
|
||||
const key = this.getSrvKey(index, "pending_srv_cache_cares");
|
||||
|
||||
var addr = result orelse {
|
||||
var pending: ?*SrvLookup = key.lookup.head.next;
|
||||
key.lookup.head.processResolveSrv(err, timeout, null);
|
||||
bun.default_allocator.destroy(key.lookup);
|
||||
|
||||
while (pending) |value| {
|
||||
pending = value.next;
|
||||
value.processResolveSrv(err, timeout, null);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
var pending: ?*SrvLookup = key.lookup.head.next;
|
||||
var prev_global = key.lookup.head.globalThis;
|
||||
var array = addr.toJSArray(this.vm.allocator, prev_global);
|
||||
defer addr.deinit();
|
||||
array.ensureStillAlive();
|
||||
key.lookup.head.onComplete(array);
|
||||
bun.default_allocator.destroy(key.lookup);
|
||||
|
||||
array.ensureStillAlive();
|
||||
|
||||
|
||||
while (pending) |value| {
|
||||
var new_global = value.globalThis;
|
||||
if (prev_global != new_global) {
|
||||
array = addr.toJSArray(this.vm.allocator, new_global);
|
||||
prev_global = new_global;
|
||||
}
|
||||
pending = value.next;
|
||||
|
||||
{
|
||||
array.ensureStillAlive();
|
||||
value.onComplete(array);
|
||||
array.ensureStillAlive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drainPendingHostCares(this: *DNSResolver, index: u8, err: ?c_ares.Error, timeout: i32, result: ?*c_ares.AddrInfo) void {
|
||||
const key = this.getKey(index, "pending_host_cache_cares");
|
||||
@@ -1070,6 +1315,39 @@ pub const DNSResolver = struct {
|
||||
new: *GetAddrInfoRequest.PendingCacheKey,
|
||||
disabled: void,
|
||||
};
|
||||
pub const SrvCacheHit = union(enum) {
|
||||
inflight: *ResolveSrvInfoRequest.PendingCacheKey,
|
||||
new: *ResolveSrvInfoRequest.PendingCacheKey,
|
||||
disabled: void,
|
||||
};
|
||||
|
||||
pub fn getOrPutIntoSrvPendingCache(
|
||||
this: *DNSResolver,
|
||||
key: ResolveSrvInfoRequest.PendingCacheKey,
|
||||
comptime field: std.meta.FieldEnum(DNSResolver),
|
||||
) SrvCacheHit {
|
||||
var cache: *SrvPendingCache = &@field(this, @tagName(field));
|
||||
var inflight_iter = cache.available.iterator(
|
||||
.{
|
||||
.kind = .unset,
|
||||
},
|
||||
);
|
||||
|
||||
while (inflight_iter.next()) |index| {
|
||||
var entry: *ResolveSrvInfoRequest.PendingCacheKey = &cache.buffer[index];
|
||||
if (entry.hash == key.hash and entry.len == key.len) {
|
||||
return .{ .inflight = entry };
|
||||
}
|
||||
}
|
||||
|
||||
if (cache.get()) |new| {
|
||||
new.hash = key.hash;
|
||||
new.len = key.len;
|
||||
return .{ .new = new };
|
||||
}
|
||||
|
||||
return .{ .disabled = {} };
|
||||
}
|
||||
|
||||
pub fn getOrPutIntoPendingCache(
|
||||
this: *DNSResolver,
|
||||
@@ -1330,6 +1608,80 @@ pub const DNSResolver = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn resolveSrv(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
||||
const arguments = callframe.arguments(2);
|
||||
if (arguments.len < 1) {
|
||||
globalThis.throwNotEnoughArguments("resolveSrv", 2, arguments.len);
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const name_value = arguments.ptr[0];
|
||||
|
||||
if (name_value.isEmptyOrUndefinedOrNull() or !name_value.isString()) {
|
||||
globalThis.throwInvalidArgumentType("resolveSrv", "hostname", "string");
|
||||
return .zero;
|
||||
}
|
||||
|
||||
const name_str = name_value.toStringOrNull(globalThis) orelse {
|
||||
return .zero;
|
||||
};
|
||||
|
||||
if (name_str.length() == 0) {
|
||||
globalThis.throwInvalidArgumentType("resolveSrv", "hostname", "non-empty string");
|
||||
return .zero;
|
||||
}
|
||||
|
||||
|
||||
const name = name_str.toSlice(globalThis, bun.default_allocator);
|
||||
defer name.deinit();
|
||||
var vm = globalThis.bunVM();
|
||||
var resolver = vm.rareData().globalDNSResolver(vm);
|
||||
|
||||
return resolver.doResolveSrv(name.slice(), globalThis);
|
||||
}
|
||||
|
||||
pub fn doResolveSrv(this: *DNSResolver, name: []const u8, globalThis: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
var channel: *c_ares.Channel = switch (this.getChannel()) {
|
||||
.result => |res| res,
|
||||
.err => |err| {
|
||||
const system_error = JSC.SystemError{
|
||||
.errno = -1,
|
||||
.code = JSC.ZigString.init(err.code()),
|
||||
.message = JSC.ZigString.init(err.label()),
|
||||
};
|
||||
|
||||
globalThis.throwValue(system_error.toErrorInstance(globalThis));
|
||||
return .zero;
|
||||
},
|
||||
};
|
||||
|
||||
const key = ResolveSrvInfoRequest.PendingCacheKey.init(name);
|
||||
|
||||
var cache = this.getOrPutIntoSrvPendingCache(key, .pending_srv_cache_cares);
|
||||
if (cache == .inflight) {
|
||||
var srv_lookup = SrvLookup.init(globalThis, globalThis.allocator()) catch unreachable;
|
||||
cache.inflight.append(srv_lookup);
|
||||
return srv_lookup.promise.value();
|
||||
}
|
||||
|
||||
var request = ResolveSrvInfoRequest.init(
|
||||
cache,
|
||||
this,
|
||||
name,
|
||||
globalThis,
|
||||
"pending_srv_cache_cares",
|
||||
) catch unreachable;
|
||||
const promise = request.tail.promise.value();
|
||||
|
||||
channel.resolveSrv(
|
||||
name,
|
||||
ResolveSrvInfoRequest,
|
||||
request,
|
||||
ResolveSrvInfoRequest.onCaresComplete,
|
||||
);
|
||||
|
||||
return promise;
|
||||
}
|
||||
pub fn c_aresLookupWithNormalizedName(this: *DNSResolver, query: GetAddrInfo, globalThis: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
var channel: *c_ares.Channel = switch (this.getChannel()) {
|
||||
.result => |res| res,
|
||||
@@ -1386,6 +1738,12 @@ pub const DNSResolver = struct {
|
||||
.name = "Bun__DNSResolver__lookup",
|
||||
},
|
||||
);
|
||||
@export(
|
||||
resolveSrv,
|
||||
.{
|
||||
.name = "Bun__DNSResolver__resolveSrv",
|
||||
},
|
||||
);
|
||||
}
|
||||
// pub fn lookupService(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
||||
// const arguments = callframe.arguments(3);
|
||||
|
||||
@@ -3225,19 +3225,22 @@ pub const PollRef = struct {
|
||||
if (this.status != .active)
|
||||
return;
|
||||
this.status = .inactive;
|
||||
log("unref", .{});
|
||||
vm.uws_event_loop.?.num_polls -= 1;
|
||||
vm.uws_event_loop.?.active -= 1;
|
||||
vm.uws_event_loop.?.unref();
|
||||
}
|
||||
/// Prevent a poll from keeping the process alive on the next tick.
|
||||
pub fn unrefOnNextTick(this: *PollRef, vm: *JSC.VirtualMachine) void {
|
||||
if (this.status != .active)
|
||||
return;
|
||||
this.status = .inactive;
|
||||
vm.uws_event_loop.?.nextTick(*uws.Loop, vm.uws_event_loop.?, uws.Loop.unref);
|
||||
}
|
||||
|
||||
/// Allow a poll to keep the process alive.
|
||||
pub fn ref(this: *PollRef, vm: *JSC.VirtualMachine) void {
|
||||
if (this.status != .inactive)
|
||||
return;
|
||||
log("ref", .{});
|
||||
this.status = .active;
|
||||
vm.uws_event_loop.?.num_polls += 1;
|
||||
vm.uws_event_loop.?.active += 1;
|
||||
vm.uws_event_loop.?.ref();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2169,6 +2169,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotask, (JSGlobalObject * globalObj
|
||||
}
|
||||
|
||||
extern "C" EncodedJSValue Bun__DNSResolver__lookup(JSGlobalObject*, JSC::CallFrame*);
|
||||
extern "C" EncodedJSValue Bun__DNSResolver__resolveSrv(JSGlobalObject*, JSC::CallFrame*);
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotaskVariadic, (JSGlobalObject * globalObject, CallFrame* callframe))
|
||||
{
|
||||
@@ -3321,9 +3322,11 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm
|
||||
JSC::JSObject* dnsObject = JSC::constructEmptyObject(this);
|
||||
dnsObject->putDirectNativeFunction(vm, this, JSC::Identifier::fromString(vm, "lookup"_s), 2, Bun__DNSResolver__lookup, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
dnsObject->putDirectNativeFunction(vm, this, JSC::Identifier::fromString(vm, "resolveSrv"_s), 2, Bun__DNSResolver__resolveSrv, ImplementationVisibility::Public, NoIntrinsic,
|
||||
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
|
||||
object->putDirect(vm, PropertyName(identifier), dnsObject, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
JSC::Identifier identifier = JSC::Identifier::fromString(vm, "plugin"_s);
|
||||
JSFunction* pluginFunction = JSFunction::create(vm, this, 1, String("plugin"_s), jsFunctionBunPlugin, ImplementationVisibility::Public, NoIntrinsic);
|
||||
|
||||
@@ -2860,7 +2860,7 @@ pub const JSValue = enum(JSValueReprInt) {
|
||||
return switch (comptime Number) {
|
||||
JSValue => number,
|
||||
f32, f64 => jsNumberFromDouble(@as(f64, number)),
|
||||
u8, i16, i32, c_int, i8, u16 => jsNumberFromInt32(@intCast(i32, number)),
|
||||
c_ushort, u8, i16, i32, c_int, i8, u16 => jsNumberFromInt32(@intCast(i32, number)),
|
||||
u32, u52, c_uint, i64 => jsNumberFromInt64(@intCast(i64, number)),
|
||||
usize, u64 => jsNumberFromUint64(@intCast(u64, number)),
|
||||
comptime_int => switch (number) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// only resolve4, resolve, lookup, and resolve6 are implemented.
|
||||
// only resolve4, resolve, lookup, resolve6 and resolveSrv are implemented.
|
||||
|
||||
const { dns } = globalThis.Bun;
|
||||
|
||||
@@ -25,6 +25,22 @@ function lookup(domain, options, callback) {
|
||||
);
|
||||
}
|
||||
|
||||
function resolveSrv(hostname, callback) {
|
||||
|
||||
if (typeof callback != "function") {
|
||||
throw new TypeError("callback must be a function");
|
||||
}
|
||||
|
||||
dns.resolveSrv(hostname, callback).then(
|
||||
(results) => {
|
||||
callback(null, results);
|
||||
},
|
||||
(error) => {
|
||||
callback(error);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function lookupService(address, port, callback) {
|
||||
if (typeof callback != "function") {
|
||||
throw new TypeError("callback must be a function");
|
||||
@@ -138,7 +154,18 @@ var InternalResolver = class Resolver {
|
||||
}
|
||||
|
||||
resolveSrv(hostname, callback) {
|
||||
callback(null, []);
|
||||
if (typeof callback != "function") {
|
||||
throw new TypeError("callback must be a function");
|
||||
}
|
||||
|
||||
dns.resolveSrv(hostname, callback).then(
|
||||
(results) => {
|
||||
callback(null, results);
|
||||
},
|
||||
(error) => {
|
||||
callback(error);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
resolveCaa(hostname, callback) {
|
||||
@@ -209,6 +236,10 @@ export const promises = {
|
||||
return dns.lookup(hostname, { family: 6 });
|
||||
},
|
||||
|
||||
resolveSrv(hostname) {
|
||||
return dns.resolveSrv(hostname);
|
||||
},
|
||||
|
||||
Resolver: class Resolver {
|
||||
constructor(options) {}
|
||||
|
||||
@@ -259,7 +290,7 @@ export const promises = {
|
||||
}
|
||||
|
||||
resolveSrv(hostname) {
|
||||
return Promise.resolve([]);
|
||||
return dns.resolveSrv(hostname);
|
||||
}
|
||||
|
||||
resolveCaa(hostname) {
|
||||
@@ -286,7 +317,6 @@ for (const key of [
|
||||
"resolveNs",
|
||||
"resolvePtr",
|
||||
"resolveSoa",
|
||||
"resolveSrv",
|
||||
"resolveTxt",
|
||||
"reverse",
|
||||
]) {
|
||||
|
||||
@@ -11,6 +11,145 @@ pub const ares_socket_t = c_int;
|
||||
pub const ares_sock_state_cb = ?*const fn (?*anyopaque, ares_socket_t, c_int, c_int) callconv(.C) void;
|
||||
pub const struct_apattern = opaque {};
|
||||
const fd_set = c.fd_set;
|
||||
|
||||
pub const NSClass = enum(c_int) {
|
||||
/// Cookie.
|
||||
ns_c_invalid = 0,
|
||||
/// Internet.
|
||||
ns_c_in = 1,
|
||||
/// unallocated/unsupported.
|
||||
ns_c_2 = 2,
|
||||
/// MIT Chaos-net.
|
||||
ns_c_chaos = 3,
|
||||
/// MIT Hesiod.
|
||||
ns_c_hs = 4,
|
||||
/// Query class values which do not appear in resource records
|
||||
/// for prereq. sections in update requests
|
||||
ns_c_none = 254,
|
||||
/// Wildcard match.
|
||||
ns_c_any = 255,
|
||||
ns_c_max = 65536,
|
||||
};
|
||||
|
||||
pub const NSType = enum(c_int) {
|
||||
/// Cookie.
|
||||
ns_t_invalid = 0,
|
||||
/// Host address.
|
||||
ns_t_a = 1,
|
||||
/// Authoritative server.
|
||||
ns_t_ns = 2,
|
||||
/// Mail destination.
|
||||
ns_t_md = 3,
|
||||
/// Mail forwarder.
|
||||
ns_t_mf = 4,
|
||||
/// Canonical name.
|
||||
ns_t_cname = 5,
|
||||
/// Start of authority zone.
|
||||
ns_t_soa = 6,
|
||||
/// Mailbox domain name.
|
||||
ns_t_mb = 7,
|
||||
/// Mail group member.
|
||||
ns_t_mg = 8,
|
||||
/// Mail rename name.
|
||||
ns_t_mr = 9,
|
||||
/// Null resource record.
|
||||
ns_t_null = 10,
|
||||
/// Well known service.
|
||||
ns_t_wks = 11,
|
||||
/// Domain name pointer.
|
||||
ns_t_ptr = 12,
|
||||
/// Host information.
|
||||
ns_t_hinfo = 13,
|
||||
/// Mailbox information.
|
||||
ns_t_minfo = 14,
|
||||
/// Mail routing information.
|
||||
ns_t_mx = 15,
|
||||
/// Text strings.
|
||||
ns_t_txt = 16,
|
||||
/// Responsible person.
|
||||
ns_t_rp = 17,
|
||||
/// AFS cell database.
|
||||
ns_t_afsdb = 18,
|
||||
/// X_25 calling address.
|
||||
ns_t_x25 = 19,
|
||||
/// ISDN calling address.
|
||||
ns_t_isdn = 20,
|
||||
/// Router.
|
||||
ns_t_rt = 21,
|
||||
/// NSAP address.
|
||||
ns_t_nsap = 22,
|
||||
/// Reverse NSAP lookup (deprecated).
|
||||
ns_t_nsap_ptr = 23,
|
||||
/// Security signature.
|
||||
ns_t_sig = 24,
|
||||
/// Security key.
|
||||
ns_t_key = 25,
|
||||
/// X.400 mail mapping.
|
||||
ns_t_px = 26,
|
||||
/// Geographical position (withdrawn).
|
||||
ns_t_gpos = 27,
|
||||
/// Ip6 Address.
|
||||
ns_t_aaaa = 28,
|
||||
/// Location Information.
|
||||
ns_t_loc = 29,
|
||||
/// Next domain (security).
|
||||
ns_t_nxt = 30,
|
||||
/// Endpoint identifier.
|
||||
ns_t_eid = 31,
|
||||
/// Nimrod Locator.
|
||||
ns_t_nimloc = 32,
|
||||
/// Server Selection.
|
||||
ns_t_srv = 33,
|
||||
/// ATM Address
|
||||
ns_t_atma = 34,
|
||||
/// Naming Authority PoinTeR
|
||||
ns_t_naptr = 35,
|
||||
/// Key Exchange
|
||||
ns_t_kx = 36,
|
||||
/// Certification record
|
||||
ns_t_cert = 37,
|
||||
/// IPv6 address (deprecates AAAA)
|
||||
ns_t_a6 = 38,
|
||||
/// Non-terminal DNAME (for IPv6)
|
||||
ns_t_dname = 39,
|
||||
/// Kitchen sink (experimentatl)
|
||||
ns_t_sink = 40,
|
||||
/// EDNS0 option (meta-RR)
|
||||
ns_t_opt = 41,
|
||||
/// Address prefix list (RFC3123)
|
||||
ns_t_apl = 42,
|
||||
/// Delegation Signer (RFC4034)
|
||||
ns_t_ds = 43,
|
||||
/// SSH Key Fingerprint (RFC4255)
|
||||
ns_t_sshfp = 44,
|
||||
/// Resource Record Signature (RFC4034)
|
||||
ns_t_rrsig = 46,
|
||||
/// Next Secure (RFC4034)
|
||||
ns_t_nsec = 47,
|
||||
/// DNS Public Key (RFC4034)
|
||||
ns_t_dnskey = 48,
|
||||
/// Transaction key
|
||||
ns_t_tkey = 249,
|
||||
/// Transaction signature.
|
||||
ns_t_tsig = 250,
|
||||
/// Incremental zone transfer.
|
||||
ns_t_ixfr = 251,
|
||||
/// Transfer zone of authority.
|
||||
ns_t_axfr = 252,
|
||||
/// Transfer mailbox records.
|
||||
ns_t_mailb = 253,
|
||||
/// Transfer mail agent records.
|
||||
ns_t_maila = 254,
|
||||
/// Wildcard match.
|
||||
ns_t_any = 255,
|
||||
/// Uniform Resource Identifier (RFC7553)
|
||||
ns_t_uri = 256,
|
||||
/// Certification Authority Authorization.
|
||||
ns_t_caa = 257,
|
||||
ns_t_max = 65536,
|
||||
_,
|
||||
};
|
||||
|
||||
pub const Options = extern struct {
|
||||
flags: c_int = 0,
|
||||
timeout: c_int = 0,
|
||||
@@ -152,6 +291,7 @@ pub const AddrInfo_hints = extern struct {
|
||||
return this.ai_flags == 0 and this.ai_family == 0 and this.ai_socktype == 0 and this.ai_protocol == 0;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Channel = opaque {
|
||||
pub fn init(comptime Container: type, this: *Container) ?Error {
|
||||
var channel: *Channel = undefined;
|
||||
@@ -273,6 +413,21 @@ pub const Channel = opaque {
|
||||
ares_getaddrinfo(this, host_ptr, port_ptr, hints_, AddrInfo.callbackWrapper(Type, callback), ctx);
|
||||
}
|
||||
|
||||
pub fn resolveSrv(this: *Channel, name: []const u8, comptime Type: type, ctx: *Type, comptime callback: struct_ares_srv_reply.Callback(Type)) void {
|
||||
var name_buf: [1024]u8 = undefined;
|
||||
const name_ptr: ?[*:0]const u8 = brk: {
|
||||
if (name.len == 0 or name.len >= 1023) {
|
||||
break :brk null;
|
||||
}
|
||||
const len = @min(name_buf.len, name_buf.len - 1);
|
||||
@memcpy(&name_buf, name.ptr, len);
|
||||
name_buf[len] = 0;
|
||||
break :brk name_buf[0..len :0];
|
||||
};
|
||||
|
||||
ares_query(this, name_ptr, NSClass.ns_c_in, NSType.ns_t_srv, struct_ares_srv_reply.callbackWrapper(Type, callback), ctx);
|
||||
}
|
||||
|
||||
pub inline fn process(this: *Channel, fd: i32, readable: bool, writable: bool) void {
|
||||
ares_process_fd(
|
||||
this,
|
||||
@@ -334,7 +489,7 @@ pub const ares_socket_functions = extern struct {
|
||||
};
|
||||
pub extern fn ares_set_socket_functions(channel: *Channel, funcs: ?*const ares_socket_functions, user_data: ?*anyopaque) void;
|
||||
pub extern fn ares_send(channel: *Channel, qbuf: [*c]const u8, qlen: c_int, callback: ares_callback, arg: ?*anyopaque) void;
|
||||
pub extern fn ares_query(channel: *Channel, name: [*c]const u8, dnsclass: c_int, @"type": c_int, callback: ares_callback, arg: ?*anyopaque) void;
|
||||
pub extern fn ares_query(channel: *Channel, name: [*c]const u8, dnsclass: NSClass, @"type": NSType, callback: ares_callback, arg: ?*anyopaque) void;
|
||||
pub extern fn ares_search(channel: *Channel, name: [*c]const u8, dnsclass: c_int, @"type": c_int, callback: ares_callback, arg: ?*anyopaque) void;
|
||||
pub extern fn ares_gethostbyname(channel: *Channel, name: [*c]const u8, family: c_int, callback: ares_host_callback, arg: ?*anyopaque) void;
|
||||
pub extern fn ares_gethostbyname_file(channel: *Channel, name: [*c]const u8, family: c_int, host: [*:null]?*struct_hostent) c_int;
|
||||
@@ -372,11 +527,90 @@ pub const struct_ares_caa_reply = extern struct {
|
||||
length: usize,
|
||||
};
|
||||
pub const struct_ares_srv_reply = extern struct {
|
||||
next: [*c]struct_ares_srv_reply,
|
||||
next: ?*struct_ares_srv_reply,
|
||||
host: [*c]u8,
|
||||
priority: c_ushort,
|
||||
weight: c_ushort,
|
||||
port: c_ushort,
|
||||
const JSC = bun.JSC;
|
||||
|
||||
pub fn toJSArray(this: *struct_ares_srv_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject) JSC.JSValue {
|
||||
var stack = std.heap.stackFallback(2048, parent_allocator);
|
||||
var arena = std.heap.ArenaAllocator.init(stack.get());
|
||||
defer arena.deinit();
|
||||
|
||||
var allocator = arena.allocator();
|
||||
var count: usize = 0;
|
||||
var srv: ?*struct_ares_srv_reply = this;
|
||||
while (srv != null) : (srv = srv.?.next) {
|
||||
count += 1;
|
||||
}
|
||||
|
||||
const array = JSC.JSValue.createEmptyArray(globalThis, count);
|
||||
|
||||
srv = this;
|
||||
var i: u32 = 0;
|
||||
while (srv != null) {
|
||||
var node = srv.?;
|
||||
array.putIndex(globalThis, i, node.toJS(globalThis, allocator));
|
||||
srv = node.next;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
pub fn toJS(this: *struct_ares_srv_reply, globalThis: *JSC.JSGlobalObject, _: std.mem.Allocator) JSC.JSValue {
|
||||
var obj = JSC.JSValue.createEmptyObject(globalThis, 4);
|
||||
// {
|
||||
// priority: 10,
|
||||
// weight: 5,
|
||||
// port: 21223,
|
||||
// name: 'service.example.com'
|
||||
// }
|
||||
|
||||
obj.put(globalThis, JSC.ZigString.static("priority"), JSC.JSValue.jsNumber(this.weight));
|
||||
obj.put(globalThis, JSC.ZigString.static("weight"), JSC.JSValue.jsNumber(this.weight));
|
||||
obj.put(globalThis, JSC.ZigString.static("port"), JSC.JSValue.jsNumber(this.port));
|
||||
|
||||
|
||||
const len = bun.len(this.host);
|
||||
var host = this.host[0..len];
|
||||
obj.put(globalThis, JSC.ZigString.static("name"), JSC.ZigString.fromUTF8(host).toValueGC(globalThis));
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
pub fn Callback(comptime Type: type) type {
|
||||
return fn (*Type, status: ?Error, timeouts: i32, results: ?*struct_ares_srv_reply) void;
|
||||
}
|
||||
|
||||
pub fn callbackWrapper(
|
||||
comptime Type: type,
|
||||
comptime function: Callback(Type),
|
||||
) ares_callback {
|
||||
return &struct {
|
||||
pub fn handleSrv(ctx: ?*anyopaque, status: c_int, timeouts: c_int, buffer: [*c]u8, buffer_length: c_int) callconv(.C) void {
|
||||
var this = bun.cast(*Type, ctx.?);
|
||||
if (status != ARES_SUCCESS) {
|
||||
function(this, Error.get(status), timeouts, null);
|
||||
return;
|
||||
}
|
||||
|
||||
var srv_start: [*c]struct_ares_srv_reply = undefined;
|
||||
var result = ares_parse_srv_reply(buffer, buffer_length, &srv_start);
|
||||
if (result != ARES_SUCCESS) {
|
||||
function(this, Error.get(result), timeouts, null);
|
||||
return;
|
||||
}
|
||||
function(this, null, timeouts, srv_start);
|
||||
}
|
||||
}.handleSrv;
|
||||
}
|
||||
|
||||
pub fn deinit(this: *struct_ares_srv_reply) void {
|
||||
ares_free_data(this);
|
||||
}
|
||||
};
|
||||
pub const struct_ares_mx_reply = extern struct {
|
||||
next: [*c]struct_ares_mx_reply,
|
||||
|
||||
@@ -429,6 +429,7 @@ pub const Loop = extern struct {
|
||||
ready_polls: [1024]EventType align(16),
|
||||
|
||||
const EventType = if (Environment.isLinux) std.os.linux.epoll_event else if (Environment.isMac) std.os.system.kevent64_s;
|
||||
const log = bun.Output.scoped(.Loop, false);
|
||||
|
||||
pub const InternalLoopData = extern struct {
|
||||
pub const us_internal_async = opaque {};
|
||||
@@ -452,6 +453,17 @@ pub const Loop = extern struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn ref(this: *Loop) void {
|
||||
log("ref", .{});
|
||||
this.num_polls += 1;
|
||||
this.active += 1;
|
||||
}
|
||||
pub fn unref(this: *Loop) void {
|
||||
log("unref", .{});
|
||||
this.num_polls -= 1;
|
||||
this.active -= 1;
|
||||
}
|
||||
|
||||
pub fn get() ?*Loop {
|
||||
return uws_get_loop();
|
||||
}
|
||||
|
||||
@@ -31,3 +31,24 @@ test("dns.lookup (example.com)", (done) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
//TODO: use a bun.sh SRV for testing
|
||||
test("dns.resolveSrv (_test._tcp.test.socketify.dev)", (done) => {
|
||||
dns.resolveSrv("_test._tcp.test.socketify.dev", (err, results) => {
|
||||
expect(err).toBeNull();
|
||||
expect(results instanceof Array).toBe(true);
|
||||
expect(results[0].name).toBe("_dc-srv.130c90ab9de1._test._tcp.test.socketify.dev");
|
||||
expect(results[0].priority).toBe(50);
|
||||
expect(results[0].weight).toBe(50);
|
||||
expect(results[0].port).toBe(80);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
test("dns.resolveSrv (_test._tcp.invalid.localhost)", (done) => {
|
||||
dns.resolveSrv("_test._tcp.invalid.localhost", (err, results) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(results).toBeUndefined(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -51,4 +51,4 @@ describe("dns.lookup", () => {
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user