diff --git a/Releases.md b/Releases.md index 816a843a23a5..54e3a1256b98 100644 --- a/Releases.md +++ b/Releases.md @@ -1,3 +1,68 @@ +### 2025.01.31 + +#### @std/bytes 1.0.5 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/cli 1.0.12 (patch) + +- feat(cli/unstable): support stderr on spinner (#6350) + +#### @std/crypto 1.0.4 (patch) + +- docs(crypto): clarify doc comment (#6368) +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/encoding 1.0.7 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/expect 1.0.13 (patch) + +- test(expect): check error message of `.toBeCloseTo()` (#6296) + +#### @std/fmt 1.0.5 (patch) + +- fix(fmt): make printf working with colors. (#6360) + +#### @std/fs 1.0.11 (patch) + +- feat(fs/unstable): add readLink and readLinkSync (#6373) +- feat(fs/unstable): add link and linkSync (#6369) +- feat(fs/unstable): add realPath and realPathSync (#6366) + +#### @std/http 1.0.13 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/io 0.225.2 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/log 0.224.14 (patch) + +- docs(log): mention potential deprecation of @std/log (#6364) + +#### @std/msgpack 1.0.3 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/streams 1.0.9 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + +#### @std/tar 0.1.5 (patch) + +- refactor(bytes,crypto,encoding,http,io,msgpack,streams,tar): make Uint8Array + usages compatible with TS 5.7 (#6372) + ### 2025.01.22 #### @std/assert 1.0.11 (patch) diff --git a/_tools/node_test_runner/run_test.mjs b/_tools/node_test_runner/run_test.mjs index 609b9052df9b..79b10428d9f1 100644 --- a/_tools/node_test_runner/run_test.mjs +++ b/_tools/node_test_runner/run_test.mjs @@ -51,6 +51,7 @@ import "../../collections/without_all_test.ts"; import "../../collections/zip_test.ts"; import "../../fs/unstable_link_test.ts"; import "../../fs/unstable_read_dir_test.ts"; +import "../../fs/unstable_read_link_test.ts"; import "../../fs/unstable_real_path_test.ts"; import "../../fs/unstable_stat_test.ts"; import "../../fs/unstable_symlink_test.ts"; diff --git a/bytes/_types.ts b/bytes/_types.ts new file mode 100644 index 000000000000..340b2fcce9d6 --- /dev/null +++ b/bytes/_types.ts @@ -0,0 +1,11 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +/** + * Proxy type of {@code Uint8Array; diff --git a/bytes/concat.ts b/bytes/concat.ts index 5031cfbcdf02..5ee31f2ea002 100644 --- a/bytes/concat.ts +++ b/bytes/concat.ts @@ -1,6 +1,9 @@ // Copyright 2018-2025 the Deno authors. MIT license. // This module is browser compatible. +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; + /** * Concatenate an array of byte slices into a single slice. * @@ -18,7 +21,7 @@ * assertEquals(concat([a, b]), new Uint8Array([0, 1, 2, 3, 4, 5])); * ``` */ -export function concat(buffers: Uint8Array[]): Uint8Array { +export function concat(buffers: Uint8Array[]): Uint8Array_ { let length = 0; for (const buffer of buffers) { length += buffer.length; diff --git a/bytes/deno.json b/bytes/deno.json index 618e91e63b41..2e927e8f9f5b 100644 --- a/bytes/deno.json +++ b/bytes/deno.json @@ -1,6 +1,6 @@ { "name": "@std/bytes", - "version": "1.0.4", + "version": "1.0.5", "exports": { ".": "./mod.ts", "./concat": "./concat.ts", diff --git a/bytes/repeat.ts b/bytes/repeat.ts index 6a13e4c511b2..b15d45af59f7 100644 --- a/bytes/repeat.ts +++ b/bytes/repeat.ts @@ -1,6 +1,8 @@ // Copyright 2018-2025 the Deno authors. MIT license. // This module is browser compatible. import { copy } from "./copy.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Returns a new byte slice composed of `count` repetitions of the `source` @@ -31,7 +33,7 @@ import { copy } from "./copy.ts"; * assertEquals(repeat(source, 0), new Uint8Array()); * ``` */ -export function repeat(source: Uint8Array, count: number): Uint8Array { +export function repeat(source: Uint8Array, count: number): Uint8Array_ { if (count < 0 || !Number.isInteger(count)) { throw new RangeError("Count must be a non-negative integer"); } diff --git a/cli/deno.json b/cli/deno.json index 569a90771550..aaab86bc67f4 100644 --- a/cli/deno.json +++ b/cli/deno.json @@ -1,6 +1,6 @@ { "name": "@std/cli", - "version": "1.0.11", + "version": "1.0.12", "exports": { ".": "./mod.ts", "./parse-args": "./parse_args.ts", diff --git a/crypto/crypto.ts b/crypto/crypto.ts index 626195006a6e..14ff82cd3c4d 100644 --- a/crypto/crypto.ts +++ b/crypto/crypto.ts @@ -188,8 +188,8 @@ export interface StdCrypto extends Crypto { } /** - * An wrapper for WebCrypto adding support for additional non-standard - * algorithms, but delegating to the runtime WebCrypto implementation whenever + * A wrapper for WebCrypto which adds support for additional non-standard + * algorithms, but delegates to the runtime WebCrypto implementation whenever * possible. */ const stdCrypto: StdCrypto = ((x) => x)({ @@ -241,7 +241,7 @@ const stdCrypto: StdCrypto = ((x) => x)({ } context.update(chunkBytes); } - return context.digestAndDrop(length).buffer; + return context.digestAndDrop(length).buffer as ArrayBuffer; } else { throw new TypeError( "data must be a BufferSource or [Async]Iterable", @@ -265,7 +265,7 @@ const stdCrypto: StdCrypto = ((x) => x)({ const wasmCrypto = instantiateWasm(); if (isBufferSource(data)) { const bytes = toUint8Array(data)!; - return wasmCrypto.digest(name, bytes, length).buffer; + return wasmCrypto.digest(name, bytes, length).buffer as ArrayBuffer; } if (isIterable(data)) { const context = new wasmCrypto.DigestContext(name); @@ -278,7 +278,7 @@ const stdCrypto: StdCrypto = ((x) => x)({ } context.update(chunkBytes); } - return context.digestAndDrop(length).buffer; + return context.digestAndDrop(length).buffer as ArrayBuffer; } throw new TypeError( "data must be a BufferSource or Iterable", diff --git a/crypto/deno.json b/crypto/deno.json index b38a0b6eee9a..b43c2d28d638 100644 --- a/crypto/deno.json +++ b/crypto/deno.json @@ -1,6 +1,6 @@ { "name": "@std/crypto", - "version": "1.0.3", + "version": "1.0.4", "exports": { ".": "./mod.ts", "./crypto": "./crypto.ts", diff --git a/encoding/_base32_common.ts b/encoding/_base32_common.ts index f567bedf60a5..8d3cd6cdda97 100644 --- a/encoding/_base32_common.ts +++ b/encoding/_base32_common.ts @@ -7,6 +7,7 @@ */ import { validateBinaryLike } from "./_validate_binary_like.ts"; +import type { Uint8Array_ } from "./_types.ts"; const placeHolderPadLookup = [0, 1, , 2, 3, , 4]; @@ -46,7 +47,10 @@ function getByteLength(validLen: number, placeHoldersLen: number): number { * @param lookup The lookup table * @returns The encoded string. */ -export function decode(b32: string, lookup: ReadonlyArray): Uint8Array { +export function decode( + b32: string, + lookup: ReadonlyArray, +): Uint8Array_ { const revLookup: number[] = []; lookup.forEach((c, i) => (revLookup[c.charCodeAt(0)] = i)); diff --git a/encoding/_types.ts b/encoding/_types.ts new file mode 100644 index 000000000000..340b2fcce9d6 --- /dev/null +++ b/encoding/_types.ts @@ -0,0 +1,11 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +/** + * Proxy type of {@code Uint8Array; diff --git a/encoding/ascii85.ts b/encoding/ascii85.ts index ef8fa702e718..043ac92f670f 100644 --- a/encoding/ascii85.ts +++ b/encoding/ascii85.ts @@ -1,6 +1,9 @@ // Copyright 2018-2025 the Deno authors. MIT license. // This module is browser compatible. +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; + /** * Utilities for working with {@link https://en.wikipedia.org/wiki/Ascii85 | ascii85} encoding. * @@ -156,7 +159,7 @@ export type DecodeAscii85Options = Omit; export function decodeAscii85( ascii85: string, options: DecodeAscii85Options = {}, -): Uint8Array { +): Uint8Array_ { const { standard = "Adobe" } = options; // translate all encodings to most basic adobe/btoa one and decompress some special characters ("z" and "y") diff --git a/encoding/base32.ts b/encoding/base32.ts index dac3c15de8c2..2f3ac4431efc 100644 --- a/encoding/base32.ts +++ b/encoding/base32.ts @@ -2,6 +2,9 @@ // Copyright (c) 2014 Jameson Little. MIT License. // This module is browser compatible. +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; + /** * Utilities for * {@link https://www.rfc-editor.org/rfc/rfc4648.html#section-6 | base32} @@ -48,7 +51,7 @@ lookup.forEach((c, i) => (revLookup[c.charCodeAt(0)] = i)); * ); * ``` */ -export function decodeBase32(b32: string): Uint8Array { +export function decodeBase32(b32: string): Uint8Array_ { return decode(b32, lookup); } diff --git a/encoding/base58.ts b/encoding/base58.ts index 06194e07e585..42c346e79ad9 100644 --- a/encoding/base58.ts +++ b/encoding/base58.ts @@ -21,6 +21,8 @@ */ import { validateBinaryLike } from "./_validate_binary_like.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; // deno-fmt-ignore const mapBase58: Record = { @@ -120,7 +122,7 @@ export function encodeBase58(data: ArrayBuffer | Uint8Array | string): string { * ); * ``` */ -export function decodeBase58(b58: string): Uint8Array { +export function decodeBase58(b58: string): Uint8Array_ { const splitInput = b58.trim().split(""); let length = 0; diff --git a/encoding/base58_test.ts b/encoding/base58_test.ts index 82e3e55c0a6f..a4ecdb92e1d1 100644 --- a/encoding/base58_test.ts +++ b/encoding/base58_test.ts @@ -53,7 +53,7 @@ Deno.test("encodeBase58() encodes binary", () => { Deno.test("encodeBase58() encodes binary buffer", () => { for (const [input, output] of testSetBinary) { - assertEquals(encodeBase58(input.buffer), output); + assertEquals(encodeBase58(input.buffer as ArrayBuffer), output); } }); diff --git a/encoding/base64.ts b/encoding/base64.ts index f791a29c5696..a0fd36f23725 100644 --- a/encoding/base64.ts +++ b/encoding/base64.ts @@ -23,6 +23,8 @@ */ import { validateBinaryLike } from "./_validate_binary_like.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; const base64abc = [ "A", @@ -163,7 +165,7 @@ export function encodeBase64(data: ArrayBuffer | Uint8Array | string): string { * ); * ``` */ -export function decodeBase64(b64: string): Uint8Array { +export function decodeBase64(b64: string): Uint8Array_ { const binString = atob(b64); const size = binString.length; const bytes = new Uint8Array(size); diff --git a/encoding/base64_test.ts b/encoding/base64_test.ts index 09345d34f5ac..26581c508e17 100644 --- a/encoding/base64_test.ts +++ b/encoding/base64_test.ts @@ -33,7 +33,7 @@ Deno.test("encodeBase64() encodes binary", () => { Deno.test("encodeBase64() encodes binary buffer", () => { for (const [input, output] of testsetBinary) { - assertEquals(encodeBase64(input.buffer), output); + assertEquals(encodeBase64(input.buffer as ArrayBuffer), output); } }); diff --git a/encoding/base64url.ts b/encoding/base64url.ts index 3485ab23091c..460c8d405dc9 100644 --- a/encoding/base64url.ts +++ b/encoding/base64url.ts @@ -10,6 +10,8 @@ */ import * as base64 from "./base64.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Some variants allow or require omitting the padding '=' signs: @@ -83,6 +85,6 @@ export function encodeBase64Url( * ); * ``` */ -export function decodeBase64Url(b64url: string): Uint8Array { +export function decodeBase64Url(b64url: string): Uint8Array_ { return base64.decodeBase64(convertBase64urlToBase64(b64url)); } diff --git a/encoding/deno.json b/encoding/deno.json index 016f8a3f47ee..cb1870a3bfae 100644 --- a/encoding/deno.json +++ b/encoding/deno.json @@ -1,6 +1,6 @@ { "name": "@std/encoding", - "version": "1.0.6", + "version": "1.0.7", "exports": { ".": "./mod.ts", "./ascii85": "./ascii85.ts", diff --git a/encoding/hex.ts b/encoding/hex.ts index 442111f58366..7efe6e42935f 100644 --- a/encoding/hex.ts +++ b/encoding/hex.ts @@ -27,6 +27,8 @@ */ import { validateBinaryLike } from "./_validate_binary_like.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; const hexTable = new TextEncoder().encode("0123456789abcdef"); const textEncoder = new TextEncoder(); @@ -100,7 +102,7 @@ export function encodeHex(src: string | Uint8Array | ArrayBuffer): string { * ); * ``` */ -export function decodeHex(src: string): Uint8Array { +export function decodeHex(src: string): Uint8Array_ { const u8 = textEncoder.encode(src); const dst = new Uint8Array(u8.length / 2); for (let i = 0; i < dst.length; i++) { diff --git a/encoding/unstable_base32_stream.ts b/encoding/unstable_base32_stream.ts index 1f14a0dd3a9e..ebe169924fbb 100644 --- a/encoding/unstable_base32_stream.ts +++ b/encoding/unstable_base32_stream.ts @@ -22,6 +22,8 @@ */ import { decodeBase32, encodeBase32 } from "./base32.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a base32-encoded stream. @@ -88,7 +90,7 @@ export class Base32EncoderStream extends TransformStream { * assertEquals(await toText(stream), "Hello World!"); * ``` */ -export class Base32DecoderStream extends TransformStream { +export class Base32DecoderStream extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/unstable_base32crockford.ts b/encoding/unstable_base32crockford.ts index 0f8b69a55b59..07cd17a9614c 100644 --- a/encoding/unstable_base32crockford.ts +++ b/encoding/unstable_base32crockford.ts @@ -24,6 +24,8 @@ * @module */ import { decode, encode } from "./_base32_common.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; const lookup: string[] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ".split(""); const revLookup: number[] = []; @@ -48,7 +50,7 @@ lookup.forEach((c, i) => (revLookup[c.charCodeAt(0)] = i)); * ); * ``` */ -export function decodeBase32Crockford(b32: string): Uint8Array { +export function decodeBase32Crockford(b32: string): Uint8Array_ { return decode(b32, lookup); } diff --git a/encoding/unstable_base32hex.ts b/encoding/unstable_base32hex.ts index 91622f31e7a5..9a4b3c6d2c12 100644 --- a/encoding/unstable_base32hex.ts +++ b/encoding/unstable_base32hex.ts @@ -28,6 +28,8 @@ * @module */ import { decode, encode } from "./_base32_common.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; const lookup: string[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV".split(""); const revLookup: number[] = []; @@ -54,7 +56,7 @@ lookup.forEach((c, i) => revLookup[c.charCodeAt(0)] = i); * ); * ``` */ -export function decodeBase32Hex(b32: string): Uint8Array { +export function decodeBase32Hex(b32: string): Uint8Array_ { return decode(b32, lookup); } diff --git a/encoding/unstable_base32hex_stream.ts b/encoding/unstable_base32hex_stream.ts index 9862d464b504..735281272900 100644 --- a/encoding/unstable_base32hex_stream.ts +++ b/encoding/unstable_base32hex_stream.ts @@ -22,6 +22,8 @@ */ import { decodeBase32Hex, encodeBase32Hex } from "./unstable_base32hex.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a base32hex-encoded stream. @@ -90,7 +92,7 @@ export class Base32HexEncoderStream * ``` */ export class Base32HexDecoderStream - extends TransformStream { + extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/unstable_base64_stream.ts b/encoding/unstable_base64_stream.ts index 2dc5232877e4..a2aa70db8c28 100644 --- a/encoding/unstable_base64_stream.ts +++ b/encoding/unstable_base64_stream.ts @@ -22,6 +22,8 @@ */ import { decodeBase64, encodeBase64 } from "./base64.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a base64-encoded stream. @@ -88,7 +90,7 @@ export class Base64EncoderStream extends TransformStream { * assertEquals(await toText(stream), "Hello, world!"); * ``` */ -export class Base64DecoderStream extends TransformStream { +export class Base64DecoderStream extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/unstable_base64url_stream.ts b/encoding/unstable_base64url_stream.ts index ee940ca15c00..53d67245dd73 100644 --- a/encoding/unstable_base64url_stream.ts +++ b/encoding/unstable_base64url_stream.ts @@ -22,6 +22,8 @@ */ import { decodeBase64Url, encodeBase64Url } from "./base64url.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a base64url-encoded stream. @@ -91,7 +93,7 @@ export class Base64UrlEncoderStream * ``` */ export class Base64UrlDecoderStream - extends TransformStream { + extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/unstable_hex_stream.ts b/encoding/unstable_hex_stream.ts index afb85869d195..7c17b8fd10ec 100644 --- a/encoding/unstable_hex_stream.ts +++ b/encoding/unstable_hex_stream.ts @@ -22,6 +22,8 @@ */ import { decodeHex, encodeHex } from "./hex.ts"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Converts a Uint8Array stream into a hex-encoded stream. @@ -74,7 +76,7 @@ export class HexEncoderStream extends TransformStream { * assertEquals(await toText(stream), "Hello, world!"); * ``` */ -export class HexDecoderStream extends TransformStream { +export class HexDecoderStream extends TransformStream { constructor() { let push = ""; super({ diff --git a/encoding/varint.ts b/encoding/varint.ts index ebf7f00c8dcd..c20f1242c80c 100644 --- a/encoding/varint.ts +++ b/encoding/varint.ts @@ -28,6 +28,9 @@ // This implementation is a port of https://deno.land/x/varint@v2.0.0 by @keithamus // This module is browser compatible. +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; + /** * The maximum value of an unsigned 64-bit integer. * Equivalent to `2n**64n - 1n` @@ -216,7 +219,7 @@ export function encodeVarint( num: bigint | number, buf: Uint8Array = new Uint8Array(MaxVarintLen64), offset = 0, -): [Uint8Array, number] { +): [Uint8Array_, number] { num = BigInt(num); if (num < 0n) { throw new RangeError( diff --git a/expect/deno.json b/expect/deno.json index 91137260ab12..b64670473e2e 100644 --- a/expect/deno.json +++ b/expect/deno.json @@ -1,6 +1,6 @@ { "name": "@std/expect", - "version": "1.0.12", + "version": "1.0.13", "exports": { ".": "./mod.ts", "./expect": "./expect.ts", diff --git a/fmt/deno.json b/fmt/deno.json index 41d40b01f525..4256ebede623 100644 --- a/fmt/deno.json +++ b/fmt/deno.json @@ -1,6 +1,6 @@ { "name": "@std/fmt", - "version": "1.0.4", + "version": "1.0.5", "exports": { "./bytes": "./bytes.ts", "./colors": "./colors.ts", diff --git a/fs/deno.json b/fs/deno.json index 78b4db0e0b0a..e9fa16175f4b 100644 --- a/fs/deno.json +++ b/fs/deno.json @@ -1,6 +1,6 @@ { "name": "@std/fs", - "version": "1.0.10", + "version": "1.0.11", "exports": { ".": "./mod.ts", "./copy": "./copy.ts", @@ -17,6 +17,7 @@ "./unstable-link": "./unstable_link.ts", "./unstable-lstat": "./unstable_lstat.ts", "./unstable-read-dir": "./unstable_read_dir.ts", + "./unstable-read-link": "./unstable_read_link.ts", "./unstable-real-path": "./unstable_real_path.ts", "./unstable-stat": "./unstable_stat.ts", "./unstable-symlink": "./unstable_symlink.ts", diff --git a/fs/unstable_read_link.ts b/fs/unstable_read_link.ts new file mode 100644 index 000000000000..3b9f75f36371 --- /dev/null +++ b/fs/unstable_read_link.ts @@ -0,0 +1,69 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { getNodeFs, isDeno } from "./_utils.ts"; +import { mapError } from "./_map_error.ts"; + +/** + * Resolves to the path destination of the named symbolic link. + * + * Throws Error if called with a hard link. + * + * Requires `allow-read` permission. + * + * @example Usage + * ```ts ignore + * import { readLink } from "@std/fs/unstable-read-link"; + * import { symlink } from "@std/fs/unstable-symlink"; + * await symlink("./test.txt", "./test_link.txt"); + * const target = await readLink("./test_link.txt"); // full path of ./test.txt + * ``` + * + * @tags allow-read + * + * @param path The path of the symbolic link. + * @returns A promise that resolves to the file path pointed by the symbolic + * link. + */ +export async function readLink(path: string | URL): Promise { + if (isDeno) { + return Deno.readLink(path); + } else { + try { + return await getNodeFs().promises.readlink(path); + } catch (error) { + throw mapError(error); + } + } +} + +/** + * Synchronously returns the path destination of the named symbolic link. + * + * Throws Error if called with a hard link. + * + * Requires `allow-read` permission. + * + * @example Usage + * ```ts ignore + * import { readLinkSync } from "@std/fs/unstable-read-link"; + * import { symlinkSync } from "@std/fs/unstable-symlink"; + * symlinkSync("./test.txt", "./test_link.txt"); + * const target = readLinkSync("./test_link.txt"); // full path of ./test.txt + * ``` + * + * @tags allow-read + * + * @param path The path of the symbolic link. + * @returns The file path pointed by the symbolic link. + */ +export function readLinkSync(path: string | URL): string { + if (isDeno) { + return Deno.readLinkSync(path); + } else { + try { + return getNodeFs().readlinkSync(path); + } catch (error) { + throw mapError(error); + } + } +} diff --git a/fs/unstable_read_link_test.ts b/fs/unstable_read_link_test.ts new file mode 100644 index 000000000000..0ef85e6a8753 --- /dev/null +++ b/fs/unstable_read_link_test.ts @@ -0,0 +1,85 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +import { assertEquals, assertRejects, assertThrows } from "@std/assert"; +import { readLink, readLinkSync } from "./unstable_read_link.ts"; +import { NotFound } from "./unstable_errors.js"; +import { + linkSync, + mkdtempSync, + rmSync, + symlinkSync, + writeFileSync, +} from "node:fs"; +import { link, mkdtemp, rm, symlink, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; + +Deno.test("readLink() can read through symlink", async () => { + const tempDirPath = await mkdtemp(resolve(tmpdir(), "readLink_")); + const testFile = join(tempDirPath, "testFile.txt"); + const symlinkFile = join(tempDirPath, "testFile.txt.link"); + + await writeFile(testFile, "Hello, Standard Library"); + await symlink(testFile, symlinkFile); + + const realFile = await readLink(symlinkFile); + assertEquals(testFile, realFile); + + await rm(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("readLink() rejects with Error when reading from a hard link", async () => { + const tempDirPath = await mkdtemp(resolve(tmpdir(), "readLink_")); + const testFile = join(tempDirPath, "testFile.txt"); + const linkFile = join(tempDirPath, "testFile.txt.hlink"); + + await writeFile(testFile, "Hello, Standard Library"); + await link(testFile, linkFile); + + await assertRejects(async () => { + await readLink(linkFile); + }, Error); + + await rm(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("readLink() rejects with NotFound when reading through a non-existent file", async () => { + await assertRejects(async () => { + await readLink("non-existent-file.txt.link"); + }, NotFound); +}); + +Deno.test("readLinkSync() can read through symlink", () => { + const tempDirPath = mkdtempSync(resolve(tmpdir(), "readLink_")); + const testFile = join(tempDirPath, "testFile.txt"); + const symlinkFile = join(tempDirPath, "testFile.txt.link"); + + writeFileSync(testFile, "Hello, Standard Library"); + symlinkSync(testFile, symlinkFile); + + const realFile = readLinkSync(symlinkFile); + assertEquals(testFile, realFile); + + rmSync(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("readLinkSync() throws Error when reading from a hard link", () => { + const tempDirPath = mkdtempSync(resolve(tmpdir(), "readLinkSync_")); + const testFile = join(tempDirPath, "testFile.txt"); + const linkFile = join(tempDirPath, "testFile.txt.hlink"); + + writeFileSync(testFile, "Hello, Standard Library!"); + linkSync(testFile, linkFile); + + assertThrows(() => { + readLinkSync(linkFile); + }, Error); + + rmSync(tempDirPath, { recursive: true, force: true }); +}); + +Deno.test("readLinkSync() throws NotFound when reading through a non-existent file", () => { + assertThrows(() => { + readLinkSync("non-existent-file.txt.hlink"); + }, NotFound); +}); diff --git a/http/deno.json b/http/deno.json index 93ba1b572176..dadf0bbc3979 100644 --- a/http/deno.json +++ b/http/deno.json @@ -1,6 +1,6 @@ { "name": "@std/http", - "version": "1.0.12", + "version": "1.0.13", "exports": { ".": "./mod.ts", "./cookie": "./cookie.ts", diff --git a/http/file_server_test.ts b/http/file_server_test.ts index 7b1e6873dc6f..e2d762512e18 100644 --- a/http/file_server_test.ts +++ b/http/file_server_test.ts @@ -1125,7 +1125,7 @@ async function readUntilMatch( match: string, ) { const reader = source.getReader(); - let buf = new Uint8Array(0); + let buf: Uint8Array = new Uint8Array(0); const dec = new TextDecoder(); while (!dec.decode(buf).includes(match)) { const { value } = await reader.read(); diff --git a/import_map.json b/import_map.json index ef2a48d65e11..f9cff79c30e6 100644 --- a/import_map.json +++ b/import_map.json @@ -8,38 +8,38 @@ "@std/assert": "jsr:@std/assert@^1.0.11", "@std/async": "jsr:@std/async@^1.0.10", - "@std/bytes": "jsr:@std/bytes@^1.0.4", + "@std/bytes": "jsr:@std/bytes@^1.0.5", "@std/cache": "jsr:@std/cache@^0.1.3", "@std/cbor": "jsr:@std/cbor@^0.1.6", - "@std/cli": "jsr:@std/cli@^1.0.11", + "@std/cli": "jsr:@std/cli@^1.0.12", "@std/collections": "jsr:@std/collections@^1.0.10", - "@std/crypto": "jsr:@std/crypto@^1.0.3", + "@std/crypto": "jsr:@std/crypto@^1.0.4", "@std/csv": "jsr:@std/csv@^1.0.5", "@std/data-structures": "jsr:@std/data-structures@^1.0.6", "@std/datetime": "jsr:@std/datetime@^0.225.3", "@std/dotenv": "jsr:@std/dotenv@^0.225.3", - "@std/encoding": "jsr:@std/encoding@^1.0.6", - "@std/expect": "jsr:@std/expect@^1.0.12", - "@std/fmt": "jsr:@std/fmt@^1.0.4", + "@std/encoding": "jsr:@std/encoding@^1.0.7", + "@std/expect": "jsr:@std/expect@^1.0.13", + "@std/fmt": "jsr:@std/fmt@^1.0.5", "@std/front-matter": "jsr:@std/front-matter@^1.0.5", - "@std/fs": "jsr:@std/fs@^1.0.10", + "@std/fs": "jsr:@std/fs@^1.0.11", "@std/html": "jsr:@std/html@^1.0.3", - "@std/http": "jsr:@std/http@^1.0.12", + "@std/http": "jsr:@std/http@^1.0.13", "@std/ini": "jsr:@std/ini@^1.0.0-rc.5", "@std/internal": "jsr:@std/internal@^1.0.5", - "@std/io": "jsr:@std/io@^0.225.1", + "@std/io": "jsr:@std/io@^0.225.2", "@std/json": "jsr:@std/json@^1.0.1", "@std/jsonc": "jsr:@std/jsonc@^1.0.1", - "@std/log": "jsr:@std/log@^0.224.13", + "@std/log": "jsr:@std/log@^0.224.14", "@std/media-types": "jsr:@std/media-types@^1.1.0", - "@std/msgpack": "jsr:@std/msgpack@^1.0.2", + "@std/msgpack": "jsr:@std/msgpack@^1.0.3", "@std/net": "jsr:@std/net@^1.0.4", "@std/path": "jsr:@std/path@^1.0.8", "@std/regexp": "jsr:@std/regexp@^1.0.1", "@std/random": "jsr:@std/random@^0.1.0", "@std/semver": "jsr:@std/semver@^1.0.3", - "@std/streams": "jsr:@std/streams@^1.0.8", - "@std/tar": "jsr:@std/tar@^0.1.4", + "@std/streams": "jsr:@std/streams@^1.0.9", + "@std/tar": "jsr:@std/tar@^0.1.5", "@std/testing": "jsr:@std/testing@^1.0.9", "@std/text": "jsr:@std/text@^1.0.10", "@std/toml": "jsr:@std/toml@^1.0.2", diff --git a/io/buffer.ts b/io/buffer.ts index 7b3630cbcdd2..48f579f6f23a 100644 --- a/io/buffer.ts +++ b/io/buffer.ts @@ -53,7 +53,14 @@ export class Buffer implements Writer, WriterSync, Reader, ReaderSync { * @param ab The ArrayBuffer to use as the initial contents of the buffer. */ constructor(ab?: ArrayBufferLike | ArrayLike) { - this.#buf = ab === undefined ? new Uint8Array(0) : new Uint8Array(ab); + if (ab === undefined) { + this.#buf = new Uint8Array(0); + } else if (ab instanceof SharedArrayBuffer) { + // Note: This is necessary to avoid type error + this.#buf = new Uint8Array(ab); + } else { + this.#buf = new Uint8Array(ab); + } } /** diff --git a/io/deno.json b/io/deno.json index 68042fab6f06..2a6ffa5fd8ba 100644 --- a/io/deno.json +++ b/io/deno.json @@ -1,6 +1,6 @@ { "name": "@std/io", - "version": "0.225.1", + "version": "0.225.2", "exports": { ".": "./mod.ts", "./buffer": "./buffer.ts", diff --git a/log/deno.json b/log/deno.json index 8437c073596e..08b9efe3c376 100644 --- a/log/deno.json +++ b/log/deno.json @@ -1,6 +1,6 @@ { "name": "@std/log", - "version": "0.224.13", + "version": "0.224.14", "exports": { ".": "./mod.ts", "./base-handler": "./base_handler.ts", diff --git a/msgpack/_types.ts b/msgpack/_types.ts new file mode 100644 index 000000000000..340b2fcce9d6 --- /dev/null +++ b/msgpack/_types.ts @@ -0,0 +1,11 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +/** + * Proxy type of {@code Uint8Array; diff --git a/msgpack/deno.json b/msgpack/deno.json index 4e39c6b0aad0..40180351ea1d 100644 --- a/msgpack/deno.json +++ b/msgpack/deno.json @@ -1,6 +1,6 @@ { "name": "@std/msgpack", - "version": "1.0.2", + "version": "1.0.3", "exports": { ".": "./mod.ts", "./decode": "./decode.ts", diff --git a/msgpack/encode.ts b/msgpack/encode.ts index ce7b73fd78dd..2d3c2f834104 100644 --- a/msgpack/encode.ts +++ b/msgpack/encode.ts @@ -2,6 +2,8 @@ // This module is browser compatible. import { concat } from "@std/bytes/concat"; +import type { Uint8Array_ } from "./_types.ts"; +export type { Uint8Array_ }; /** * Value types that can be encoded to MessagePack. @@ -61,7 +63,7 @@ const encoder = new TextEncoder(); * @param object Value to encode to MessagePack binary format. * @returns Encoded MessagePack binary data. */ -export function encode(object: ValueType): Uint8Array { +export function encode(object: ValueType): Uint8Array_ { const byteParts: Uint8Array[] = []; encodeSlice(object, byteParts); return concat(byteParts); diff --git a/streams/buffer.ts b/streams/buffer.ts index b9abc98c08af..52324692f69f 100644 --- a/streams/buffer.ts +++ b/streams/buffer.ts @@ -133,7 +133,14 @@ export class Buffer { * @param ab An optional buffer to use as the initial buffer. */ constructor(ab?: ArrayBufferLike | ArrayLike) { - this.#buf = ab === undefined ? new Uint8Array(0) : new Uint8Array(ab); + if (ab === undefined) { + this.#buf = new Uint8Array(0); + } else if (ab instanceof SharedArrayBuffer) { + // Note: This is necessary to avoid type error + this.#buf = new Uint8Array(ab); + } else { + this.#buf = new Uint8Array(ab); + } } /** diff --git a/streams/deno.json b/streams/deno.json index cd5a18764ddb..81ca3e6f11c8 100644 --- a/streams/deno.json +++ b/streams/deno.json @@ -1,6 +1,6 @@ { "name": "@std/streams", - "version": "1.0.8", + "version": "1.0.9", "exports": { ".": "./mod.ts", "./buffer": "./buffer.ts", diff --git a/streams/to_array_buffer.ts b/streams/to_array_buffer.ts index 0a67b1e2754b..d1fae7178eff 100644 --- a/streams/to_array_buffer.ts +++ b/streams/to_array_buffer.ts @@ -39,5 +39,5 @@ export async function toArrayBuffer( chunks.push(value); } - return concat(chunks).buffer; + return concat(chunks).buffer as ArrayBuffer; } diff --git a/tar/deno.json b/tar/deno.json index 033d4caa621a..4d7d40e927c3 100644 --- a/tar/deno.json +++ b/tar/deno.json @@ -1,6 +1,6 @@ { "name": "@std/tar", - "version": "0.1.4", + "version": "0.1.5", "exports": { ".": "./mod.ts", "./tar-stream": "./tar_stream.ts", diff --git a/tar/untar_stream_test.ts b/tar/untar_stream_test.ts index 0d7023c0b143..fa0ce3f5f952 100644 --- a/tar/untar_stream_test.ts +++ b/tar/untar_stream_test.ts @@ -97,7 +97,7 @@ Deno.test("expandTarArchiveCheckingBodies", async () => { .pipeThrough(new TarStream()) .pipeThrough(new UntarStream()); - let buffer = new Uint8Array(); + let buffer: Uint8Array = new Uint8Array(); for await (const item of readable) { if (item.readable) buffer = await toBytes(item.readable); } @@ -122,7 +122,7 @@ Deno.test("UntarStream() with size equals to multiple of 512", async () => { .pipeThrough(new TarStream()) .pipeThrough(new UntarStream()); - let buffer = new Uint8Array(); + let buffer: Uint8Array = new Uint8Array(); for await (const entry of readable) { if (entry.readable) buffer = await toBytes(entry.readable); }