mirror of
https://github.com/denoland/deno.git
synced 2025-01-22 15:10:44 -05:00
feat(std/node): consistent Node.js builtin shapes (#8274)
This commit is contained in:
parent
293cae5e1f
commit
8b7f5531ee
27 changed files with 1900 additions and 1843 deletions
599
std/node/_buffer.ts
Normal file
599
std/node/_buffer.ts
Normal file
|
@ -0,0 +1,599 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import * as hex from "../encoding/hex.ts";
|
||||
import * as base64 from "../encoding/base64.ts";
|
||||
import { normalizeEncoding, notImplemented } from "./_utils.ts";
|
||||
|
||||
const notImplementedEncodings = [
|
||||
"ascii",
|
||||
"binary",
|
||||
"latin1",
|
||||
"ucs2",
|
||||
"utf16le",
|
||||
];
|
||||
|
||||
function checkEncoding(encoding = "utf8", strict = true): string {
|
||||
if (typeof encoding !== "string" || (strict && encoding === "")) {
|
||||
if (!strict) return "utf8";
|
||||
throw new TypeError(`Unkown encoding: ${encoding}`);
|
||||
}
|
||||
|
||||
const normalized = normalizeEncoding(encoding);
|
||||
|
||||
if (normalized === undefined) {
|
||||
throw new TypeError(`Unkown encoding: ${encoding}`);
|
||||
}
|
||||
|
||||
if (notImplementedEncodings.includes(encoding)) {
|
||||
notImplemented(`"${encoding}" encoding`);
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
interface EncodingOp {
|
||||
byteLength(string: string): number;
|
||||
}
|
||||
|
||||
// https://github.com/nodejs/node/blob/56dbe466fdbc598baea3bfce289bf52b97b8b8f7/lib/buffer.js#L598
|
||||
const encodingOps: { [key: string]: EncodingOp } = {
|
||||
utf8: {
|
||||
byteLength: (string: string): number =>
|
||||
new TextEncoder().encode(string).byteLength,
|
||||
},
|
||||
ucs2: {
|
||||
byteLength: (string: string): number => string.length * 2,
|
||||
},
|
||||
utf16le: {
|
||||
byteLength: (string: string): number => string.length * 2,
|
||||
},
|
||||
latin1: {
|
||||
byteLength: (string: string): number => string.length,
|
||||
},
|
||||
ascii: {
|
||||
byteLength: (string: string): number => string.length,
|
||||
},
|
||||
base64: {
|
||||
byteLength: (string: string): number =>
|
||||
base64ByteLength(string, string.length),
|
||||
},
|
||||
hex: {
|
||||
byteLength: (string: string): number => string.length >>> 1,
|
||||
},
|
||||
};
|
||||
|
||||
function base64ByteLength(str: string, bytes: number): number {
|
||||
// Handle padding
|
||||
if (str.charCodeAt(bytes - 1) === 0x3d) bytes--;
|
||||
if (bytes > 1 && str.charCodeAt(bytes - 1) === 0x3d) bytes--;
|
||||
|
||||
// Base64 ratio: 3/4
|
||||
return (bytes * 3) >>> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* See also https://nodejs.org/api/buffer.html
|
||||
*/
|
||||
export class Buffer extends Uint8Array {
|
||||
/**
|
||||
* Allocates a new Buffer of size bytes.
|
||||
*/
|
||||
static alloc(
|
||||
size: number,
|
||||
fill?: number | string | Uint8Array | Buffer,
|
||||
encoding = "utf8",
|
||||
): Buffer {
|
||||
if (typeof size !== "number") {
|
||||
throw new TypeError(
|
||||
`The "size" argument must be of type number. Received type ${typeof size}`,
|
||||
);
|
||||
}
|
||||
|
||||
const buf = new Buffer(size);
|
||||
if (size === 0) return buf;
|
||||
|
||||
let bufFill;
|
||||
if (typeof fill === "string") {
|
||||
encoding = checkEncoding(encoding);
|
||||
if (
|
||||
typeof fill === "string" &&
|
||||
fill.length === 1 &&
|
||||
encoding === "utf8"
|
||||
) {
|
||||
buf.fill(fill.charCodeAt(0));
|
||||
} else bufFill = Buffer.from(fill, encoding);
|
||||
} else if (typeof fill === "number") {
|
||||
buf.fill(fill);
|
||||
} else if (fill instanceof Uint8Array) {
|
||||
if (fill.length === 0) {
|
||||
throw new TypeError(
|
||||
`The argument "value" is invalid. Received ${fill.constructor.name} []`,
|
||||
);
|
||||
}
|
||||
|
||||
bufFill = fill;
|
||||
}
|
||||
|
||||
if (bufFill) {
|
||||
if (bufFill.length > buf.length) {
|
||||
bufFill = bufFill.subarray(0, buf.length);
|
||||
}
|
||||
|
||||
let offset = 0;
|
||||
while (offset < size) {
|
||||
buf.set(bufFill, offset);
|
||||
offset += bufFill.length;
|
||||
if (offset + bufFill.length >= size) break;
|
||||
}
|
||||
if (offset !== size) {
|
||||
buf.set(bufFill.subarray(0, size - offset), offset);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static allocUnsafe(size: number): Buffer {
|
||||
return new Buffer(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the byte length of a string when encoded. This is not the same as
|
||||
* String.prototype.length, which does not account for the encoding that is
|
||||
* used to convert the string into bytes.
|
||||
*/
|
||||
static byteLength(
|
||||
string: string | Buffer | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
|
||||
encoding = "utf8",
|
||||
): number {
|
||||
if (typeof string != "string") return string.byteLength;
|
||||
|
||||
encoding = normalizeEncoding(encoding) || "utf8";
|
||||
return encodingOps[encoding].byteLength(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Buffer which is the result of concatenating all the Buffer
|
||||
* instances in the list together.
|
||||
*/
|
||||
static concat(list: Buffer[] | Uint8Array[], totalLength?: number): Buffer {
|
||||
if (totalLength == undefined) {
|
||||
totalLength = 0;
|
||||
for (const buf of list) {
|
||||
totalLength += buf.length;
|
||||
}
|
||||
}
|
||||
|
||||
const buffer = Buffer.allocUnsafe(totalLength);
|
||||
let pos = 0;
|
||||
for (const item of list) {
|
||||
let buf: Buffer;
|
||||
if (!(item instanceof Buffer)) {
|
||||
buf = Buffer.from(item);
|
||||
} else {
|
||||
buf = item;
|
||||
}
|
||||
buf.copy(buffer, pos);
|
||||
pos += buf.length;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a new Buffer using an array of bytes in the range 0 – 255. Array
|
||||
* entries outside that range will be truncated to fit into it.
|
||||
*/
|
||||
static from(array: number[]): Buffer;
|
||||
/**
|
||||
* This creates a view of the ArrayBuffer without copying the underlying
|
||||
* memory. For example, when passed a reference to the .buffer property of a
|
||||
* TypedArray instance, the newly created Buffer will share the same allocated
|
||||
* memory as the TypedArray.
|
||||
*/
|
||||
static from(
|
||||
arrayBuffer: ArrayBuffer | SharedArrayBuffer,
|
||||
byteOffset?: number,
|
||||
length?: number,
|
||||
): Buffer;
|
||||
/**
|
||||
* Copies the passed buffer data onto a new Buffer instance.
|
||||
*/
|
||||
static from(buffer: Buffer | Uint8Array): Buffer;
|
||||
/**
|
||||
* Creates a new Buffer containing string.
|
||||
*/
|
||||
static from(string: string, encoding?: string): Buffer;
|
||||
static from(
|
||||
// deno-lint-ignore no-explicit-any
|
||||
value: any,
|
||||
offsetOrEncoding?: number | string,
|
||||
length?: number,
|
||||
): Buffer {
|
||||
const offset = typeof offsetOrEncoding === "string"
|
||||
? undefined
|
||||
: offsetOrEncoding;
|
||||
let encoding = typeof offsetOrEncoding === "string"
|
||||
? offsetOrEncoding
|
||||
: undefined;
|
||||
|
||||
if (typeof value == "string") {
|
||||
encoding = checkEncoding(encoding, false);
|
||||
if (encoding === "hex") return new Buffer(hex.decodeString(value).buffer);
|
||||
if (encoding === "base64") return new Buffer(base64.decode(value).buffer);
|
||||
return new Buffer(new TextEncoder().encode(value).buffer);
|
||||
}
|
||||
|
||||
// workaround for https://github.com/microsoft/TypeScript/issues/38446
|
||||
return new Buffer(value, offset!, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if obj is a Buffer, false otherwise.
|
||||
*/
|
||||
static isBuffer(obj: unknown): obj is Buffer {
|
||||
return obj instanceof Buffer;
|
||||
}
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
static isEncoding(encoding: any): boolean {
|
||||
return (
|
||||
typeof encoding === "string" &&
|
||||
encoding.length !== 0 &&
|
||||
normalizeEncoding(encoding) !== undefined
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies data from a region of buf to a region in target, even if the target
|
||||
* memory region overlaps with buf.
|
||||
*/
|
||||
copy(
|
||||
targetBuffer: Buffer | Uint8Array,
|
||||
targetStart = 0,
|
||||
sourceStart = 0,
|
||||
sourceEnd = this.length,
|
||||
): number {
|
||||
const sourceBuffer = this
|
||||
.subarray(sourceStart, sourceEnd)
|
||||
.subarray(0, Math.max(0, targetBuffer.length - targetStart));
|
||||
|
||||
if (sourceBuffer.length === 0) return 0;
|
||||
|
||||
targetBuffer.set(sourceBuffer, targetStart);
|
||||
return sourceBuffer.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if both buf and otherBuffer have exactly the same bytes, false otherwise.
|
||||
*/
|
||||
equals(otherBuffer: Uint8Array | Buffer): boolean {
|
||||
if (!(otherBuffer instanceof Uint8Array)) {
|
||||
throw new TypeError(
|
||||
`The "otherBuffer" argument must be an instance of Buffer or Uint8Array. Received type ${typeof otherBuffer}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (this === otherBuffer) return true;
|
||||
if (this.byteLength !== otherBuffer.byteLength) return false;
|
||||
|
||||
for (let i = 0; i < this.length; i++) {
|
||||
if (this[i] !== otherBuffer[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
readBigInt64BE(offset = 0): bigint {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getBigInt64(offset);
|
||||
}
|
||||
readBigInt64LE(offset = 0): bigint {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getBigInt64(offset, true);
|
||||
}
|
||||
|
||||
readBigUInt64BE(offset = 0): bigint {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getBigUint64(offset);
|
||||
}
|
||||
readBigUInt64LE(offset = 0): bigint {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getBigUint64(offset, true);
|
||||
}
|
||||
|
||||
readDoubleBE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getFloat64(offset);
|
||||
}
|
||||
readDoubleLE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getFloat64(offset, true);
|
||||
}
|
||||
|
||||
readFloatBE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getFloat32(offset);
|
||||
}
|
||||
readFloatLE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getFloat32(offset, true);
|
||||
}
|
||||
|
||||
readInt8(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt8(
|
||||
offset,
|
||||
);
|
||||
}
|
||||
|
||||
readInt16BE(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt16(
|
||||
offset,
|
||||
);
|
||||
}
|
||||
readInt16LE(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt16(
|
||||
offset,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
readInt32BE(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt32(
|
||||
offset,
|
||||
);
|
||||
}
|
||||
readInt32LE(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt32(
|
||||
offset,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
readUInt8(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getUint8(
|
||||
offset,
|
||||
);
|
||||
}
|
||||
|
||||
readUInt16BE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getUint16(offset);
|
||||
}
|
||||
readUInt16LE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getUint16(offset, true);
|
||||
}
|
||||
|
||||
readUInt32BE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getUint32(offset);
|
||||
}
|
||||
readUInt32LE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getUint32(offset, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Buffer that references the same memory as the original, but
|
||||
* offset and cropped by the start and end indices.
|
||||
*/
|
||||
slice(begin = 0, end = this.length): Buffer {
|
||||
// workaround for https://github.com/microsoft/TypeScript/issues/38665
|
||||
return this.subarray(begin, end) as Buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON representation of buf. JSON.stringify() implicitly calls
|
||||
* this function when stringifying a Buffer instance.
|
||||
*/
|
||||
toJSON(): Record<string, unknown> {
|
||||
return { type: "Buffer", data: Array.from(this) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes buf to a string according to the specified character encoding in
|
||||
* encoding. start and end may be passed to decode only a subset of buf.
|
||||
*/
|
||||
toString(encoding = "utf8", start = 0, end = this.length): string {
|
||||
encoding = checkEncoding(encoding);
|
||||
|
||||
const b = this.subarray(start, end);
|
||||
if (encoding === "hex") return hex.encodeToString(b);
|
||||
if (encoding === "base64") return base64.encode(b.buffer);
|
||||
|
||||
return new TextDecoder(encoding).decode(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes string to buf at offset according to the character encoding in
|
||||
* encoding. The length parameter is the number of bytes to write. If buf did
|
||||
* not contain enough space to fit the entire string, only part of string will
|
||||
* be written. However, partially encoded characters will not be written.
|
||||
*/
|
||||
write(string: string, offset = 0, length = this.length): number {
|
||||
return new TextEncoder().encodeInto(
|
||||
string,
|
||||
this.subarray(offset, offset + length),
|
||||
).written;
|
||||
}
|
||||
|
||||
writeBigInt64BE(value: bigint, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setBigInt64(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeBigInt64LE(value: bigint, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setBigInt64(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
writeBigUInt64BE(value: bigint, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setBigUint64(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeBigUInt64LE(value: bigint, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setBigUint64(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
writeDoubleBE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat64(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 8;
|
||||
}
|
||||
writeDoubleLE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat64(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 8;
|
||||
}
|
||||
|
||||
writeFloatBE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat32(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeFloatLE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat32(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
writeInt8(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setInt8(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
writeInt16BE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setInt16(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 2;
|
||||
}
|
||||
writeInt16LE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setInt16(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
writeInt32BE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint32(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeInt32LE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setInt32(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
writeUInt8(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint8(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
writeUInt16BE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint16(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 2;
|
||||
}
|
||||
writeUInt16LE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint16(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
writeUInt32BE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint32(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeUInt32LE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint32(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
}
|
3
std/node/_crypto.ts
Normal file
3
std/node/_crypto.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
export { default as randomBytes } from "./_crypto/randomBytes.ts";
|
||||
export { pbkdf2, pbkdf2Sync } from "./_crypto/pbkdf2.ts";
|
|
@ -1,5 +1,5 @@
|
|||
import { createHash } from "../../hash/mod.ts";
|
||||
import Buffer from "../buffer.ts";
|
||||
import { Buffer } from "../buffer.ts";
|
||||
import { MAX_ALLOC } from "./constants.ts";
|
||||
import { HASH_DATA } from "./types.ts";
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Buffer from "../buffer.ts";
|
||||
import { Buffer } from "../buffer.ts";
|
||||
|
||||
export const MAX_RANDOM_VALUES = 65536;
|
||||
export const MAX_SIZE = 4294967295;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import Buffer from "../buffer.ts";
|
||||
import { Buffer } from "../buffer.ts";
|
||||
|
||||
export type HASH_DATA = string | ArrayBufferView | Buffer;
|
||||
|
|
68
std/node/_fs.ts
Normal file
68
std/node/_fs.ts
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { access, accessSync } from "./_fs/_fs_access.ts";
|
||||
import { appendFile, appendFileSync } from "./_fs/_fs_appendFile.ts";
|
||||
import { chmod, chmodSync } from "./_fs/_fs_chmod.ts";
|
||||
import { chown, chownSync } from "./_fs/_fs_chown.ts";
|
||||
import { close, closeSync } from "./_fs/_fs_close.ts";
|
||||
import * as constants from "./_fs/_fs_constants.ts";
|
||||
import { readFile, readFileSync } from "./_fs/_fs_readFile.ts";
|
||||
import { readlink, readlinkSync } from "./_fs/_fs_readlink.ts";
|
||||
import { exists, existsSync } from "./_fs/_fs_exists.ts";
|
||||
import { mkdir, mkdirSync } from "./_fs/_fs_mkdir.ts";
|
||||
import { copyFile, copyFileSync } from "./_fs/_fs_copy.ts";
|
||||
import { writeFile, writeFileSync } from "./_fs/_fs_writeFile.ts";
|
||||
import { readdir, readdirSync } from "./_fs/_fs_readdir.ts";
|
||||
import { realpath, realpathSync } from "./_fs/_fs_realpath.ts";
|
||||
import { rename, renameSync } from "./_fs/_fs_rename.ts";
|
||||
import { rmdir, rmdirSync } from "./_fs/_fs_rmdir.ts";
|
||||
import { unlink, unlinkSync } from "./_fs/_fs_unlink.ts";
|
||||
import { watch } from "./_fs/_fs_watch.ts";
|
||||
import { open, openSync } from "./_fs/_fs_open.ts";
|
||||
import { stat, statSync } from "./_fs/_fs_stat.ts";
|
||||
import { lstat, lstatSync } from "./_fs/_fs_lstat.ts";
|
||||
|
||||
import * as promises from "./_fs/promises/mod.ts";
|
||||
|
||||
export {
|
||||
access,
|
||||
accessSync,
|
||||
appendFile,
|
||||
appendFileSync,
|
||||
chmod,
|
||||
chmodSync,
|
||||
chown,
|
||||
chownSync,
|
||||
close,
|
||||
closeSync,
|
||||
constants,
|
||||
copyFile,
|
||||
copyFileSync,
|
||||
exists,
|
||||
existsSync,
|
||||
lstat,
|
||||
lstatSync,
|
||||
mkdir,
|
||||
mkdirSync,
|
||||
open,
|
||||
openSync,
|
||||
promises,
|
||||
readdir,
|
||||
readdirSync,
|
||||
readFile,
|
||||
readFileSync,
|
||||
readlink,
|
||||
readlinkSync,
|
||||
realpath,
|
||||
realpathSync,
|
||||
rename,
|
||||
renameSync,
|
||||
rmdir,
|
||||
rmdirSync,
|
||||
stat,
|
||||
statSync,
|
||||
unlink,
|
||||
unlinkSync,
|
||||
watch,
|
||||
writeFile,
|
||||
writeFileSync,
|
||||
};
|
224
std/node/_os.ts
Normal file
224
std/node/_os.ts
Normal file
|
@ -0,0 +1,224 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
import { notImplemented } from "./_utils.ts";
|
||||
import { validateIntegerRange } from "./_utils.ts";
|
||||
import { EOL as fsEOL } from "../fs/eol.ts";
|
||||
import process from "./process.ts";
|
||||
|
||||
const SEE_GITHUB_ISSUE = "See https://github.com/denoland/deno/issues/3802";
|
||||
|
||||
interface CPUTimes {
|
||||
/** The number of milliseconds the CPU has spent in user mode */
|
||||
user: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in nice mode */
|
||||
nice: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in sys mode */
|
||||
sys: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in idle mode */
|
||||
idle: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in irq mode */
|
||||
irq: number;
|
||||
}
|
||||
|
||||
interface CPUCoreInfo {
|
||||
model: string;
|
||||
|
||||
/** in MHz */
|
||||
speed: number;
|
||||
|
||||
times: CPUTimes;
|
||||
}
|
||||
|
||||
interface NetworkAddress {
|
||||
/** The assigned IPv4 or IPv6 address */
|
||||
address: string;
|
||||
|
||||
/** The IPv4 or IPv6 network mask */
|
||||
netmask: string;
|
||||
|
||||
family: "IPv4" | "IPv6";
|
||||
|
||||
/** The MAC address of the network interface */
|
||||
mac: string;
|
||||
|
||||
/** true if the network interface is a loopback or similar interface that is not remotely accessible; otherwise false */
|
||||
internal: boolean;
|
||||
|
||||
/** The numeric IPv6 scope ID (only specified when family is IPv6) */
|
||||
scopeid?: number;
|
||||
|
||||
/** The assigned IPv4 or IPv6 address with the routing prefix in CIDR notation. If the netmask is invalid, this property is set to null. */
|
||||
cidr: string;
|
||||
}
|
||||
|
||||
interface NetworkInterfaces {
|
||||
[key: string]: NetworkAddress[];
|
||||
}
|
||||
|
||||
export interface UserInfoOptions {
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
interface UserInfo {
|
||||
username: string;
|
||||
uid: number;
|
||||
gid: number;
|
||||
shell: string;
|
||||
homedir: string;
|
||||
}
|
||||
|
||||
arch[Symbol.toPrimitive] = (): string => arch();
|
||||
endianness[Symbol.toPrimitive] = (): string => endianness();
|
||||
freemem[Symbol.toPrimitive] = (): number => freemem();
|
||||
homedir[Symbol.toPrimitive] = (): string | null => homedir();
|
||||
hostname[Symbol.toPrimitive] = (): string | null => hostname();
|
||||
platform[Symbol.toPrimitive] = (): string => platform();
|
||||
release[Symbol.toPrimitive] = (): string => release();
|
||||
totalmem[Symbol.toPrimitive] = (): number => totalmem();
|
||||
type[Symbol.toPrimitive] = (): string => type();
|
||||
uptime[Symbol.toPrimitive] = (): number => uptime();
|
||||
|
||||
/** Returns the operating system CPU architecture for which the Deno binary was compiled */
|
||||
export function arch(): string {
|
||||
return Deno.build.arch;
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function cpus(): CPUCoreInfo[] {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string identifying the endianness of the CPU for which the Deno
|
||||
* binary was compiled. Possible values are 'BE' for big endian and 'LE' for
|
||||
* little endian.
|
||||
**/
|
||||
export function endianness(): "BE" | "LE" {
|
||||
// Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness
|
||||
const buffer = new ArrayBuffer(2);
|
||||
new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
|
||||
// Int16Array uses the platform's endianness.
|
||||
return new Int16Array(buffer)[0] === 256 ? "LE" : "BE";
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function freemem(): number {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function getPriority(pid = 0): number {
|
||||
validateIntegerRange(pid, "pid");
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Returns the string path of the current user's home directory. */
|
||||
export function homedir(): string | null {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Returns the host name of the operating system as a string. */
|
||||
export function hostname(): string {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Returns an array containing the 1, 5, and 15 minute load averages */
|
||||
export function loadavg(): number[] {
|
||||
if (Deno.build.os === "windows") {
|
||||
return [0, 0, 0];
|
||||
}
|
||||
return Deno.loadavg();
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function networkInterfaces(): NetworkInterfaces {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
/** Returns the a string identifying the operating system platform. The value is set at compile time. Possible values are 'darwin', 'linux', and 'win32'. */
|
||||
export function platform(): string {
|
||||
return process.platform;
|
||||
}
|
||||
|
||||
/** Returns the operating system as a string */
|
||||
export function release(): string {
|
||||
return Deno.osRelease();
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function setPriority(pid: number, priority?: number): void {
|
||||
/* The node API has the 'pid' as the first parameter and as optional.
|
||||
This makes for a problematic implementation in Typescript. */
|
||||
if (priority === undefined) {
|
||||
priority = pid;
|
||||
pid = 0;
|
||||
}
|
||||
validateIntegerRange(pid, "pid");
|
||||
validateIntegerRange(priority, "priority", -20, 19);
|
||||
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Returns the operating system's default directory for temporary files as a string. */
|
||||
export function tmpdir(): string | null {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function totalmem(): number {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function type(): string {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function uptime(): number {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function userInfo(
|
||||
options: UserInfoOptions = { encoding: "utf-8" },
|
||||
): UserInfo {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
export const constants = {
|
||||
// UV_UDP_REUSEADDR: 4, //see https://nodejs.org/docs/latest-v12.x/api/os.html#os_libuv_constants
|
||||
dlopen: {
|
||||
// see https://nodejs.org/docs/latest-v12.x/api/os.html#os_dlopen_constants
|
||||
},
|
||||
errno: {
|
||||
// see https://nodejs.org/docs/latest-v12.x/api/os.html#os_error_constants
|
||||
},
|
||||
signals: Deno.Signal,
|
||||
priority: {
|
||||
// see https://nodejs.org/docs/latest-v12.x/api/os.html#os_priority_constants
|
||||
},
|
||||
};
|
||||
|
||||
export const EOL = Deno.build.os == "windows" ? fsEOL.CRLF : fsEOL.LF;
|
156
std/node/_querystring.ts
Normal file
156
std/node/_querystring.ts
Normal file
|
@ -0,0 +1,156 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
interface ParseOptions {
|
||||
/** The function to use when decoding percent-encoded characters in the query string. */
|
||||
decodeURIComponent?: (string: string) => string;
|
||||
/** Specifies the maximum number of keys to parse. */
|
||||
maxKeys?: number;
|
||||
}
|
||||
|
||||
export const hexTable = new Array(256);
|
||||
for (let i = 0; i < 256; ++i) {
|
||||
hexTable[i] = "%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a URL query string into a collection of key and value pairs.
|
||||
* @param str The URL query string to parse
|
||||
* @param sep The substring used to delimit key and value pairs in the query string. Default: '&'.
|
||||
* @param eq The substring used to delimit keys and values in the query string. Default: '='.
|
||||
* @param options The parse options
|
||||
*/
|
||||
export function parse(
|
||||
str: string,
|
||||
sep = "&",
|
||||
eq = "=",
|
||||
{ decodeURIComponent = unescape, maxKeys = 1000 }: ParseOptions = {},
|
||||
): { [key: string]: string[] | string } {
|
||||
const entries = str
|
||||
.split(sep)
|
||||
.map((entry) => entry.split(eq).map(decodeURIComponent));
|
||||
const final: { [key: string]: string[] | string } = {};
|
||||
|
||||
let i = 0;
|
||||
while (true) {
|
||||
if ((Object.keys(final).length === maxKeys && !!maxKeys) || !entries[i]) {
|
||||
break;
|
||||
}
|
||||
|
||||
const [key, val] = entries[i];
|
||||
if (final[key]) {
|
||||
if (Array.isArray(final[key])) {
|
||||
(final[key] as string[]).push(val);
|
||||
} else {
|
||||
final[key] = [final[key] as string, val];
|
||||
}
|
||||
} else {
|
||||
final[key] = val;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
interface StringifyOptions {
|
||||
/** The function to use when converting URL-unsafe characters to percent-encoding in the query string. */
|
||||
encodeURIComponent?: (string: string) => string;
|
||||
}
|
||||
|
||||
export function encodeStr(
|
||||
str: string,
|
||||
noEscapeTable: number[],
|
||||
hexTable: string[],
|
||||
): string {
|
||||
const len = str.length;
|
||||
if (len === 0) return "";
|
||||
|
||||
let out = "";
|
||||
let lastPos = 0;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
let c = str.charCodeAt(i);
|
||||
// ASCII
|
||||
if (c < 0x80) {
|
||||
if (noEscapeTable[c] === 1) continue;
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
lastPos = i + 1;
|
||||
out += hexTable[c];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
|
||||
// Multi-byte characters ...
|
||||
if (c < 0x800) {
|
||||
lastPos = i + 1;
|
||||
out += hexTable[0xc0 | (c >> 6)] + hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
if (c < 0xd800 || c >= 0xe000) {
|
||||
lastPos = i + 1;
|
||||
out += hexTable[0xe0 | (c >> 12)] +
|
||||
hexTable[0x80 | ((c >> 6) & 0x3f)] +
|
||||
hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
// Surrogate pair
|
||||
++i;
|
||||
|
||||
// This branch should never happen because all URLSearchParams entries
|
||||
// should already be converted to USVString. But, included for
|
||||
// completion's sake anyway.
|
||||
if (i >= len) throw new Deno.errors.InvalidData("invalid URI");
|
||||
|
||||
const c2 = str.charCodeAt(i) & 0x3ff;
|
||||
|
||||
lastPos = i + 1;
|
||||
c = 0x10000 + (((c & 0x3ff) << 10) | c2);
|
||||
out += hexTable[0xf0 | (c >> 18)] +
|
||||
hexTable[0x80 | ((c >> 12) & 0x3f)] +
|
||||
hexTable[0x80 | ((c >> 6) & 0x3f)] +
|
||||
hexTable[0x80 | (c & 0x3f)];
|
||||
}
|
||||
if (lastPos === 0) return str;
|
||||
if (lastPos < len) return out + str.slice(lastPos);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a URL query string from a given obj by iterating through the object's "own properties".
|
||||
* @param obj The object to serialize into a URL query string.
|
||||
* @param sep The substring used to delimit key and value pairs in the query string. Default: '&'.
|
||||
* @param eq The substring used to delimit keys and values in the query string. Default: '='.
|
||||
* @param options The stringify options
|
||||
*/
|
||||
export function stringify(
|
||||
// deno-lint-ignore no-explicit-any
|
||||
obj: Record<string, any>,
|
||||
sep = "&",
|
||||
eq = "=",
|
||||
{ encodeURIComponent = escape }: StringifyOptions = {},
|
||||
): string {
|
||||
const final = [];
|
||||
|
||||
for (const entry of Object.entries(obj)) {
|
||||
if (Array.isArray(entry[1])) {
|
||||
for (const val of entry[1]) {
|
||||
final.push(encodeURIComponent(entry[0]) + eq + encodeURIComponent(val));
|
||||
}
|
||||
} else if (typeof entry[1] !== "object" && entry[1] !== undefined) {
|
||||
final.push(entry.map(encodeURIComponent).join(eq));
|
||||
} else {
|
||||
final.push(encodeURIComponent(entry[0]) + eq);
|
||||
}
|
||||
}
|
||||
|
||||
return final.join(sep);
|
||||
}
|
||||
|
||||
/** Alias of querystring.parse() */
|
||||
export const decode = parse;
|
||||
/** Alias of querystring.stringify() */
|
||||
export const encode = stringify;
|
||||
export const unescape = decodeURIComponent;
|
||||
export const escape = encodeURIComponent;
|
299
std/node/_string_decoder.ts
Normal file
299
std/node/_string_decoder.ts
Normal file
|
@ -0,0 +1,299 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import { Buffer } from "./buffer.ts";
|
||||
import { normalizeEncoding as castEncoding, notImplemented } from "./_utils.ts";
|
||||
|
||||
enum NotImplemented {
|
||||
"ascii",
|
||||
"latin1",
|
||||
"utf16le",
|
||||
}
|
||||
|
||||
function normalizeEncoding(enc?: string): string {
|
||||
const encoding = castEncoding(enc ?? null);
|
||||
if (encoding && encoding in NotImplemented) notImplemented(encoding);
|
||||
if (!encoding && typeof enc === "string" && enc.toLowerCase() !== "raw") {
|
||||
throw new Error(`Unknown encoding: ${enc}`);
|
||||
}
|
||||
return String(encoding);
|
||||
}
|
||||
/*
|
||||
* Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
|
||||
* continuation byte. If an invalid byte is detected, -2 is returned.
|
||||
* */
|
||||
function utf8CheckByte(byte: number): number {
|
||||
if (byte <= 0x7f) return 0;
|
||||
else if (byte >> 5 === 0x06) return 2;
|
||||
else if (byte >> 4 === 0x0e) return 3;
|
||||
else if (byte >> 3 === 0x1e) return 4;
|
||||
return byte >> 6 === 0x02 ? -1 : -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks at most 3 bytes at the end of a Buffer in order to detect an
|
||||
* incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4)
|
||||
* needed to complete the UTF-8 character (if applicable) are returned.
|
||||
* */
|
||||
function utf8CheckIncomplete(
|
||||
self: StringDecoderBase,
|
||||
buf: Buffer,
|
||||
i: number,
|
||||
): number {
|
||||
let j = buf.length - 1;
|
||||
if (j < i) return 0;
|
||||
let nb = utf8CheckByte(buf[j]);
|
||||
if (nb >= 0) {
|
||||
if (nb > 0) self.lastNeed = nb - 1;
|
||||
return nb;
|
||||
}
|
||||
if (--j < i || nb === -2) return 0;
|
||||
nb = utf8CheckByte(buf[j]);
|
||||
if (nb >= 0) {
|
||||
if (nb > 0) self.lastNeed = nb - 2;
|
||||
return nb;
|
||||
}
|
||||
if (--j < i || nb === -2) return 0;
|
||||
nb = utf8CheckByte(buf[j]);
|
||||
if (nb >= 0) {
|
||||
if (nb > 0) {
|
||||
if (nb === 2) nb = 0;
|
||||
else self.lastNeed = nb - 3;
|
||||
}
|
||||
return nb;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validates as many continuation bytes for a multi-byte UTF-8 character as
|
||||
* needed or are available. If we see a non-continuation byte where we expect
|
||||
* one, we "replace" the validated continuation bytes we've seen so far with
|
||||
* a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding
|
||||
* behavior. The continuation byte check is included three times in the case
|
||||
* where all of the continuation bytes for a character exist in the same buffer.
|
||||
* It is also done this way as a slight performance increase instead of using a
|
||||
* loop.
|
||||
* */
|
||||
function utf8CheckExtraBytes(
|
||||
self: StringDecoderBase,
|
||||
buf: Buffer,
|
||||
): string | undefined {
|
||||
if ((buf[0] & 0xc0) !== 0x80) {
|
||||
self.lastNeed = 0;
|
||||
return "\ufffd";
|
||||
}
|
||||
if (self.lastNeed > 1 && buf.length > 1) {
|
||||
if ((buf[1] & 0xc0) !== 0x80) {
|
||||
self.lastNeed = 1;
|
||||
return "\ufffd";
|
||||
}
|
||||
if (self.lastNeed > 2 && buf.length > 2) {
|
||||
if ((buf[2] & 0xc0) !== 0x80) {
|
||||
self.lastNeed = 2;
|
||||
return "\ufffd";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer.
|
||||
* */
|
||||
function utf8FillLastComplete(
|
||||
this: StringDecoderBase,
|
||||
buf: Buffer,
|
||||
): string | undefined {
|
||||
const p = this.lastTotal - this.lastNeed;
|
||||
const r = utf8CheckExtraBytes(this, buf);
|
||||
if (r !== undefined) return r;
|
||||
if (this.lastNeed <= buf.length) {
|
||||
buf.copy(this.lastChar, p, 0, this.lastNeed);
|
||||
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
||||
}
|
||||
buf.copy(this.lastChar, p, 0, buf.length);
|
||||
this.lastNeed -= buf.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to complete a partial non-UTF-8 character using bytes from a Buffer
|
||||
* */
|
||||
function utf8FillLastIncomplete(
|
||||
this: StringDecoderBase,
|
||||
buf: Buffer,
|
||||
): string | undefined {
|
||||
if (this.lastNeed <= buf.length) {
|
||||
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
|
||||
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
||||
}
|
||||
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length);
|
||||
this.lastNeed -= buf.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a
|
||||
* partial character, the character's bytes are buffered until the required
|
||||
* number of bytes are available.
|
||||
* */
|
||||
function utf8Text(this: StringDecoderBase, buf: Buffer, i: number): string {
|
||||
const total = utf8CheckIncomplete(this, buf, i);
|
||||
if (!this.lastNeed) return buf.toString("utf8", i);
|
||||
this.lastTotal = total;
|
||||
const end = buf.length - (total - this.lastNeed);
|
||||
buf.copy(this.lastChar, 0, end);
|
||||
return buf.toString("utf8", i, end);
|
||||
}
|
||||
|
||||
/*
|
||||
* For UTF-8, a replacement character is added when ending on a partial
|
||||
* character.
|
||||
* */
|
||||
function utf8End(this: Utf8Decoder, buf?: Buffer): string {
|
||||
const r = buf && buf.length ? this.write(buf) : "";
|
||||
if (this.lastNeed) return r + "\ufffd";
|
||||
return r;
|
||||
}
|
||||
|
||||
function utf8Write(this: Utf8Decoder | Base64Decoder, buf: Buffer): string {
|
||||
if (buf.length === 0) return "";
|
||||
let r;
|
||||
let i;
|
||||
if (this.lastNeed) {
|
||||
r = this.fillLast(buf);
|
||||
if (r === undefined) return "";
|
||||
i = this.lastNeed;
|
||||
this.lastNeed = 0;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
|
||||
return r || "";
|
||||
}
|
||||
|
||||
function base64Text(this: StringDecoderBase, buf: Buffer, i: number): string {
|
||||
const n = (buf.length - i) % 3;
|
||||
if (n === 0) return buf.toString("base64", i);
|
||||
this.lastNeed = 3 - n;
|
||||
this.lastTotal = 3;
|
||||
if (n === 1) {
|
||||
this.lastChar[0] = buf[buf.length - 1];
|
||||
} else {
|
||||
this.lastChar[0] = buf[buf.length - 2];
|
||||
this.lastChar[1] = buf[buf.length - 1];
|
||||
}
|
||||
return buf.toString("base64", i, buf.length - n);
|
||||
}
|
||||
|
||||
function base64End(this: Base64Decoder, buf?: Buffer): string {
|
||||
const r = buf && buf.length ? this.write(buf) : "";
|
||||
if (this.lastNeed) {
|
||||
return r + this.lastChar.toString("base64", 0, 3 - this.lastNeed);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function simpleWrite(this: StringDecoderBase, buf: Buffer): string {
|
||||
return buf.toString(this.encoding);
|
||||
}
|
||||
|
||||
function simpleEnd(this: GenericDecoder, buf?: Buffer): string {
|
||||
return buf && buf.length ? this.write(buf) : "";
|
||||
}
|
||||
|
||||
class StringDecoderBase {
|
||||
public lastChar: Buffer;
|
||||
public lastNeed = 0;
|
||||
public lastTotal = 0;
|
||||
constructor(public encoding: string, nb: number) {
|
||||
this.lastChar = Buffer.allocUnsafe(nb);
|
||||
}
|
||||
}
|
||||
|
||||
class Base64Decoder extends StringDecoderBase {
|
||||
public end = base64End;
|
||||
public fillLast = utf8FillLastIncomplete;
|
||||
public text = base64Text;
|
||||
public write = utf8Write;
|
||||
|
||||
constructor(encoding?: string) {
|
||||
super(normalizeEncoding(encoding), 3);
|
||||
}
|
||||
}
|
||||
|
||||
class GenericDecoder extends StringDecoderBase {
|
||||
public end = simpleEnd;
|
||||
public fillLast = undefined;
|
||||
public text = utf8Text;
|
||||
public write = simpleWrite;
|
||||
|
||||
constructor(encoding?: string) {
|
||||
super(normalizeEncoding(encoding), 4);
|
||||
}
|
||||
}
|
||||
|
||||
class Utf8Decoder extends StringDecoderBase {
|
||||
public end = utf8End;
|
||||
public fillLast = utf8FillLastComplete;
|
||||
public text = utf8Text;
|
||||
public write = utf8Write;
|
||||
|
||||
constructor(encoding?: string) {
|
||||
super(normalizeEncoding(encoding), 4);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* StringDecoder provides an interface for efficiently splitting a series of
|
||||
* buffers into a series of JS strings without breaking apart multi-byte
|
||||
* characters.
|
||||
* */
|
||||
export class StringDecoder {
|
||||
public encoding: string;
|
||||
public end: (buf?: Buffer) => string;
|
||||
public fillLast: ((buf: Buffer) => string | undefined) | undefined;
|
||||
public lastChar: Buffer;
|
||||
public lastNeed: number;
|
||||
public lastTotal: number;
|
||||
public text: (buf: Buffer, n: number) => string;
|
||||
public write: (buf: Buffer) => string;
|
||||
|
||||
constructor(encoding?: string) {
|
||||
let decoder;
|
||||
switch (encoding) {
|
||||
case "utf8":
|
||||
decoder = new Utf8Decoder(encoding);
|
||||
break;
|
||||
case "base64":
|
||||
decoder = new Base64Decoder(encoding);
|
||||
break;
|
||||
default:
|
||||
decoder = new GenericDecoder(encoding);
|
||||
}
|
||||
this.encoding = decoder.encoding;
|
||||
this.end = decoder.end;
|
||||
this.fillLast = decoder.fillLast;
|
||||
this.lastChar = decoder.lastChar;
|
||||
this.lastNeed = decoder.lastNeed;
|
||||
this.lastTotal = decoder.lastTotal;
|
||||
this.text = decoder.text;
|
||||
this.write = decoder.write;
|
||||
}
|
||||
}
|
14
std/node/_timers.ts
Normal file
14
std/node/_timers.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
// TODO: implement the 'NodeJS.Timeout' and 'NodeJS.Immediate' versions of the timers.
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/1163ead296d84e7a3c80d71e7c81ecbd1a130e9a/types/node/v12/globals.d.ts#L1120-L1131
|
||||
export const setTimeout = window.setTimeout;
|
||||
export const clearTimeout = window.clearTimeout;
|
||||
export const setInterval = window.setInterval;
|
||||
export const clearInterval = window.clearInterval;
|
||||
export const setImmediate = (
|
||||
// deno-lint-ignore no-explicit-any
|
||||
cb: (...args: any[]) => void,
|
||||
// deno-lint-ignore no-explicit-any
|
||||
...args: any[]
|
||||
): number => window.setTimeout(cb, 0, ...args);
|
||||
export const clearImmediate = window.clearTimeout;
|
140
std/node/_url.ts
Normal file
140
std/node/_url.ts
Normal file
|
@ -0,0 +1,140 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import {
|
||||
CHAR_BACKWARD_SLASH,
|
||||
CHAR_FORWARD_SLASH,
|
||||
CHAR_LOWERCASE_A,
|
||||
CHAR_LOWERCASE_Z,
|
||||
} from "../path/_constants.ts";
|
||||
import * as path from "./path.ts";
|
||||
|
||||
const isWindows = Deno.build.os === "windows";
|
||||
|
||||
const forwardSlashRegEx = /\//g;
|
||||
const percentRegEx = /%/g;
|
||||
const backslashRegEx = /\\/g;
|
||||
const newlineRegEx = /\n/g;
|
||||
const carriageReturnRegEx = /\r/g;
|
||||
const tabRegEx = /\t/g;
|
||||
|
||||
const _url = URL;
|
||||
export { _url as URL };
|
||||
|
||||
/**
|
||||
* Get fully resolved platform-specific file path from the given URL string/ object
|
||||
* @param path The file URL string or URL object to convert to a path
|
||||
*/
|
||||
export function fileURLToPath(path: string | URL): string {
|
||||
if (typeof path === "string") path = new URL(path);
|
||||
else if (!(path instanceof URL)) {
|
||||
throw new Deno.errors.InvalidData(
|
||||
"invalid argument path , must be a string or URL",
|
||||
);
|
||||
}
|
||||
if (path.protocol !== "file:") {
|
||||
throw new Deno.errors.InvalidData("invalid url scheme");
|
||||
}
|
||||
return isWindows ? getPathFromURLWin(path) : getPathFromURLPosix(path);
|
||||
}
|
||||
|
||||
function getPathFromURLWin(url: URL): string {
|
||||
const hostname = url.hostname;
|
||||
let pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === "%") {
|
||||
const third = pathname.codePointAt(n + 2) || 0x20;
|
||||
if (
|
||||
(pathname[n + 1] === "2" && third === 102) || // 2f 2F /
|
||||
(pathname[n + 1] === "5" && third === 99)
|
||||
) {
|
||||
// 5c 5C \
|
||||
throw new Deno.errors.InvalidData(
|
||||
"must not include encoded \\ or / characters",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pathname = pathname.replace(forwardSlashRegEx, "\\");
|
||||
pathname = decodeURIComponent(pathname);
|
||||
if (hostname !== "") {
|
||||
//TODO add support for punycode encodings
|
||||
return `\\\\${hostname}${pathname}`;
|
||||
} else {
|
||||
// Otherwise, it's a local path that requires a drive letter
|
||||
const letter = pathname.codePointAt(1)! | 0x20;
|
||||
const sep = pathname[2];
|
||||
if (
|
||||
letter < CHAR_LOWERCASE_A ||
|
||||
letter > CHAR_LOWERCASE_Z || // a..z A..Z
|
||||
sep !== ":"
|
||||
) {
|
||||
throw new Deno.errors.InvalidData("file url path must be absolute");
|
||||
}
|
||||
return pathname.slice(1);
|
||||
}
|
||||
}
|
||||
|
||||
function getPathFromURLPosix(url: URL): string {
|
||||
if (url.hostname !== "") {
|
||||
throw new Deno.errors.InvalidData("invalid file url hostname");
|
||||
}
|
||||
const pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === "%") {
|
||||
const third = pathname.codePointAt(n + 2) || 0x20;
|
||||
if (pathname[n + 1] === "2" && third === 102) {
|
||||
throw new Deno.errors.InvalidData(
|
||||
"must not include encoded / characters",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return decodeURIComponent(pathname);
|
||||
}
|
||||
|
||||
/** Get fully resolved platform-specific File URL from the given file path */
|
||||
export function pathToFileURL(filepath: string): URL {
|
||||
let resolved = path.resolve(filepath);
|
||||
// path.resolve strips trailing slashes so we must add them back
|
||||
const filePathLast = filepath.charCodeAt(filepath.length - 1);
|
||||
if (
|
||||
(filePathLast === CHAR_FORWARD_SLASH ||
|
||||
(isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&
|
||||
resolved[resolved.length - 1] !== path.sep
|
||||
) {
|
||||
resolved += "/";
|
||||
}
|
||||
const outURL = new URL("file://");
|
||||
if (resolved.includes("%")) resolved = resolved.replace(percentRegEx, "%25");
|
||||
// In posix, "/" is a valid character in paths
|
||||
if (!isWindows && resolved.includes("\\")) {
|
||||
resolved = resolved.replace(backslashRegEx, "%5C");
|
||||
}
|
||||
if (resolved.includes("\n")) resolved = resolved.replace(newlineRegEx, "%0A");
|
||||
if (resolved.includes("\r")) {
|
||||
resolved = resolved.replace(carriageReturnRegEx, "%0D");
|
||||
}
|
||||
if (resolved.includes("\t")) resolved = resolved.replace(tabRegEx, "%09");
|
||||
outURL.pathname = resolved;
|
||||
return outURL;
|
||||
}
|
134
std/node/_util.ts
Normal file
134
std/node/_util.ts
Normal file
|
@ -0,0 +1,134 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
export { promisify } from "./_util/_util_promisify.ts";
|
||||
export { callbackify } from "./_util/_util_callbackify.ts";
|
||||
import { codes, errorMap } from "./_errors.ts";
|
||||
import * as types from "./_util/_util_types.ts";
|
||||
export { types };
|
||||
|
||||
const NumberIsSafeInteger = Number.isSafeInteger;
|
||||
const {
|
||||
ERR_OUT_OF_RANGE,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
} = codes;
|
||||
|
||||
const DEFAULT_INSPECT_OPTIONS = {
|
||||
showHidden: false,
|
||||
depth: 2,
|
||||
colors: false,
|
||||
customInspect: true,
|
||||
showProxy: false,
|
||||
maxArrayLength: 100,
|
||||
maxStringLength: Infinity,
|
||||
breakLength: 80,
|
||||
compact: 3,
|
||||
sorted: false,
|
||||
getters: false,
|
||||
};
|
||||
|
||||
inspect.defaultOptions = DEFAULT_INSPECT_OPTIONS;
|
||||
inspect.custom = Deno.customInspect;
|
||||
|
||||
// TODO(schwarzkopfb): make it in-line with Node's implementation
|
||||
// Ref: https://nodejs.org/dist/latest-v14.x/docs/api/util.html#util_util_inspect_object_options
|
||||
// deno-lint-ignore no-explicit-any
|
||||
export function inspect(object: unknown, ...opts: any): string {
|
||||
opts = { ...DEFAULT_INSPECT_OPTIONS, ...opts };
|
||||
return Deno.inspect(object, {
|
||||
depth: opts.depth,
|
||||
iterableLimit: opts.maxArrayLength,
|
||||
compact: !!opts.compact,
|
||||
sorted: !!opts.sorted,
|
||||
showProxy: !!opts.showProxy,
|
||||
});
|
||||
}
|
||||
|
||||
/** @deprecated - use `Array.isArray()` instead. */
|
||||
export function isArray(value: unknown): boolean {
|
||||
return Array.isArray(value);
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "boolean" || value instanceof Boolean` instead. */
|
||||
export function isBoolean(value: unknown): boolean {
|
||||
return typeof value === "boolean" || value instanceof Boolean;
|
||||
}
|
||||
|
||||
/** @deprecated - use `value === null` instead. */
|
||||
export function isNull(value: unknown): boolean {
|
||||
return value === null;
|
||||
}
|
||||
|
||||
/** @deprecated - use `value === null || value === undefined` instead. */
|
||||
export function isNullOrUndefined(value: unknown): boolean {
|
||||
return value === null || value === undefined;
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "number" || value instanceof Number` instead. */
|
||||
export function isNumber(value: unknown): boolean {
|
||||
return typeof value === "number" || value instanceof Number;
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "string" || value instanceof String` instead. */
|
||||
export function isString(value: unknown): boolean {
|
||||
return typeof value === "string" || value instanceof String;
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "symbol"` instead. */
|
||||
export function isSymbol(value: unknown): boolean {
|
||||
return typeof value === "symbol";
|
||||
}
|
||||
|
||||
/** @deprecated - use `value === undefined` instead. */
|
||||
export function isUndefined(value: unknown): boolean {
|
||||
return value === undefined;
|
||||
}
|
||||
|
||||
/** @deprecated - use `value !== null && typeof value === "object"` instead. */
|
||||
export function isObject(value: unknown): boolean {
|
||||
return value !== null && typeof value === "object";
|
||||
}
|
||||
|
||||
/** @deprecated - use `e instanceof Error` instead. */
|
||||
export function isError(e: unknown): boolean {
|
||||
return e instanceof Error;
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "function"` instead. */
|
||||
export function isFunction(value: unknown): boolean {
|
||||
return typeof value === "function";
|
||||
}
|
||||
|
||||
/** @deprecated - use `value instanceof RegExp` instead. */
|
||||
export function isRegExp(value: unknown): boolean {
|
||||
return value instanceof RegExp;
|
||||
}
|
||||
|
||||
/** @deprecated - use `value === null || (typeof value !== "object" && typeof value !== "function")` instead. */
|
||||
export function isPrimitive(value: unknown): boolean {
|
||||
return (
|
||||
value === null || (typeof value !== "object" && typeof value !== "function")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a system error name from an error code number.
|
||||
* @param code error code number
|
||||
*/
|
||||
export function getSystemErrorName(code: number): string | undefined {
|
||||
if (typeof code !== "number") {
|
||||
throw new ERR_INVALID_ARG_TYPE("err", "number", code);
|
||||
}
|
||||
if (code >= 0 || !NumberIsSafeInteger(code)) {
|
||||
throw new ERR_OUT_OF_RANGE("err", "a negative integer", code);
|
||||
}
|
||||
return errorMap.get(code)?.[0];
|
||||
}
|
||||
|
||||
import { _TextDecoder, _TextEncoder } from "./_utils.ts";
|
||||
|
||||
/** The global TextDecoder */
|
||||
export type TextDecoder = import("./_utils.ts")._TextDecoder;
|
||||
export const TextDecoder = _TextDecoder;
|
||||
|
||||
/** The global TextEncoder */
|
||||
export type TextEncoder = import("./_utils.ts")._TextEncoder;
|
||||
export const TextEncoder = _TextEncoder;
|
|
@ -1,25 +1,42 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import {
|
||||
assertEquals,
|
||||
assertMatch,
|
||||
assertNotEquals,
|
||||
assertNotStrictEquals,
|
||||
assertStrictEquals,
|
||||
assertThrows,
|
||||
} from "../testing/asserts.ts";
|
||||
|
||||
export { AssertionError } from "./assertion_error.ts";
|
||||
|
||||
export {
|
||||
assert,
|
||||
assert as default,
|
||||
assert as ok,
|
||||
import {
|
||||
assertEquals as deepStrictEqual,
|
||||
AssertionError,
|
||||
assertMatch as match,
|
||||
assertNotEquals as notDeepStrictEqual,
|
||||
assertNotStrictEquals as notStrictEqual,
|
||||
assertStrictEquals as strictEqual,
|
||||
assertThrows as throws,
|
||||
fail,
|
||||
} from "../testing/asserts.ts";
|
||||
|
||||
export const deepStrictEqual = assertEquals;
|
||||
export const notDeepStrictEqual = assertNotEquals;
|
||||
export const strictEqual = assertStrictEquals;
|
||||
export const notStrictEqual = assertNotStrictEquals;
|
||||
export const match = assertMatch;
|
||||
export const throws = assertThrows;
|
||||
function assert(expr: unknown, msg = ""): asserts expr {
|
||||
if (!expr) {
|
||||
throw new AssertionError(msg);
|
||||
}
|
||||
}
|
||||
const ok = assert;
|
||||
export default assert;
|
||||
|
||||
Object.assign(assert, {
|
||||
deepStrictEqual,
|
||||
fail,
|
||||
match,
|
||||
notDeepStrictEqual,
|
||||
notStrictEqual,
|
||||
ok,
|
||||
strictEqual,
|
||||
throws,
|
||||
});
|
||||
|
||||
export {
|
||||
deepStrictEqual,
|
||||
fail,
|
||||
match,
|
||||
notDeepStrictEqual,
|
||||
notStrictEqual,
|
||||
ok,
|
||||
strictEqual,
|
||||
throws,
|
||||
};
|
||||
|
|
|
@ -13,7 +13,6 @@ import {
|
|||
import AssertionError from "./assertion_error.ts";
|
||||
|
||||
import assert, {
|
||||
assert as assert_,
|
||||
AssertionError as AssertionError_,
|
||||
deepStrictEqual,
|
||||
fail,
|
||||
|
@ -26,13 +25,7 @@ import assert, {
|
|||
} from "./assert.ts";
|
||||
|
||||
Deno.test("API should be exposed", () => {
|
||||
assertStrictEquals(
|
||||
assert_,
|
||||
assert,
|
||||
"`assert()` should be the default export",
|
||||
);
|
||||
assertStrictEquals(assert_, denoAssert, "`assert()` should be exposed");
|
||||
assertStrictEquals(assert_, ok, "`assert()` should be an alias of `ok()`");
|
||||
assertStrictEquals(assert, ok, "`assert()` should be an alias of `ok()`");
|
||||
assertStrictEquals(
|
||||
assertEquals,
|
||||
deepStrictEqual,
|
||||
|
|
|
@ -1,601 +1,4 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import * as hex from "../encoding/hex.ts";
|
||||
import * as base64 from "../encoding/base64.ts";
|
||||
import { normalizeEncoding, notImplemented } from "./_utils.ts";
|
||||
|
||||
const notImplementedEncodings = [
|
||||
"ascii",
|
||||
"binary",
|
||||
"latin1",
|
||||
"ucs2",
|
||||
"utf16le",
|
||||
];
|
||||
|
||||
function checkEncoding(encoding = "utf8", strict = true): string {
|
||||
if (typeof encoding !== "string" || (strict && encoding === "")) {
|
||||
if (!strict) return "utf8";
|
||||
throw new TypeError(`Unkown encoding: ${encoding}`);
|
||||
}
|
||||
|
||||
const normalized = normalizeEncoding(encoding);
|
||||
|
||||
if (normalized === undefined) {
|
||||
throw new TypeError(`Unkown encoding: ${encoding}`);
|
||||
}
|
||||
|
||||
if (notImplementedEncodings.includes(encoding)) {
|
||||
notImplemented(`"${encoding}" encoding`);
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
interface EncodingOp {
|
||||
byteLength(string: string): number;
|
||||
}
|
||||
|
||||
// https://github.com/nodejs/node/blob/56dbe466fdbc598baea3bfce289bf52b97b8b8f7/lib/buffer.js#L598
|
||||
const encodingOps: { [key: string]: EncodingOp } = {
|
||||
utf8: {
|
||||
byteLength: (string: string): number =>
|
||||
new TextEncoder().encode(string).byteLength,
|
||||
},
|
||||
ucs2: {
|
||||
byteLength: (string: string): number => string.length * 2,
|
||||
},
|
||||
utf16le: {
|
||||
byteLength: (string: string): number => string.length * 2,
|
||||
},
|
||||
latin1: {
|
||||
byteLength: (string: string): number => string.length,
|
||||
},
|
||||
ascii: {
|
||||
byteLength: (string: string): number => string.length,
|
||||
},
|
||||
base64: {
|
||||
byteLength: (string: string): number =>
|
||||
base64ByteLength(string, string.length),
|
||||
},
|
||||
hex: {
|
||||
byteLength: (string: string): number => string.length >>> 1,
|
||||
},
|
||||
};
|
||||
|
||||
function base64ByteLength(str: string, bytes: number): number {
|
||||
// Handle padding
|
||||
if (str.charCodeAt(bytes - 1) === 0x3d) bytes--;
|
||||
if (bytes > 1 && str.charCodeAt(bytes - 1) === 0x3d) bytes--;
|
||||
|
||||
// Base64 ratio: 3/4
|
||||
return (bytes * 3) >>> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* See also https://nodejs.org/api/buffer.html
|
||||
*/
|
||||
export default class Buffer extends Uint8Array {
|
||||
/**
|
||||
* Allocates a new Buffer of size bytes.
|
||||
*/
|
||||
static alloc(
|
||||
size: number,
|
||||
fill?: number | string | Uint8Array | Buffer,
|
||||
encoding = "utf8",
|
||||
): Buffer {
|
||||
if (typeof size !== "number") {
|
||||
throw new TypeError(
|
||||
`The "size" argument must be of type number. Received type ${typeof size}`,
|
||||
);
|
||||
}
|
||||
|
||||
const buf = new Buffer(size);
|
||||
if (size === 0) return buf;
|
||||
|
||||
let bufFill;
|
||||
if (typeof fill === "string") {
|
||||
encoding = checkEncoding(encoding);
|
||||
if (
|
||||
typeof fill === "string" &&
|
||||
fill.length === 1 &&
|
||||
encoding === "utf8"
|
||||
) {
|
||||
buf.fill(fill.charCodeAt(0));
|
||||
} else bufFill = Buffer.from(fill, encoding);
|
||||
} else if (typeof fill === "number") {
|
||||
buf.fill(fill);
|
||||
} else if (fill instanceof Uint8Array) {
|
||||
if (fill.length === 0) {
|
||||
throw new TypeError(
|
||||
`The argument "value" is invalid. Received ${fill.constructor.name} []`,
|
||||
);
|
||||
}
|
||||
|
||||
bufFill = fill;
|
||||
}
|
||||
|
||||
if (bufFill) {
|
||||
if (bufFill.length > buf.length) {
|
||||
bufFill = bufFill.subarray(0, buf.length);
|
||||
}
|
||||
|
||||
let offset = 0;
|
||||
while (offset < size) {
|
||||
buf.set(bufFill, offset);
|
||||
offset += bufFill.length;
|
||||
if (offset + bufFill.length >= size) break;
|
||||
}
|
||||
if (offset !== size) {
|
||||
buf.set(bufFill.subarray(0, size - offset), offset);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static allocUnsafe(size: number): Buffer {
|
||||
return new Buffer(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the byte length of a string when encoded. This is not the same as
|
||||
* String.prototype.length, which does not account for the encoding that is
|
||||
* used to convert the string into bytes.
|
||||
*/
|
||||
static byteLength(
|
||||
string: string | Buffer | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
|
||||
encoding = "utf8",
|
||||
): number {
|
||||
if (typeof string != "string") return string.byteLength;
|
||||
|
||||
encoding = normalizeEncoding(encoding) || "utf8";
|
||||
return encodingOps[encoding].byteLength(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Buffer which is the result of concatenating all the Buffer
|
||||
* instances in the list together.
|
||||
*/
|
||||
static concat(list: Buffer[] | Uint8Array[], totalLength?: number): Buffer {
|
||||
if (totalLength == undefined) {
|
||||
totalLength = 0;
|
||||
for (const buf of list) {
|
||||
totalLength += buf.length;
|
||||
}
|
||||
}
|
||||
|
||||
const buffer = Buffer.allocUnsafe(totalLength);
|
||||
let pos = 0;
|
||||
for (const item of list) {
|
||||
let buf: Buffer;
|
||||
if (!(item instanceof Buffer)) {
|
||||
buf = Buffer.from(item);
|
||||
} else {
|
||||
buf = item;
|
||||
}
|
||||
buf.copy(buffer, pos);
|
||||
pos += buf.length;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a new Buffer using an array of bytes in the range 0 – 255. Array
|
||||
* entries outside that range will be truncated to fit into it.
|
||||
*/
|
||||
static from(array: number[]): Buffer;
|
||||
/**
|
||||
* This creates a view of the ArrayBuffer without copying the underlying
|
||||
* memory. For example, when passed a reference to the .buffer property of a
|
||||
* TypedArray instance, the newly created Buffer will share the same allocated
|
||||
* memory as the TypedArray.
|
||||
*/
|
||||
static from(
|
||||
arrayBuffer: ArrayBuffer | SharedArrayBuffer,
|
||||
byteOffset?: number,
|
||||
length?: number,
|
||||
): Buffer;
|
||||
/**
|
||||
* Copies the passed buffer data onto a new Buffer instance.
|
||||
*/
|
||||
static from(buffer: Buffer | Uint8Array): Buffer;
|
||||
/**
|
||||
* Creates a new Buffer containing string.
|
||||
*/
|
||||
static from(string: string, encoding?: string): Buffer;
|
||||
static from(
|
||||
// deno-lint-ignore no-explicit-any
|
||||
value: any,
|
||||
offsetOrEncoding?: number | string,
|
||||
length?: number,
|
||||
): Buffer {
|
||||
const offset = typeof offsetOrEncoding === "string"
|
||||
? undefined
|
||||
: offsetOrEncoding;
|
||||
let encoding = typeof offsetOrEncoding === "string"
|
||||
? offsetOrEncoding
|
||||
: undefined;
|
||||
|
||||
if (typeof value == "string") {
|
||||
encoding = checkEncoding(encoding, false);
|
||||
if (encoding === "hex") return new Buffer(hex.decodeString(value).buffer);
|
||||
if (encoding === "base64") return new Buffer(base64.decode(value).buffer);
|
||||
return new Buffer(new TextEncoder().encode(value).buffer);
|
||||
}
|
||||
|
||||
// workaround for https://github.com/microsoft/TypeScript/issues/38446
|
||||
return new Buffer(value, offset!, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if obj is a Buffer, false otherwise.
|
||||
*/
|
||||
static isBuffer(obj: unknown): obj is Buffer {
|
||||
return obj instanceof Buffer;
|
||||
}
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
static isEncoding(encoding: any): boolean {
|
||||
return (
|
||||
typeof encoding === "string" &&
|
||||
encoding.length !== 0 &&
|
||||
normalizeEncoding(encoding) !== undefined
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies data from a region of buf to a region in target, even if the target
|
||||
* memory region overlaps with buf.
|
||||
*/
|
||||
copy(
|
||||
targetBuffer: Buffer | Uint8Array,
|
||||
targetStart = 0,
|
||||
sourceStart = 0,
|
||||
sourceEnd = this.length,
|
||||
): number {
|
||||
const sourceBuffer = this
|
||||
.subarray(sourceStart, sourceEnd)
|
||||
.subarray(0, Math.max(0, targetBuffer.length - targetStart));
|
||||
|
||||
if (sourceBuffer.length === 0) return 0;
|
||||
|
||||
targetBuffer.set(sourceBuffer, targetStart);
|
||||
return sourceBuffer.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if both buf and otherBuffer have exactly the same bytes, false otherwise.
|
||||
*/
|
||||
equals(otherBuffer: Uint8Array | Buffer): boolean {
|
||||
if (!(otherBuffer instanceof Uint8Array)) {
|
||||
throw new TypeError(
|
||||
`The "otherBuffer" argument must be an instance of Buffer or Uint8Array. Received type ${typeof otherBuffer}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (this === otherBuffer) return true;
|
||||
if (this.byteLength !== otherBuffer.byteLength) return false;
|
||||
|
||||
for (let i = 0; i < this.length; i++) {
|
||||
if (this[i] !== otherBuffer[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
readBigInt64BE(offset = 0): bigint {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getBigInt64(offset);
|
||||
}
|
||||
readBigInt64LE(offset = 0): bigint {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getBigInt64(offset, true);
|
||||
}
|
||||
|
||||
readBigUInt64BE(offset = 0): bigint {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getBigUint64(offset);
|
||||
}
|
||||
readBigUInt64LE(offset = 0): bigint {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getBigUint64(offset, true);
|
||||
}
|
||||
|
||||
readDoubleBE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getFloat64(offset);
|
||||
}
|
||||
readDoubleLE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getFloat64(offset, true);
|
||||
}
|
||||
|
||||
readFloatBE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getFloat32(offset);
|
||||
}
|
||||
readFloatLE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getFloat32(offset, true);
|
||||
}
|
||||
|
||||
readInt8(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt8(
|
||||
offset,
|
||||
);
|
||||
}
|
||||
|
||||
readInt16BE(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt16(
|
||||
offset,
|
||||
);
|
||||
}
|
||||
readInt16LE(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt16(
|
||||
offset,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
readInt32BE(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt32(
|
||||
offset,
|
||||
);
|
||||
}
|
||||
readInt32LE(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt32(
|
||||
offset,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
readUInt8(offset = 0): number {
|
||||
return new DataView(this.buffer, this.byteOffset, this.byteLength).getUint8(
|
||||
offset,
|
||||
);
|
||||
}
|
||||
|
||||
readUInt16BE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getUint16(offset);
|
||||
}
|
||||
readUInt16LE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getUint16(offset, true);
|
||||
}
|
||||
|
||||
readUInt32BE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getUint32(offset);
|
||||
}
|
||||
readUInt32LE(offset = 0): number {
|
||||
return new DataView(
|
||||
this.buffer,
|
||||
this.byteOffset,
|
||||
this.byteLength,
|
||||
).getUint32(offset, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Buffer that references the same memory as the original, but
|
||||
* offset and cropped by the start and end indices.
|
||||
*/
|
||||
slice(begin = 0, end = this.length): Buffer {
|
||||
// workaround for https://github.com/microsoft/TypeScript/issues/38665
|
||||
return this.subarray(begin, end) as Buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON representation of buf. JSON.stringify() implicitly calls
|
||||
* this function when stringifying a Buffer instance.
|
||||
*/
|
||||
toJSON(): Record<string, unknown> {
|
||||
return { type: "Buffer", data: Array.from(this) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes buf to a string according to the specified character encoding in
|
||||
* encoding. start and end may be passed to decode only a subset of buf.
|
||||
*/
|
||||
toString(encoding = "utf8", start = 0, end = this.length): string {
|
||||
encoding = checkEncoding(encoding);
|
||||
|
||||
const b = this.subarray(start, end);
|
||||
if (encoding === "hex") return hex.encodeToString(b);
|
||||
if (encoding === "base64") return base64.encode(b.buffer);
|
||||
|
||||
return new TextDecoder(encoding).decode(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes string to buf at offset according to the character encoding in
|
||||
* encoding. The length parameter is the number of bytes to write. If buf did
|
||||
* not contain enough space to fit the entire string, only part of string will
|
||||
* be written. However, partially encoded characters will not be written.
|
||||
*/
|
||||
write(string: string, offset = 0, length = this.length): number {
|
||||
return new TextEncoder().encodeInto(
|
||||
string,
|
||||
this.subarray(offset, offset + length),
|
||||
).written;
|
||||
}
|
||||
|
||||
writeBigInt64BE(value: bigint, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setBigInt64(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeBigInt64LE(value: bigint, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setBigInt64(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
writeBigUInt64BE(value: bigint, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setBigUint64(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeBigUInt64LE(value: bigint, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setBigUint64(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
writeDoubleBE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat64(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 8;
|
||||
}
|
||||
writeDoubleLE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat64(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 8;
|
||||
}
|
||||
|
||||
writeFloatBE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat32(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeFloatLE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat32(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
writeInt8(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setInt8(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
writeInt16BE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setInt16(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 2;
|
||||
}
|
||||
writeInt16LE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setInt16(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
writeInt32BE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint32(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeInt32LE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setInt32(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
writeUInt8(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint8(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
writeUInt16BE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint16(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 2;
|
||||
}
|
||||
writeUInt16LE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint16(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
writeUInt32BE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint32(
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
writeUInt32LE(value: number, offset = 0): number {
|
||||
new DataView(this.buffer, this.byteOffset, this.byteLength).setUint32(
|
||||
offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
return offset + 4;
|
||||
}
|
||||
}
|
||||
|
||||
export { Buffer };
|
||||
export * from "./_buffer.ts";
|
||||
import * as m from "./_buffer.ts";
|
||||
export default m;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { assert, assertEquals, assertThrows } from "../testing/asserts.ts";
|
||||
import Buffer from "./buffer.ts";
|
||||
import { Buffer } from "./buffer.ts";
|
||||
|
||||
Deno.test({
|
||||
name: "Buffer global scope",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import randomBytes from "./_crypto/randomBytes.ts";
|
||||
import { pbkdf2, pbkdf2Sync } from "./_crypto/pbkdf2.ts";
|
||||
|
||||
export { pbkdf2, pbkdf2Sync, randomBytes };
|
||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
export * from "./_crypto.ts";
|
||||
import * as m from "./_crypto.ts";
|
||||
export default m;
|
||||
|
|
|
@ -31,12 +31,36 @@ export interface WrappedFunction extends Function {
|
|||
listener: GenericFunction;
|
||||
}
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
function createIterResult(value: any, done: boolean): IteratorResult<any> {
|
||||
return { value, done };
|
||||
}
|
||||
|
||||
interface AsyncIterable {
|
||||
// deno-lint-ignore no-explicit-any
|
||||
next(): Promise<IteratorResult<any, any>>;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
return(): Promise<IteratorResult<any, any>>;
|
||||
throw(err: Error): void;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
[Symbol.asyncIterator](): any;
|
||||
}
|
||||
|
||||
export let defaultMaxListeners = 10;
|
||||
|
||||
/**
|
||||
* See also https://nodejs.org/api/events.html
|
||||
*/
|
||||
export default class EventEmitter {
|
||||
public static defaultMaxListeners = 10;
|
||||
public static captureRejectionSymbol = Symbol.for("nodejs.rejection");
|
||||
public static errorMonitor = Symbol("events.errorMonitor");
|
||||
public static get defaultMaxListeners() {
|
||||
return defaultMaxListeners;
|
||||
}
|
||||
public static set defaultMaxListeners(value: number) {
|
||||
defaultMaxListeners = value;
|
||||
}
|
||||
|
||||
private maxListeners: number | undefined;
|
||||
private _events: Map<
|
||||
string | symbol,
|
||||
|
@ -367,16 +391,13 @@ export default class EventEmitter {
|
|||
this.maxListeners = n;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export { EventEmitter };
|
||||
|
||||
/**
|
||||
* Creates a Promise that is fulfilled when the EventEmitter emits the given
|
||||
* event or that is rejected when the EventEmitter emits 'error'. The Promise
|
||||
* will resolve with an array of all the arguments emitted to the given event.
|
||||
*/
|
||||
export function once(
|
||||
public static once(
|
||||
emitter: EventEmitter | EventTarget,
|
||||
name: string,
|
||||
// deno-lint-ignore no-explicit-any
|
||||
|
@ -425,31 +446,16 @@ export function once(
|
|||
});
|
||||
}
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
function createIterResult(value: any, done: boolean): IteratorResult<any> {
|
||||
return { value, done };
|
||||
}
|
||||
|
||||
interface AsyncInterable {
|
||||
// deno-lint-ignore no-explicit-any
|
||||
next(): Promise<IteratorResult<any, any>>;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
return(): Promise<IteratorResult<any, any>>;
|
||||
throw(err: Error): void;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
[Symbol.asyncIterator](): any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an AsyncIterator that iterates eventName events. It will throw if
|
||||
* the EventEmitter emits 'error'. It removes all listeners when exiting the
|
||||
* loop. The value returned by each iteration is an array composed of the
|
||||
* emitted event arguments.
|
||||
*/
|
||||
export function on(
|
||||
public static on(
|
||||
emitter: EventEmitter,
|
||||
event: string | symbol,
|
||||
): AsyncInterable {
|
||||
): AsyncIterable {
|
||||
// deno-lint-ignore no-explicit-any
|
||||
const unconsumedEventValues: any[] = [];
|
||||
// deno-lint-ignore no-explicit-any
|
||||
|
@ -543,4 +549,10 @@ export function on(
|
|||
iterator.return();
|
||||
}
|
||||
}
|
||||
export const captureRejectionSymbol = Symbol.for("nodejs.rejection");
|
||||
}
|
||||
|
||||
export { EventEmitter };
|
||||
export const once = EventEmitter.once;
|
||||
export const on = EventEmitter.on;
|
||||
export const captureRejectionSymbol = EventEmitter.captureRejectionSymbol;
|
||||
export const errorMonitor = EventEmitter.errorMonitor;
|
||||
|
|
|
@ -1,68 +1,4 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { access, accessSync } from "./_fs/_fs_access.ts";
|
||||
import { appendFile, appendFileSync } from "./_fs/_fs_appendFile.ts";
|
||||
import { chmod, chmodSync } from "./_fs/_fs_chmod.ts";
|
||||
import { chown, chownSync } from "./_fs/_fs_chown.ts";
|
||||
import { close, closeSync } from "./_fs/_fs_close.ts";
|
||||
import * as constants from "./_fs/_fs_constants.ts";
|
||||
import { readFile, readFileSync } from "./_fs/_fs_readFile.ts";
|
||||
import { readlink, readlinkSync } from "./_fs/_fs_readlink.ts";
|
||||
import { exists, existsSync } from "./_fs/_fs_exists.ts";
|
||||
import { mkdir, mkdirSync } from "./_fs/_fs_mkdir.ts";
|
||||
import { copyFile, copyFileSync } from "./_fs/_fs_copy.ts";
|
||||
import { writeFile, writeFileSync } from "./_fs/_fs_writeFile.ts";
|
||||
import { readdir, readdirSync } from "./_fs/_fs_readdir.ts";
|
||||
import { realpath, realpathSync } from "./_fs/_fs_realpath.ts";
|
||||
import { rename, renameSync } from "./_fs/_fs_rename.ts";
|
||||
import { rmdir, rmdirSync } from "./_fs/_fs_rmdir.ts";
|
||||
import { unlink, unlinkSync } from "./_fs/_fs_unlink.ts";
|
||||
import { watch } from "./_fs/_fs_watch.ts";
|
||||
import { open, openSync } from "./_fs/_fs_open.ts";
|
||||
import { stat, statSync } from "./_fs/_fs_stat.ts";
|
||||
import { lstat, lstatSync } from "./_fs/_fs_lstat.ts";
|
||||
|
||||
import * as promises from "./_fs/promises/mod.ts";
|
||||
|
||||
export {
|
||||
access,
|
||||
accessSync,
|
||||
appendFile,
|
||||
appendFileSync,
|
||||
chmod,
|
||||
chmodSync,
|
||||
chown,
|
||||
chownSync,
|
||||
close,
|
||||
closeSync,
|
||||
constants,
|
||||
copyFile,
|
||||
copyFileSync,
|
||||
exists,
|
||||
existsSync,
|
||||
lstat,
|
||||
lstatSync,
|
||||
mkdir,
|
||||
mkdirSync,
|
||||
open,
|
||||
openSync,
|
||||
promises,
|
||||
readdir,
|
||||
readdirSync,
|
||||
readFile,
|
||||
readFileSync,
|
||||
readlink,
|
||||
readlinkSync,
|
||||
realpath,
|
||||
realpathSync,
|
||||
rename,
|
||||
renameSync,
|
||||
rmdir,
|
||||
rmdirSync,
|
||||
stat,
|
||||
statSync,
|
||||
unlink,
|
||||
unlinkSync,
|
||||
watch,
|
||||
writeFile,
|
||||
writeFileSync,
|
||||
};
|
||||
export * from "./_fs.ts";
|
||||
import * as m from "./_fs.ts";
|
||||
export default m;
|
||||
|
|
228
std/node/os.ts
228
std/node/os.ts
|
@ -1,224 +1,4 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
import { notImplemented } from "./_utils.ts";
|
||||
import { validateIntegerRange } from "./_utils.ts";
|
||||
import { EOL as fsEOL } from "../fs/eol.ts";
|
||||
import process from "./process.ts";
|
||||
|
||||
const SEE_GITHUB_ISSUE = "See https://github.com/denoland/deno/issues/3802";
|
||||
|
||||
interface CPUTimes {
|
||||
/** The number of milliseconds the CPU has spent in user mode */
|
||||
user: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in nice mode */
|
||||
nice: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in sys mode */
|
||||
sys: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in idle mode */
|
||||
idle: number;
|
||||
|
||||
/** The number of milliseconds the CPU has spent in irq mode */
|
||||
irq: number;
|
||||
}
|
||||
|
||||
interface CPUCoreInfo {
|
||||
model: string;
|
||||
|
||||
/** in MHz */
|
||||
speed: number;
|
||||
|
||||
times: CPUTimes;
|
||||
}
|
||||
|
||||
interface NetworkAddress {
|
||||
/** The assigned IPv4 or IPv6 address */
|
||||
address: string;
|
||||
|
||||
/** The IPv4 or IPv6 network mask */
|
||||
netmask: string;
|
||||
|
||||
family: "IPv4" | "IPv6";
|
||||
|
||||
/** The MAC address of the network interface */
|
||||
mac: string;
|
||||
|
||||
/** true if the network interface is a loopback or similar interface that is not remotely accessible; otherwise false */
|
||||
internal: boolean;
|
||||
|
||||
/** The numeric IPv6 scope ID (only specified when family is IPv6) */
|
||||
scopeid?: number;
|
||||
|
||||
/** The assigned IPv4 or IPv6 address with the routing prefix in CIDR notation. If the netmask is invalid, this property is set to null. */
|
||||
cidr: string;
|
||||
}
|
||||
|
||||
interface NetworkInterfaces {
|
||||
[key: string]: NetworkAddress[];
|
||||
}
|
||||
|
||||
export interface UserInfoOptions {
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
interface UserInfo {
|
||||
username: string;
|
||||
uid: number;
|
||||
gid: number;
|
||||
shell: string;
|
||||
homedir: string;
|
||||
}
|
||||
|
||||
arch[Symbol.toPrimitive] = (): string => arch();
|
||||
endianness[Symbol.toPrimitive] = (): string => endianness();
|
||||
freemem[Symbol.toPrimitive] = (): number => freemem();
|
||||
homedir[Symbol.toPrimitive] = (): string | null => homedir();
|
||||
hostname[Symbol.toPrimitive] = (): string | null => hostname();
|
||||
platform[Symbol.toPrimitive] = (): string => platform();
|
||||
release[Symbol.toPrimitive] = (): string => release();
|
||||
totalmem[Symbol.toPrimitive] = (): number => totalmem();
|
||||
type[Symbol.toPrimitive] = (): string => type();
|
||||
uptime[Symbol.toPrimitive] = (): number => uptime();
|
||||
|
||||
/** Returns the operating system CPU architecture for which the Deno binary was compiled */
|
||||
export function arch(): string {
|
||||
return Deno.build.arch;
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function cpus(): CPUCoreInfo[] {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string identifying the endianness of the CPU for which the Deno
|
||||
* binary was compiled. Possible values are 'BE' for big endian and 'LE' for
|
||||
* little endian.
|
||||
**/
|
||||
export function endianness(): "BE" | "LE" {
|
||||
// Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness
|
||||
const buffer = new ArrayBuffer(2);
|
||||
new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
|
||||
// Int16Array uses the platform's endianness.
|
||||
return new Int16Array(buffer)[0] === 256 ? "LE" : "BE";
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function freemem(): number {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function getPriority(pid = 0): number {
|
||||
validateIntegerRange(pid, "pid");
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Returns the string path of the current user's home directory. */
|
||||
export function homedir(): string | null {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Returns the host name of the operating system as a string. */
|
||||
export function hostname(): string {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Returns an array containing the 1, 5, and 15 minute load averages */
|
||||
export function loadavg(): number[] {
|
||||
if (Deno.build.os === "windows") {
|
||||
return [0, 0, 0];
|
||||
}
|
||||
return Deno.loadavg();
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function networkInterfaces(): NetworkInterfaces {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
/** Returns the a string identifying the operating system platform. The value is set at compile time. Possible values are 'darwin', 'linux', and 'win32'. */
|
||||
export function platform(): string {
|
||||
return process.platform;
|
||||
}
|
||||
|
||||
/** Returns the operating system as a string */
|
||||
export function release(): string {
|
||||
return Deno.osRelease();
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function setPriority(pid: number, priority?: number): void {
|
||||
/* The node API has the 'pid' as the first parameter and as optional.
|
||||
This makes for a problematic implementation in Typescript. */
|
||||
if (priority === undefined) {
|
||||
priority = pid;
|
||||
pid = 0;
|
||||
}
|
||||
validateIntegerRange(pid, "pid");
|
||||
validateIntegerRange(priority, "priority", -20, 19);
|
||||
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Returns the operating system's default directory for temporary files as a string. */
|
||||
export function tmpdir(): string | null {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function totalmem(): number {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function type(): string {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function uptime(): number {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
/** Not yet implemented */
|
||||
export function userInfo(
|
||||
options: UserInfoOptions = { encoding: "utf-8" },
|
||||
): UserInfo {
|
||||
notImplemented(SEE_GITHUB_ISSUE);
|
||||
}
|
||||
|
||||
export const constants = {
|
||||
// UV_UDP_REUSEADDR: 4, //see https://nodejs.org/docs/latest-v12.x/api/os.html#os_libuv_constants
|
||||
dlopen: {
|
||||
// see https://nodejs.org/docs/latest-v12.x/api/os.html#os_dlopen_constants
|
||||
},
|
||||
errno: {
|
||||
// see https://nodejs.org/docs/latest-v12.x/api/os.html#os_error_constants
|
||||
},
|
||||
signals: Deno.Signal,
|
||||
priority: {
|
||||
// see https://nodejs.org/docs/latest-v12.x/api/os.html#os_priority_constants
|
||||
},
|
||||
};
|
||||
|
||||
export const EOL = Deno.build.os == "windows" ? fsEOL.CRLF : fsEOL.LF;
|
||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
export * from "./_os.ts";
|
||||
import * as m from "./_os.ts";
|
||||
export default m;
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
export * from "../path/mod.ts";
|
||||
import * as m from "../path/mod.ts";
|
||||
export default m;
|
||||
|
|
|
@ -1,156 +1,4 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
interface ParseOptions {
|
||||
/** The function to use when decoding percent-encoded characters in the query string. */
|
||||
decodeURIComponent?: (string: string) => string;
|
||||
/** Specifies the maximum number of keys to parse. */
|
||||
maxKeys?: number;
|
||||
}
|
||||
|
||||
export const hexTable = new Array(256);
|
||||
for (let i = 0; i < 256; ++i) {
|
||||
hexTable[i] = "%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a URL query string into a collection of key and value pairs.
|
||||
* @param str The URL query string to parse
|
||||
* @param sep The substring used to delimit key and value pairs in the query string. Default: '&'.
|
||||
* @param eq The substring used to delimit keys and values in the query string. Default: '='.
|
||||
* @param options The parse options
|
||||
*/
|
||||
export function parse(
|
||||
str: string,
|
||||
sep = "&",
|
||||
eq = "=",
|
||||
{ decodeURIComponent = unescape, maxKeys = 1000 }: ParseOptions = {},
|
||||
): { [key: string]: string[] | string } {
|
||||
const entries = str
|
||||
.split(sep)
|
||||
.map((entry) => entry.split(eq).map(decodeURIComponent));
|
||||
const final: { [key: string]: string[] | string } = {};
|
||||
|
||||
let i = 0;
|
||||
while (true) {
|
||||
if ((Object.keys(final).length === maxKeys && !!maxKeys) || !entries[i]) {
|
||||
break;
|
||||
}
|
||||
|
||||
const [key, val] = entries[i];
|
||||
if (final[key]) {
|
||||
if (Array.isArray(final[key])) {
|
||||
(final[key] as string[]).push(val);
|
||||
} else {
|
||||
final[key] = [final[key] as string, val];
|
||||
}
|
||||
} else {
|
||||
final[key] = val;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
interface StringifyOptions {
|
||||
/** The function to use when converting URL-unsafe characters to percent-encoding in the query string. */
|
||||
encodeURIComponent?: (string: string) => string;
|
||||
}
|
||||
|
||||
export function encodeStr(
|
||||
str: string,
|
||||
noEscapeTable: number[],
|
||||
hexTable: string[],
|
||||
): string {
|
||||
const len = str.length;
|
||||
if (len === 0) return "";
|
||||
|
||||
let out = "";
|
||||
let lastPos = 0;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
let c = str.charCodeAt(i);
|
||||
// ASCII
|
||||
if (c < 0x80) {
|
||||
if (noEscapeTable[c] === 1) continue;
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
lastPos = i + 1;
|
||||
out += hexTable[c];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
|
||||
// Multi-byte characters ...
|
||||
if (c < 0x800) {
|
||||
lastPos = i + 1;
|
||||
out += hexTable[0xc0 | (c >> 6)] + hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
if (c < 0xd800 || c >= 0xe000) {
|
||||
lastPos = i + 1;
|
||||
out += hexTable[0xe0 | (c >> 12)] +
|
||||
hexTable[0x80 | ((c >> 6) & 0x3f)] +
|
||||
hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
// Surrogate pair
|
||||
++i;
|
||||
|
||||
// This branch should never happen because all URLSearchParams entries
|
||||
// should already be converted to USVString. But, included for
|
||||
// completion's sake anyway.
|
||||
if (i >= len) throw new Deno.errors.InvalidData("invalid URI");
|
||||
|
||||
const c2 = str.charCodeAt(i) & 0x3ff;
|
||||
|
||||
lastPos = i + 1;
|
||||
c = 0x10000 + (((c & 0x3ff) << 10) | c2);
|
||||
out += hexTable[0xf0 | (c >> 18)] +
|
||||
hexTable[0x80 | ((c >> 12) & 0x3f)] +
|
||||
hexTable[0x80 | ((c >> 6) & 0x3f)] +
|
||||
hexTable[0x80 | (c & 0x3f)];
|
||||
}
|
||||
if (lastPos === 0) return str;
|
||||
if (lastPos < len) return out + str.slice(lastPos);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a URL query string from a given obj by iterating through the object's "own properties".
|
||||
* @param obj The object to serialize into a URL query string.
|
||||
* @param sep The substring used to delimit key and value pairs in the query string. Default: '&'.
|
||||
* @param eq The substring used to delimit keys and values in the query string. Default: '='.
|
||||
* @param options The stringify options
|
||||
*/
|
||||
export function stringify(
|
||||
// deno-lint-ignore no-explicit-any
|
||||
obj: Record<string, any>,
|
||||
sep = "&",
|
||||
eq = "=",
|
||||
{ encodeURIComponent = escape }: StringifyOptions = {},
|
||||
): string {
|
||||
const final = [];
|
||||
|
||||
for (const entry of Object.entries(obj)) {
|
||||
if (Array.isArray(entry[1])) {
|
||||
for (const val of entry[1]) {
|
||||
final.push(encodeURIComponent(entry[0]) + eq + encodeURIComponent(val));
|
||||
}
|
||||
} else if (typeof entry[1] !== "object" && entry[1] !== undefined) {
|
||||
final.push(entry.map(encodeURIComponent).join(eq));
|
||||
} else {
|
||||
final.push(encodeURIComponent(entry[0]) + eq);
|
||||
}
|
||||
}
|
||||
|
||||
return final.join(sep);
|
||||
}
|
||||
|
||||
/** Alias of querystring.parse() */
|
||||
export const decode = parse;
|
||||
/** Alias of querystring.stringify() */
|
||||
export const encode = stringify;
|
||||
export const unescape = decodeURIComponent;
|
||||
export const escape = encodeURIComponent;
|
||||
export * from "./_querystring.ts";
|
||||
import * as m from "./_querystring.ts";
|
||||
export default m;
|
||||
|
|
|
@ -1,299 +1,4 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import { Buffer } from "./buffer.ts";
|
||||
import { normalizeEncoding as castEncoding, notImplemented } from "./_utils.ts";
|
||||
|
||||
enum NotImplemented {
|
||||
"ascii",
|
||||
"latin1",
|
||||
"utf16le",
|
||||
}
|
||||
|
||||
function normalizeEncoding(enc?: string): string {
|
||||
const encoding = castEncoding(enc ?? null);
|
||||
if (encoding && encoding in NotImplemented) notImplemented(encoding);
|
||||
if (!encoding && typeof enc === "string" && enc.toLowerCase() !== "raw") {
|
||||
throw new Error(`Unknown encoding: ${enc}`);
|
||||
}
|
||||
return String(encoding);
|
||||
}
|
||||
/*
|
||||
* Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
|
||||
* continuation byte. If an invalid byte is detected, -2 is returned.
|
||||
* */
|
||||
function utf8CheckByte(byte: number): number {
|
||||
if (byte <= 0x7f) return 0;
|
||||
else if (byte >> 5 === 0x06) return 2;
|
||||
else if (byte >> 4 === 0x0e) return 3;
|
||||
else if (byte >> 3 === 0x1e) return 4;
|
||||
return byte >> 6 === 0x02 ? -1 : -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks at most 3 bytes at the end of a Buffer in order to detect an
|
||||
* incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4)
|
||||
* needed to complete the UTF-8 character (if applicable) are returned.
|
||||
* */
|
||||
function utf8CheckIncomplete(
|
||||
self: StringDecoderBase,
|
||||
buf: Buffer,
|
||||
i: number,
|
||||
): number {
|
||||
let j = buf.length - 1;
|
||||
if (j < i) return 0;
|
||||
let nb = utf8CheckByte(buf[j]);
|
||||
if (nb >= 0) {
|
||||
if (nb > 0) self.lastNeed = nb - 1;
|
||||
return nb;
|
||||
}
|
||||
if (--j < i || nb === -2) return 0;
|
||||
nb = utf8CheckByte(buf[j]);
|
||||
if (nb >= 0) {
|
||||
if (nb > 0) self.lastNeed = nb - 2;
|
||||
return nb;
|
||||
}
|
||||
if (--j < i || nb === -2) return 0;
|
||||
nb = utf8CheckByte(buf[j]);
|
||||
if (nb >= 0) {
|
||||
if (nb > 0) {
|
||||
if (nb === 2) nb = 0;
|
||||
else self.lastNeed = nb - 3;
|
||||
}
|
||||
return nb;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validates as many continuation bytes for a multi-byte UTF-8 character as
|
||||
* needed or are available. If we see a non-continuation byte where we expect
|
||||
* one, we "replace" the validated continuation bytes we've seen so far with
|
||||
* a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding
|
||||
* behavior. The continuation byte check is included three times in the case
|
||||
* where all of the continuation bytes for a character exist in the same buffer.
|
||||
* It is also done this way as a slight performance increase instead of using a
|
||||
* loop.
|
||||
* */
|
||||
function utf8CheckExtraBytes(
|
||||
self: StringDecoderBase,
|
||||
buf: Buffer,
|
||||
): string | undefined {
|
||||
if ((buf[0] & 0xc0) !== 0x80) {
|
||||
self.lastNeed = 0;
|
||||
return "\ufffd";
|
||||
}
|
||||
if (self.lastNeed > 1 && buf.length > 1) {
|
||||
if ((buf[1] & 0xc0) !== 0x80) {
|
||||
self.lastNeed = 1;
|
||||
return "\ufffd";
|
||||
}
|
||||
if (self.lastNeed > 2 && buf.length > 2) {
|
||||
if ((buf[2] & 0xc0) !== 0x80) {
|
||||
self.lastNeed = 2;
|
||||
return "\ufffd";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer.
|
||||
* */
|
||||
function utf8FillLastComplete(
|
||||
this: StringDecoderBase,
|
||||
buf: Buffer,
|
||||
): string | undefined {
|
||||
const p = this.lastTotal - this.lastNeed;
|
||||
const r = utf8CheckExtraBytes(this, buf);
|
||||
if (r !== undefined) return r;
|
||||
if (this.lastNeed <= buf.length) {
|
||||
buf.copy(this.lastChar, p, 0, this.lastNeed);
|
||||
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
||||
}
|
||||
buf.copy(this.lastChar, p, 0, buf.length);
|
||||
this.lastNeed -= buf.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to complete a partial non-UTF-8 character using bytes from a Buffer
|
||||
* */
|
||||
function utf8FillLastIncomplete(
|
||||
this: StringDecoderBase,
|
||||
buf: Buffer,
|
||||
): string | undefined {
|
||||
if (this.lastNeed <= buf.length) {
|
||||
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
|
||||
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
||||
}
|
||||
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length);
|
||||
this.lastNeed -= buf.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a
|
||||
* partial character, the character's bytes are buffered until the required
|
||||
* number of bytes are available.
|
||||
* */
|
||||
function utf8Text(this: StringDecoderBase, buf: Buffer, i: number): string {
|
||||
const total = utf8CheckIncomplete(this, buf, i);
|
||||
if (!this.lastNeed) return buf.toString("utf8", i);
|
||||
this.lastTotal = total;
|
||||
const end = buf.length - (total - this.lastNeed);
|
||||
buf.copy(this.lastChar, 0, end);
|
||||
return buf.toString("utf8", i, end);
|
||||
}
|
||||
|
||||
/*
|
||||
* For UTF-8, a replacement character is added when ending on a partial
|
||||
* character.
|
||||
* */
|
||||
function utf8End(this: Utf8Decoder, buf?: Buffer): string {
|
||||
const r = buf && buf.length ? this.write(buf) : "";
|
||||
if (this.lastNeed) return r + "\ufffd";
|
||||
return r;
|
||||
}
|
||||
|
||||
function utf8Write(this: Utf8Decoder | Base64Decoder, buf: Buffer): string {
|
||||
if (buf.length === 0) return "";
|
||||
let r;
|
||||
let i;
|
||||
if (this.lastNeed) {
|
||||
r = this.fillLast(buf);
|
||||
if (r === undefined) return "";
|
||||
i = this.lastNeed;
|
||||
this.lastNeed = 0;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
|
||||
return r || "";
|
||||
}
|
||||
|
||||
function base64Text(this: StringDecoderBase, buf: Buffer, i: number): string {
|
||||
const n = (buf.length - i) % 3;
|
||||
if (n === 0) return buf.toString("base64", i);
|
||||
this.lastNeed = 3 - n;
|
||||
this.lastTotal = 3;
|
||||
if (n === 1) {
|
||||
this.lastChar[0] = buf[buf.length - 1];
|
||||
} else {
|
||||
this.lastChar[0] = buf[buf.length - 2];
|
||||
this.lastChar[1] = buf[buf.length - 1];
|
||||
}
|
||||
return buf.toString("base64", i, buf.length - n);
|
||||
}
|
||||
|
||||
function base64End(this: Base64Decoder, buf?: Buffer): string {
|
||||
const r = buf && buf.length ? this.write(buf) : "";
|
||||
if (this.lastNeed) {
|
||||
return r + this.lastChar.toString("base64", 0, 3 - this.lastNeed);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function simpleWrite(this: StringDecoderBase, buf: Buffer): string {
|
||||
return buf.toString(this.encoding);
|
||||
}
|
||||
|
||||
function simpleEnd(this: GenericDecoder, buf?: Buffer): string {
|
||||
return buf && buf.length ? this.write(buf) : "";
|
||||
}
|
||||
|
||||
class StringDecoderBase {
|
||||
public lastChar: Buffer;
|
||||
public lastNeed = 0;
|
||||
public lastTotal = 0;
|
||||
constructor(public encoding: string, nb: number) {
|
||||
this.lastChar = Buffer.allocUnsafe(nb);
|
||||
}
|
||||
}
|
||||
|
||||
class Base64Decoder extends StringDecoderBase {
|
||||
public end = base64End;
|
||||
public fillLast = utf8FillLastIncomplete;
|
||||
public text = base64Text;
|
||||
public write = utf8Write;
|
||||
|
||||
constructor(encoding?: string) {
|
||||
super(normalizeEncoding(encoding), 3);
|
||||
}
|
||||
}
|
||||
|
||||
class GenericDecoder extends StringDecoderBase {
|
||||
public end = simpleEnd;
|
||||
public fillLast = undefined;
|
||||
public text = utf8Text;
|
||||
public write = simpleWrite;
|
||||
|
||||
constructor(encoding?: string) {
|
||||
super(normalizeEncoding(encoding), 4);
|
||||
}
|
||||
}
|
||||
|
||||
class Utf8Decoder extends StringDecoderBase {
|
||||
public end = utf8End;
|
||||
public fillLast = utf8FillLastComplete;
|
||||
public text = utf8Text;
|
||||
public write = utf8Write;
|
||||
|
||||
constructor(encoding?: string) {
|
||||
super(normalizeEncoding(encoding), 4);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* StringDecoder provides an interface for efficiently splitting a series of
|
||||
* buffers into a series of JS strings without breaking apart multi-byte
|
||||
* characters.
|
||||
* */
|
||||
export class StringDecoder {
|
||||
public encoding: string;
|
||||
public end: (buf?: Buffer) => string;
|
||||
public fillLast: ((buf: Buffer) => string | undefined) | undefined;
|
||||
public lastChar: Buffer;
|
||||
public lastNeed: number;
|
||||
public lastTotal: number;
|
||||
public text: (buf: Buffer, n: number) => string;
|
||||
public write: (buf: Buffer) => string;
|
||||
|
||||
constructor(encoding?: string) {
|
||||
let decoder;
|
||||
switch (encoding) {
|
||||
case "utf8":
|
||||
decoder = new Utf8Decoder(encoding);
|
||||
break;
|
||||
case "base64":
|
||||
decoder = new Base64Decoder(encoding);
|
||||
break;
|
||||
default:
|
||||
decoder = new GenericDecoder(encoding);
|
||||
}
|
||||
this.encoding = decoder.encoding;
|
||||
this.end = decoder.end;
|
||||
this.fillLast = decoder.fillLast;
|
||||
this.lastChar = decoder.lastChar;
|
||||
this.lastNeed = decoder.lastNeed;
|
||||
this.lastTotal = decoder.lastTotal;
|
||||
this.text = decoder.text;
|
||||
this.write = decoder.write;
|
||||
}
|
||||
}
|
||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
export * from "./_string_decoder.ts";
|
||||
import * as m from "./_string_decoder.ts";
|
||||
export default m;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import Buffer from "./buffer.ts";
|
||||
import { Buffer } from "./buffer.ts";
|
||||
import { StringDecoder } from "./string_decoder.ts";
|
||||
|
||||
Deno.test({
|
||||
|
|
|
@ -1,14 +1,4 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
// TODO: implement the 'NodeJS.Timeout' and 'NodeJS.Immediate' versions of the timers.
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/1163ead296d84e7a3c80d71e7c81ecbd1a130e9a/types/node/v12/globals.d.ts#L1120-L1131
|
||||
export const setTimeout = window.setTimeout;
|
||||
export const clearTimeout = window.clearTimeout;
|
||||
export const setInterval = window.setInterval;
|
||||
export const clearInterval = window.clearInterval;
|
||||
export const setImmediate = (
|
||||
// deno-lint-ignore no-explicit-any
|
||||
cb: (...args: any[]) => void,
|
||||
// deno-lint-ignore no-explicit-any
|
||||
...args: any[]
|
||||
): number => window.setTimeout(cb, 0, ...args);
|
||||
export const clearImmediate = window.clearTimeout;
|
||||
export * from "./_timers.ts";
|
||||
import * as m from "./_timers.ts";
|
||||
export default m;
|
||||
|
|
144
std/node/url.ts
144
std/node/url.ts
|
@ -1,140 +1,4 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import {
|
||||
CHAR_BACKWARD_SLASH,
|
||||
CHAR_FORWARD_SLASH,
|
||||
CHAR_LOWERCASE_A,
|
||||
CHAR_LOWERCASE_Z,
|
||||
} from "../path/_constants.ts";
|
||||
import * as path from "./path.ts";
|
||||
|
||||
const isWindows = Deno.build.os === "windows";
|
||||
|
||||
const forwardSlashRegEx = /\//g;
|
||||
const percentRegEx = /%/g;
|
||||
const backslashRegEx = /\\/g;
|
||||
const newlineRegEx = /\n/g;
|
||||
const carriageReturnRegEx = /\r/g;
|
||||
const tabRegEx = /\t/g;
|
||||
|
||||
const _url = URL;
|
||||
export { _url as URL };
|
||||
|
||||
/**
|
||||
* Get fully resolved platform-specific file path from the given URL string/ object
|
||||
* @param path The file URL string or URL object to convert to a path
|
||||
*/
|
||||
export function fileURLToPath(path: string | URL): string {
|
||||
if (typeof path === "string") path = new URL(path);
|
||||
else if (!(path instanceof URL)) {
|
||||
throw new Deno.errors.InvalidData(
|
||||
"invalid argument path , must be a string or URL",
|
||||
);
|
||||
}
|
||||
if (path.protocol !== "file:") {
|
||||
throw new Deno.errors.InvalidData("invalid url scheme");
|
||||
}
|
||||
return isWindows ? getPathFromURLWin(path) : getPathFromURLPosix(path);
|
||||
}
|
||||
|
||||
function getPathFromURLWin(url: URL): string {
|
||||
const hostname = url.hostname;
|
||||
let pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === "%") {
|
||||
const third = pathname.codePointAt(n + 2) || 0x20;
|
||||
if (
|
||||
(pathname[n + 1] === "2" && third === 102) || // 2f 2F /
|
||||
(pathname[n + 1] === "5" && third === 99)
|
||||
) {
|
||||
// 5c 5C \
|
||||
throw new Deno.errors.InvalidData(
|
||||
"must not include encoded \\ or / characters",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pathname = pathname.replace(forwardSlashRegEx, "\\");
|
||||
pathname = decodeURIComponent(pathname);
|
||||
if (hostname !== "") {
|
||||
//TODO add support for punycode encodings
|
||||
return `\\\\${hostname}${pathname}`;
|
||||
} else {
|
||||
// Otherwise, it's a local path that requires a drive letter
|
||||
const letter = pathname.codePointAt(1)! | 0x20;
|
||||
const sep = pathname[2];
|
||||
if (
|
||||
letter < CHAR_LOWERCASE_A ||
|
||||
letter > CHAR_LOWERCASE_Z || // a..z A..Z
|
||||
sep !== ":"
|
||||
) {
|
||||
throw new Deno.errors.InvalidData("file url path must be absolute");
|
||||
}
|
||||
return pathname.slice(1);
|
||||
}
|
||||
}
|
||||
|
||||
function getPathFromURLPosix(url: URL): string {
|
||||
if (url.hostname !== "") {
|
||||
throw new Deno.errors.InvalidData("invalid file url hostname");
|
||||
}
|
||||
const pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === "%") {
|
||||
const third = pathname.codePointAt(n + 2) || 0x20;
|
||||
if (pathname[n + 1] === "2" && third === 102) {
|
||||
throw new Deno.errors.InvalidData(
|
||||
"must not include encoded / characters",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return decodeURIComponent(pathname);
|
||||
}
|
||||
|
||||
/** Get fully resolved platform-specific File URL from the given file path */
|
||||
export function pathToFileURL(filepath: string): URL {
|
||||
let resolved = path.resolve(filepath);
|
||||
// path.resolve strips trailing slashes so we must add them back
|
||||
const filePathLast = filepath.charCodeAt(filepath.length - 1);
|
||||
if (
|
||||
(filePathLast === CHAR_FORWARD_SLASH ||
|
||||
(isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&
|
||||
resolved[resolved.length - 1] !== path.sep
|
||||
) {
|
||||
resolved += "/";
|
||||
}
|
||||
const outURL = new URL("file://");
|
||||
if (resolved.includes("%")) resolved = resolved.replace(percentRegEx, "%25");
|
||||
// In posix, "/" is a valid character in paths
|
||||
if (!isWindows && resolved.includes("\\")) {
|
||||
resolved = resolved.replace(backslashRegEx, "%5C");
|
||||
}
|
||||
if (resolved.includes("\n")) resolved = resolved.replace(newlineRegEx, "%0A");
|
||||
if (resolved.includes("\r")) {
|
||||
resolved = resolved.replace(carriageReturnRegEx, "%0D");
|
||||
}
|
||||
if (resolved.includes("\t")) resolved = resolved.replace(tabRegEx, "%09");
|
||||
outURL.pathname = resolved;
|
||||
return outURL;
|
||||
}
|
||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
export * from "./_url.ts";
|
||||
import * as m from "./_url.ts";
|
||||
export default m;
|
||||
|
|
136
std/node/util.ts
136
std/node/util.ts
|
@ -1,134 +1,4 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
export { promisify } from "./_util/_util_promisify.ts";
|
||||
export { callbackify } from "./_util/_util_callbackify.ts";
|
||||
import { codes, errorMap } from "./_errors.ts";
|
||||
import * as types from "./_util/_util_types.ts";
|
||||
export { types };
|
||||
|
||||
const NumberIsSafeInteger = Number.isSafeInteger;
|
||||
const {
|
||||
ERR_OUT_OF_RANGE,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
} = codes;
|
||||
|
||||
const DEFAULT_INSPECT_OPTIONS = {
|
||||
showHidden: false,
|
||||
depth: 2,
|
||||
colors: false,
|
||||
customInspect: true,
|
||||
showProxy: false,
|
||||
maxArrayLength: 100,
|
||||
maxStringLength: Infinity,
|
||||
breakLength: 80,
|
||||
compact: 3,
|
||||
sorted: false,
|
||||
getters: false,
|
||||
};
|
||||
|
||||
inspect.defaultOptions = DEFAULT_INSPECT_OPTIONS;
|
||||
inspect.custom = Deno.customInspect;
|
||||
|
||||
// TODO(schwarzkopfb): make it in-line with Node's implementation
|
||||
// Ref: https://nodejs.org/dist/latest-v14.x/docs/api/util.html#util_util_inspect_object_options
|
||||
// deno-lint-ignore no-explicit-any
|
||||
export function inspect(object: unknown, ...opts: any): string {
|
||||
opts = { ...DEFAULT_INSPECT_OPTIONS, ...opts };
|
||||
return Deno.inspect(object, {
|
||||
depth: opts.depth,
|
||||
iterableLimit: opts.maxArrayLength,
|
||||
compact: !!opts.compact,
|
||||
sorted: !!opts.sorted,
|
||||
showProxy: !!opts.showProxy,
|
||||
});
|
||||
}
|
||||
|
||||
/** @deprecated - use `Array.isArray()` instead. */
|
||||
export function isArray(value: unknown): boolean {
|
||||
return Array.isArray(value);
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "boolean" || value instanceof Boolean` instead. */
|
||||
export function isBoolean(value: unknown): boolean {
|
||||
return typeof value === "boolean" || value instanceof Boolean;
|
||||
}
|
||||
|
||||
/** @deprecated - use `value === null` instead. */
|
||||
export function isNull(value: unknown): boolean {
|
||||
return value === null;
|
||||
}
|
||||
|
||||
/** @deprecated - use `value === null || value === undefined` instead. */
|
||||
export function isNullOrUndefined(value: unknown): boolean {
|
||||
return value === null || value === undefined;
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "number" || value instanceof Number` instead. */
|
||||
export function isNumber(value: unknown): boolean {
|
||||
return typeof value === "number" || value instanceof Number;
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "string" || value instanceof String` instead. */
|
||||
export function isString(value: unknown): boolean {
|
||||
return typeof value === "string" || value instanceof String;
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "symbol"` instead. */
|
||||
export function isSymbol(value: unknown): boolean {
|
||||
return typeof value === "symbol";
|
||||
}
|
||||
|
||||
/** @deprecated - use `value === undefined` instead. */
|
||||
export function isUndefined(value: unknown): boolean {
|
||||
return value === undefined;
|
||||
}
|
||||
|
||||
/** @deprecated - use `value !== null && typeof value === "object"` instead. */
|
||||
export function isObject(value: unknown): boolean {
|
||||
return value !== null && typeof value === "object";
|
||||
}
|
||||
|
||||
/** @deprecated - use `e instanceof Error` instead. */
|
||||
export function isError(e: unknown): boolean {
|
||||
return e instanceof Error;
|
||||
}
|
||||
|
||||
/** @deprecated - use `typeof value === "function"` instead. */
|
||||
export function isFunction(value: unknown): boolean {
|
||||
return typeof value === "function";
|
||||
}
|
||||
|
||||
/** @deprecated - use `value instanceof RegExp` instead. */
|
||||
export function isRegExp(value: unknown): boolean {
|
||||
return value instanceof RegExp;
|
||||
}
|
||||
|
||||
/** @deprecated - use `value === null || (typeof value !== "object" && typeof value !== "function")` instead. */
|
||||
export function isPrimitive(value: unknown): boolean {
|
||||
return (
|
||||
value === null || (typeof value !== "object" && typeof value !== "function")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a system error name from an error code number.
|
||||
* @param code error code number
|
||||
*/
|
||||
export function getSystemErrorName(code: number): string | undefined {
|
||||
if (typeof code !== "number") {
|
||||
throw new ERR_INVALID_ARG_TYPE("err", "number", code);
|
||||
}
|
||||
if (code >= 0 || !NumberIsSafeInteger(code)) {
|
||||
throw new ERR_OUT_OF_RANGE("err", "a negative integer", code);
|
||||
}
|
||||
return errorMap.get(code)?.[0];
|
||||
}
|
||||
|
||||
import { _TextDecoder, _TextEncoder } from "./_utils.ts";
|
||||
|
||||
/** The global TextDecoder */
|
||||
export type TextDecoder = import("./_utils.ts")._TextDecoder;
|
||||
export const TextDecoder = _TextDecoder;
|
||||
|
||||
/** The global TextEncoder */
|
||||
export type TextEncoder = import("./_utils.ts")._TextEncoder;
|
||||
export const TextEncoder = _TextEncoder;
|
||||
export * from "./_util.ts";
|
||||
import * as m from "./_util.ts";
|
||||
export default m;
|
||||
|
|
Loading…
Add table
Reference in a new issue