summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuy Bedford <guybedford@gmail.com>2020-11-09 06:25:13 -0800
committerGitHub <noreply@github.com>2020-11-09 09:25:13 -0500
commit8b7f5531ee1ccde897e87890e9aabc554fedb9dd (patch)
tree117a85b98d1488c290d8acc392cfb99b1b21f8e0
parent293cae5e1ff2a5768e2f3a73cc18f99acc3fbfbd (diff)
feat(std/node): consistent Node.js builtin shapes (#8274)
-rw-r--r--std/node/_buffer.ts599
-rw-r--r--std/node/_crypto.ts3
-rw-r--r--std/node/_crypto/pbkdf2.ts2
-rw-r--r--std/node/_crypto/randomBytes.ts2
-rw-r--r--std/node/_crypto/types.ts2
-rw-r--r--std/node/_fs.ts68
-rw-r--r--std/node/_os.ts224
-rw-r--r--std/node/_querystring.ts156
-rw-r--r--std/node/_string_decoder.ts299
-rw-r--r--std/node/_timers.ts14
-rw-r--r--std/node/_url.ts140
-rw-r--r--std/node/_util.ts134
-rw-r--r--std/node/assert.ts53
-rw-r--r--std/node/assert_test.ts9
-rw-r--r--std/node/buffer.ts603
-rw-r--r--std/node/buffer_test.ts2
-rw-r--r--std/node/crypto.ts8
-rw-r--r--std/node/events.ts316
-rw-r--r--std/node/fs.ts70
-rw-r--r--std/node/os.ts228
-rw-r--r--std/node/path.ts2
-rw-r--r--std/node/querystring.ts158
-rw-r--r--std/node/string_decoder.ts303
-rw-r--r--std/node/string_decoder_test.ts2
-rw-r--r--std/node/timers.ts16
-rw-r--r--std/node/url.ts144
-rw-r--r--std/node/util.ts136
27 files changed, 1875 insertions, 1818 deletions
diff --git a/std/node/_buffer.ts b/std/node/_buffer.ts
new file mode 100644
index 000000000..8cbd117ca
--- /dev/null
+++ b/std/node/_buffer.ts
@@ -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;
+ }
+}
diff --git a/std/node/_crypto.ts b/std/node/_crypto.ts
new file mode 100644
index 000000000..86c2b772f
--- /dev/null
+++ b/std/node/_crypto.ts
@@ -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";
diff --git a/std/node/_crypto/pbkdf2.ts b/std/node/_crypto/pbkdf2.ts
index 15b5eec3a..80aacdaf2 100644
--- a/std/node/_crypto/pbkdf2.ts
+++ b/std/node/_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";
diff --git a/std/node/_crypto/randomBytes.ts b/std/node/_crypto/randomBytes.ts
index 7b8276151..28c7e454e 100644
--- a/std/node/_crypto/randomBytes.ts
+++ b/std/node/_crypto/randomBytes.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;
diff --git a/std/node/_crypto/types.ts b/std/node/_crypto/types.ts
index 093fccadc..e56d8416c 100644
--- a/std/node/_crypto/types.ts
+++ b/std/node/_crypto/types.ts
@@ -1,3 +1,3 @@
-import Buffer from "../buffer.ts";
+import { Buffer } from "../buffer.ts";
export type HASH_DATA = string | ArrayBufferView | Buffer;
diff --git a/std/node/_fs.ts b/std/node/_fs.ts
new file mode 100644
index 000000000..052394e21
--- /dev/null
+++ b/std/node/_fs.ts
@@ -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,
+};
diff --git a/std/node/_os.ts b/std/node/_os.ts
new file mode 100644
index 000000000..773cca8bd
--- /dev/null
+++ b/std/node/_os.ts
@@ -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;
diff --git a/std/node/_querystring.ts b/std/node/_querystring.ts
new file mode 100644
index 000000000..a49f55f54
--- /dev/null
+++ b/std/node/_querystring.ts
@@ -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;
diff --git a/std/node/_string_decoder.ts b/std/node/_string_decoder.ts
new file mode 100644
index 000000000..ce7c19538
--- /dev/null
+++ b/std/node/_string_decoder.ts
@@ -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;
+ }
+}
diff --git a/std/node/_timers.ts b/std/node/_timers.ts
new file mode 100644
index 000000000..872e1f9ae
--- /dev/null
+++ b/std/node/_timers.ts
@@ -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;
diff --git a/std/node/_url.ts b/std/node/_url.ts
new file mode 100644
index 000000000..82daa25e9
--- /dev/null
+++ b/std/node/_url.ts
@@ -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;
+}
diff --git a/std/node/_util.ts b/std/node/_util.ts
new file mode 100644
index 000000000..9cf996670
--- /dev/null
+++ b/std/node/_util.ts
@@ -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;
diff --git a/std/node/assert.ts b/std/node/assert.ts
index ad353912e..ed402dd7f 100644
--- a/std/node/assert.ts
+++ b/std/node/assert.ts
@@ -1,25 +1,42 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+export { AssertionError } from "./assertion_error.ts";
import {
- assertEquals,
- assertMatch,
- assertNotEquals,
- assertNotStrictEquals,
- assertStrictEquals,
- assertThrows,
+ 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 { AssertionError } from "./assertion_error.ts";
+function assert(expr: unknown, msg = ""): asserts expr {
+ if (!expr) {
+ throw new AssertionError(msg);
+ }
+}
+const ok = assert;
+export default assert;
-export {
- assert,
- assert as default,
- assert as ok,
+Object.assign(assert, {
+ deepStrictEqual,
fail,
-} from "../testing/asserts.ts";
+ match,
+ notDeepStrictEqual,
+ notStrictEqual,
+ ok,
+ strictEqual,
+ throws,
+});
-export const deepStrictEqual = assertEquals;
-export const notDeepStrictEqual = assertNotEquals;
-export const strictEqual = assertStrictEquals;
-export const notStrictEqual = assertNotStrictEquals;
-export const match = assertMatch;
-export const throws = assertThrows;
+export {
+ deepStrictEqual,
+ fail,
+ match,
+ notDeepStrictEqual,
+ notStrictEqual,
+ ok,
+ strictEqual,
+ throws,
+};
diff --git a/std/node/assert_test.ts b/std/node/assert_test.ts
index 01a722ed3..f90587c94 100644
--- a/std/node/assert_test.ts
+++ b/std/node/assert_test.ts
@@ -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,
diff --git a/std/node/buffer.ts b/std/node/buffer.ts
index 16cf3abc0..664c1ed25 100644
--- a/std/node/buffer.ts
+++ b/std/node/buffer.ts
@@ -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;
diff --git a/std/node/buffer_test.ts b/std/node/buffer_test.ts
index fbd8d3cca..a360c91ff 100644
--- a/std/node/buffer_test.ts
+++ b/std/node/buffer_test.ts
@@ -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",
diff --git a/std/node/crypto.ts b/std/node/crypto.ts
index 49bf897d7..d27cab67d 100644
--- a/std/node/crypto.ts
+++ b/std/node/crypto.ts
@@ -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;
diff --git a/std/node/events.ts b/std/node/events.ts
index 568393f7f..16790907e 100644
--- a/std/node/events.ts
+++ b/std/node/events.ts
@@ -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,180 +391,168 @@ 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(
- emitter: EventEmitter | EventTarget,
- name: string,
- // deno-lint-ignore no-explicit-any
-): Promise<any[]> {
- return new Promise((resolve, reject) => {
- if (emitter instanceof EventTarget) {
- // EventTarget does not have `error` event semantics like Node
- // EventEmitters, we do not listen to `error` events here.
- emitter.addEventListener(
- name,
- (...args) => {
- resolve(args);
- },
- { once: true, passive: false, capture: false },
- );
- return;
- } else if (emitter instanceof EventEmitter) {
- // deno-lint-ignore no-explicit-any
- const eventListener = (...args: any[]): void => {
- if (errorListener !== undefined) {
- emitter.removeListener("error", errorListener);
- }
- resolve(args);
- };
- let errorListener: GenericFunction;
-
- // Adding an error listener is not optional because
- // if an error is thrown on an event emitter we cannot
- // guarantee that the actual event we are waiting will
- // be fired. The result could be a silent way to create
- // memory or file descriptor leaks, which is something
- // we should avoid.
- if (name !== "error") {
+ /**
+ * 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.
+ */
+ public static once(
+ emitter: EventEmitter | EventTarget,
+ name: string,
+ // deno-lint-ignore no-explicit-any
+ ): Promise<any[]> {
+ return new Promise((resolve, reject) => {
+ if (emitter instanceof EventTarget) {
+ // EventTarget does not have `error` event semantics like Node
+ // EventEmitters, we do not listen to `error` events here.
+ emitter.addEventListener(
+ name,
+ (...args) => {
+ resolve(args);
+ },
+ { once: true, passive: false, capture: false },
+ );
+ return;
+ } else if (emitter instanceof EventEmitter) {
// deno-lint-ignore no-explicit-any
- errorListener = (err: any): void => {
- emitter.removeListener(name, eventListener);
- reject(err);
+ const eventListener = (...args: any[]): void => {
+ if (errorListener !== undefined) {
+ emitter.removeListener("error", errorListener);
+ }
+ resolve(args);
};
+ let errorListener: GenericFunction;
+
+ // Adding an error listener is not optional because
+ // if an error is thrown on an event emitter we cannot
+ // guarantee that the actual event we are waiting will
+ // be fired. The result could be a silent way to create
+ // memory or file descriptor leaks, which is something
+ // we should avoid.
+ if (name !== "error") {
+ // deno-lint-ignore no-explicit-any
+ errorListener = (err: any): void => {
+ emitter.removeListener(name, eventListener);
+ reject(err);
+ };
+
+ emitter.once("error", errorListener);
+ }
- emitter.once("error", errorListener);
+ emitter.once(name, eventListener);
+ return;
}
+ });
+ }
- emitter.once(name, eventListener);
- return;
- }
- });
-}
+ /**
+ * 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.
+ */
+ public static on(
+ emitter: EventEmitter,
+ event: string | symbol,
+ ): AsyncIterable {
+ // deno-lint-ignore no-explicit-any
+ const unconsumedEventValues: any[] = [];
+ // deno-lint-ignore no-explicit-any
+ const unconsumedPromises: any[] = [];
+ let error: Error | null = null;
+ let finished = false;
-// deno-lint-ignore no-explicit-any
-function createIterResult(value: any, done: boolean): IteratorResult<any> {
- return { value, done };
-}
+ const iterator = {
+ // deno-lint-ignore no-explicit-any
+ next(): Promise<IteratorResult<any>> {
+ // First, we consume all unread events
+ // deno-lint-ignore no-explicit-any
+ const value: any = unconsumedEventValues.shift();
+ if (value) {
+ return Promise.resolve(createIterResult(value, false));
+ }
-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;
-}
+ // Then we error, if an error happened
+ // This happens one time if at all, because after 'error'
+ // we stop listening
+ if (error) {
+ const p: Promise<never> = Promise.reject(error);
+ // Only the first element errors
+ error = null;
+ return p;
+ }
-/**
- * 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(
- emitter: EventEmitter,
- event: string | symbol,
-): AsyncInterable {
- // deno-lint-ignore no-explicit-any
- const unconsumedEventValues: any[] = [];
- // deno-lint-ignore no-explicit-any
- const unconsumedPromises: any[] = [];
- let error: Error | null = null;
- let finished = false;
+ // If the iterator is finished, resolve to done
+ if (finished) {
+ return Promise.resolve(createIterResult(undefined, true));
+ }
+
+ // Wait until an event happens
+ return new Promise(function (resolve, reject) {
+ unconsumedPromises.push({ resolve, reject });
+ });
+ },
- const iterator = {
- // deno-lint-ignore no-explicit-any
- next(): Promise<IteratorResult<any>> {
- // First, we consume all unread events
// deno-lint-ignore no-explicit-any
- const value: any = unconsumedEventValues.shift();
- if (value) {
- return Promise.resolve(createIterResult(value, false));
- }
+ return(): Promise<IteratorResult<any>> {
+ emitter.removeListener(event, eventHandler);
+ emitter.removeListener("error", errorHandler);
+ finished = true;
- // Then we error, if an error happened
- // This happens one time if at all, because after 'error'
- // we stop listening
- if (error) {
- const p: Promise<never> = Promise.reject(error);
- // Only the first element errors
- error = null;
- return p;
- }
+ for (const promise of unconsumedPromises) {
+ promise.resolve(createIterResult(undefined, true));
+ }
- // If the iterator is finished, resolve to done
- if (finished) {
return Promise.resolve(createIterResult(undefined, true));
- }
-
- // Wait until an event happens
- return new Promise(function (resolve, reject) {
- unconsumedPromises.push({ resolve, reject });
- });
- },
+ },
- // deno-lint-ignore no-explicit-any
- return(): Promise<IteratorResult<any>> {
- emitter.removeListener(event, eventHandler);
- emitter.removeListener("error", errorHandler);
- finished = true;
+ throw(err: Error): void {
+ error = err;
+ emitter.removeListener(event, eventHandler);
+ emitter.removeListener("error", errorHandler);
+ },
- for (const promise of unconsumedPromises) {
- promise.resolve(createIterResult(undefined, true));
- }
+ // deno-lint-ignore no-explicit-any
+ [Symbol.asyncIterator](): any {
+ return this;
+ },
+ };
- return Promise.resolve(createIterResult(undefined, true));
- },
+ emitter.on(event, eventHandler);
+ emitter.on("error", errorHandler);
- throw(err: Error): void {
- error = err;
- emitter.removeListener(event, eventHandler);
- emitter.removeListener("error", errorHandler);
- },
+ return iterator;
// deno-lint-ignore no-explicit-any
- [Symbol.asyncIterator](): any {
- return this;
- },
- };
-
- emitter.on(event, eventHandler);
- emitter.on("error", errorHandler);
-
- return iterator;
-
- // deno-lint-ignore no-explicit-any
- function eventHandler(...args: any[]): void {
- const promise = unconsumedPromises.shift();
- if (promise) {
- promise.resolve(createIterResult(args, false));
- } else {
- unconsumedEventValues.push(args);
+ function eventHandler(...args: any[]): void {
+ const promise = unconsumedPromises.shift();
+ if (promise) {
+ promise.resolve(createIterResult(args, false));
+ } else {
+ unconsumedEventValues.push(args);
+ }
}
- }
- // deno-lint-ignore no-explicit-any
- function errorHandler(err: any): void {
- finished = true;
+ // deno-lint-ignore no-explicit-any
+ function errorHandler(err: any): void {
+ finished = true;
- const toError = unconsumedPromises.shift();
- if (toError) {
- toError.reject(err);
- } else {
- // The next time we call next()
- error = err;
- }
+ const toError = unconsumedPromises.shift();
+ if (toError) {
+ toError.reject(err);
+ } else {
+ // The next time we call next()
+ error = err;
+ }
- iterator.return();
+ 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;
diff --git a/std/node/fs.ts b/std/node/fs.ts
index 052394e21..04adbf417 100644
--- a/std/node/fs.ts
+++ b/std/node/fs.ts
@@ -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;
diff --git a/std/node/os.ts b/std/node/os.ts
index 773cca8bd..1599fbeb3 100644
--- a/std/node/os.ts
+++ b/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;
diff --git a/std/node/path.ts b/std/node/path.ts
index a206eb792..9234c9de9 100644
--- a/std/node/path.ts
+++ b/std/node/path.ts
@@ -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;
diff --git a/std/node/querystring.ts b/std/node/querystring.ts
index a49f55f54..ff68b2ae8 100644
--- a/std/node/querystring.ts
+++ b/std/node/querystring.ts
@@ -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;
diff --git a/std/node/string_decoder.ts b/std/node/string_decoder.ts
index ce7c19538..cc6fb5186 100644
--- a/std/node/string_decoder.ts
+++ b/std/node/string_decoder.ts
@@ -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;
diff --git a/std/node/string_decoder_test.ts b/std/node/string_decoder_test.ts
index 7c36ea383..c18f5ce56 100644
--- a/std/node/string_decoder_test.ts
+++ b/std/node/string_decoder_test.ts
@@ -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({
diff --git a/std/node/timers.ts b/std/node/timers.ts
index 872e1f9ae..095f6c5dc 100644
--- a/std/node/timers.ts
+++ b/std/node/timers.ts
@@ -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;
diff --git a/std/node/url.ts b/std/node/url.ts
index 82daa25e9..2aa2702aa 100644
--- a/std/node/url.ts
+++ b/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;
diff --git a/std/node/util.ts b/std/node/util.ts
index 9cf996670..b9239ec5d 100644
--- a/std/node/util.ts
+++ b/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;