diff options
author | Kitson Kelly <me@kitsonkelly.com> | 2019-03-10 04:30:38 +1100 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2019-03-09 12:30:38 -0500 |
commit | 034e2cc02829c9244b32232074c7a48af827a2fb (patch) | |
tree | bade01606a1ee076c1f753ce99c97ddb1e4edf30 /js | |
parent | 8c7a12d1b258f0ef5ab27f49c424331d43e8d97f (diff) |
Migrate from tslint to eslint for linting (#1905)
Diffstat (limited to 'js')
67 files changed, 972 insertions, 991 deletions
diff --git a/js/assets.ts b/js/assets.ts index 18bf97548..5f1790646 100644 --- a/js/assets.ts +++ b/js/assets.ts @@ -1,10 +1,9 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -// tslint:disable-next-line:no-reference +// eslint-disable-next-line @typescript-eslint/no-triple-slash-reference /// <reference path="./plugins.d.ts" /> // There is a rollup plugin that will inline any module ending with `!string` -// tslint:disable:max-line-length // Generated default library import libDts from "gen/lib/lib.deno_runtime.d.ts!string"; @@ -39,7 +38,6 @@ import libEsnextBigintDts from "/third_party/node_modules/typescript/lib/lib.esn import libEsnextDts from "/third_party/node_modules/typescript/lib/lib.esnext.d.ts!string"; import libEsnextIntlDts from "/third_party/node_modules/typescript/lib/lib.esnext.intl.d.ts!string"; import libEsnextSymbolDts from "/third_party/node_modules/typescript/lib/lib.esnext.symbol.d.ts!string"; -// tslint:enable:max-line-length // @internal export const assetSourceCode: { [key: string]: string } = { diff --git a/js/blob.ts b/js/blob.ts index 7510c9cef..c23b74afb 100644 --- a/js/blob.ts +++ b/js/blob.ts @@ -5,6 +5,75 @@ import { TextEncoder } from "./text_encoding"; export const bytesSymbol = Symbol("bytes"); +function convertLineEndingsToNative(s: string): string { + // TODO(qti3e) Implement convertLineEndingsToNative. + // https://w3c.github.io/FileAPI/#convert-line-endings-to-native + return s; +} + +function toUint8Arrays( + blobParts: domTypes.BlobPart[], + doNormalizeLineEndingsToNative: boolean +): Uint8Array[] { + const ret: Uint8Array[] = []; + const enc = new TextEncoder(); + for (const element of blobParts) { + if (typeof element === "string") { + let str = element; + if (doNormalizeLineEndingsToNative) { + str = convertLineEndingsToNative(element); + } + ret.push(enc.encode(str)); + // eslint-disable-next-line @typescript-eslint/no-use-before-define + } else if (element instanceof DenoBlob) { + ret.push(element[bytesSymbol]); + } else if (element instanceof Uint8Array) { + ret.push(element); + } else if (element instanceof Uint16Array) { + const uint8 = new Uint8Array(element.buffer); + ret.push(uint8); + } else if (element instanceof Uint32Array) { + const uint8 = new Uint8Array(element.buffer); + ret.push(uint8); + } else if (ArrayBuffer.isView(element)) { + // Convert view to Uint8Array. + const uint8 = new Uint8Array(element.buffer); + ret.push(uint8); + } else if (element instanceof ArrayBuffer) { + // Create a new Uint8Array view for the given ArrayBuffer. + const uint8 = new Uint8Array(element); + ret.push(uint8); + } else { + ret.push(enc.encode(String(element))); + } + } + return ret; +} + +function processBlobParts( + blobParts: domTypes.BlobPart[], + options: domTypes.BlobPropertyBag +): Uint8Array { + const normalizeLineEndingsToNative = options.ending === "native"; + // ArrayBuffer.transfer is not yet implemented in V8, so we just have to + // pre compute size of the array buffer and do some sort of static allocation + // instead of dynamic allocation. + const uint8Arrays = toUint8Arrays(blobParts, normalizeLineEndingsToNative); + const byteLength = uint8Arrays + .map(u8 => u8.byteLength) + .reduce((a, b) => a + b, 0); + const ab = new ArrayBuffer(byteLength); + const bytes = new Uint8Array(ab); + + let courser = 0; + for (const u8 of uint8Arrays) { + bytes.set(u8, courser); + courser += u8.byteLength; + } + + return bytes; +} + export class DenoBlob implements domTypes.Blob { private readonly [bytesSymbol]: Uint8Array; readonly size: number = 0; @@ -56,71 +125,3 @@ export class DenoBlob implements domTypes.Blob { }); } } - -function processBlobParts( - blobParts: domTypes.BlobPart[], - options: domTypes.BlobPropertyBag -): Uint8Array { - const normalizeLineEndingsToNative = options.ending === "native"; - // ArrayBuffer.transfer is not yet implemented in V8, so we just have to - // pre compute size of the array buffer and do some sort of static allocation - // instead of dynamic allocation. - const uint8Arrays = toUint8Arrays(blobParts, normalizeLineEndingsToNative); - const byteLength = uint8Arrays - .map(u8 => u8.byteLength) - .reduce((a, b) => a + b, 0); - const ab = new ArrayBuffer(byteLength); - const bytes = new Uint8Array(ab); - - let courser = 0; - for (const u8 of uint8Arrays) { - bytes.set(u8, courser); - courser += u8.byteLength; - } - - return bytes; -} - -function toUint8Arrays( - blobParts: domTypes.BlobPart[], - doNormalizeLineEndingsToNative: boolean -): Uint8Array[] { - const ret: Uint8Array[] = []; - const enc = new TextEncoder(); - for (const element of blobParts) { - if (typeof element === "string") { - let str = element; - if (doNormalizeLineEndingsToNative) { - str = convertLineEndingsToNative(element); - } - ret.push(enc.encode(str)); - } else if (element instanceof DenoBlob) { - ret.push(element[bytesSymbol]); - } else if (element instanceof Uint8Array) { - ret.push(element); - } else if (element instanceof Uint16Array) { - const uint8 = new Uint8Array(element.buffer); - ret.push(uint8); - } else if (element instanceof Uint32Array) { - const uint8 = new Uint8Array(element.buffer); - ret.push(uint8); - } else if (ArrayBuffer.isView(element)) { - // Convert view to Uint8Array. - const uint8 = new Uint8Array(element.buffer); - ret.push(uint8); - } else if (element instanceof ArrayBuffer) { - // Create a new Uint8Array view for the given ArrayBuffer. - const uint8 = new Uint8Array(element); - ret.push(uint8); - } else { - ret.push(enc.encode(String(element))); - } - } - return ret; -} - -function convertLineEndingsToNative(s: string): string { - // TODO(qti3e) Implement convertLineEndingsToNative. - // https://w3c.github.io/FileAPI/#convert-line-endings-to-native - return s; -} diff --git a/js/buffer.ts b/js/buffer.ts index db060f2ff..c5be762f5 100644 --- a/js/buffer.ts +++ b/js/buffer.ts @@ -66,14 +66,14 @@ export class Buffer implements Reader, Writer { } /** empty() returns whether the unread portion of the buffer is empty. */ - empty() { + empty(): boolean { return this.buf.byteLength <= this.off; } /** length is a getter that returns the number of bytes of the unread * portion of the buffer */ - get length() { + get length(): number { return this.buf.byteLength - this.off; } diff --git a/js/buffer_test.ts b/js/buffer_test.ts index 691d97e20..90e171330 100644 --- a/js/buffer_test.ts +++ b/js/buffer_test.ts @@ -13,7 +13,7 @@ const N = 100; let testBytes: Uint8Array | null; let testString: string | null; -function init() { +function init(): void { if (testBytes == null) { testBytes = new Uint8Array(N); for (let i = 0; i < N; i++) { @@ -24,7 +24,7 @@ function init() { } } -function check(buf: Deno.Buffer, s: string) { +function check(buf: Deno.Buffer, s: string): void { const bytes = buf.bytes(); assertEquals(buf.length, bytes.byteLength); const decoder = new TextDecoder(); @@ -69,6 +69,13 @@ async function empty(buf: Buffer, s: string, fub: Uint8Array): Promise<void> { check(buf, ""); } +function repeat(c: string, bytes: number): Uint8Array { + assertEquals(c.length, 1); + const ui8 = new Uint8Array(bytes); + ui8.fill(c.charCodeAt(0)); + return ui8; +} + test(function bufferNewBuffer() { init(); const buf = new Buffer(testBytes.buffer as ArrayBuffer); @@ -140,7 +147,7 @@ test(async function bufferTooLargeByteWrites() { const growLen = Number.MAX_VALUE; const xBytes = repeat("x", 0); const buf = new Buffer(xBytes.buffer as ArrayBuffer); - const { nread, eof } = await buf.read(tmp); + await buf.read(tmp); let err; try { @@ -186,13 +193,6 @@ test(async function bufferReadFrom() { } }); -function repeat(c: string, bytes: number): Uint8Array { - assertEquals(c.length, 1); - const ui8 = new Uint8Array(bytes); - ui8.fill(c.charCodeAt(0)); - return ui8; -} - test(async function bufferTestGrow() { const tmp = new Uint8Array(72); for (let startLen of [0, 100, 1000, 10000, 100000]) { @@ -200,7 +200,7 @@ test(async function bufferTestGrow() { for (let growLen of [0, 100, 1000, 10000, 100000]) { const buf = new Buffer(xBytes.buffer as ArrayBuffer); // If we read, this affects buf.off, which is good to test. - const { nread, eof } = await buf.read(tmp); + const { nread } = await buf.read(tmp); buf.grow(growLen); const yBytes = repeat("y", growLen); await buf.write(yBytes); diff --git a/js/build.ts b/js/build.ts index 636f9a082..347dd4e72 100644 --- a/js/build.ts +++ b/js/build.ts @@ -15,12 +15,12 @@ export interface BuildInfo { // 'build' is injected by rollup.config.js at compile time. export const build: BuildInfo = { - // tslint:disable:no-any + /* eslint-disable @typescript-eslint/no-explicit-any */ // These string will be replaced by rollup arch: `ROLLUP_REPLACE_ARCH` as any, os: `ROLLUP_REPLACE_OS` as any, gnArgs: `ROLLUP_REPLACE_GN_ARGS` - // tslint:disable:any + /* eslint-enable @typescript-eslint/no-explicit-any */ }; // TODO(kevinkassimo): deprecate Deno.platform diff --git a/js/chmod.ts b/js/chmod.ts index 2a9b1b01d..3b14ef5bc 100644 --- a/js/chmod.ts +++ b/js/chmod.ts @@ -3,6 +3,19 @@ import * as msg from "gen/msg_generated"; import * as flatbuffers from "./flatbuffers"; import * as dispatch from "./dispatch"; +function req( + path: string, + mode: number +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + const builder = flatbuffers.createBuilder(); + const path_ = builder.createString(path); + msg.Chmod.startChmod(builder); + msg.Chmod.addPath(builder, path_); + msg.Chmod.addMode(builder, mode); + const inner = msg.Chmod.endChmod(builder); + return [builder, msg.Any.Chmod, inner]; +} + /** Changes the permission of a specific file/directory of specified path * synchronously. * @@ -19,16 +32,3 @@ export function chmodSync(path: string, mode: number): void { export async function chmod(path: string, mode: number): Promise<void> { await dispatch.sendAsync(...req(path, mode)); } - -function req( - path: string, - mode: number -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - const builder = flatbuffers.createBuilder(); - const path_ = builder.createString(path); - msg.Chmod.startChmod(builder); - msg.Chmod.addPath(builder, path_); - msg.Chmod.addMode(builder, mode); - const inner = msg.Chmod.endChmod(builder); - return [builder, msg.Any.Chmod, inner]; -} diff --git a/js/compiler.ts b/js/compiler.ts index 39a32bc24..aefdf989d 100644 --- a/js/compiler.ts +++ b/js/compiler.ts @@ -61,7 +61,6 @@ interface Os { */ interface Ts { createLanguageService: typeof ts.createLanguageService; - /* tslint:disable-next-line:max-line-length */ formatDiagnosticsWithColorAndContext: typeof ts.formatDiagnosticsWithColorAndContext; formatDiagnostics: typeof ts.formatDiagnostics; } @@ -529,7 +528,6 @@ window.compilerMain = function compilerMain() { }; }; -/* tslint:disable-next-line:no-default-export */ -export default function denoMain() { +export default function denoMain(): void { os.start("TS"); } diff --git a/js/compiler_test.ts b/js/compiler_test.ts index e8101995e..e3631641a 100644 --- a/js/compiler_test.ts +++ b/js/compiler_test.ts @@ -2,7 +2,8 @@ import { test, assert, assertEquals } from "./test_util.ts"; // We use a silly amount of `any` in these tests... -// tslint:disable:no-any + +/* eslint-disable @typescript-eslint/no-explicit-any */ const { Compiler, jsonEsmTemplate } = (Deno as any)._compiler; @@ -106,7 +107,6 @@ const modBModuleInfo = mockModuleInfo( undefined ); -// tslint:disable:max-line-length const fooBarTsOutput = `import * as deno from "deno"; console.log(deno); export const foo = "bar"; @@ -119,7 +119,6 @@ const loadConfigSource = `import * as config from "./config.json"; console.log(config.foo.baz); `; const configJsonSource = `{"foo":{"bar": true,"baz": ["qat", 1]}}`; -// tslint:enable:max-line-length const moduleMap: { [containFile: string]: { [moduleSpecifier: string]: ModuleInfo }; @@ -244,10 +243,6 @@ const moduleCache: { "/root/project/modB.ts": modBModuleInfo }; -const emittedFiles = { - "/root/project/foo/qat.ts": "console.log('foo');" -}; - let getEmitOutputStack: string[] = []; let logStack: any[][] = []; let codeCacheStack: Array<{ @@ -351,7 +346,7 @@ const mocks = { /** * Setup the mocks for a test */ -function setup() { +function setup(): void { // monkey patch mocks on instance Object.assign(compilerInstance, mocks); } @@ -359,7 +354,7 @@ function setup() { /** * Teardown the mocks for a test */ -function teardown() { +function teardown(): void { // reset compiler internal state (compilerInstance as any)._moduleMetaDataMap.clear(); (compilerInstance as any)._fileNamesMap.clear(); diff --git a/js/console.ts b/js/console.ts index 4cfd0211d..20eafbacf 100644 --- a/js/console.ts +++ b/js/console.ts @@ -33,12 +33,14 @@ export class CSI { static kClearScreenDown = "\x1b[0J"; } -function cursorTo(stream: File, x: number, y?: number) { +/* eslint-disable @typescript-eslint/no-use-before-define */ + +function cursorTo(stream: File, _x: number, _y?: number): void { const uint8 = new TextEncoder().encode(CSI.kClear); stream.write(uint8); } -function clearScreenDown(stream: File) { +function clearScreenDown(stream: File): void { const uint8 = new TextEncoder().encode(CSI.kClearScreenDown); stream.write(uint8); } @@ -56,7 +58,7 @@ function getClassInstanceName(instance: unknown): string { return ""; } -function createFunctionString(value: Function, ctx: ConsoleContext): string { +function createFunctionString(value: Function, _ctx: ConsoleContext): string { // Might be Function/AsyncFunction/GeneratorFunction const cstrName = Object.getPrototypeOf(value).constructor.name; if (value.name && value.name !== "anonymous") { @@ -103,6 +105,54 @@ function createIterableString<T>( return `${iPrefix}${config.delims[0]}${iContent}${config.delims[1]}`; } +function stringify( + value: unknown, + ctx: ConsoleContext, + level: number, + maxLevel: number +): string { + switch (typeof value) { + case "string": + return value; + case "number": + case "boolean": + case "undefined": + case "symbol": + return String(value); + case "bigint": + return `${value}n`; + case "function": + return createFunctionString(value as Function, ctx); + case "object": + if (value === null) { + return "null"; + } + + if (ctx.has(value)) { + return "[Circular]"; + } + + return createObjectString(value, ctx, level, maxLevel); + default: + return "[Not Implemented]"; + } +} + +// Print strings when they are inside of arrays or objects with quotes +function stringifyWithQuotes( + value: unknown, + ctx: ConsoleContext, + level: number, + maxLevel: number +): string { + switch (typeof value) { + case "string": + return `"${value}"`; + default: + return stringify(value, ctx, level, maxLevel); + } +} + function createArrayString( value: unknown[], ctx: ConsoleContext, @@ -183,30 +233,31 @@ function createWeakMapString(): string { return "WeakMap { [items unknown] }"; // as seen in Node } -function createDateString(value: Date) { +function createDateString(value: Date): string { // without quotes, ISO format return value.toISOString(); } -function createRegExpString(value: RegExp) { +function createRegExpString(value: RegExp): string { return value.toString(); } -// tslint:disable-next-line:ban-types -function createStringWrapperString(value: String) { +/* eslint-disable @typescript-eslint/ban-types */ + +function createStringWrapperString(value: String): string { return `[String: "${value.toString()}"]`; } -// tslint:disable-next-line:ban-types -function createBooleanWrapperString(value: Boolean) { +function createBooleanWrapperString(value: Boolean): string { return `[Boolean: ${value.toString()}]`; } -// tslint:disable-next-line:ban-types -function createNumberWrapperString(value: Number) { +function createNumberWrapperString(value: Number): string { return `[Number: ${value.toString()}]`; } +/* eslint-enable @typescript-eslint/ban-types */ + // TODO: Promise, requires v8 bindings to get info // TODO: Proxy @@ -261,22 +312,19 @@ function createObjectString( } else if (Array.isArray(value)) { return createArrayString(value, ...args); } else if (value instanceof Number) { - // tslint:disable-next-line:ban-types - return createNumberWrapperString(value as Number); + return createNumberWrapperString(value); } else if (value instanceof Boolean) { - // tslint:disable-next-line:ban-types - return createBooleanWrapperString(value as Boolean); + return createBooleanWrapperString(value); } else if (value instanceof String) { - // tslint:disable-next-line:ban-types - return createStringWrapperString(value as String); + return createStringWrapperString(value); } else if (value instanceof RegExp) { - return createRegExpString(value as RegExp); + return createRegExpString(value); } else if (value instanceof Date) { - return createDateString(value as Date); + return createDateString(value); } else if (value instanceof Set) { - return createSetString(value as Set<unknown>, ...args); + return createSetString(value, ...args); } else if (value instanceof Map) { - return createMapString(value as Map<unknown, unknown>, ...args); + return createMapString(value, ...args); } else if (value instanceof WeakSet) { return createWeakSetString(); } else if (value instanceof WeakMap) { @@ -293,54 +341,6 @@ function createObjectString( } } -function stringify( - value: unknown, - ctx: ConsoleContext, - level: number, - maxLevel: number -): string { - switch (typeof value) { - case "string": - return value; - case "number": - case "boolean": - case "undefined": - case "symbol": - return String(value); - case "bigint": - return `${value}n`; - case "function": - return createFunctionString(value as Function, ctx); - case "object": - if (value === null) { - return "null"; - } - - if (ctx.has(value)) { - return "[Circular]"; - } - - return createObjectString(value, ctx, level, maxLevel); - default: - return "[Not Implemented]"; - } -} - -// Print strings when they are inside of arrays or objects with quotes -function stringifyWithQuotes( - value: unknown, - ctx: ConsoleContext, - level: number, - maxLevel: number -): string { - switch (typeof value) { - case "string": - return `"${value}"`; - default: - return stringify(value, ctx, level, maxLevel); - } -} - /** TODO Do not expose this from "deno" namespace. * @internal */ @@ -394,7 +394,6 @@ export function stringifyArgs( args[++a], new Set<unknown>(), 0, - // tslint:disable-next-line:triple-equals options.depth != undefined ? options.depth : DEFAULT_MAX_DEPTH ); break; @@ -443,7 +442,6 @@ export function stringifyArgs( value, new Set<unknown>(), 0, - // tslint:disable-next-line:triple-equals options.depth != undefined ? options.depth : DEFAULT_MAX_DEPTH ); } @@ -581,9 +579,9 @@ export class Console { const indexKeys: string[] = []; const values: string[] = []; - const stringifyValue = (value: unknown) => + const stringifyValue = (value: unknown): string => stringifyWithQuotes(value, new Set<unknown>(), 0, 1); - const toTable = (header: string[], body: string[][]) => + const toTable = (header: string[], body: string[][]): void => this.log(cliTable(header, body)); const createColumn = (value: unknown, shift?: number): string[] => [ ...(shift ? [...new Array(shift)].map(() => "") : []), @@ -725,7 +723,7 @@ export class Console { * inspect() converts input into string that has the same format * as printed by console.log(...); */ -export function inspect(value: unknown, options?: ConsoleOptions) { +export function inspect(value: unknown, options?: ConsoleOptions): string { const opts = options || {}; if (typeof value === "string") { return value; @@ -734,7 +732,6 @@ export function inspect(value: unknown, options?: ConsoleOptions) { value, new Set<unknown>(), 0, - // tslint:disable-next-line:triple-equals opts.depth != undefined ? opts.depth : DEFAULT_MAX_DEPTH ); } diff --git a/js/console_table.ts b/js/console_table.ts index 735ed0f9e..d7cae124c 100644 --- a/js/console_table.ts +++ b/js/console_table.ts @@ -51,7 +51,7 @@ function renderRow(row: string[], columnWidths: number[]): string { } export function cliTable(head: string[], columns: string[][]): string { - const rows = []; + const rows: string[][] = []; const columnWidths = head.map((h: string) => countBytes(h)); const longestColumn = columns.reduce( (n: number, a: string[]) => Math.max(n, a.length), @@ -64,10 +64,7 @@ export function cliTable(head: string[], columns: string[][]): string { if (rows[j] === undefined) { rows[j] = []; } - // tslint:disable-next-line:no-any - const value = ((rows[j][i] as any) = column.hasOwnProperty(j) - ? column[j] - : ""); + const value = (rows[j][i] = column.hasOwnProperty(j) ? column[j] : ""); const width = columnWidths[i] || 0; const counted = countBytes(value); columnWidths[i] = Math.max(width, counted); diff --git a/js/console_test.ts b/js/console_test.ts index ed9910006..ddc48de05 100644 --- a/js/console_test.ts +++ b/js/console_test.ts @@ -3,13 +3,12 @@ import { assert, assertEquals, test } from "./test_util.ts"; // Some of these APIs aren't exposed in the types and so we have to cast to any // in order to "trick" TypeScript. -// tslint:disable-next-line:no-any +// eslint-disable-next-line @typescript-eslint/no-explicit-any const { Console, libdeno, stringifyArgs, inspect, write, stdout } = Deno as any; const console = new Console(libdeno.print); -// tslint:disable-next-line:no-any -function stringify(...args: any[]): string { +function stringify(...args: unknown[]): string { return stringifyArgs(args).replace(/\n$/, ""); } @@ -35,15 +34,15 @@ test(function consoleTestStringifyComplexObjects() { test(function consoleTestStringifyCircular() { class Base { a = 1; - m1() {} + m1(): void {} } class Extended extends Base { b = 2; - m2() {} + m2(): void {} } - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any const nestedObj: any = { num: 1, bool: true, @@ -73,18 +72,14 @@ test(function consoleTestStringifyCircular() { }; nestedObj.o = circularObj; - // tslint:disable-next-line:max-line-length const nestedObjExpected = `{ num: 1, bool: true, str: "a", method: [Function: method], asyncMethod: [AsyncFunction: asyncMethod], generatorMethod: [GeneratorFunction: generatorMethod], un: undefined, nu: null, arrowFunc: [Function: arrowFunc], extendedClass: Extended { a: 1, b: 2 }, nFunc: [Function], extendedCstr: [Function: Extended], o: { num: 2, bool: false, str: "b", method: [Function: method], un: undefined, nu: null, nested: [Circular], emptyObj: {}, arr: [ 1, "s", false, null, [Circular] ], baseClass: Base { a: 1 } } }`; assertEquals(stringify(1), "1"); assertEquals(stringify(1n), "1n"); assertEquals(stringify("s"), "s"); assertEquals(stringify(false), "false"); - // tslint:disable-next-line:no-construct assertEquals(stringify(new Number(1)), "[Number: 1]"); - // tslint:disable-next-line:no-construct assertEquals(stringify(new Boolean(true)), "[Boolean: true]"); - // tslint:disable-next-line:no-construct assertEquals(stringify(new String("deno")), `[String: "deno"]`); assertEquals(stringify(/[0-9]*/), "/[0-9]*/"); assertEquals( @@ -119,7 +114,6 @@ test(function consoleTestStringifyCircular() { assertEquals(stringify(JSON), "{}"); assertEquals( stringify(console), - // tslint:disable-next-line:max-line-length "Console { printFunc: [Function], log: [Function], debug: [Function], info: [Function], dir: [Function], warn: [Function], error: [Function], assert: [Function], count: [Function], countReset: [Function], table: [Function], time: [Function], timeLog: [Function], timeEnd: [Function], group: [Function], groupCollapsed: [Function], groupEnd: [Function], clear: [Function], indentLevel: 0, collapsedAt: null }" ); // test inspect is working the same @@ -127,7 +121,7 @@ test(function consoleTestStringifyCircular() { }); test(function consoleTestStringifyWithDepth() { - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any const nestedObj: any = { a: { b: { c: { d: { e: { f: 42 } } } } } }; assertEquals( stringifyArgs([nestedObj], { depth: 3 }), @@ -313,22 +307,23 @@ test(function consoleDetachedLog() { class StringBuffer { chunks: string[] = []; - add(x: string) { + add(x: string): void { this.chunks.push(x); } - toString() { + toString(): string { return this.chunks.join(""); } } type ConsoleExamineFunc = ( - csl: any, // tslint:disable-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any + csl: any, out: StringBuffer, err?: StringBuffer, both?: StringBuffer ) => void; -function mockConsole(f: ConsoleExamineFunc) { +function mockConsole(f: ConsoleExamineFunc): void { const out = new StringBuffer(); const err = new StringBuffer(); const both = new StringBuffer(); diff --git a/js/copy_file.ts b/js/copy_file.ts index dc099f701..a7792d588 100644 --- a/js/copy_file.ts +++ b/js/copy_file.ts @@ -3,6 +3,20 @@ import * as msg from "gen/msg_generated"; import * as flatbuffers from "./flatbuffers"; import * as dispatch from "./dispatch"; +function req( + from: string, + to: string +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + const builder = flatbuffers.createBuilder(); + const from_ = builder.createString(from); + const to_ = builder.createString(to); + msg.CopyFile.startCopyFile(builder); + msg.CopyFile.addFrom(builder, from_); + msg.CopyFile.addTo(builder, to_); + const inner = msg.CopyFile.endCopyFile(builder); + return [builder, msg.Any.CopyFile, inner]; +} + /** Copies the contents of a file to another by name synchronously. * Creates a new file if target does not exists, and if target exists, * overwrites original content of the target file. @@ -29,17 +43,3 @@ export function copyFileSync(from: string, to: string): void { export async function copyFile(from: string, to: string): Promise<void> { await dispatch.sendAsync(...req(from, to)); } - -function req( - from: string, - to: string -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - const builder = flatbuffers.createBuilder(); - const from_ = builder.createString(from); - const to_ = builder.createString(to); - msg.CopyFile.startCopyFile(builder); - msg.CopyFile.addFrom(builder, from_); - msg.CopyFile.addTo(builder, to_); - const inner = msg.CopyFile.endCopyFile(builder); - return [builder, msg.Any.CopyFile, inner]; -} diff --git a/js/copy_file_test.ts b/js/copy_file_test.ts index 33f8f027f..5348094c4 100644 --- a/js/copy_file_test.ts +++ b/js/copy_file_test.ts @@ -7,13 +7,13 @@ function readFileString(filename: string): string { return dec.decode(dataRead); } -function writeFileString(filename: string, s: string) { +function writeFileString(filename: string, s: string): void { const enc = new TextEncoder(); const data = enc.encode(s); Deno.writeFileSync(filename, data, { perm: 0o666 }); } -function assertSameContent(filename1: string, filename2: string) { +function assertSameContent(filename1: string, filename2: string): void { const data1 = Deno.readFileSync(filename1); const data2 = Deno.readFileSync(filename2); assertEquals(data1, data2); diff --git a/js/custom_event.ts b/js/custom_event.ts index dd1c33d58..d2092a2be 100644 --- a/js/custom_event.ts +++ b/js/custom_event.ts @@ -4,13 +4,12 @@ import * as event from "./event"; import { getPrivateValue } from "./util"; // WeakMaps are recommended for private attributes (see MDN link below) -// tslint:disable-next-line:max-line-length // https://developer.mozilla.org/en-US/docs/Archive/Add-ons/Add-on_SDK/Guides/Contributor_s_Guide/Private_Properties#Using_WeakMaps export const customEventAttributes = new WeakMap(); export class CustomEventInit extends event.EventInit implements domTypes.CustomEventInit { - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any detail: any; constructor({ @@ -34,7 +33,7 @@ export class CustomEvent extends event.Event implements domTypes.CustomEvent { customEventAttributes.set(this, { detail }); } - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any get detail(): any { return getPrivateValue(this, customEventAttributes, "detail"); } @@ -43,9 +42,9 @@ export class CustomEvent extends event.Event implements domTypes.CustomEvent { type: string, bubbles?: boolean, cancelable?: boolean, - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any detail?: any - ) { + ): void { if (this.dispatched) { return; } diff --git a/js/dispatch.ts b/js/dispatch.ts index 55ea682fc..537291877 100644 --- a/js/dispatch.ts +++ b/js/dispatch.ts @@ -10,11 +10,11 @@ const promiseTable = new Map<number, util.Resolvable<msg.Base>>(); let fireTimers: () => void; -export function setFireTimersCallback(fn: () => void) { +export function setFireTimersCallback(fn: () => void): void { fireTimers = fn; } -export function handleAsyncMsgFromRust(ui8: Uint8Array) { +export function handleAsyncMsgFromRust(ui8: Uint8Array): void { // If a the buffer is empty, recv() on the native side timed out and we // did not receive a message. if (ui8 && ui8.length) { @@ -35,6 +35,25 @@ export function handleAsyncMsgFromRust(ui8: Uint8Array) { fireTimers(); } +function sendInternal( + builder: flatbuffers.Builder, + innerType: msg.Any, + inner: flatbuffers.Offset, + data: undefined | ArrayBufferView, + sync = true +): [number, null | Uint8Array] { + const cmdId = nextCmdId++; + msg.Base.startBase(builder); + msg.Base.addInner(builder, inner); + msg.Base.addInnerType(builder, innerType); + msg.Base.addSync(builder, sync); + msg.Base.addCmdId(builder, cmdId); + builder.finish(msg.Base.endBase(builder)); + const res = libdeno.send(builder.asUint8Array(), data); + builder.inUse = false; + return [cmdId, res]; +} + // @internal export function sendAsync( builder: flatbuffers.Builder, @@ -68,22 +87,3 @@ export function sendSync( return baseRes; } } - -function sendInternal( - builder: flatbuffers.Builder, - innerType: msg.Any, - inner: flatbuffers.Offset, - data: undefined | ArrayBufferView, - sync = true -): [number, null | Uint8Array] { - const cmdId = nextCmdId++; - msg.Base.startBase(builder); - msg.Base.addInner(builder, inner); - msg.Base.addInnerType(builder, innerType); - msg.Base.addSync(builder, sync); - msg.Base.addCmdId(builder, cmdId); - builder.finish(msg.Base.endBase(builder)); - const res = libdeno.send(builder.asUint8Array(), data); - builder.inUse = false; - return [cmdId, res]; -} diff --git a/js/dom_types.ts b/js/dom_types.ts index 651eece9a..bf6e07796 100644 --- a/js/dom_types.ts +++ b/js/dom_types.ts @@ -15,6 +15,8 @@ See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. *******************************************************************************/ +/* eslint-disable @typescript-eslint/no-explicit-any */ + export type BufferSource = ArrayBufferView | ArrayBuffer; export type HeadersInit = @@ -50,7 +52,6 @@ export interface DomIterable<K, V> { [Symbol.iterator](): IterableIterator<[K, V]>; forEach( callback: (value: V, key: K, parent: this) => void, - // tslint:disable-next-line:no-any thisArg?: any ): void; } @@ -129,7 +130,6 @@ export interface URLSearchParams { */ forEach( callbackfn: (value: string, key: string, parent: URLSearchParams) => void, - // tslint:disable-next-line:no-any thisArg?: any ): void; } @@ -145,7 +145,6 @@ export interface EventInit { } export interface CustomEventInit extends EventInit { - // tslint:disable-next-line:no-any detail?: any; } @@ -188,13 +187,11 @@ export interface Event { } export interface CustomEvent extends Event { - // tslint:disable-next-line:no-any readonly detail: any; initCustomEvent( type: string, bubbles?: boolean, cancelable?: boolean, - // tslint:disable-next-line:no-any detail?: any | null ): void; } @@ -228,11 +225,9 @@ export interface AddEventListenerOptions extends EventListenerOptions { interface AbortSignal extends EventTarget { readonly aborted: boolean; - // tslint:disable-next-line:no-any onabort: ((this: AbortSignal, ev: ProgressEvent) => any) | null; addEventListener<K extends keyof AbortSignalEventMap>( type: K, - // tslint:disable-next-line:no-any listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | AddEventListenerOptions ): void; @@ -243,7 +238,6 @@ interface AbortSignal extends EventTarget { ): void; removeEventListener<K extends keyof AbortSignalEventMap>( type: K, - // tslint:disable-next-line:no-any listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | EventListenerOptions ): void; @@ -266,7 +260,6 @@ export interface EventListenerObject { export interface ReadableStreamReader { cancel(): Promise<void>; - // tslint:disable-next-line:no-any read(): Promise<any>; releaseLock(): void; } @@ -321,7 +314,6 @@ export interface Body { /** Takes a `Response` stream and reads it to completion. It returns a promise * that resolves with the result of parsing the body text as JSON. */ - // tslint:disable-next-line:no-any json(): Promise<any>; /** Takes a `Response` stream and reads it to completion. It returns a promise * that resolves with a `USVString` (text). @@ -363,7 +355,6 @@ export interface Headers extends DomIterable<string, string> { values(): IterableIterator<string>; forEach( callbackfn: (value: string, key: string, parent: this) => void, - // tslint:disable-next-line:no-any thisArg?: any ): void; /** The Symbol.iterator well-known symbol specifies the default @@ -427,7 +418,6 @@ export interface RequestInit { referrer?: string; referrerPolicy?: ReferrerPolicy; signal?: AbortSignal | null; - // tslint:disable-next-line:no-any window?: any; } diff --git a/js/errors.ts b/js/errors.ts index 452b2372e..cefa4a863 100644 --- a/js/errors.ts +++ b/js/errors.ts @@ -25,14 +25,6 @@ export class DenoError<T extends ErrorKind> extends Error { } // @internal -export function maybeThrowError(base: Base): void { - const err = maybeError(base); - if (err != null) { - throw err; - } -} - -// @internal export function maybeError(base: Base): null | DenoError<ErrorKind> { const kind = base.errorKind(); if (kind === ErrorKind.NoError) { @@ -41,3 +33,11 @@ export function maybeError(base: Base): null | DenoError<ErrorKind> { return new DenoError(kind, base.error()!); } } + +// @internal +export function maybeThrowError(base: Base): void { + const err = maybeError(base); + if (err != null) { + throw err; + } +} diff --git a/js/event.ts b/js/event.ts index 1cc711b32..f39739190 100644 --- a/js/event.ts +++ b/js/event.ts @@ -3,7 +3,6 @@ import * as domTypes from "./dom_types"; import { getPrivateValue } from "./util"; // WeakMaps are recommended for private attributes (see MDN link below) -// tslint:disable-next-line:max-line-length // https://developer.mozilla.org/en-US/docs/Archive/Add-ons/Add-on_SDK/Guides/Contributor_s_Guide/Private_Properties#Using_WeakMaps export const eventAttributes = new WeakMap(); diff --git a/js/event_target.ts b/js/event_target.ts index 112ad1705..98b7bbcb8 100644 --- a/js/event_target.ts +++ b/js/event_target.ts @@ -12,7 +12,7 @@ export class EventTarget implements domTypes.EventTarget { public addEventListener( type: string, listener: domTypes.EventListenerOrEventListenerObject | null, - options?: boolean | domTypes.AddEventListenerOptions + _options?: boolean | domTypes.AddEventListenerOptions ): void { if (!(type in this.listeners)) { this.listeners[type] = []; @@ -25,7 +25,7 @@ export class EventTarget implements domTypes.EventTarget { public removeEventListener( type: string, callback: domTypes.EventListenerOrEventListenerObject | null, - options?: domTypes.EventListenerOptions | boolean + _options?: domTypes.EventListenerOptions | boolean ): void { if (type in this.listeners && callback !== null) { this.listeners[type] = this.listeners[type].filter( diff --git a/js/event_target_test.ts b/js/event_target_test.ts index 783724795..bad3828a1 100644 --- a/js/event_target_test.ts +++ b/js/event_target_test.ts @@ -14,7 +14,7 @@ test(function constructedEventTargetCanBeUsedAsExpected() { const event = new Event("foo", { bubbles: true, cancelable: false }); let callCount = 0; - function listener(e) { + function listener(e): void { assertEquals(e, event); ++callCount; } @@ -34,20 +34,20 @@ test(function constructedEventTargetCanBeUsedAsExpected() { test(function anEventTargetCanBeSubclassed() { class NicerEventTarget extends EventTarget { - on(type, callback?, options?) { + on(type, callback?, options?): void { this.addEventListener(type, callback, options); } - off(type, callback?, options?) { + off(type, callback?, options?): void { this.removeEventListener(type, callback, options); } } const target = new NicerEventTarget(); - const event = new Event("foo", { bubbles: true, cancelable: false }); + new Event("foo", { bubbles: true, cancelable: false }); let callCount = 0; - function listener() { + function listener(): void { ++callCount; } diff --git a/js/fetch.ts b/js/fetch.ts index 2823869ca..355535dfe 100644 --- a/js/fetch.ts +++ b/js/fetch.ts @@ -26,7 +26,7 @@ function getHeaderValueParams(value: string): Map<string, string> { return params; } -function hasHeaderValueOf(s: string, value: string) { +function hasHeaderValueOf(s: string, value: string): boolean { return new RegExp(`^${value}[\t\s]*;?`).test(s); } @@ -204,7 +204,7 @@ class Body implements domTypes.Body, domTypes.ReadableStream, io.ReadCloser { } } - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any async json(): Promise<any> { const text = await this.text(); return JSON.parse(text); @@ -272,7 +272,7 @@ class Response implements domTypes.Response { return this.body.formData(); } - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any async json(): Promise<any> { return this.body.json(); } @@ -336,6 +336,15 @@ function msgHttpRequest( return msg.HttpHeader.endHttpHeader(builder); } +function deserializeHeaderFields(m: msg.HttpHeader): Array<[string, string]> { + const out: Array<[string, string]> = []; + for (let i = 0; i < m.fieldsLength(); i++) { + const item = m.fields(i)!; + out.push([item.key()!, item.value()!]); + } + return out; +} + /** Fetch a resource from the network. */ export async function fetch( input: domTypes.Request | string, @@ -420,12 +429,3 @@ export async function fetch( const response = new Response(status, headersList, bodyRid); return response; } - -function deserializeHeaderFields(m: msg.HttpHeader): Array<[string, string]> { - const out: Array<[string, string]> = []; - for (let i = 0; i < m.fieldsLength(); i++) { - const item = m.fields(i)!; - out.push([item.key()!, item.value()!]); - } - return out; -} diff --git a/js/file_info.ts b/js/file_info.ts index cf9ede85c..deaafe5ea 100644 --- a/js/file_info.ts +++ b/js/file_info.ts @@ -83,15 +83,15 @@ export class FileInfoImpl implements FileInfo { this.path = path ? path : null; } - isFile() { + isFile(): boolean { return this._isFile; } - isDirectory() { + isDirectory(): boolean { return !this._isFile && !this._isSymlink; } - isSymlink() { + isSymlink(): boolean { return this._isSymlink; } } diff --git a/js/file_test.ts b/js/file_test.ts index 77320c113..65ddfde92 100644 --- a/js/file_test.ts +++ b/js/file_test.ts @@ -1,7 +1,7 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. import { test, assert, assertEquals } from "./test_util.ts"; -function testFirstArgument(arg1, expectedSize) { +function testFirstArgument(arg1, expectedSize): void { const file = new File(arg1, "name"); assert(file instanceof File); assertEquals(file.name, "name"); @@ -22,7 +22,6 @@ test(function fileUnicodeStringFileBits() { }); test(function fileStringObjectFileBits() { - // tslint:disable-next-line no-construct testFirstArgument([new String("string object")], 13); }); @@ -77,7 +76,7 @@ test(function fileObjectInFileBits() { testFirstArgument([{}], 15); }); -function testSecondArgument(arg2, expectedFileName) { +function testSecondArgument(arg2, expectedFileName): void { const file = new File(["bits"], arg2); assert(file instanceof File); assertEquals(file.name, expectedFileName); diff --git a/js/files.ts b/js/files.ts index a77f788df..9ea378735 100644 --- a/js/files.ts +++ b/js/files.ts @@ -5,68 +5,6 @@ import * as msg from "gen/msg_generated"; import { assert } from "./util"; import * as flatbuffers from "./flatbuffers"; -/** The Deno abstraction for reading and writing files. */ -export class File implements Reader, Writer, Seeker, Closer { - constructor(readonly rid: number) {} - - write(p: Uint8Array): Promise<number> { - return write(this.rid, p); - } - - read(p: Uint8Array): Promise<ReadResult> { - return read(this.rid, p); - } - - seek(offset: number, whence: SeekMode): Promise<void> { - return seek(this.rid, offset, whence); - } - - close(): void { - close(this.rid); - } -} - -/** An instance of `File` for stdin. */ -export const stdin = new File(0); -/** An instance of `File` for stdout. */ -export const stdout = new File(1); -/** An instance of `File` for stderr. */ -export const stderr = new File(2); - -export type OpenMode = - /** Read-only. Default. Starts at beginning of file. */ - | "r" - /** Read-write. Start at beginning of file. */ - | "r+" - /** Write-only. Opens and truncates existing file or creates new one for - * writing only. - */ - | "w" - /** Read-write. Opens and truncates existing file or creates new one for - * writing and reading. - */ - | "w+" - /** Write-only. Opens existing file or creates new one. Each write appends - * content to the end of file. - */ - | "a" - /** Read-write. Behaves like "a" and allows to read from file. */ - | "a+" - /** Write-only. Exclusive create - creates new file only if one doesn't exist - * already. - */ - | "x" - /** Read-write. Behaves like `x` and allows to read from file. */ - | "x+"; - -/** A factory function for creating instances of `File` associated with the - * supplied file name. - * @internal - */ -export function create(filename: string): Promise<File> { - return open(filename, "w+"); -} - /** Open a file and return an instance of the `File` object. * * (async () => { @@ -90,6 +28,7 @@ export async function open( const res = new msg.OpenRes(); assert(baseRes!.inner(res) != null); const rid = res.rid(); + // eslint-disable-next-line @typescript-eslint/no-use-before-define return new File(rid); } @@ -152,3 +91,65 @@ export function close(rid: number): void { const inner = msg.Close.endClose(builder); dispatch.sendSync(builder, msg.Any.Close, inner); } + +/** The Deno abstraction for reading and writing files. */ +export class File implements Reader, Writer, Seeker, Closer { + constructor(readonly rid: number) {} + + write(p: Uint8Array): Promise<number> { + return write(this.rid, p); + } + + read(p: Uint8Array): Promise<ReadResult> { + return read(this.rid, p); + } + + seek(offset: number, whence: SeekMode): Promise<void> { + return seek(this.rid, offset, whence); + } + + close(): void { + close(this.rid); + } +} + +/** An instance of `File` for stdin. */ +export const stdin = new File(0); +/** An instance of `File` for stdout. */ +export const stdout = new File(1); +/** An instance of `File` for stderr. */ +export const stderr = new File(2); + +export type OpenMode = + /** Read-only. Default. Starts at beginning of file. */ + | "r" + /** Read-write. Start at beginning of file. */ + | "r+" + /** Write-only. Opens and truncates existing file or creates new one for + * writing only. + */ + | "w" + /** Read-write. Opens and truncates existing file or creates new one for + * writing and reading. + */ + | "w+" + /** Write-only. Opens existing file or creates new one. Each write appends + * content to the end of file. + */ + | "a" + /** Read-write. Behaves like "a" and allows to read from file. */ + | "a+" + /** Write-only. Exclusive create - creates new file only if one doesn't exist + * already. + */ + | "x" + /** Read-write. Behaves like `x` and allows to read from file. */ + | "x+"; + +/** A factory function for creating instances of `File` associated with the + * supplied file name. + * @internal + */ +export function create(filename: string): Promise<File> { + return open(filename, "w+"); +} diff --git a/js/flatbuffers.ts b/js/flatbuffers.ts index 74eaf40ff..73f3ceb82 100644 --- a/js/flatbuffers.ts +++ b/js/flatbuffers.ts @@ -2,6 +2,8 @@ import { flatbuffers } from "flatbuffers"; import * as util from "./util"; +/* eslint-disable @typescript-eslint/camelcase */ + // Re-export some types. export type Offset = flatbuffers.Offset; export class ByteBuffer extends flatbuffers.ByteBuffer {} @@ -17,7 +19,7 @@ globalBuilder.inUse = false; // We can do this because the "control" messages sent to the privileged // side are guaranteed to be used during the call to libdeno.send(). export function createBuilder(): Builder { - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any const gb = globalBuilder as any; util.assert(!gb.inUse); diff --git a/js/form_data.ts b/js/form_data.ts index f9a76b80b..3b3096785 100644 --- a/js/form_data.ts +++ b/js/form_data.ts @@ -138,7 +138,6 @@ class FormDataBase { } } -// tslint:disable-next-line:variable-name export class FormData extends DomIterableMixin< string, domTypes.FormDataEntryValue, diff --git a/js/form_data_test.ts b/js/form_data_test.ts index 02e2c989a..bdf1e7cda 100644 --- a/js/form_data_test.ts +++ b/js/form_data_test.ts @@ -72,7 +72,7 @@ test(function formDataParamsSetSuccess() { test(function formDataSetEmptyBlobSuccess() { const formData = new FormData(); formData.set("a", new Blob([]), "blank.txt"); - const file = formData.get("a"); + formData.get("a"); /* TODO Fix this test. assert(file instanceof File); if (typeof file !== "string") { diff --git a/js/globals.ts b/js/globals.ts index 9bd0584b2..45a4ccb01 100644 --- a/js/globals.ts +++ b/js/globals.ts @@ -56,7 +56,6 @@ window.clearInterval = timers.clearTimer; window.console = new consoleTypes.Console(libdeno.print); window.setTimeout = timers.setTimeout; window.setInterval = timers.setInterval; -// tslint:disable-next-line:no-any window.location = (undefined as unknown) as domTypes.Location; // When creating the runtime type library, we use modifications to `window` to diff --git a/js/headers.ts b/js/headers.ts index 31a29111e..dcb5f4c6a 100644 --- a/js/headers.ts +++ b/js/headers.ts @@ -8,8 +8,9 @@ import { requiredArguments } from "./util"; const invalidTokenRegex = /[^\^_`a-zA-Z\-0-9!#$%&'*+.|~]/; const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/; -// tslint:disable-next-line:no-any +// eslint-disable-next-line @typescript-eslint/no-explicit-any function isHeaders(value: any): value is domTypes.Headers { + // eslint-disable-next-line @typescript-eslint/no-use-before-define return value instanceof Headers; } @@ -30,13 +31,13 @@ class HeadersBase { // The following name/value validations are copied from // https://github.com/bitinn/node-fetch/blob/master/src/headers.js // Copyright (c) 2016 David Frank. MIT License. - private _validateName(name: string) { + private _validateName(name: string): void { if (invalidTokenRegex.test(name) || name === "") { throw new TypeError(`${name} is not a legal HTTP header name`); } } - private _validateValue(value: string) { + private _validateValue(value: string): void { if (invalidHeaderCharRegex.test(value)) { throw new TypeError(`${value} is not a legal HTTP header value`); } @@ -57,9 +58,9 @@ class HeadersBase { // then throw a TypeError. // ref: https://fetch.spec.whatwg.org/#concept-headers-fill if (tuple.length !== 2) { - // tslint:disable:max-line-length - // prettier-ignore - throw new TypeError("Failed to construct 'Headers'; Each header pair must be an iterable [name, value] tuple"); + throw new TypeError( + "Failed to construct 'Headers'; Each header pair must be an iterable [name, value] tuple" + ); } const [name, value] = this._normalizeParams(tuple[0], tuple[1]); @@ -127,7 +128,6 @@ class HeadersBase { } // @internal -// tslint:disable-next-line:variable-name export class Headers extends DomIterableMixin< string, string, diff --git a/js/headers_test.ts b/js/headers_test.ts index 223e08daf..4a911f9a5 100644 --- a/js/headers_test.ts +++ b/js/headers_test.ts @@ -3,9 +3,7 @@ import { test, assert, assertEquals } from "./test_util.ts"; // Logic heavily copied from web-platform-tests, make // sure pass mostly header basic test -/* tslint:disable-next-line:max-line-length */ // ref: https://github.com/web-platform-tests/wpt/blob/7c50c216081d6ea3c9afe553ee7b64534020a1b2/fetch/api/headers/headers-basic.html -/* tslint:disable:no-unused-expression */ test(function newHeaderTest() { new Headers(); new Headers(undefined); @@ -75,7 +73,6 @@ test(function headerHasSuccess() { const headers = new Headers(headerDict); for (const name in headerDict) { assert(headers.has(name), "headers has name " + name); - /* tslint:disable-next-line:max-line-length */ assert( !headers.has("nameNotInHeaders"), "headers do not have header: nameNotInHeaders" @@ -177,7 +174,6 @@ test(function headerTypesAvailable() { assert(headers instanceof Headers); }); -// tslint:disable-next-line:max-line-length // Modified from https://github.com/bitinn/node-fetch/blob/7d3293200a91ad52b5ca7962f9d6fd1c04983edb/test/test.js#L2001-L2014 // Copyright (c) 2016 David Frank. MIT License. test(function headerIllegalReject() { diff --git a/js/lib.web_assembly.d.ts b/js/lib.web_assembly.d.ts index e69c4c629..ccefdd077 100644 --- a/js/lib.web_assembly.d.ts +++ b/js/lib.web_assembly.d.ts @@ -1,11 +1,13 @@ // This follows the WebIDL at: https://webassembly.github.io/spec/js-api/ // And follow on WebIDL at: https://webassembly.github.io/spec/web-api/ +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any */ + declare namespace WebAssembly { - type WebAssemblyInstantiatedSource = { + interface WebAssemblyInstantiatedSource { module: Module; instance: Instance; - }; + } /** Compiles a `WebAssembly.Module` from WebAssembly binary code. This * function is useful if it is necessary to a compile a module before it can @@ -52,12 +54,15 @@ declare namespace WebAssembly { type ImportExportKind = "function" | "table" | "memory" | "global"; - type ModuleExportDescriptor = { name: string; kind: ImportExportKind }; - type ModuleImportDescriptor = { + interface ModuleExportDescriptor { + name: string; + kind: ImportExportKind; + } + interface ModuleImportDescriptor { module: string; name: string; kind: ImportExportKind; - }; + } class Module { constructor(bufferSource: domTypes.BufferSource); @@ -87,10 +92,10 @@ declare namespace WebAssembly { readonly exports: T; } - type MemoryDescriptor = { + interface MemoryDescriptor { initial: number; maximum?: number; - }; + } class Memory { constructor(descriptor: MemoryDescriptor); @@ -128,7 +133,10 @@ declare namespace WebAssembly { set(index: number, value: (...args: any[]) => any): void; } - type GlobalDescriptor = { value: string; mutable?: boolean }; + interface GlobalDescriptor { + value: string; + mutable?: boolean; + } /** Represents a global variable instance, accessible from both JavaScript and * importable/exportable across one or more `WebAssembly.Module` instances. @@ -167,3 +175,5 @@ interface ImportMeta { url: string; main: boolean; } + +/* eslint-enable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any */ diff --git a/js/libdeno.ts b/js/libdeno.ts index ee43413f3..33e9e4f5f 100644 --- a/js/libdeno.ts +++ b/js/libdeno.ts @@ -12,7 +12,8 @@ interface EvalErrorInfo { // The actual thrown entity // (might be an Error or anything else thrown by the user) // If isNativeError is true, this is an Error - thrown: any; // tslint:disable-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any + thrown: any; } interface Libdeno { @@ -29,11 +30,9 @@ interface Libdeno { * Returns an array: [output, errInfo]. * If an error occurs, `output` becomes null and `errInfo` is non-null. */ - evalContext( - code: string - ): [any, EvalErrorInfo | null] /* tslint:disable-line:no-any */; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + evalContext(code: string): [any, EvalErrorInfo | null]; - // tslint:disable-next-line:no-any errorToJSON: (e: Error) => string; } diff --git a/js/location.ts b/js/location.ts index 5d7f44707..535a2bcea 100644 --- a/js/location.ts +++ b/js/location.ts @@ -4,11 +4,6 @@ import { notImplemented } from "./util"; import { Location } from "./dom_types"; import { window } from "./window"; -export function setLocation(url: string): void { - window.location = new LocationImpl(url); - Object.freeze(window.location); -} - export class LocationImpl implements Location { constructor(url: string) { const u = new URL(url); @@ -40,13 +35,18 @@ export class LocationImpl implements Location { port: string; protocol: string; search: string; - assign(url: string): void { + assign(_url: string): void { throw notImplemented(); } reload(): void { throw notImplemented(); } - replace(url: string): void { + replace(_url: string): void { throw notImplemented(); } } + +export function setLocation(url: string): void { + window.location = new LocationImpl(url); + Object.freeze(window.location); +} diff --git a/js/main.ts b/js/main.ts index 830c77eb6..887d6b3c2 100644 --- a/js/main.ts +++ b/js/main.ts @@ -1,5 +1,6 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -// tslint:disable-next-line:no-reference + +// eslint-disable-next-line @typescript-eslint/no-triple-slash-reference /// <reference path="./plugins.d.ts" /> import "./globals"; @@ -17,8 +18,7 @@ import * as deno from "./deno"; // TODO(kitsonk) remove with `--types` below import libDts from "gen/lib/lib.deno_runtime.d.ts!string"; -/* tslint:disable-next-line:no-default-export */ -export default function denoMain() { +export default function denoMain(): void { const startResMsg = os.start(); setVersions(startResMsg.denoVersion()!, startResMsg.v8Version()!); diff --git a/js/make_temp_dir.ts b/js/make_temp_dir.ts index 1ee095bbc..dc04522ee 100644 --- a/js/make_temp_dir.ts +++ b/js/make_temp_dir.ts @@ -10,32 +10,6 @@ export interface MakeTempDirOptions { suffix?: string; } -/** makeTempDirSync is the synchronous version of `makeTempDir`. - * - * const tempDirName0 = Deno.makeTempDirSync(); - * const tempDirName1 = Deno.makeTempDirSync({ prefix: 'my_temp' }); - */ -export function makeTempDirSync(options: MakeTempDirOptions = {}): string { - return res(dispatch.sendSync(...req(options))); -} - -/** makeTempDir creates a new temporary directory in the directory `dir`, its - * name beginning with `prefix` and ending with `suffix`. - * It returns the full path to the newly created directory. - * If `dir` is unspecified, tempDir uses the default directory for temporary - * files. Multiple programs calling tempDir simultaneously will not choose the - * same directory. It is the caller's responsibility to remove the directory - * when no longer needed. - * - * const tempDirName0 = await Deno.makeTempDir(); - * const tempDirName1 = await Deno.makeTempDir({ prefix: 'my_temp' }); - */ -export async function makeTempDir( - options: MakeTempDirOptions = {} -): Promise<string> { - return res(await dispatch.sendAsync(...req(options))); -} - function req({ dir, prefix, @@ -68,3 +42,29 @@ function res(baseRes: null | msg.Base): string { assert(path != null); return path!; } + +/** makeTempDirSync is the synchronous version of `makeTempDir`. + * + * const tempDirName0 = Deno.makeTempDirSync(); + * const tempDirName1 = Deno.makeTempDirSync({ prefix: 'my_temp' }); + */ +export function makeTempDirSync(options: MakeTempDirOptions = {}): string { + return res(dispatch.sendSync(...req(options))); +} + +/** makeTempDir creates a new temporary directory in the directory `dir`, its + * name beginning with `prefix` and ending with `suffix`. + * It returns the full path to the newly created directory. + * If `dir` is unspecified, tempDir uses the default directory for temporary + * files. Multiple programs calling tempDir simultaneously will not choose the + * same directory. It is the caller's responsibility to remove the directory + * when no longer needed. + * + * const tempDirName0 = await Deno.makeTempDir(); + * const tempDirName1 = await Deno.makeTempDir({ prefix: 'my_temp' }); + */ +export async function makeTempDir( + options: MakeTempDirOptions = {} +): Promise<string> { + return res(await dispatch.sendAsync(...req(options))); +} diff --git a/js/metrics.ts b/js/metrics.ts index 1cbc9f13b..111015078 100644 --- a/js/metrics.ts +++ b/js/metrics.ts @@ -12,11 +12,6 @@ export interface Metrics { bytesReceived: number; } -/** Receive metrics from the privileged side of Deno. */ -export function metrics(): Metrics { - return res(dispatch.sendSync(...req())); -} - function req(): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { const builder = flatbuffers.createBuilder(); msg.Metrics.startMetrics(builder); @@ -38,3 +33,8 @@ function res(baseRes: null | msg.Base): Metrics { bytesReceived: res.bytesReceived().toFloat64() }; } + +/** Receive metrics from the privileged side of Deno. */ +export function metrics(): Metrics { + return res(dispatch.sendSync(...req())); +} diff --git a/js/mixins/dom_iterable.ts b/js/mixins/dom_iterable.ts index ae5a030ce..97e8133ec 100644 --- a/js/mixins/dom_iterable.ts +++ b/js/mixins/dom_iterable.ts @@ -1,9 +1,10 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +// eslint-disable-next-line @typescript-eslint/no-unused-vars import { DomIterable } from "../dom_types"; import { window } from "../window"; import { requiredArguments } from "../util"; -// tslint:disable:no-any +// eslint-disable-next-line @typescript-eslint/no-explicit-any type Constructor<T = {}> = new (...args: any[]) => T; /** Mixes in a DOM iterable methods into a base class, assumes that there is @@ -12,7 +13,6 @@ type Constructor<T = {}> = new (...args: any[]) => T; * TODO Don't expose DomIterableMixin from "deno" namespace. */ export function DomIterableMixin<K, V, TBase extends Constructor>( - // tslint:disable-next-line:variable-name Base: TBase, dataSymbol: symbol ): TBase & Constructor<DomIterable<K, V>> { @@ -25,21 +25,23 @@ export function DomIterableMixin<K, V, TBase extends Constructor>( // Symbol.iterator, and some have an Array, which yields V, in this case // [K, V] too as they are arrays of tuples. - // tslint:disable-next-line:variable-name const DomIterable = class extends Base { *entries(): IterableIterator<[K, V]> { + // eslint-disable-next-line @typescript-eslint/no-explicit-any for (const entry of (this as any)[dataSymbol]) { yield entry; } } *keys(): IterableIterator<K> { + // eslint-disable-next-line @typescript-eslint/no-explicit-any for (const [key] of (this as any)[dataSymbol]) { yield key; } } *values(): IterableIterator<V> { + // eslint-disable-next-line @typescript-eslint/no-explicit-any for (const [, value] of (this as any)[dataSymbol]) { yield value; } @@ -47,7 +49,7 @@ export function DomIterableMixin<K, V, TBase extends Constructor>( forEach( callbackfn: (value: V, key: K, parent: this) => void, - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any thisArg?: any ): void { requiredArguments( @@ -56,12 +58,14 @@ export function DomIterableMixin<K, V, TBase extends Constructor>( 1 ); callbackfn = callbackfn.bind(thisArg == null ? window : Object(thisArg)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any for (const [key, value] of (this as any)[dataSymbol]) { callbackfn(value, key, this); } } *[Symbol.iterator](): IterableIterator<[K, V]> { + // eslint-disable-next-line @typescript-eslint/no-explicit-any for (const entry of (this as any)[dataSymbol]) { yield entry; } @@ -76,4 +80,3 @@ export function DomIterableMixin<K, V, TBase extends Constructor>( return DomIterable; } -// tslint:enable:no-any diff --git a/js/mixins/dom_iterable_test.ts b/js/mixins/dom_iterable_test.ts index a0bed7bd3..36e3de678 100644 --- a/js/mixins/dom_iterable_test.ts +++ b/js/mixins/dom_iterable_test.ts @@ -1,6 +1,7 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. import { test, assert, assertEquals } from "../test_util.ts"; +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type function setup() { const dataSymbol = Symbol("data symbol"); class Base { @@ -19,13 +20,12 @@ function setup() { Base, // This is using an internal API we don't want published as types, so having // to cast to any to "trick" TypeScript - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any DomIterable: (Deno as any).DomIterableMixin(Base, dataSymbol) }; } test(function testDomIterable() { - // tslint:disable-next-line:variable-name const { DomIterable, Base } = setup(); const fixture: Array<[string, number]> = [["foo", 1], ["bar", 2]]; @@ -46,7 +46,7 @@ test(function testDomIterable() { result = []; const scope = {}; - function callback(value, key, parent) { + function callback(value, key, parent): void { assertEquals(parent, domIterable); assert(key != null); assert(value != null); @@ -60,14 +60,13 @@ test(function testDomIterable() { }); test(function testDomIterableScope() { - // tslint:disable-next-line:variable-name const { DomIterable } = setup(); const domIterable = new DomIterable([["foo", 1]]); - // tslint:disable-next-line:no-any - function checkScope(thisArg: any, expected: any) { - function callback() { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function checkScope(thisArg: any, expected: any): void { + function callback(): void { assertEquals(this, expected); } domIterable.forEach(callback, thisArg); diff --git a/js/mkdir.ts b/js/mkdir.ts index a620c3764..784d891f9 100644 --- a/js/mkdir.ts +++ b/js/mkdir.ts @@ -3,6 +3,21 @@ import * as msg from "gen/msg_generated"; import * as flatbuffers from "./flatbuffers"; import * as dispatch from "./dispatch"; +function req( + path: string, + recursive: boolean, + mode: number +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + const builder = flatbuffers.createBuilder(); + const path_ = builder.createString(path); + msg.Mkdir.startMkdir(builder); + msg.Mkdir.addPath(builder, path_); + msg.Mkdir.addRecursive(builder, recursive); + msg.Mkdir.addMode(builder, mode); + const inner = msg.Mkdir.endMkdir(builder); + return [builder, msg.Any.Mkdir, inner]; +} + /** Creates a new directory with the specified path synchronously. * If `recursive` is set to true, nested directories will be created (also known * as "mkdir -p"). @@ -32,18 +47,3 @@ export async function mkdir( ): Promise<void> { await dispatch.sendAsync(...req(path, recursive, mode)); } - -function req( - path: string, - recursive: boolean, - mode: number -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - const builder = flatbuffers.createBuilder(); - const path_ = builder.createString(path); - msg.Mkdir.startMkdir(builder); - msg.Mkdir.addPath(builder, path_); - msg.Mkdir.addRecursive(builder, recursive); - msg.Mkdir.addMode(builder, mode); - const inner = msg.Mkdir.endMkdir(builder); - return [builder, msg.Any.Mkdir, inner]; -} @@ -27,46 +27,22 @@ export interface Listener { addr(): Addr; } -class ListenerImpl implements Listener { - constructor(readonly rid: number) {} - - async accept(): Promise<Conn> { - const builder = flatbuffers.createBuilder(); - msg.Accept.startAccept(builder); - msg.Accept.addRid(builder, this.rid); - const inner = msg.Accept.endAccept(builder); - const baseRes = await dispatch.sendAsync(builder, msg.Any.Accept, inner); - assert(baseRes != null); - assert(msg.Any.NewConn === baseRes!.innerType()); - const res = new msg.NewConn(); - assert(baseRes!.inner(res) != null); - return new ConnImpl(res.rid(), res.remoteAddr()!, res.localAddr()!); - } - - close(): void { - close(this.rid); - } - - addr(): Addr { - return notImplemented(); - } +enum ShutdownMode { + // See http://man7.org/linux/man-pages/man2/shutdown.2.html + // Corresponding to SHUT_RD, SHUT_WR, SHUT_RDWR + Read = 0, + Write, + ReadWrite // unused } -export interface Conn extends Reader, Writer, Closer { - /** The local address of the connection. */ - localAddr: string; - /** The remote address of the connection. */ - remoteAddr: string; - /** The resource ID of the connection. */ - rid: number; - /** Shuts down (`shutdown(2)`) the reading side of the TCP connection. Most - * callers should just use `close()`. - */ - closeRead(): void; - /** Shuts down (`shutdown(2)`) the writing side of the TCP connection. Most - * callers should just use `close()`. - */ - closeWrite(): void; +function shutdown(rid: number, how: ShutdownMode): void { + const builder = flatbuffers.createBuilder(); + msg.Shutdown.startShutdown(builder); + msg.Shutdown.addRid(builder, rid); + msg.Shutdown.addHow(builder, how); + const inner = msg.Shutdown.endShutdown(builder); + const baseRes = dispatch.sendSync(builder, msg.Any.Shutdown, inner); + assert(baseRes == null); } class ConnImpl implements Conn { @@ -103,22 +79,46 @@ class ConnImpl implements Conn { } } -enum ShutdownMode { - // See http://man7.org/linux/man-pages/man2/shutdown.2.html - // Corresponding to SHUT_RD, SHUT_WR, SHUT_RDWR - Read = 0, - Write, - ReadWrite // unused +class ListenerImpl implements Listener { + constructor(readonly rid: number) {} + + async accept(): Promise<Conn> { + const builder = flatbuffers.createBuilder(); + msg.Accept.startAccept(builder); + msg.Accept.addRid(builder, this.rid); + const inner = msg.Accept.endAccept(builder); + const baseRes = await dispatch.sendAsync(builder, msg.Any.Accept, inner); + assert(baseRes != null); + assert(msg.Any.NewConn === baseRes!.innerType()); + const res = new msg.NewConn(); + assert(baseRes!.inner(res) != null); + return new ConnImpl(res.rid(), res.remoteAddr()!, res.localAddr()!); + } + + close(): void { + close(this.rid); + } + + addr(): Addr { + return notImplemented(); + } } -function shutdown(rid: number, how: ShutdownMode) { - const builder = flatbuffers.createBuilder(); - msg.Shutdown.startShutdown(builder); - msg.Shutdown.addRid(builder, rid); - msg.Shutdown.addHow(builder, how); - const inner = msg.Shutdown.endShutdown(builder); - const baseRes = dispatch.sendSync(builder, msg.Any.Shutdown, inner); - assert(baseRes == null); +export interface Conn extends Reader, Writer, Closer { + /** The local address of the connection. */ + localAddr: string; + /** The remote address of the connection. */ + remoteAddr: string; + /** The resource ID of the connection. */ + rid: number; + /** Shuts down (`shutdown(2)`) the reading side of the TCP connection. Most + * callers should just use `close()`. + */ + closeRead(): void; + /** Shuts down (`shutdown(2)`) the writing side of the TCP connection. Most + * callers should just use `close()`. + */ + closeWrite(): void; } /** Listen announces on the local network address. @@ -197,8 +197,8 @@ export async function dial(network: Network, address: string): Promise<Conn> { /** **RESERVED** */ export async function connect( - network: Network, - address: string + _network: Network, + _address: string ): Promise<Conn> { return notImplemented(); } diff --git a/js/net_test.ts b/js/net_test.ts index 5b8b80bea..cb9a9163a 100644 --- a/js/net_test.ts +++ b/js/net_test.ts @@ -24,7 +24,7 @@ testPerm({ net: true }, async function netCloseWhileAccept() { testPerm({ net: true }, async function netConcurrentAccept() { const listener = Deno.listen("tcp", ":4502"); let acceptErrCount = 0; - const checkErr = e => { + const checkErr = (e): void => { assertEquals(e.kind, Deno.ErrorKind.Other); if (e.message === "Listener has been closed") { assertEquals(acceptErrCount, 1); @@ -97,6 +97,17 @@ export function fetchModuleMetaData( }; } +function setEnv(key: string, value: string): void { + const builder = flatbuffers.createBuilder(); + const _key = builder.createString(key); + const _value = builder.createString(value); + msg.SetEnv.startSetEnv(builder); + msg.SetEnv.addKey(builder, _key); + msg.SetEnv.addValue(builder, _value); + const inner = msg.SetEnv.endSetEnv(builder); + sendSync(builder, msg.Any.SetEnv, inner); +} + function createEnv(inner: msg.EnvironRes): { [index: string]: string } { const env: { [index: string]: string } = {}; @@ -113,17 +124,6 @@ function createEnv(inner: msg.EnvironRes): { [index: string]: string } { }); } -function setEnv(key: string, value: string): void { - const builder = flatbuffers.createBuilder(); - const _key = builder.createString(key); - const _value = builder.createString(value); - msg.SetEnv.startSetEnv(builder); - msg.SetEnv.addKey(builder, _key); - msg.SetEnv.addValue(builder, _value); - const inner = msg.SetEnv.endSetEnv(builder); - sendSync(builder, msg.Any.SetEnv, inner); -} - /** Returns a snapshot of the environment variables at invocation. Mutating a * property in the object will set that variable in the environment for * the process. The environment object will only accept `string`s diff --git a/js/os_test.ts b/js/os_test.ts index 0773bf685..39429d919 100644 --- a/js/os_test.ts +++ b/js/os_test.ts @@ -4,6 +4,7 @@ import { test, testPerm, assert, assertEquals } from "./test_util.ts"; testPerm({ env: true }, function envSuccess() { const env = Deno.env(); assert(env !== null); + // eslint-disable-next-line @typescript-eslint/camelcase env.test_var = "Hello World"; const newEnv = Deno.env(); assertEquals(env.test_var, newEnv.test_var); @@ -12,7 +13,7 @@ testPerm({ env: true }, function envSuccess() { test(function envFailure() { let caughtError = false; try { - const env = Deno.env(); + Deno.env(); } catch (err) { caughtError = true; assertEquals(err.kind, Deno.ErrorKind.PermissionDenied); diff --git a/js/permissions.ts b/js/permissions.ts index 6acb80b1f..f4fe6826f 100644 --- a/js/permissions.ts +++ b/js/permissions.ts @@ -5,7 +5,7 @@ import * as dispatch from "./dispatch"; import { assert } from "./util"; /** Permissions as granted by the caller */ -export type Permissions = { +export interface Permissions { read: boolean; write: boolean; net: boolean; @@ -13,10 +13,27 @@ export type Permissions = { run: boolean; // NOTE: Keep in sync with src/permissions.rs -}; +} export type Permission = keyof Permissions; +function getReq(): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + const builder = flatbuffers.createBuilder(); + msg.Permissions.startPermissions(builder); + const inner = msg.Permissions.endPermissions(builder); + return [builder, msg.Any.Permissions, inner]; +} + +function createPermissions(inner: msg.PermissionsRes): Permissions { + return { + read: inner.read(), + write: inner.write(), + net: inner.net(), + env: inner.env(), + run: inner.run() + }; +} + /** Inspect granted permissions for the current program. * * if (Deno.permissions().read) { @@ -33,6 +50,17 @@ export function permissions(): Permissions { return createPermissions(res); } +function revokeReq( + permission: string +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + const builder = flatbuffers.createBuilder(); + const permission_ = builder.createString(permission); + msg.PermissionRevoke.startPermissionRevoke(builder); + msg.PermissionRevoke.addPermission(builder, permission_); + const inner = msg.PermissionRevoke.endPermissionRevoke(builder); + return [builder, msg.Any.PermissionRevoke, inner]; +} + /** Revoke a permission. When the permission was already revoked nothing changes * * if (Deno.permissions().read) { @@ -44,31 +72,3 @@ export function permissions(): Permissions { export function revokePermission(permission: Permission): void { dispatch.sendSync(...revokeReq(permission)); } - -function createPermissions(inner: msg.PermissionsRes): Permissions { - return { - read: inner.read(), - write: inner.write(), - net: inner.net(), - env: inner.env(), - run: inner.run() - }; -} - -function getReq(): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - const builder = flatbuffers.createBuilder(); - msg.Permissions.startPermissions(builder); - const inner = msg.Permissions.endPermissions(builder); - return [builder, msg.Any.Permissions, inner]; -} - -function revokeReq( - permission: string -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - const builder = flatbuffers.createBuilder(); - const permission_ = builder.createString(permission); - msg.PermissionRevoke.startPermissionRevoke(builder); - msg.PermissionRevoke.addPermission(builder, permission_); - const inner = msg.PermissionRevoke.endPermissionRevoke(builder); - return [builder, msg.Any.PermissionRevoke, inner]; -} diff --git a/js/process.ts b/js/process.ts index 2f60e5c4a..bf75b6b32 100644 --- a/js/process.ts +++ b/js/process.ts @@ -22,7 +22,6 @@ import { assert, unreachable } from "./util"; export type ProcessStdio = "inherit" | "piped" | "null"; // TODO Maybe extend VSCode's 'CommandOptions'? -// tslint:disable-next-line:max-line-length // See https://code.visualstudio.com/docs/editor/tasks-appendix#_schema-for-tasksjson export interface RunOptions { args: string[]; @@ -33,6 +32,27 @@ export interface RunOptions { stdin?: ProcessStdio; } +async function runStatus(rid: number): Promise<ProcessStatus> { + const builder = flatbuffers.createBuilder(); + msg.RunStatus.startRunStatus(builder); + msg.RunStatus.addRid(builder, rid); + const inner = msg.RunStatus.endRunStatus(builder); + + const baseRes = await dispatch.sendAsync(builder, msg.Any.RunStatus, inner); + assert(baseRes != null); + assert(msg.Any.RunStatusRes === baseRes!.innerType()); + const res = new msg.RunStatusRes(); + assert(baseRes!.inner(res) != null); + + if (res.gotSignal()) { + const signal = res.exitSignal(); + return { signal, success: false }; + } else { + const code = res.exitCode(); + return { code, success: code === 0 }; + } +} + export class Process { readonly rid: number; readonly pid: number; @@ -156,24 +176,3 @@ export function run(opt: RunOptions): Process { return new Process(res); } - -async function runStatus(rid: number): Promise<ProcessStatus> { - const builder = flatbuffers.createBuilder(); - msg.RunStatus.startRunStatus(builder); - msg.RunStatus.addRid(builder, rid); - const inner = msg.RunStatus.endRunStatus(builder); - - const baseRes = await dispatch.sendAsync(builder, msg.Any.RunStatus, inner); - assert(baseRes != null); - assert(msg.Any.RunStatusRes === baseRes!.innerType()); - const res = new msg.RunStatusRes(); - assert(baseRes!.inner(res) != null); - - if (res.gotSignal()) { - const signal = res.exitSignal(); - return { signal, success: false }; - } else { - const code = res.exitCode(); - return { code, success: code === 0 }; - } -} diff --git a/js/read_dir.ts b/js/read_dir.ts index d7d20644b..2515a61c6 100644 --- a/js/read_dir.ts +++ b/js/read_dir.ts @@ -5,23 +5,6 @@ import * as dispatch from "./dispatch"; import { FileInfo, FileInfoImpl } from "./file_info"; import { assert } from "./util"; -/** Reads the directory given by path and returns a list of file info - * synchronously. - * - * const files = Deno.readDirSync("/"); - */ -export function readDirSync(path: string): FileInfo[] { - return res(dispatch.sendSync(...req(path))); -} - -/** Reads the directory given by path and returns a list of file info. - * - * const files = await Deno.readDir("/"); - */ -export async function readDir(path: string): Promise<FileInfo[]> { - return res(await dispatch.sendAsync(...req(path))); -} - function req(path: string): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { const builder = flatbuffers.createBuilder(); const path_ = builder.createString(path); @@ -42,3 +25,20 @@ function res(baseRes: null | msg.Base): FileInfo[] { } return fileInfos; } + +/** Reads the directory given by path and returns a list of file info + * synchronously. + * + * const files = Deno.readDirSync("/"); + */ +export function readDirSync(path: string): FileInfo[] { + return res(dispatch.sendSync(...req(path))); +} + +/** Reads the directory given by path and returns a list of file info. + * + * const files = await Deno.readDir("/"); + */ +export async function readDir(path: string): Promise<FileInfo[]> { + return res(await dispatch.sendAsync(...req(path))); +} diff --git a/js/read_dir_test.ts b/js/read_dir_test.ts index 914c2b2a8..c2d90642c 100644 --- a/js/read_dir_test.ts +++ b/js/read_dir_test.ts @@ -3,7 +3,7 @@ import { testPerm, assert, assertEquals } from "./test_util.ts"; type FileInfo = Deno.FileInfo; -function assertSameContent(files: FileInfo[]) { +function assertSameContent(files: FileInfo[]): void { let counter = 0; for (const file of files) { @@ -30,7 +30,7 @@ testPerm({ read: true }, function readDirSyncSuccess() { testPerm({ read: false }, function readDirSyncPerm() { let caughtError = false; try { - const files = Deno.readDirSync("tests/"); + Deno.readDirSync("tests/"); } catch (e) { caughtError = true; assertEquals(e.kind, Deno.ErrorKind.PermissionDenied); @@ -75,7 +75,7 @@ testPerm({ read: true }, async function readDirSuccess() { testPerm({ read: false }, async function readDirPerm() { let caughtError = false; try { - const files = await Deno.readDir("tests/"); + await Deno.readDir("tests/"); } catch (e) { caughtError = true; assertEquals(e.kind, Deno.ErrorKind.PermissionDenied); diff --git a/js/read_file.ts b/js/read_file.ts index 288841672..3aeedec28 100644 --- a/js/read_file.ts +++ b/js/read_file.ts @@ -4,26 +4,6 @@ import * as flatbuffers from "./flatbuffers"; import { assert } from "./util"; import * as dispatch from "./dispatch"; -/** Read the entire contents of a file synchronously. - * - * const decoder = new TextDecoder("utf-8"); - * const data = Deno.readFileSync("hello.txt"); - * console.log(decoder.decode(data)); - */ -export function readFileSync(filename: string): Uint8Array { - return res(dispatch.sendSync(...req(filename))); -} - -/** Read the entire contents of a file. - * - * const decoder = new TextDecoder("utf-8"); - * const data = await Deno.readFile("hello.txt"); - * console.log(decoder.decode(data)); - */ -export async function readFile(filename: string): Promise<Uint8Array> { - return res(await dispatch.sendAsync(...req(filename))); -} - function req( filename: string ): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { @@ -44,3 +24,23 @@ function res(baseRes: null | msg.Base): Uint8Array { assert(dataArray != null); return new Uint8Array(dataArray!); } + +/** Read the entire contents of a file synchronously. + * + * const decoder = new TextDecoder("utf-8"); + * const data = Deno.readFileSync("hello.txt"); + * console.log(decoder.decode(data)); + */ +export function readFileSync(filename: string): Uint8Array { + return res(dispatch.sendSync(...req(filename))); +} + +/** Read the entire contents of a file. + * + * const decoder = new TextDecoder("utf-8"); + * const data = await Deno.readFile("hello.txt"); + * console.log(decoder.decode(data)); + */ +export async function readFile(filename: string): Promise<Uint8Array> { + return res(await dispatch.sendAsync(...req(filename))); +} diff --git a/js/read_file_test.ts b/js/read_file_test.ts index 4724158e9..2e0525d3f 100644 --- a/js/read_file_test.ts +++ b/js/read_file_test.ts @@ -13,7 +13,7 @@ testPerm({ read: true }, function readFileSyncSuccess() { testPerm({ read: false }, function readFileSyncPerm() { let caughtError = false; try { - const data = Deno.readFileSync("package.json"); + Deno.readFileSync("package.json"); } catch (e) { caughtError = true; assertEquals(e.kind, Deno.ErrorKind.PermissionDenied); diff --git a/js/read_link.ts b/js/read_link.ts index 6a518231f..b63fdd841 100644 --- a/js/read_link.ts +++ b/js/read_link.ts @@ -4,22 +4,6 @@ import * as flatbuffers from "./flatbuffers"; import { assert } from "./util"; import * as dispatch from "./dispatch"; -/** Returns the destination of the named symbolic link synchronously. - * - * const targetPath = Deno.readlinkSync("symlink/path"); - */ -export function readlinkSync(name: string): string { - return res(dispatch.sendSync(...req(name))); -} - -/** Returns the destination of the named symbolic link. - * - * const targetPath = await Deno.readlink("symlink/path"); - */ -export async function readlink(name: string): Promise<string> { - return res(await dispatch.sendAsync(...req(name))); -} - function req(name: string): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { const builder = flatbuffers.createBuilder(); const name_ = builder.createString(name); @@ -38,3 +22,19 @@ function res(baseRes: null | msg.Base): string { assert(path !== null); return path!; } + +/** Returns the destination of the named symbolic link synchronously. + * + * const targetPath = Deno.readlinkSync("symlink/path"); + */ +export function readlinkSync(name: string): string { + return res(dispatch.sendSync(...req(name))); +} + +/** Returns the destination of the named symbolic link. + * + * const targetPath = await Deno.readlink("symlink/path"); + */ +export async function readlink(name: string): Promise<string> { + return res(await dispatch.sendAsync(...req(name))); +} diff --git a/js/remove.ts b/js/remove.ts index 89c2ba672..1c9df6830 100644 --- a/js/remove.ts +++ b/js/remove.ts @@ -7,6 +7,19 @@ export interface RemoveOption { recursive?: boolean; } +function req( + path: string, + options: RemoveOption +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + const builder = flatbuffers.createBuilder(); + const path_ = builder.createString(path); + msg.Remove.startRemove(builder); + msg.Remove.addPath(builder, path_); + msg.Remove.addRecursive(builder, !!options.recursive); + const inner = msg.Remove.endRemove(builder); + return [builder, msg.Any.Remove, inner]; +} + /** Removes the named file or directory synchronously. Would throw * error if permission denied, not found, or directory not empty if `recursive` * set to false. @@ -31,16 +44,3 @@ export async function remove( ): Promise<void> { await dispatch.sendAsync(...req(path, options)); } - -function req( - path: string, - options: RemoveOption -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - const builder = flatbuffers.createBuilder(); - const path_ = builder.createString(path); - msg.Remove.startRemove(builder); - msg.Remove.addPath(builder, path_); - msg.Remove.addRecursive(builder, !!options.recursive); - const inner = msg.Remove.endRemove(builder); - return [builder, msg.Any.Remove, inner]; -} diff --git a/js/rename.ts b/js/rename.ts index e5e08d647..9d475f7e9 100644 --- a/js/rename.ts +++ b/js/rename.ts @@ -3,6 +3,20 @@ import * as msg from "gen/msg_generated"; import * as flatbuffers from "./flatbuffers"; import * as dispatch from "./dispatch"; +function req( + oldpath: string, + newpath: string +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + const builder = flatbuffers.createBuilder(); + const oldpath_ = builder.createString(oldpath); + const newpath_ = builder.createString(newpath); + msg.Rename.startRename(builder); + msg.Rename.addOldpath(builder, oldpath_); + msg.Rename.addNewpath(builder, newpath_); + const inner = msg.Rename.endRename(builder); + return [builder, msg.Any.Rename, inner]; +} + /** Synchronously renames (moves) `oldpath` to `newpath`. If `newpath` already * exists and is not a directory, `renameSync()` replaces it. OS-specific * restrictions may apply when `oldpath` and `newpath` are in different @@ -23,17 +37,3 @@ export function renameSync(oldpath: string, newpath: string): void { export async function rename(oldpath: string, newpath: string): Promise<void> { await dispatch.sendAsync(...req(oldpath, newpath)); } - -function req( - oldpath: string, - newpath: string -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - const builder = flatbuffers.createBuilder(); - const oldpath_ = builder.createString(oldpath); - const newpath_ = builder.createString(newpath); - msg.Rename.startRename(builder); - msg.Rename.addOldpath(builder, oldpath_); - msg.Rename.addNewpath(builder, newpath_); - const inner = msg.Rename.endRename(builder); - return [builder, msg.Any.Rename, inner]; -} diff --git a/js/repl.ts b/js/repl.ts index 2c050bf5b..c39a79a7d 100644 --- a/js/repl.ts +++ b/js/repl.ts @@ -68,6 +68,47 @@ export async function readline(rid: number, prompt: string): Promise<string> { return line || ""; } +// Error messages that allow users to continue input +// instead of throwing an error to REPL +// ref: https://github.com/v8/v8/blob/master/src/message-template.h +// TODO(kevinkassimo): this list might not be comprehensive +const recoverableErrorMessages = [ + "Unexpected end of input", // { or [ or ( + "Missing initializer in const declaration", // const a + "Missing catch or finally after try", // try {} + "missing ) after argument list", // console.log(1 + "Unterminated template literal" // `template + // TODO(kevinkassimo): need a parser to handling errors such as: + // "Missing } in template expression" // `${ or `${ a 123 }` +]; + +function isRecoverableError(e: Error): boolean { + return recoverableErrorMessages.includes(e.message); +} + +// Evaluate code. +// Returns true if code is consumed (no error/irrecoverable error). +// Returns false if error is recoverable +function evaluate(code: string): boolean { + const [result, errInfo] = libdeno.evalContext(code); + if (!errInfo) { + console.log(result); + } else if (errInfo.isCompileError && isRecoverableError(errInfo.thrown)) { + // Recoverable compiler error + return false; // don't consume code. + } else { + if (errInfo.isNativeError) { + const formattedError = formatError( + libdeno.errorToJSON(errInfo.thrown as Error) + ); + console.error(formattedError); + } else { + console.error("Thrown:", errInfo.thrown); + } + } + return true; +} + // @internal export async function replLoop(): Promise<void> { Object.defineProperties(window, replCommands); @@ -75,7 +116,7 @@ export async function replLoop(): Promise<void> { const historyFile = "deno_history.txt"; const rid = startRepl(historyFile); - const quitRepl = (exitCode: number) => { + const quitRepl = (exitCode: number): void => { // Special handling in case user calls deno.close(3). try { close(rid); // close signals Drop on REPL and saves history. @@ -129,44 +170,3 @@ export async function replLoop(): Promise<void> { } } } - -// Evaluate code. -// Returns true if code is consumed (no error/irrecoverable error). -// Returns false if error is recoverable -function evaluate(code: string): boolean { - const [result, errInfo] = libdeno.evalContext(code); - if (!errInfo) { - console.log(result); - } else if (errInfo.isCompileError && isRecoverableError(errInfo.thrown)) { - // Recoverable compiler error - return false; // don't consume code. - } else { - if (errInfo.isNativeError) { - const formattedError = formatError( - libdeno.errorToJSON(errInfo.thrown as Error) - ); - console.error(formattedError); - } else { - console.error("Thrown:", errInfo.thrown); - } - } - return true; -} - -// Error messages that allow users to continue input -// instead of throwing an error to REPL -// ref: https://github.com/v8/v8/blob/master/src/message-template.h -// TODO(kevinkassimo): this list might not be comprehensive -const recoverableErrorMessages = [ - "Unexpected end of input", // { or [ or ( - "Missing initializer in const declaration", // const a - "Missing catch or finally after try", // try {} - "missing ) after argument list", // console.log(1 - "Unterminated template literal" // `template - // TODO(kevinkassimo): need a parser to handling errors such as: - // "Missing } in template expression" // `${ or `${ a 123 }` -]; - -function isRecoverableError(e: Error): boolean { - return recoverableErrorMessages.includes(e.message); -} diff --git a/js/resources.ts b/js/resources.ts index 0c62c2116..2cabd26dc 100644 --- a/js/resources.ts +++ b/js/resources.ts @@ -4,7 +4,9 @@ import * as flatbuffers from "./flatbuffers"; import { assert } from "./util"; import * as dispatch from "./dispatch"; -export type ResourceMap = { [rid: number]: string }; +export interface ResourceMap { + [rid: number]: string; +} /** Returns a map of open _file like_ resource ids along with their string * representation. @@ -19,7 +21,7 @@ export function resources(): ResourceMap { const res = new msg.ResourcesRes(); assert(baseRes!.inner(res) !== null); - const resources = {} as ResourceMap; + const resources: ResourceMap = {}; for (let i = 0; i < res.resourcesLength(); i++) { const item = res.resources(i)!; diff --git a/js/stat.ts b/js/stat.ts index 4d04ea221..9f99ab441 100644 --- a/js/stat.ts +++ b/js/stat.ts @@ -5,6 +5,27 @@ import * as dispatch from "./dispatch"; import { assert } from "./util"; import { FileInfo, FileInfoImpl } from "./file_info"; +function req( + filename: string, + lstat: boolean +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + const builder = flatbuffers.createBuilder(); + const filename_ = builder.createString(filename); + msg.Stat.startStat(builder); + msg.Stat.addFilename(builder, filename_); + msg.Stat.addLstat(builder, lstat); + const inner = msg.Stat.endStat(builder); + return [builder, msg.Any.Stat, inner]; +} + +function res(baseRes: null | msg.Base): FileInfo { + assert(baseRes != null); + assert(msg.Any.StatRes === baseRes!.innerType()); + const res = new msg.StatRes(); + assert(baseRes!.inner(res) != null); + return new FileInfoImpl(res); +} + /** Queries the file system for information on the path provided. If the given * path is a symlink information about the symlink will be returned. * @@ -45,24 +66,3 @@ export async function stat(filename: string): Promise<FileInfo> { export function statSync(filename: string): FileInfo { return res(dispatch.sendSync(...req(filename, false))); } - -function req( - filename: string, - lstat: boolean -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - const builder = flatbuffers.createBuilder(); - const filename_ = builder.createString(filename); - msg.Stat.startStat(builder); - msg.Stat.addFilename(builder, filename_); - msg.Stat.addLstat(builder, lstat); - const inner = msg.Stat.endStat(builder); - return [builder, msg.Any.Stat, inner]; -} - -function res(baseRes: null | msg.Base): FileInfo { - assert(baseRes != null); - assert(msg.Any.StatRes === baseRes!.innerType()); - const res = new msg.StatRes(); - assert(baseRes!.inner(res) != null); - return new FileInfoImpl(res); -} diff --git a/js/symlink.ts b/js/symlink.ts index fb92688ad..74c1f74fe 100644 --- a/js/symlink.ts +++ b/js/symlink.ts @@ -4,6 +4,25 @@ import * as flatbuffers from "./flatbuffers"; import * as dispatch from "./dispatch"; import * as util from "./util"; +function req( + oldname: string, + newname: string, + type?: string +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + // TODO Use type for Windows. + if (type) { + return util.notImplemented(); + } + const builder = flatbuffers.createBuilder(); + const oldname_ = builder.createString(oldname); + const newname_ = builder.createString(newname); + msg.Symlink.startSymlink(builder); + msg.Symlink.addOldname(builder, oldname_); + msg.Symlink.addNewname(builder, newname_); + const inner = msg.Symlink.endSymlink(builder); + return [builder, msg.Any.Symlink, inner]; +} + /** Synchronously creates `newname` as a symbolic link to `oldname`. The type * argument can be set to `dir` or `file` and is only available on Windows * (ignored on other platforms). @@ -31,22 +50,3 @@ export async function symlink( ): Promise<void> { await dispatch.sendAsync(...req(oldname, newname, type)); } - -function req( - oldname: string, - newname: string, - type?: string -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - // TODO Use type for Windows. - if (type) { - return util.notImplemented(); - } - const builder = flatbuffers.createBuilder(); - const oldname_ = builder.createString(oldname); - const newname_ = builder.createString(newname); - msg.Symlink.startSymlink(builder); - msg.Symlink.addOldname(builder, oldname_); - msg.Symlink.addNewname(builder, newname_); - const inner = msg.Symlink.endSymlink(builder); - return [builder, msg.Any.Symlink, inner]; -} diff --git a/js/test_util.ts b/js/test_util.ts index 7cc80e581..e683d32b1 100644 --- a/js/test_util.ts +++ b/js/test_util.ts @@ -52,12 +52,15 @@ function permFromString(s: string): DenoPermissions { }; } -export function testPerm(perms: DenoPermissions, fn: testing.TestFunction) { +export function testPerm( + perms: DenoPermissions, + fn: testing.TestFunction +): void { const name = `${fn.name}_${permToString(perms)}`; testing.test({ fn, name }); } -export function test(fn: testing.TestFunction) { +export function test(fn: testing.TestFunction): void { testPerm( { read: false, write: false, net: false, env: false, run: false }, fn diff --git a/js/text_encoding.ts b/js/text_encoding.ts index dd1b22d65..d0e08f73b 100644 --- a/js/text_encoding.ts +++ b/js/text_encoding.ts @@ -27,6 +27,153 @@ import * as base64 from "base64-js"; import * as domTypes from "./dom_types"; import { DenoError, ErrorKind } from "./errors"; +const CONTINUE = null; +const END_OF_STREAM = -1; +const FINISHED = -1; + +function decoderError(fatal: boolean): number | never { + if (fatal) { + throw new TypeError("Decoder error."); + } + return 0xfffd; // default code point +} + +function inRange(a: number, min: number, max: number): boolean { + return min <= a && a <= max; +} + +function isASCIIByte(a: number): boolean { + return inRange(a, 0x00, 0x7f); +} + +function stringToCodePoints(input: string): number[] { + const u: number[] = []; + for (const c of input) { + u.push(c.codePointAt(0)!); + } + return u; +} + +class UTF8Decoder implements Decoder { + private _codePoint = 0; + private _bytesSeen = 0; + private _bytesNeeded = 0; + private _fatal: boolean; + private _lowerBoundary = 0x80; + private _upperBoundary = 0xbf; + + constructor(options: DecoderOptions) { + this._fatal = options.fatal || false; + } + + handler(stream: Stream, byte: number): number | null { + if (byte === END_OF_STREAM && this._bytesNeeded !== 0) { + this._bytesNeeded = 0; + return decoderError(this._fatal); + } + + if (byte === END_OF_STREAM) { + return FINISHED; + } + + if (this._bytesNeeded === 0) { + if (isASCIIByte(byte)) { + // Single byte code point + return byte; + } else if (inRange(byte, 0xc2, 0xdf)) { + // Two byte code point + this._bytesNeeded = 1; + this._codePoint = byte & 0x1f; + } else if (inRange(byte, 0xe0, 0xef)) { + // Three byte code point + if (byte === 0xe0) { + this._lowerBoundary = 0xa0; + } else if (byte === 0xed) { + this._upperBoundary = 0x9f; + } + this._bytesNeeded = 2; + this._codePoint = byte & 0xf; + } else if (inRange(byte, 0xf0, 0xf4)) { + if (byte === 0xf0) { + this._lowerBoundary = 0x90; + } else if (byte === 0xf4) { + this._upperBoundary = 0x8f; + } + this._bytesNeeded = 3; + this._codePoint = byte & 0x7; + } else { + return decoderError(this._fatal); + } + return CONTINUE; + } + + if (!inRange(byte, this._lowerBoundary, this._upperBoundary)) { + // Byte out of range, so encoding error + this._codePoint = 0; + this._bytesNeeded = 0; + this._bytesSeen = 0; + stream.prepend(byte); + return decoderError(this._fatal); + } + + this._lowerBoundary = 0x80; + this._upperBoundary = 0xbf; + + this._codePoint = (this._codePoint << 6) | (byte & 0x3f); + + this._bytesSeen++; + + if (this._bytesSeen !== this._bytesNeeded) { + return CONTINUE; + } + + const codePoint = this._codePoint; + + this._codePoint = 0; + this._bytesNeeded = 0; + this._bytesSeen = 0; + + return codePoint; + } +} + +class UTF8Encoder implements Encoder { + handler(codePoint: number): number | number[] { + if (codePoint === END_OF_STREAM) { + return FINISHED; + } + + if (inRange(codePoint, 0x00, 0x7f)) { + return codePoint; + } + + let count: number; + let offset: number; + if (inRange(codePoint, 0x0080, 0x07ff)) { + count = 1; + offset = 0xc0; + } else if (inRange(codePoint, 0x0800, 0xffff)) { + count = 2; + offset = 0xe0; + } else if (inRange(codePoint, 0x10000, 0x10ffff)) { + count = 3; + offset = 0xf0; + } else { + throw TypeError(`Code point out of range: \\x${codePoint.toString(16)}`); + } + + const bytes = [(codePoint >> (6 * count)) + offset]; + + while (count > 0) { + const temp = codePoint >> (6 * (count - 1)); + bytes.push(0x80 | (temp & 0x3f)); + count--; + } + + return bytes; + } +} + /** Decodes a string of data which has been encoded using base-64. */ export function atob(s: string): string { const rem = s.length % 4; @@ -80,9 +227,30 @@ interface Encoder { handler(codePoint: number): number | number[]; } -const CONTINUE = null; -const END_OF_STREAM = -1; -const FINISHED = -1; +class SingleByteDecoder implements Decoder { + private _index: number[]; + private _fatal: boolean; + + constructor(index: number[], options: DecoderOptions) { + this._fatal = options.fatal || false; + this._index = index; + } + handler(stream: Stream, byte: number): number { + if (byte === END_OF_STREAM) { + return FINISHED; + } + if (isASCIIByte(byte)) { + return byte; + } + const codePoint = this._index[byte - 0x80]; + + if (codePoint == null) { + return decoderError(this._fatal); + } + + return codePoint; + } +} // The encodingMap is a hash of labels that are indexed by the conical // encoding. @@ -127,10 +295,8 @@ decoders.set("utf-8", (options: DecoderOptions) => { // Single byte decoders are an array of code point lookups const encodingIndexes = new Map<string, number[]>(); -// tslint:disable:max-line-length // prettier-ignore encodingIndexes.set("windows-1252", [8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]); -// tslint:enable for (const [key, index] of encodingIndexes) { decoders.set(key, (options: DecoderOptions) => { return new SingleByteDecoder(index, options); @@ -145,29 +311,6 @@ function codePointsToString(codePoints: number[]): string { return s; } -function decoderError(fatal: boolean): number | never { - if (fatal) { - throw new TypeError("Decoder error."); - } - return 0xfffd; // default code point -} - -function inRange(a: number, min: number, max: number) { - return min <= a && a <= max; -} - -function isASCIIByte(a: number) { - return inRange(a, 0x00, 0x7f); -} - -function stringToCodePoints(input: string): number[] { - const u: number[] = []; - for (const c of input) { - u.push(c.codePointAt(0)!); - } - return u; -} - class Stream { private _tokens: number[]; constructor(tokens: number[] | Uint8Array) { @@ -204,151 +347,6 @@ class Stream { } } -class SingleByteDecoder implements Decoder { - private _index: number[]; - private _fatal: boolean; - - constructor(index: number[], options: DecoderOptions) { - this._fatal = options.fatal || false; - this._index = index; - } - handler(stream: Stream, byte: number): number { - if (byte === END_OF_STREAM) { - return FINISHED; - } - if (isASCIIByte(byte)) { - return byte; - } - const codePoint = this._index[byte - 0x80]; - - if (codePoint == null) { - return decoderError(this._fatal); - } - - return codePoint; - } -} - -class UTF8Decoder implements Decoder { - private _codePoint = 0; - private _bytesSeen = 0; - private _bytesNeeded = 0; - private _fatal: boolean; - private _lowerBoundary = 0x80; - private _upperBoundary = 0xbf; - - constructor(options: DecoderOptions) { - this._fatal = options.fatal || false; - } - - handler(stream: Stream, byte: number): number | null { - if (byte === END_OF_STREAM && this._bytesNeeded !== 0) { - this._bytesNeeded = 0; - return decoderError(this._fatal); - } - - if (byte === END_OF_STREAM) { - return FINISHED; - } - - if (this._bytesNeeded === 0) { - if (isASCIIByte(byte)) { - // Single byte code point - return byte; - } else if (inRange(byte, 0xc2, 0xdf)) { - // Two byte code point - this._bytesNeeded = 1; - this._codePoint = byte & 0x1f; - } else if (inRange(byte, 0xe0, 0xef)) { - // Three byte code point - if (byte === 0xe0) { - this._lowerBoundary = 0xa0; - } else if (byte === 0xed) { - this._upperBoundary = 0x9f; - } - this._bytesNeeded = 2; - this._codePoint = byte & 0xf; - } else if (inRange(byte, 0xf0, 0xf4)) { - if (byte === 0xf0) { - this._lowerBoundary = 0x90; - } else if (byte === 0xf4) { - this._upperBoundary = 0x8f; - } - this._bytesNeeded = 3; - this._codePoint = byte & 0x7; - } else { - return decoderError(this._fatal); - } - return CONTINUE; - } - - if (!inRange(byte, this._lowerBoundary, this._upperBoundary)) { - // Byte out of range, so encoding error - this._codePoint = 0; - this._bytesNeeded = 0; - this._bytesSeen = 0; - stream.prepend(byte); - return decoderError(this._fatal); - } - - this._lowerBoundary = 0x80; - this._upperBoundary = 0xbf; - - this._codePoint = (this._codePoint << 6) | (byte & 0x3f); - - this._bytesSeen++; - - if (this._bytesSeen !== this._bytesNeeded) { - return CONTINUE; - } - - const codePoint = this._codePoint; - - this._codePoint = 0; - this._bytesNeeded = 0; - this._bytesSeen = 0; - - return codePoint; - } -} - -class UTF8Encoder implements Encoder { - handler(codePoint: number): number | number[] { - if (codePoint === END_OF_STREAM) { - return FINISHED; - } - - if (inRange(codePoint, 0x00, 0x7f)) { - return codePoint; - } - - let count: number; - let offset: number; - if (inRange(codePoint, 0x0080, 0x07ff)) { - count = 1; - offset = 0xc0; - } else if (inRange(codePoint, 0x0800, 0xffff)) { - count = 2; - offset = 0xe0; - } else if (inRange(codePoint, 0x10000, 0x10ffff)) { - count = 3; - offset = 0xf0; - } else { - throw TypeError(`Code point out of range: \\x${codePoint.toString(16)}`); - } - - const bytes = [(codePoint >> (6 * count)) + offset]; - - while (count > 0) { - const temp = codePoint >> (6 * (count - 1)); - bytes.push(0x80 | (temp & 0x3f)); - count--; - } - - return bytes; - } -} - export interface TextDecodeOptions { stream?: false; } diff --git a/js/text_encoding_test.ts b/js/text_encoding_test.ts index f7939499a..4eab24808 100644 --- a/js/text_encoding_test.ts +++ b/js/text_encoding_test.ts @@ -46,7 +46,7 @@ test(function textDecoderASCII() { test(function textDecoderErrorEncoding() { let didThrow = false; try { - const decoder = new TextDecoder("foo"); + new TextDecoder("foo"); } catch (e) { didThrow = true; assertEquals(e.message, "The encoding label provided ('foo') is invalid."); diff --git a/js/timers.ts b/js/timers.ts index 9e9c312ee..d06056cf2 100644 --- a/js/timers.ts +++ b/js/timers.ts @@ -4,10 +4,6 @@ import * as msg from "gen/msg_generated"; import * as flatbuffers from "./flatbuffers"; import { sendSync, setFireTimersCallback } from "./dispatch"; -// Tell the dispatcher which function it should call to fire timers that are -// due. This is done using a callback because circular imports are disallowed. -setFireTimersCallback(fireTimers); - interface Timer { id: number; callback: () => void; @@ -34,14 +30,14 @@ let nextTimerId = 1; const idMap = new Map<number, Timer>(); const dueMap: { [due: number]: Timer[] } = Object.create(null); -function getTime() { +function getTime(): number { // TODO: use a monotonic clock. const now = Date.now() - EPOCH; assert(now >= 0 && now < APOCALYPSE); return now; } -function setGlobalTimeout(due: number | null, now: number) { +function setGlobalTimeout(due: number | null, now: number): void { // Since JS and Rust don't use the same clock, pass the time to rust as a // relative time value. On the Rust side we'll turn that into an absolute // value again. @@ -65,7 +61,7 @@ function setGlobalTimeout(due: number | null, now: number) { globalTimeoutDue = due; } -function schedule(timer: Timer, now: number) { +function schedule(timer: Timer, now: number): void { assert(!timer.scheduled); assert(now <= timer.due); // Find or create the list of timers that will fire at point-in-time `due`. @@ -83,7 +79,7 @@ function schedule(timer: Timer, now: number) { } } -function unschedule(timer: Timer) { +function unschedule(timer: Timer): void { if (!timer.scheduled) { return; } @@ -112,7 +108,7 @@ function unschedule(timer: Timer) { } } -function fire(timer: Timer) { +function fire(timer: Timer): void { // If the timer isn't found in the ID map, that means it has been cancelled // between the timer firing and the promise callback (this function). if (!idMap.has(timer.id)) { @@ -135,7 +131,7 @@ function fire(timer: Timer) { callback(); } -function fireTimers() { +function fireTimers(): void { const now = getTime(); // Bail out if we're not expecting the global timer to fire (yet). if (globalTimeoutDue === null || now < globalTimeoutDue) { @@ -171,7 +167,7 @@ function fireTimers() { setGlobalTimeout(nextTimerDue, now); } -export type Args = any[]; // tslint:disable-line:no-any +export type Args = unknown[]; function setTimer( cb: (...args: Args) => void, @@ -241,3 +237,7 @@ export function clearTimer(id: number): void { unschedule(timer); idMap.delete(timer.id); } + +// Tell the dispatcher which function it should call to fire timers that are +// due. This is done using a callback because circular imports are disallowed. +setFireTimersCallback(fireTimers); diff --git a/js/timers_test.ts b/js/timers_test.ts index d40c01376..d1bce82a9 100644 --- a/js/timers_test.ts +++ b/js/timers_test.ts @@ -1,7 +1,12 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. import { test, assertEquals } from "./test_util.ts"; -function deferred() { +function deferred(): { + promise: Promise<{}>; + resolve: (value?: {} | PromiseLike<{}>) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + reject: (reason?: any) => void; +} { let resolve; let reject; const promise = new Promise((res, rej) => { @@ -15,7 +20,7 @@ function deferred() { }; } -function waitForMs(ms) { +async function waitForMs(ms): Promise<number> { return new Promise(resolve => setTimeout(resolve, ms)); } @@ -62,6 +67,10 @@ test(async function timeoutCancelSuccess() { }); test(async function timeoutCancelMultiple() { + function uncalled(): never { + throw new Error("This function should not be called."); + } + // Set timers and cancel them in the same order. const t1 = setTimeout(uncalled, 10); const t2 = setTimeout(uncalled, 10); @@ -80,10 +89,6 @@ test(async function timeoutCancelMultiple() { // Sleep until we're certain that the cancelled timers aren't gonna fire. await waitForMs(50); - - function uncalled() { - throw new Error("This function should not be called."); - } }); test(async function timeoutCancelInvalidSilentFail() { @@ -138,15 +143,15 @@ test(async function intervalCancelSuccess() { test(async function intervalOrdering() { const timers = []; let timeouts = 0; - for (let i = 0; i < 10; i++) { - timers[i] = setTimeout(onTimeout, 20); - } - function onTimeout() { + function onTimeout(): void { ++timeouts; for (let i = 1; i < timers.length; i++) { clearTimeout(timers[i]); } } + for (let i = 0; i < 10; i++) { + timers[i] = setTimeout(onTimeout, 20); + } await waitForMs(100); assertEquals(timeouts, 1); }); diff --git a/js/truncate.ts b/js/truncate.ts index 329c5db1d..2d700ab5d 100644 --- a/js/truncate.ts +++ b/js/truncate.ts @@ -3,6 +3,20 @@ import * as msg from "gen/msg_generated"; import * as flatbuffers from "./flatbuffers"; import * as dispatch from "./dispatch"; +function req( + name: string, + len?: number +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { + const builder = flatbuffers.createBuilder(); + const name_ = builder.createString(name); + len = len && len > 0 ? Math.floor(len) : 0; + msg.Truncate.startTruncate(builder); + msg.Truncate.addName(builder, name_); + msg.Truncate.addLen(builder, len); + const inner = msg.Truncate.endTruncate(builder); + return [builder, msg.Any.Truncate, inner]; +} + /** Truncates or extends the specified file synchronously, updating the size of * this file to become size. * @@ -21,17 +35,3 @@ export function truncateSync(name: string, len?: number): void { export async function truncate(name: string, len?: number): Promise<void> { await dispatch.sendAsync(...req(name, len)); } - -function req( - name: string, - len?: number -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset] { - const builder = flatbuffers.createBuilder(); - const name_ = builder.createString(name); - len = len && len > 0 ? Math.floor(len) : 0; - msg.Truncate.startTruncate(builder); - msg.Truncate.addName(builder, name_); - msg.Truncate.addLen(builder, len); - const inner = msg.Truncate.endTruncate(builder); - return [builder, msg.Any.Truncate, inner]; -} @@ -67,17 +67,16 @@ export class URL { private _parts: URLParts; private _searchParams!: urlSearchParams.URLSearchParams; - private _updateSearchParams() { + private _updateSearchParams(): void { const searchParams = new urlSearchParams.URLSearchParams(this.search); for (const methodName of searchParamsMethods) { - // tslint:disable:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any const method: (...args: any[]) => any = searchParams[methodName]; - searchParams[methodName] = (...args: any[]) => { + searchParams[methodName] = (...args: unknown[]) => { method.apply(searchParams, args); this.search = searchParams.toString(); }; - // tslint:enable } this._searchParams = searchParams; } diff --git a/js/url_search_params.ts b/js/url_search_params.ts index dec7ca869..ac4ac01b1 100644 --- a/js/url_search_params.ts +++ b/js/url_search_params.ts @@ -175,9 +175,9 @@ export class URLSearchParams { */ forEach( callbackfn: (value: string, key: string, parent: URLSearchParams) => void, - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any thisArg?: any - ) { + ): void { requiredArguments("URLSearchParams.forEach", arguments.length, 1); if (typeof thisArg !== "undefined") { diff --git a/js/util.ts b/js/util.ts index 6f8c72f50..e6f38c8e1 100644 --- a/js/util.ts +++ b/js/util.ts @@ -16,15 +16,14 @@ export function setLogDebug(debug: boolean, source?: string): void { * Enable with the `--log-debug` or `-D` command line flag. * @internal */ -// tslint:disable-next-line:no-any -export function log(...args: any[]): void { +export function log(...args: unknown[]): void { if (logDebug) { console.log(`DEBUG ${logSource} -`, ...args); } } // @internal -export function assert(cond: boolean, msg = "assert") { +export function assert(cond: boolean, msg = "assert"): void { if (!cond) { throw Error(msg); } @@ -62,7 +61,7 @@ export function arrayToStr(ui8: Uint8Array): string { export interface ResolvableMethods<T> { resolve: (value?: T | PromiseLike<T>) => void; - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any reject: (reason?: any) => void; } @@ -107,7 +106,6 @@ export function containsOnlyASCII(str: string): boolean { return /^[\x00-\x7F]*$/.test(str); } -// tslint:disable-next-line:variable-name const TypedArrayConstructor = Object.getPrototypeOf(Uint8Array); export function isTypedArray(x: unknown): x is TypedArray { return x instanceof TypedArrayConstructor; diff --git a/js/workers.ts b/js/workers.ts index 1716f8ef6..b2f4231c4 100644 --- a/js/workers.ts +++ b/js/workers.ts @@ -50,7 +50,7 @@ export function workerClose(): void { isClosing = true; } -export async function workerMain() { +export async function workerMain(): Promise<void> { log("workerMain"); while (!isClosing) { diff --git a/js/write_file.ts b/js/write_file.ts index a75da2582..8c5c7ac0a 100644 --- a/js/write_file.ts +++ b/js/write_file.ts @@ -3,6 +3,34 @@ import * as msg from "gen/msg_generated"; import * as flatbuffers from "./flatbuffers"; import * as dispatch from "./dispatch"; +function req( + filename: string, + data: Uint8Array, + options: WriteFileOptions +): [flatbuffers.Builder, msg.Any, flatbuffers.Offset, Uint8Array] { + const builder = flatbuffers.createBuilder(); + const filename_ = builder.createString(filename); + msg.WriteFile.startWriteFile(builder); + msg.WriteFile.addFilename(builder, filename_); + // Perm is not updated by default + if (options.perm !== undefined && options.perm !== null) { + msg.WriteFile.addUpdatePerm(builder, true); + msg.WriteFile.addPerm(builder, options.perm!); + } else { + msg.WriteFile.addUpdatePerm(builder, false); + msg.WriteFile.addPerm(builder, 0o666); + } + // Create is turned on by default + if (options.create !== undefined) { + msg.WriteFile.addIsCreate(builder, !!options.create); + } else { + msg.WriteFile.addIsCreate(builder, true); + } + msg.WriteFile.addIsAppend(builder, !!options.append); + const inner = msg.WriteFile.endWriteFile(builder); + return [builder, msg.Any.WriteFile, inner, data]; +} + /** Options for writing to a file. * `perm` would change the file's permission if set. * `create` decides if the file should be created if not exists (default: true) @@ -41,31 +69,3 @@ export async function writeFile( ): Promise<void> { await dispatch.sendAsync(...req(filename, data, options)); } - -function req( - filename: string, - data: Uint8Array, - options: WriteFileOptions -): [flatbuffers.Builder, msg.Any, flatbuffers.Offset, Uint8Array] { - const builder = flatbuffers.createBuilder(); - const filename_ = builder.createString(filename); - msg.WriteFile.startWriteFile(builder); - msg.WriteFile.addFilename(builder, filename_); - // Perm is not updated by default - if (options.perm !== undefined && options.perm !== null) { - msg.WriteFile.addUpdatePerm(builder, true); - msg.WriteFile.addPerm(builder, options.perm!); - } else { - msg.WriteFile.addUpdatePerm(builder, false); - msg.WriteFile.addPerm(builder, 0o666); - } - // Create is turned on by default - if (options.create !== undefined) { - msg.WriteFile.addIsCreate(builder, !!options.create); - } else { - msg.WriteFile.addIsCreate(builder, true); - } - msg.WriteFile.addIsAppend(builder, !!options.append); - const inner = msg.WriteFile.endWriteFile(builder); - return [builder, msg.Any.WriteFile, inner, data]; -} |