mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
Compare commits
7 commits
f5d6e92c4e
...
b9e4c6fe2a
Author | SHA1 | Date | |
---|---|---|---|
|
b9e4c6fe2a | ||
|
0d3d4f5466 | ||
|
5e9b3712de | ||
|
3bc7642dcf | ||
|
e9a1b8e83a | ||
|
f5d1f3f038 | ||
|
406162d7b8 |
15 changed files with 431 additions and 78 deletions
|
@ -115,10 +115,16 @@ exec deno {} "$@"
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_installer_root() -> Result<PathBuf, io::Error> {
|
fn get_installer_root() -> Result<PathBuf, AnyError> {
|
||||||
if let Ok(env_dir) = env::var("DENO_INSTALL_ROOT") {
|
if let Some(env_dir) = env::var_os("DENO_INSTALL_ROOT") {
|
||||||
if !env_dir.is_empty() {
|
if !env_dir.is_empty() {
|
||||||
return canonicalize_path_maybe_not_exists(&PathBuf::from(env_dir));
|
let env_dir = PathBuf::from(env_dir);
|
||||||
|
return canonicalize_path_maybe_not_exists(&env_dir).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"Canonicalizing DENO_INSTALL_ROOT ('{}').",
|
||||||
|
env_dir.display()
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Note: on Windows, the $HOME environment variable may be set by users or by
|
// Note: on Windows, the $HOME environment variable may be set by users or by
|
||||||
|
@ -587,11 +593,22 @@ async fn resolve_shim_data(
|
||||||
let copy_path = get_hidden_file_with_ext(&file_path, "deno.json");
|
let copy_path = get_hidden_file_with_ext(&file_path, "deno.json");
|
||||||
executable_args.push("--config".to_string());
|
executable_args.push("--config".to_string());
|
||||||
executable_args.push(copy_path.to_str().unwrap().to_string());
|
executable_args.push(copy_path.to_str().unwrap().to_string());
|
||||||
extra_files.push((
|
let mut config_text = fs::read_to_string(config_path)
|
||||||
copy_path,
|
.with_context(|| format!("error reading {config_path}"))?;
|
||||||
fs::read_to_string(config_path)
|
// always remove the import map field because when someone specifies `--import-map` we
|
||||||
.with_context(|| format!("error reading {config_path}"))?,
|
// don't want that file to be attempted to be loaded and when they don't specify that
|
||||||
));
|
// (which is just something we haven't implemented yet)
|
||||||
|
if let Some(new_text) = remove_import_map_field_from_text(&config_text) {
|
||||||
|
if flags.import_map_path.is_none() {
|
||||||
|
log::warn!(
|
||||||
|
"{} \"importMap\" field in the specified config file we be ignored. Use the --import-map flag instead.",
|
||||||
|
crate::colors::yellow("Warning"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
config_text = new_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
extra_files.push((copy_path, config_text));
|
||||||
} else {
|
} else {
|
||||||
executable_args.push("--no-config".to_string());
|
executable_args.push("--no-config".to_string());
|
||||||
}
|
}
|
||||||
|
@ -631,6 +648,16 @@ async fn resolve_shim_data(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove_import_map_field_from_text(config_text: &str) -> Option<String> {
|
||||||
|
let value =
|
||||||
|
jsonc_parser::cst::CstRootNode::parse(config_text, &Default::default())
|
||||||
|
.ok()?;
|
||||||
|
let root_value = value.object_value()?;
|
||||||
|
let import_map_value = root_value.get("importMap")?;
|
||||||
|
import_map_value.remove();
|
||||||
|
Some(value.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_hidden_file_with_ext(file_path: &Path, ext: &str) -> PathBuf {
|
fn get_hidden_file_with_ext(file_path: &Path, ext: &str) -> PathBuf {
|
||||||
// use a dot file to prevent the file from showing up in some
|
// use a dot file to prevent the file from showing up in some
|
||||||
// users shell auto-complete since this directory is on the PATH
|
// users shell auto-complete since this directory is on the PATH
|
||||||
|
@ -1585,4 +1612,17 @@ mod tests {
|
||||||
assert!(!file_path.exists());
|
assert!(!file_path.exists());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_remove_import_map_field_from_text() {
|
||||||
|
assert_eq!(
|
||||||
|
remove_import_map_field_from_text(
|
||||||
|
r#"{
|
||||||
|
"importMap": "./value.json"
|
||||||
|
}"#,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
"{}"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
48
cli/tsc/dts/lib.deno.ns.d.ts
vendored
48
cli/tsc/dts/lib.deno.ns.d.ts
vendored
|
@ -4674,6 +4674,22 @@ declare namespace Deno {
|
||||||
* and the promise returned will be rejected with an AbortError.
|
* and the promise returned will be rejected with an AbortError.
|
||||||
*/
|
*/
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
|
/** */
|
||||||
|
ttl?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RecordWithTtl {
|
||||||
|
/** */
|
||||||
|
data:
|
||||||
|
| string
|
||||||
|
| CaaRecord
|
||||||
|
| MxRecord
|
||||||
|
| NaptrRecord
|
||||||
|
| SoaRecord
|
||||||
|
| SrvRecord
|
||||||
|
| string[];
|
||||||
|
/** */
|
||||||
|
ttl: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If {@linkcode Deno.resolveDns} is called with `"CAA"` record type
|
/** If {@linkcode Deno.resolveDns} is called with `"CAA"` record type
|
||||||
|
@ -4748,6 +4764,37 @@ declare namespace Deno {
|
||||||
target: string;
|
target: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs DNS resolution against the given query, returning resolved
|
||||||
|
* records with ttl values.
|
||||||
|
*
|
||||||
|
* Fails in the cases such as:
|
||||||
|
*
|
||||||
|
* - the query is in invalid format.
|
||||||
|
* - the options have an invalid parameter. For example `nameServer.port` is
|
||||||
|
* beyond the range of 16-bit unsigned integer.
|
||||||
|
* - the request timed out.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const a = await Deno.resolveDns("example.com", "A", { ttl: true });
|
||||||
|
*
|
||||||
|
* const aaaa = await Deno.resolveDns("example.com", "AAAA", {
|
||||||
|
* nameServer: { ipAddr: "8.8.8.8", port: 53 },
|
||||||
|
* ttl: true,
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission.
|
||||||
|
*
|
||||||
|
* @tags allow-net
|
||||||
|
* @category Network
|
||||||
|
*/
|
||||||
|
export function resolveDns(
|
||||||
|
query: string,
|
||||||
|
recordType: RecordType,
|
||||||
|
options?: { ttl: true } & ResolveDnsOptions,
|
||||||
|
): Promise<RecordWithTtl[]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs DNS resolution against the given query, returning resolved
|
* Performs DNS resolution against the given query, returning resolved
|
||||||
* records.
|
* records.
|
||||||
|
@ -4994,6 +5041,7 @@ declare namespace Deno {
|
||||||
| SoaRecord[]
|
| SoaRecord[]
|
||||||
| SrvRecord[]
|
| SrvRecord[]
|
||||||
| string[][]
|
| string[][]
|
||||||
|
| RecordWithTtl[]
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
114
ext/net/ops.rs
114
ext/net/ops.rs
|
@ -561,7 +561,7 @@ where
|
||||||
|
|
||||||
#[derive(Serialize, Eq, PartialEq, Debug)]
|
#[derive(Serialize, Eq, PartialEq, Debug)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum DnsReturnRecord {
|
pub enum DnsRecordData {
|
||||||
A(String),
|
A(String),
|
||||||
Aaaa(String),
|
Aaaa(String),
|
||||||
Aname(String),
|
Aname(String),
|
||||||
|
@ -603,6 +603,20 @@ pub enum DnsReturnRecord {
|
||||||
Txt(Vec<String>),
|
Txt(Vec<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Eq, PartialEq, Debug)]
|
||||||
|
#[serde()]
|
||||||
|
pub struct DnsRecordWithTtl {
|
||||||
|
pub data: DnsRecordData,
|
||||||
|
pub ttl: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Eq, PartialEq, Debug)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum DnsReturnRecord {
|
||||||
|
WithoutTtl(DnsRecordData),
|
||||||
|
WithTtl(DnsRecordWithTtl),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ResolveAddrArgs {
|
pub struct ResolveAddrArgs {
|
||||||
|
@ -616,6 +630,7 @@ pub struct ResolveAddrArgs {
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ResolveDnsOption {
|
pub struct ResolveDnsOption {
|
||||||
name_server: Option<NameServer>,
|
name_server: Option<NameServer>,
|
||||||
|
ttl: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_port() -> u16 {
|
fn default_port() -> u16 {
|
||||||
|
@ -662,6 +677,8 @@ where
|
||||||
system_conf::read_system_conf()?
|
system_conf::read_system_conf()?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let ttl = options.as_ref().and_then(|o| o.ttl).unwrap_or(false);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut s = state.borrow_mut();
|
let mut s = state.borrow_mut();
|
||||||
let perm = s.borrow_mut::<NP>();
|
let perm = s.borrow_mut::<NP>();
|
||||||
|
@ -720,8 +737,20 @@ where
|
||||||
}
|
}
|
||||||
_ => NetError::Dns(e),
|
_ => NetError::Dns(e),
|
||||||
})?
|
})?
|
||||||
|
.records()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|rdata| rdata_to_return_record(record_type)(rdata).transpose())
|
.filter_map(|rec| {
|
||||||
|
let data = format_rdata(record_type)(rec.data()).unwrap();
|
||||||
|
if ttl {
|
||||||
|
Some(DnsReturnRecord::WithTtl(DnsRecordWithTtl {
|
||||||
|
data: data?,
|
||||||
|
ttl: rec.ttl(),
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
Some(DnsReturnRecord::WithoutTtl(data?))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(Ok)
|
||||||
.collect::<Result<Vec<DnsReturnRecord>, NetError>>()
|
.collect::<Result<Vec<DnsReturnRecord>, NetError>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,22 +794,22 @@ pub fn op_set_keepalive_inner(
|
||||||
resource.set_keepalive(keepalive).map_err(NetError::Map)
|
resource.set_keepalive(keepalive).map_err(NetError::Map)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rdata_to_return_record(
|
fn format_rdata(
|
||||||
ty: RecordType,
|
ty: RecordType,
|
||||||
) -> impl Fn(&RData) -> Result<Option<DnsReturnRecord>, NetError> {
|
) -> impl Fn(&RData) -> Result<Option<DnsRecordData>, NetError> {
|
||||||
use RecordType::*;
|
use RecordType::*;
|
||||||
move |r: &RData| -> Result<Option<DnsReturnRecord>, NetError> {
|
move |r: &RData| -> Result<Option<DnsRecordData>, NetError> {
|
||||||
let record = match ty {
|
let record = match ty {
|
||||||
A => r.as_a().map(ToString::to_string).map(DnsReturnRecord::A),
|
A => r.as_a().map(ToString::to_string).map(DnsRecordData::A),
|
||||||
AAAA => r
|
AAAA => r
|
||||||
.as_aaaa()
|
.as_aaaa()
|
||||||
.map(ToString::to_string)
|
.map(ToString::to_string)
|
||||||
.map(DnsReturnRecord::Aaaa),
|
.map(DnsRecordData::Aaaa),
|
||||||
ANAME => r
|
ANAME => r
|
||||||
.as_aname()
|
.as_aname()
|
||||||
.map(ToString::to_string)
|
.map(ToString::to_string)
|
||||||
.map(DnsReturnRecord::Aname),
|
.map(DnsRecordData::Aname),
|
||||||
CAA => r.as_caa().map(|caa| DnsReturnRecord::Caa {
|
CAA => r.as_caa().map(|caa| DnsRecordData::Caa {
|
||||||
critical: caa.issuer_critical(),
|
critical: caa.issuer_critical(),
|
||||||
tag: caa.tag().to_string(),
|
tag: caa.tag().to_string(),
|
||||||
value: match caa.value() {
|
value: match caa.value() {
|
||||||
|
@ -807,12 +836,12 @@ fn rdata_to_return_record(
|
||||||
CNAME => r
|
CNAME => r
|
||||||
.as_cname()
|
.as_cname()
|
||||||
.map(ToString::to_string)
|
.map(ToString::to_string)
|
||||||
.map(DnsReturnRecord::Cname),
|
.map(DnsRecordData::Cname),
|
||||||
MX => r.as_mx().map(|mx| DnsReturnRecord::Mx {
|
MX => r.as_mx().map(|mx| DnsRecordData::Mx {
|
||||||
preference: mx.preference(),
|
preference: mx.preference(),
|
||||||
exchange: mx.exchange().to_string(),
|
exchange: mx.exchange().to_string(),
|
||||||
}),
|
}),
|
||||||
NAPTR => r.as_naptr().map(|naptr| DnsReturnRecord::Naptr {
|
NAPTR => r.as_naptr().map(|naptr| DnsRecordData::Naptr {
|
||||||
order: naptr.order(),
|
order: naptr.order(),
|
||||||
preference: naptr.preference(),
|
preference: naptr.preference(),
|
||||||
flags: String::from_utf8(naptr.flags().to_vec()).unwrap(),
|
flags: String::from_utf8(naptr.flags().to_vec()).unwrap(),
|
||||||
|
@ -820,12 +849,9 @@ fn rdata_to_return_record(
|
||||||
regexp: String::from_utf8(naptr.regexp().to_vec()).unwrap(),
|
regexp: String::from_utf8(naptr.regexp().to_vec()).unwrap(),
|
||||||
replacement: naptr.replacement().to_string(),
|
replacement: naptr.replacement().to_string(),
|
||||||
}),
|
}),
|
||||||
NS => r.as_ns().map(ToString::to_string).map(DnsReturnRecord::Ns),
|
NS => r.as_ns().map(ToString::to_string).map(DnsRecordData::Ns),
|
||||||
PTR => r
|
PTR => r.as_ptr().map(ToString::to_string).map(DnsRecordData::Ptr),
|
||||||
.as_ptr()
|
SOA => r.as_soa().map(|soa| DnsRecordData::Soa {
|
||||||
.map(ToString::to_string)
|
|
||||||
.map(DnsReturnRecord::Ptr),
|
|
||||||
SOA => r.as_soa().map(|soa| DnsReturnRecord::Soa {
|
|
||||||
mname: soa.mname().to_string(),
|
mname: soa.mname().to_string(),
|
||||||
rname: soa.rname().to_string(),
|
rname: soa.rname().to_string(),
|
||||||
serial: soa.serial(),
|
serial: soa.serial(),
|
||||||
|
@ -834,7 +860,7 @@ fn rdata_to_return_record(
|
||||||
expire: soa.expire(),
|
expire: soa.expire(),
|
||||||
minimum: soa.minimum(),
|
minimum: soa.minimum(),
|
||||||
}),
|
}),
|
||||||
SRV => r.as_srv().map(|srv| DnsReturnRecord::Srv {
|
SRV => r.as_srv().map(|srv| DnsRecordData::Srv {
|
||||||
priority: srv.priority(),
|
priority: srv.priority(),
|
||||||
weight: srv.weight(),
|
weight: srv.weight(),
|
||||||
port: srv.port(),
|
port: srv.port(),
|
||||||
|
@ -848,7 +874,7 @@ fn rdata_to_return_record(
|
||||||
bytes.iter().map(|&b| b as char).collect::<String>()
|
bytes.iter().map(|&b| b as char).collect::<String>()
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
DnsReturnRecord::Txt(texts)
|
DnsRecordData::Txt(texts)
|
||||||
}),
|
}),
|
||||||
_ => return Err(NetError::UnsupportedRecordType),
|
_ => return Err(NetError::UnsupportedRecordType),
|
||||||
};
|
};
|
||||||
|
@ -891,37 +917,37 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_a() {
|
fn rdata_to_return_record_a() {
|
||||||
let func = rdata_to_return_record(RecordType::A);
|
let func = format_rdata(RecordType::A);
|
||||||
let rdata = RData::A(A(Ipv4Addr::new(127, 0, 0, 1)));
|
let rdata = RData::A(A(Ipv4Addr::new(127, 0, 0, 1)));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::A("127.0.0.1".to_string()))
|
Some(DnsRecordData::A("127.0.0.1".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_aaaa() {
|
fn rdata_to_return_record_aaaa() {
|
||||||
let func = rdata_to_return_record(RecordType::AAAA);
|
let func = format_rdata(RecordType::AAAA);
|
||||||
let rdata = RData::AAAA(AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)));
|
let rdata = RData::AAAA(AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Aaaa("::1".to_string()))
|
Some(DnsRecordData::Aaaa("::1".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_aname() {
|
fn rdata_to_return_record_aname() {
|
||||||
let func = rdata_to_return_record(RecordType::ANAME);
|
let func = format_rdata(RecordType::ANAME);
|
||||||
let rdata = RData::ANAME(ANAME(Name::new()));
|
let rdata = RData::ANAME(ANAME(Name::new()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Aname("".to_string()))
|
Some(DnsRecordData::Aname("".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_caa() {
|
fn rdata_to_return_record_caa() {
|
||||||
let func = rdata_to_return_record(RecordType::CAA);
|
let func = format_rdata(RecordType::CAA);
|
||||||
let rdata = RData::CAA(CAA::new_issue(
|
let rdata = RData::CAA(CAA::new_issue(
|
||||||
false,
|
false,
|
||||||
Some(Name::parse("example.com", None).unwrap()),
|
Some(Name::parse("example.com", None).unwrap()),
|
||||||
|
@ -929,7 +955,7 @@ mod tests {
|
||||||
));
|
));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Caa {
|
Some(DnsRecordData::Caa {
|
||||||
critical: false,
|
critical: false,
|
||||||
tag: "issue".to_string(),
|
tag: "issue".to_string(),
|
||||||
value: "example.com; account=123456".to_string(),
|
value: "example.com; account=123456".to_string(),
|
||||||
|
@ -939,21 +965,21 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_cname() {
|
fn rdata_to_return_record_cname() {
|
||||||
let func = rdata_to_return_record(RecordType::CNAME);
|
let func = format_rdata(RecordType::CNAME);
|
||||||
let rdata = RData::CNAME(CNAME(Name::new()));
|
let rdata = RData::CNAME(CNAME(Name::new()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Cname("".to_string()))
|
Some(DnsRecordData::Cname("".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_mx() {
|
fn rdata_to_return_record_mx() {
|
||||||
let func = rdata_to_return_record(RecordType::MX);
|
let func = format_rdata(RecordType::MX);
|
||||||
let rdata = RData::MX(MX::new(10, Name::new()));
|
let rdata = RData::MX(MX::new(10, Name::new()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Mx {
|
Some(DnsRecordData::Mx {
|
||||||
preference: 10,
|
preference: 10,
|
||||||
exchange: "".to_string()
|
exchange: "".to_string()
|
||||||
})
|
})
|
||||||
|
@ -962,7 +988,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_naptr() {
|
fn rdata_to_return_record_naptr() {
|
||||||
let func = rdata_to_return_record(RecordType::NAPTR);
|
let func = format_rdata(RecordType::NAPTR);
|
||||||
let rdata = RData::NAPTR(NAPTR::new(
|
let rdata = RData::NAPTR(NAPTR::new(
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
|
@ -973,7 +999,7 @@ mod tests {
|
||||||
));
|
));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Naptr {
|
Some(DnsRecordData::Naptr {
|
||||||
order: 1,
|
order: 1,
|
||||||
preference: 2,
|
preference: 2,
|
||||||
flags: "".to_string(),
|
flags: "".to_string(),
|
||||||
|
@ -986,27 +1012,27 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_ns() {
|
fn rdata_to_return_record_ns() {
|
||||||
let func = rdata_to_return_record(RecordType::NS);
|
let func = format_rdata(RecordType::NS);
|
||||||
let rdata = RData::NS(NS(Name::new()));
|
let rdata = RData::NS(NS(Name::new()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Ns("".to_string()))
|
Some(DnsRecordData::Ns("".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_ptr() {
|
fn rdata_to_return_record_ptr() {
|
||||||
let func = rdata_to_return_record(RecordType::PTR);
|
let func = format_rdata(RecordType::PTR);
|
||||||
let rdata = RData::PTR(PTR(Name::new()));
|
let rdata = RData::PTR(PTR(Name::new()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Ptr("".to_string()))
|
Some(DnsRecordData::Ptr("".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_soa() {
|
fn rdata_to_return_record_soa() {
|
||||||
let func = rdata_to_return_record(RecordType::SOA);
|
let func = format_rdata(RecordType::SOA);
|
||||||
let rdata = RData::SOA(SOA::new(
|
let rdata = RData::SOA(SOA::new(
|
||||||
Name::new(),
|
Name::new(),
|
||||||
Name::new(),
|
Name::new(),
|
||||||
|
@ -1018,7 +1044,7 @@ mod tests {
|
||||||
));
|
));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Soa {
|
Some(DnsRecordData::Soa {
|
||||||
mname: "".to_string(),
|
mname: "".to_string(),
|
||||||
rname: "".to_string(),
|
rname: "".to_string(),
|
||||||
serial: 0,
|
serial: 0,
|
||||||
|
@ -1032,11 +1058,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_srv() {
|
fn rdata_to_return_record_srv() {
|
||||||
let func = rdata_to_return_record(RecordType::SRV);
|
let func = format_rdata(RecordType::SRV);
|
||||||
let rdata = RData::SRV(SRV::new(1, 2, 3, Name::new()));
|
let rdata = RData::SRV(SRV::new(1, 2, 3, Name::new()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Srv {
|
Some(DnsRecordData::Srv {
|
||||||
priority: 1,
|
priority: 1,
|
||||||
weight: 2,
|
weight: 2,
|
||||||
port: 3,
|
port: 3,
|
||||||
|
@ -1047,7 +1073,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_txt() {
|
fn rdata_to_return_record_txt() {
|
||||||
let func = rdata_to_return_record(RecordType::TXT);
|
let func = format_rdata(RecordType::TXT);
|
||||||
let rdata = RData::TXT(TXT::from_bytes(vec![
|
let rdata = RData::TXT(TXT::from_bytes(vec![
|
||||||
"foo".as_bytes(),
|
"foo".as_bytes(),
|
||||||
"bar".as_bytes(),
|
"bar".as_bytes(),
|
||||||
|
@ -1056,7 +1082,7 @@ mod tests {
|
||||||
]));
|
]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
func(&rdata).unwrap(),
|
func(&rdata).unwrap(),
|
||||||
Some(DnsReturnRecord::Txt(vec![
|
Some(DnsRecordData::Txt(vec![
|
||||||
"foo".to_string(),
|
"foo".to_string(),
|
||||||
"bar".to_string(),
|
"bar".to_string(),
|
||||||
"£".to_string(),
|
"£".to_string(),
|
||||||
|
|
|
@ -186,20 +186,22 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery {
|
||||||
this.#tries = tries;
|
this.#tries = tries;
|
||||||
}
|
}
|
||||||
|
|
||||||
async #query(query: string, recordType: Deno.RecordType) {
|
async #query(query: string, recordType: Deno.RecordType, ttl?: boolean) {
|
||||||
// TODO(@bartlomieju): TTL logic.
|
|
||||||
|
|
||||||
let code: number;
|
let code: number;
|
||||||
let ret: Awaited<ReturnType<typeof Deno.resolveDns>>;
|
let ret: Awaited<ReturnType<typeof Deno.resolveDns>>;
|
||||||
|
|
||||||
|
const resolveOptions: Deno.ResolveDnsOptions = {
|
||||||
|
...ttl !== undefined ? { ttl } : {},
|
||||||
|
};
|
||||||
|
|
||||||
if (this.#servers.length) {
|
if (this.#servers.length) {
|
||||||
for (const [ipAddr, port] of this.#servers) {
|
for (const [ipAddr, port] of this.#servers) {
|
||||||
const resolveOptions = {
|
Object.assign(resolveOptions, {
|
||||||
nameServer: {
|
nameServer: {
|
||||||
ipAddr,
|
ipAddr,
|
||||||
port,
|
port,
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|
||||||
({ code, ret } = await this.#resolve(
|
({ code, ret } = await this.#resolve(
|
||||||
query,
|
query,
|
||||||
|
@ -212,7 +214,7 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
({ code, ret } = await this.#resolve(query, recordType));
|
({ code, ret } = await this.#resolve(query, recordType, resolveOptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
return { code: code!, ret: ret! };
|
return { code: code!, ret: ret! };
|
||||||
|
@ -351,18 +353,34 @@ export class ChannelWrap extends AsyncWrap implements ChannelWrapQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
queryA(req: QueryReqWrap, name: string): number {
|
queryA(req: QueryReqWrap, name: string): number {
|
||||||
this.#query(name, "A").then(({ code, ret }) => {
|
this.#query(name, "A", req.ttl).then(({ code, ret }) => {
|
||||||
req.oncomplete(code, ret);
|
let recordsWithTtl;
|
||||||
|
if (req.ttl) {
|
||||||
|
recordsWithTtl = (ret as Deno.RecordWithTtl[]).map((val) => ({
|
||||||
|
address: val?.data,
|
||||||
|
ttl: val?.ttl,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
req.oncomplete(code, recordsWithTtl ?? ret);
|
||||||
});
|
});
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
queryAaaa(req: QueryReqWrap, name: string): number {
|
queryAaaa(req: QueryReqWrap, name: string): number {
|
||||||
this.#query(name, "AAAA").then(({ code, ret }) => {
|
this.#query(name, "AAAA", req.ttl).then(({ code, ret }) => {
|
||||||
const records = (ret as string[]).map((record) => compressIPv6(record));
|
let recordsWithTtl;
|
||||||
|
if (req.ttl) {
|
||||||
|
recordsWithTtl = (ret as Deno.RecordWithTtl[]).map((val) => ({
|
||||||
|
address: compressIPv6(val?.data as string),
|
||||||
|
ttl: val?.ttl,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
ret = (ret as string[]).map((record) => compressIPv6(record));
|
||||||
|
}
|
||||||
|
|
||||||
req.oncomplete(code, records);
|
req.oncomplete(code, recordsWithTtl ?? ret);
|
||||||
});
|
});
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -42,6 +42,7 @@ use opentelemetry::metrics::InstrumentBuilder;
|
||||||
use opentelemetry::metrics::MeterProvider as _;
|
use opentelemetry::metrics::MeterProvider as _;
|
||||||
use opentelemetry::otel_debug;
|
use opentelemetry::otel_debug;
|
||||||
use opentelemetry::otel_error;
|
use opentelemetry::otel_error;
|
||||||
|
use opentelemetry::trace::Link;
|
||||||
use opentelemetry::trace::SpanContext;
|
use opentelemetry::trace::SpanContext;
|
||||||
use opentelemetry::trace::SpanId;
|
use opentelemetry::trace::SpanId;
|
||||||
use opentelemetry::trace::SpanKind;
|
use opentelemetry::trace::SpanKind;
|
||||||
|
@ -94,6 +95,7 @@ deno_core::extension!(
|
||||||
op_otel_span_attribute1,
|
op_otel_span_attribute1,
|
||||||
op_otel_span_attribute2,
|
op_otel_span_attribute2,
|
||||||
op_otel_span_attribute3,
|
op_otel_span_attribute3,
|
||||||
|
op_otel_span_add_link,
|
||||||
op_otel_span_update_name,
|
op_otel_span_update_name,
|
||||||
op_otel_metric_attribute3,
|
op_otel_metric_attribute3,
|
||||||
op_otel_metric_record0,
|
op_otel_metric_record0,
|
||||||
|
@ -1324,17 +1326,6 @@ impl OtelSpan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fast]
|
|
||||||
fn drop_link(&self) {
|
|
||||||
let mut state = self.0.borrow_mut();
|
|
||||||
match &mut **state {
|
|
||||||
OtelSpanState::Recording(span) => {
|
|
||||||
span.links.dropped_count += 1;
|
|
||||||
}
|
|
||||||
OtelSpanState::Done(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[fast]
|
#[fast]
|
||||||
fn end(&self, end_time: f64) {
|
fn end(&self, end_time: f64) {
|
||||||
let end_time = if end_time.is_nan() {
|
let end_time = if end_time.is_nan() {
|
||||||
|
@ -1448,6 +1439,48 @@ fn op_otel_span_update_name<'s>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
fn op_otel_span_add_link<'s>(
|
||||||
|
scope: &mut v8::HandleScope<'s>,
|
||||||
|
span: v8::Local<'s, v8::Value>,
|
||||||
|
trace_id: v8::Local<'s, v8::Value>,
|
||||||
|
span_id: v8::Local<'s, v8::Value>,
|
||||||
|
#[smi] trace_flags: u8,
|
||||||
|
is_remote: bool,
|
||||||
|
#[smi] dropped_attributes_count: u32,
|
||||||
|
) -> bool {
|
||||||
|
let trace_id = parse_trace_id(scope, trace_id);
|
||||||
|
if trace_id == TraceId::INVALID {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let span_id = parse_span_id(scope, span_id);
|
||||||
|
if span_id == SpanId::INVALID {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let span_context = SpanContext::new(
|
||||||
|
trace_id,
|
||||||
|
span_id,
|
||||||
|
TraceFlags::new(trace_flags),
|
||||||
|
is_remote,
|
||||||
|
TraceState::NONE,
|
||||||
|
);
|
||||||
|
|
||||||
|
let Some(span) =
|
||||||
|
deno_core::_ops::try_unwrap_cppgc_object::<OtelSpan>(scope, span)
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
let mut state = span.0.borrow_mut();
|
||||||
|
if let OtelSpanState::Recording(span) = &mut **state {
|
||||||
|
span.links.links.push(Link::new(
|
||||||
|
span_context,
|
||||||
|
vec![],
|
||||||
|
dropped_attributes_count,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
struct OtelMeter(opentelemetry::metrics::Meter);
|
struct OtelMeter(opentelemetry::metrics::Meter);
|
||||||
|
|
||||||
impl deno_core::GarbageCollected for OtelMeter {}
|
impl deno_core::GarbageCollected for OtelMeter {}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
op_otel_metric_record2,
|
op_otel_metric_record2,
|
||||||
op_otel_metric_record3,
|
op_otel_metric_record3,
|
||||||
op_otel_metric_wait_to_observe,
|
op_otel_metric_wait_to_observe,
|
||||||
|
op_otel_span_add_link,
|
||||||
op_otel_span_attribute1,
|
op_otel_span_attribute1,
|
||||||
op_otel_span_attribute2,
|
op_otel_span_attribute2,
|
||||||
op_otel_span_attribute3,
|
op_otel_span_attribute3,
|
||||||
|
@ -186,7 +187,6 @@ interface OtelSpan {
|
||||||
spanContext(): SpanContext;
|
spanContext(): SpanContext;
|
||||||
setStatus(status: SpanStatusCode, errorDescription: string): void;
|
setStatus(status: SpanStatusCode, errorDescription: string): void;
|
||||||
dropEvent(): void;
|
dropEvent(): void;
|
||||||
dropLink(): void;
|
|
||||||
end(endTime: number): void;
|
end(endTime: number): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,14 +359,24 @@ class Span {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addLink(_link: Link): Span {
|
addLink(link: Link): Span {
|
||||||
this.#otelSpan?.dropLink();
|
const droppedAttributeCount = (link.droppedAttributesCount ?? 0) +
|
||||||
|
(link.attributes ? ObjectKeys(link.attributes).length : 0);
|
||||||
|
const valid = op_otel_span_add_link(
|
||||||
|
this.#otelSpan,
|
||||||
|
link.context.traceId,
|
||||||
|
link.context.spanId,
|
||||||
|
link.context.traceFlags,
|
||||||
|
link.context.isRemote ?? false,
|
||||||
|
droppedAttributeCount,
|
||||||
|
);
|
||||||
|
if (!valid) return this;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addLinks(links: Link[]): Span {
|
addLinks(links: Link[]): Span {
|
||||||
for (let i = 0; i < links.length; i++) {
|
for (let i = 0; i < links.length; i++) {
|
||||||
this.#otelSpan?.dropLink();
|
this.addLink(links[i]);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,10 @@
|
||||||
},
|
},
|
||||||
"args": "run -A main.ts metric.ts",
|
"args": "run -A main.ts metric.ts",
|
||||||
"output": "metric.out"
|
"output": "metric.out"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"args": "run -A main.ts links.ts",
|
||||||
|
"output": "links.out"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
96
tests/specs/cli/otel_basic/links.out
Normal file
96
tests/specs/cli/otel_basic/links.out
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
"spans": [
|
||||||
|
{
|
||||||
|
"traceId": "00000000000000000000000000000001",
|
||||||
|
"spanId": "0000000000000001",
|
||||||
|
"traceState": "",
|
||||||
|
"parentSpanId": "",
|
||||||
|
"flags": 1,
|
||||||
|
"name": "example span",
|
||||||
|
"kind": 1,
|
||||||
|
"startTimeUnixNano": "[WILDCARD]",
|
||||||
|
"endTimeUnixNano": "[WILDCARD]",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"events": [],
|
||||||
|
"droppedEventsCount": 0,
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"traceId": "1234567890abcdef1234567890abcdef",
|
||||||
|
"spanId": "1234567890abcdef",
|
||||||
|
"traceState": "",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"flags": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"droppedLinksCount": 0,
|
||||||
|
"status": {
|
||||||
|
"message": "",
|
||||||
|
"code": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"traceId": "00000000000000000000000000000002",
|
||||||
|
"spanId": "0000000000000002",
|
||||||
|
"traceState": "",
|
||||||
|
"parentSpanId": "",
|
||||||
|
"flags": 1,
|
||||||
|
"name": "example span",
|
||||||
|
"kind": 1,
|
||||||
|
"startTimeUnixNano": "[WILDCARD]",
|
||||||
|
"endTimeUnixNano": "[WILDCARD]",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"events": [],
|
||||||
|
"droppedEventsCount": 0,
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"traceId": "1234567890abcdef1234567890abcdef",
|
||||||
|
"spanId": "1234567890abcdef",
|
||||||
|
"traceState": "",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"flags": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"droppedLinksCount": 0,
|
||||||
|
"status": {
|
||||||
|
"message": "",
|
||||||
|
"code": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"traceId": "00000000000000000000000000000003",
|
||||||
|
"spanId": "0000000000000003",
|
||||||
|
"traceState": "",
|
||||||
|
"parentSpanId": "",
|
||||||
|
"flags": 1,
|
||||||
|
"name": "example span",
|
||||||
|
"kind": 1,
|
||||||
|
"startTimeUnixNano": "[WILDCARD]",
|
||||||
|
"endTimeUnixNano": "[WILDCARD]",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 0,
|
||||||
|
"events": [],
|
||||||
|
"droppedEventsCount": 0,
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"traceId": "1234567890abcdef1234567890abcdef",
|
||||||
|
"spanId": "1234567890abcdef",
|
||||||
|
"traceState": "",
|
||||||
|
"attributes": [],
|
||||||
|
"droppedAttributesCount": 2,
|
||||||
|
"flags": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"droppedLinksCount": 0,
|
||||||
|
"status": {
|
||||||
|
"message": "",
|
||||||
|
"code": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"logs": [],
|
||||||
|
"metrics": []
|
||||||
|
}
|
40
tests/specs/cli/otel_basic/links.ts
Normal file
40
tests/specs/cli/otel_basic/links.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
import { trace } from "npm:@opentelemetry/api@1.9.0";
|
||||||
|
|
||||||
|
const tracer = trace.getTracer("example-tracer");
|
||||||
|
|
||||||
|
const span1 = tracer.startSpan("example span", {
|
||||||
|
links: [{
|
||||||
|
context: {
|
||||||
|
traceId: "1234567890abcdef1234567890abcdef",
|
||||||
|
spanId: "1234567890abcdef",
|
||||||
|
traceFlags: 1,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
span1.end();
|
||||||
|
|
||||||
|
const span2 = tracer.startSpan("example span");
|
||||||
|
span2.addLink({
|
||||||
|
context: {
|
||||||
|
traceId: "1234567890abcdef1234567890abcdef",
|
||||||
|
spanId: "1234567890abcdef",
|
||||||
|
traceFlags: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
span2.end();
|
||||||
|
|
||||||
|
const span3 = tracer.startSpan("example span");
|
||||||
|
span3.addLink({
|
||||||
|
context: {
|
||||||
|
traceId: "1234567890abcdef1234567890abcdef",
|
||||||
|
spanId: "1234567890abcdef",
|
||||||
|
traceFlags: 1,
|
||||||
|
},
|
||||||
|
attributes: {
|
||||||
|
key: "value",
|
||||||
|
},
|
||||||
|
droppedAttributesCount: 1,
|
||||||
|
});
|
||||||
|
span3.end();
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"tempDir": true,
|
||||||
|
"args": "install -g --root ./folder --config deno.json main.ts --name my-cli",
|
||||||
|
"output": "install.out"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"importMap": "./import_map.json"
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
Warning "importMap" field in the specified config file we be ignored. Use the --import-map flag instead.
|
||||||
|
✅ Successfully installed my-cli
|
||||||
|
[WILDCARD]
|
|
@ -0,0 +1 @@
|
||||||
|
console.log(1);
|
24
tests/unit/dns_test.ts
Normal file
24
tests/unit/dns_test.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
import { resolve4, resolve6 } from "node:dns/promises";
|
||||||
|
import { assertEquals } from "@std/assert/equals";
|
||||||
|
|
||||||
|
Deno.test({
|
||||||
|
name: "Dns resolving for ttl values, A and AAAA records",
|
||||||
|
async fn() {
|
||||||
|
const ARecord = "34.120.54.55";
|
||||||
|
const AAAARecord = "2600:1901::6d85::";
|
||||||
|
|
||||||
|
const ARes1 = await Deno.resolveDns("deno.com", "A", { ttl: true });
|
||||||
|
const ARes2 = await resolve4("deno.com", { ttl: true });
|
||||||
|
|
||||||
|
assertEquals(ARes1[0].data, ARecord);
|
||||||
|
assertEquals(ARes2[0].address, ARecord);
|
||||||
|
|
||||||
|
const AAAARes1 = await Deno.resolveDns("deno.com", "AAAA", { ttl: true });
|
||||||
|
const AAAARes2 = await resolve6("deno.com", { ttl: true });
|
||||||
|
|
||||||
|
assertEquals(AAAARes1[0].data, AAAARecord);
|
||||||
|
assertEquals(AAAARes2[0].address, AAAARecord);
|
||||||
|
},
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue