From 034e2cc02829c9244b32232074c7a48af827a2fb Mon Sep 17 00:00:00 2001 From: Kitson Kelly Date: Sun, 10 Mar 2019 04:30:38 +1100 Subject: [PATCH] Migrate from tslint to eslint for linting (#1905) --- .eslintignore | 3 + .eslintrc.json | 23 ++ core/http_bench.js | 34 +- js/assets.ts | 4 +- js/blob.ts | 137 ++++---- js/buffer.ts | 4 +- js/buffer_test.ts | 22 +- js/build.ts | 4 +- js/chmod.ts | 26 +- js/compiler.ts | 4 +- js/compiler_test.ts | 13 +- js/console.ts | 147 ++++---- js/console_table.ts | 7 +- js/console_test.ts | 27 +- js/copy_file.ts | 28 +- js/copy_file_test.ts | 4 +- js/custom_event.ts | 9 +- js/dispatch.ts | 42 +-- js/dom_types.ts | 14 +- js/errors.ts | 16 +- js/event.ts | 1 - js/event_target.ts | 4 +- js/event_target_test.ts | 10 +- js/fetch.ts | 24 +- js/file_info.ts | 6 +- js/file_test.ts | 5 +- js/files.ts | 125 +++---- js/flatbuffers.ts | 4 +- js/form_data.ts | 1 - js/form_data_test.ts | 2 +- js/globals.ts | 1 - js/headers.ts | 14 +- js/headers_test.ts | 4 - js/lib.web_assembly.d.ts | 26 +- js/libdeno.ts | 9 +- js/location.ts | 14 +- js/main.ts | 6 +- js/make_temp_dir.ts | 52 +-- js/metrics.ts | 10 +- js/mixins/dom_iterable.ts | 13 +- js/mixins/dom_iterable_test.ts | 13 +- js/mkdir.ts | 30 +- js/net.ts | 108 +++--- js/net_test.ts | 2 +- js/os.ts | 22 +- js/os_test.ts | 3 +- js/permissions.ts | 60 ++-- js/process.ts | 43 ++- js/read_dir.ts | 34 +- js/read_dir_test.ts | 6 +- js/read_file.ts | 40 +-- js/read_file_test.ts | 2 +- js/read_link.ts | 32 +- js/remove.ts | 26 +- js/rename.ts | 28 +- js/repl.ts | 84 ++--- js/resources.ts | 6 +- js/stat.ts | 42 +-- js/symlink.ts | 38 +- js/test_util.ts | 7 +- js/text_encoding.ts | 352 +++++++++---------- js/text_encoding_test.ts | 2 +- js/timers.ts | 22 +- js/timers_test.ts | 25 +- js/truncate.ts | 28 +- js/url.ts | 7 +- js/url_search_params.ts | 4 +- js/util.ts | 8 +- js/workers.ts | 2 +- js/write_file.ts | 56 +-- package.json | 7 +- tests/012_async.ts | 4 +- tests/017_import_redirect.ts | 1 - tests/018_async_catch.ts | 4 +- tests/019_media_types.ts | 1 - tests/async_error.ts | 2 +- tests/cat.ts | 2 +- tests/error_001.ts | 4 +- tests/error_002.ts | 2 +- tests/error_004_missing_module.ts | 1 + tests/error_005_missing_dynamic_import.ts | 1 + tests/error_008_checkjs.js | 2 +- tests/fetch_deps.ts | 2 +- tests/https_import.ts | 1 - third_party | 2 +- tools/lint.py | 9 +- tools/ts_library_builder/build_library.ts | 1 - tools/ts_library_builder/main.ts | 1 - tools/ts_library_builder/testdata/globals.ts | 1 - tslint.json | 66 ---- 90 files changed, 1041 insertions(+), 1104 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.json delete mode 100644 tslint.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..de3425c583 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +/js/deps/ +/js/gen/ +/tests/error_syntax.js diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000000..43405e21eb --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,23 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.json" + }, + "plugins": ["@typescript-eslint"], + "extends": [ + "plugin:@typescript-eslint/recommended", + "prettier", + "prettier/@typescript-eslint" + ], + "rules": { + "@typescript-eslint/array-type": ["error", "array-simple"], + "@typescript-eslint/explicit-member-accessibility": ["off"], + "@typescript-eslint/no-non-null-assertion": ["off"], + "@typescript-eslint/no-parameter-properties": ["off"], + "@typescript-eslint/no-unused-vars": [ + "error", + { "argsIgnorePattern": "^_" } + ] + } +} diff --git a/core/http_bench.js b/core/http_bench.js index b9615e6896..29a79c4362 100644 --- a/core/http_bench.js +++ b/core/http_bench.js @@ -39,6 +39,20 @@ function createResolvable() { return Object.assign(promise, methods); } +function setRecord(i, off, value) { + if (i >= NUM_RECORDS) { + throw Error("out of range"); + } + shared32[INDEX_RECORDS + RECORD_SIZE * i + off] = value; +} + +function getRecord(i, off) { + if (i >= NUM_RECORDS) { + throw Error("out of range"); + } + return shared32[INDEX_RECORDS + RECORD_SIZE * i + off]; +} + /** Returns Promise */ function sendAsync(op, arg, zeroCopyData) { const id = nextPromiseId++; @@ -64,20 +78,6 @@ function sendSync(op, arg) { return getRecord(0, RECORD_OFFSET_RESULT); } -function setRecord(i, off, value) { - if (i >= NUM_RECORDS) { - throw Error("out of range"); - } - shared32[INDEX_RECORDS + RECORD_SIZE * i + off] = value; -} - -function getRecord(i, off) { - if (i >= NUM_RECORDS) { - throw Error("out of range"); - } - return shared32[INDEX_RECORDS + RECORD_SIZE * i + off]; -} - function handleAsyncMsgFromRust() { for (let i = 0; i < shared32[INDEX_NUM_RECORDS]; i++) { let id = getRecord(i, RECORD_OFFSET_PROMISE_ID); @@ -134,10 +134,10 @@ async function main() { libdeno.print("http_bench.js start"); - const listener_rid = listen(); - libdeno.print(`listening http://127.0.0.1:4544/ rid = ${listener_rid}`); + const listenerRid = listen(); + libdeno.print(`listening http://127.0.0.1:4544/ rid = ${listenerRid}`); while (true) { - const rid = await accept(listener_rid); + const rid = await accept(listenerRid); // libdeno.print(`accepted ${rid}`); if (rid < 0) { libdeno.print(`accept error ${rid}`); diff --git a/js/assets.ts b/js/assets.ts index 18bf975483..5f1790646f 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 /// // 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 7510c9cef4..c23b74afb5 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 db060f2ff6..c5be762f5b 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 691d97e205..90e171330b 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 { 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 636f9a0825..347dd4e72c 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 2a9b1b01db..3b14ef5bcb 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 { 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 39a32bc246..aefdf989d3 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 e8101995e6..e3631641a5 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 4cfd0211d3..20eafbacf7 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( 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, ...args); + return createSetString(value, ...args); } else if (value instanceof Map) { - return createMapString(value as Map, ...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(), 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(), 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(), 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(), 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 735ed0f9e4..d7cae124c7 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 ed99100068..ddc48de051 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 dc099f7019..a7792d588a 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 { 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 33f8f027f3..5348094c48 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 dd1c33d58f..d2092a2be5 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 55ea682fc1..5372918777 100644 --- a/js/dispatch.ts +++ b/js/dispatch.ts @@ -10,11 +10,11 @@ const promiseTable = new Map>(); 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 651eece9af..bf6e077962 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 { [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( 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( 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; - // tslint:disable-next-line:no-any read(): Promise; 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; /** 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 { values(): IterableIterator; 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 452b2372ea..cefa4a8634 100644 --- a/js/errors.ts +++ b/js/errors.ts @@ -24,14 +24,6 @@ export class DenoError 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 { const kind = base.errorKind(); @@ -41,3 +33,11 @@ export function maybeError(base: Base): null | DenoError { 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 1cc711b32f..f397391909 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 112ad17059..98b7bbcb8d 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 7837247958..bad3828a12 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 2823869ca5..355535dfe8 100644 --- a/js/fetch.ts +++ b/js/fetch.ts @@ -26,7 +26,7 @@ function getHeaderValueParams(value: string): Map { 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 { 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 { 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 cf9ede85cd..deaafe5ea1 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 77320c1137..65ddfde92b 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 a77f788df3..9ea3787356 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 { - return write(this.rid, p); - } - - read(p: Uint8Array): Promise { - return read(this.rid, p); - } - - seek(offset: number, whence: SeekMode): Promise { - 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 { - 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 { + return write(this.rid, p); + } + + read(p: Uint8Array): Promise { + return read(this.rid, p); + } + + seek(offset: number, whence: SeekMode): Promise { + 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 { + return open(filename, "w+"); +} diff --git a/js/flatbuffers.ts b/js/flatbuffers.ts index 74eaf40ff8..73f3ceb824 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 f9a76b80bb..3b30967859 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 02e2c989ac..bdf1e7cda9 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 9bd0584b2e..45a4ccb01a 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 31a29111e6..dcb5f4c6a4 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 223e08dafb..4a911f9a55 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 e69c4c629b..ccefdd077f 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 ee43413f38..33e9e4f5fd 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 5d7f44707e..535a2bceab 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 830c77eb67..887d6b3c25 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 /// 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 1ee095bbcc..dc04522ee6 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 { - 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 { + return res(await dispatch.sendAsync(...req(options))); +} diff --git a/js/metrics.ts b/js/metrics.ts index 1cbc9f13b8..111015078f 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 ae5a030ce1..97e8133ec0 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 = new (...args: any[]) => T; /** Mixes in a DOM iterable methods into a base class, assumes that there is @@ -12,7 +13,6 @@ type Constructor = new (...args: any[]) => T; * TODO Don't expose DomIterableMixin from "deno" namespace. */ export function DomIterableMixin( - // tslint:disable-next-line:variable-name Base: TBase, dataSymbol: symbol ): TBase & Constructor> { @@ -25,21 +25,23 @@ export function DomIterableMixin( // 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 { + // eslint-disable-next-line @typescript-eslint/no-explicit-any for (const [key] of (this as any)[dataSymbol]) { yield key; } } *values(): IterableIterator { + // 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( 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( 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( return DomIterable; } -// tslint:enable:no-any diff --git a/js/mixins/dom_iterable_test.ts b/js/mixins/dom_iterable_test.ts index a0bed7bd30..36e3de6784 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 a620c3764d..784d891f91 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 { 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]; -} diff --git a/js/net.ts b/js/net.ts index aecff1fde6..0b56a4c308 100644 --- a/js/net.ts +++ b/js/net.ts @@ -27,6 +27,58 @@ export interface Listener { addr(): Addr; } +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 +} + +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 { + constructor( + readonly rid: number, + readonly remoteAddr: string, + readonly localAddr: string + ) {} + + write(p: Uint8Array): Promise { + return write(this.rid, p); + } + + read(p: Uint8Array): Promise { + return read(this.rid, p); + } + + close(): void { + close(this.rid); + } + + /** closeRead shuts down (shutdown(2)) the reading side of the TCP connection. + * Most callers should just use close(). + */ + closeRead(): void { + shutdown(this.rid, ShutdownMode.Read); + } + + /** closeWrite shuts down (shutdown(2)) the writing side of the TCP + * connection. Most callers should just use close(). + */ + closeWrite(): void { + shutdown(this.rid, ShutdownMode.Write); + } +} + class ListenerImpl implements Listener { constructor(readonly rid: number) {} @@ -69,58 +121,6 @@ export interface Conn extends Reader, Writer, Closer { closeWrite(): void; } -class ConnImpl implements Conn { - constructor( - readonly rid: number, - readonly remoteAddr: string, - readonly localAddr: string - ) {} - - write(p: Uint8Array): Promise { - return write(this.rid, p); - } - - read(p: Uint8Array): Promise { - return read(this.rid, p); - } - - close(): void { - close(this.rid); - } - - /** closeRead shuts down (shutdown(2)) the reading side of the TCP connection. - * Most callers should just use close(). - */ - closeRead(): void { - shutdown(this.rid, ShutdownMode.Read); - } - - /** closeWrite shuts down (shutdown(2)) the writing side of the TCP - * connection. Most callers should just use close(). - */ - closeWrite(): void { - shutdown(this.rid, ShutdownMode.Write); - } -} - -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 -} - -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); -} - /** Listen announces on the local network address. * * The network must be `tcp`, `tcp4`, `tcp6`, `unix` or `unixpacket`. @@ -197,8 +197,8 @@ export async function dial(network: Network, address: string): Promise { /** **RESERVED** */ export async function connect( - network: Network, - address: string + _network: Network, + _address: string ): Promise { return notImplemented(); } diff --git a/js/net_test.ts b/js/net_test.ts index 5b8b80bea2..cb9a9163aa 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); diff --git a/js/os.ts b/js/os.ts index 03bb7bb42e..f95114f049 100644 --- a/js/os.ts +++ b/js/os.ts @@ -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 0773bf685b..39429d919e 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 6acb80b1f9..f4fe6826fa 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 2f60e5c4a0..bf75b6b32d 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 { + 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 { - 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 d7d20644b8..2515a61c63 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 { - 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 { + return res(await dispatch.sendAsync(...req(path))); +} diff --git a/js/read_dir_test.ts b/js/read_dir_test.ts index 914c2b2a85..c2d90642ca 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 288841672d..3aeedec28c 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 { - 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 { + return res(await dispatch.sendAsync(...req(filename))); +} diff --git a/js/read_file_test.ts b/js/read_file_test.ts index 4724158e95..2e0525d3f2 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 6a518231fa..b63fdd8417 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 { - 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 { + return res(await dispatch.sendAsync(...req(name))); +} diff --git a/js/remove.ts b/js/remove.ts index 89c2ba672b..1c9df68308 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 { 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 e5e08d6477..9d475f7e9c 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 { 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 2c050bf5bc..c39a79a7d1 100644 --- a/js/repl.ts +++ b/js/repl.ts @@ -68,6 +68,47 @@ export async function readline(rid: number, prompt: string): Promise { 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 { Object.defineProperties(window, replCommands); @@ -75,7 +116,7 @@ export async function replLoop(): Promise { 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 { } } } - -// 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 0c62c2116e..2cabd26dc1 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 4d04ea2219..9f99ab4418 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 { 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 fb92688ad2..74c1f74fea 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 { 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 7cc80e5816..e683d32b10 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 dd1b22d657..d0e08f73b6 100644 --- a/js/text_encoding.ts +++ b/js/text_encoding.ts @@ -27,124 +27,10 @@ import * as base64 from "base64-js"; import * as domTypes from "./dom_types"; import { DenoError, ErrorKind } from "./errors"; -/** Decodes a string of data which has been encoded using base-64. */ -export function atob(s: string): string { - const rem = s.length % 4; - // base64-js requires length exactly times of 4 - if (rem > 0) { - s = s.padEnd(s.length + (4 - rem), "="); - } - let byteArray; - try { - byteArray = base64.toByteArray(s); - } catch (_) { - throw new DenoError( - ErrorKind.InvalidInput, - "The string to be decoded is not correctly encoded" - ); - } - let result = ""; - for (let i = 0; i < byteArray.length; i++) { - result += String.fromCharCode(byteArray[i]); - } - return result; -} - -/** Creates a base-64 ASCII string from the input string. */ -export function btoa(s: string): string { - const byteArray = []; - for (let i = 0; i < s.length; i++) { - const charCode = s[i].charCodeAt(0); - if (charCode > 0xff) { - throw new DenoError( - ErrorKind.InvalidInput, - "The string to be encoded contains characters " + - "outside of the Latin1 range." - ); - } - byteArray.push(charCode); - } - const result = base64.fromByteArray(Uint8Array.from(byteArray)); - return result; -} - -interface DecoderOptions { - fatal?: boolean; -} - -interface Decoder { - handler(stream: Stream, byte: number): number | null; -} - -interface Encoder { - handler(codePoint: number): number | number[]; -} - const CONTINUE = null; const END_OF_STREAM = -1; const FINISHED = -1; -// The encodingMap is a hash of labels that are indexed by the conical -// encoding. -const encodingMap: { [key: string]: string[] } = { - "windows-1252": [ - "ansi_x3.4-1968", - "ascii", - "cp1252", - "cp819", - "csisolatin1", - "ibm819", - "iso-8859-1", - "iso-ir-100", - "iso8859-1", - "iso88591", - "iso_8859-1", - "iso_8859-1:1987", - "l1", - "latin1", - "us-ascii", - "windows-1252", - "x-cp1252" - ], - "utf-8": ["unicode-1-1-utf-8", "utf-8", "utf8"] -}; -// We convert these into a Map where every label resolves to its canonical -// encoding type. -const encodings = new Map(); -for (const key of Object.keys(encodingMap)) { - const labels = encodingMap[key]; - for (const label of labels) { - encodings.set(label, key); - } -} - -// A map of functions that return new instances of a decoder indexed by the -// encoding type. -const decoders = new Map Decoder>(); -decoders.set("utf-8", (options: DecoderOptions) => { - return new UTF8Decoder(options); -}); - -// Single byte decoders are an array of code point lookups -const encodingIndexes = new Map(); -// 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); - }); -} - -function codePointsToString(codePoints: number[]): string { - let s = ""; - for (const cp of codePoints) { - s += String.fromCodePoint(cp); - } - return s; -} - function decoderError(fatal: boolean): number | never { if (fatal) { throw new TypeError("Decoder error."); @@ -152,11 +38,11 @@ function decoderError(fatal: boolean): number | never { return 0xfffd; // default code point } -function inRange(a: number, min: number, max: number) { +function inRange(a: number, min: number, max: number): boolean { return min <= a && a <= max; } -function isASCIIByte(a: number) { +function isASCIIByte(a: number): boolean { return inRange(a, 0x00, 0x7f); } @@ -168,67 +54,6 @@ function stringToCodePoints(input: string): number[] { return u; } -class Stream { - private _tokens: number[]; - constructor(tokens: number[] | Uint8Array) { - this._tokens = [].slice.call(tokens); - this._tokens.reverse(); - } - - endOfStream(): boolean { - return !this._tokens.length; - } - - read(): number { - return !this._tokens.length ? END_OF_STREAM : this._tokens.pop()!; - } - - prepend(token: number | number[]): void { - if (Array.isArray(token)) { - while (token.length) { - this._tokens.push(token.pop()!); - } - } else { - this._tokens.push(token); - } - } - - push(token: number | number[]): void { - if (Array.isArray(token)) { - while (token.length) { - this._tokens.unshift(token.shift()!); - } - } else { - this._tokens.unshift(token); - } - } -} - -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; @@ -349,6 +174,179 @@ class UTF8Encoder implements Encoder { } } +/** Decodes a string of data which has been encoded using base-64. */ +export function atob(s: string): string { + const rem = s.length % 4; + // base64-js requires length exactly times of 4 + if (rem > 0) { + s = s.padEnd(s.length + (4 - rem), "="); + } + let byteArray; + try { + byteArray = base64.toByteArray(s); + } catch (_) { + throw new DenoError( + ErrorKind.InvalidInput, + "The string to be decoded is not correctly encoded" + ); + } + let result = ""; + for (let i = 0; i < byteArray.length; i++) { + result += String.fromCharCode(byteArray[i]); + } + return result; +} + +/** Creates a base-64 ASCII string from the input string. */ +export function btoa(s: string): string { + const byteArray = []; + for (let i = 0; i < s.length; i++) { + const charCode = s[i].charCodeAt(0); + if (charCode > 0xff) { + throw new DenoError( + ErrorKind.InvalidInput, + "The string to be encoded contains characters " + + "outside of the Latin1 range." + ); + } + byteArray.push(charCode); + } + const result = base64.fromByteArray(Uint8Array.from(byteArray)); + return result; +} + +interface DecoderOptions { + fatal?: boolean; +} + +interface Decoder { + handler(stream: Stream, byte: number): number | null; +} + +interface Encoder { + handler(codePoint: number): number | number[]; +} + +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. +const encodingMap: { [key: string]: string[] } = { + "windows-1252": [ + "ansi_x3.4-1968", + "ascii", + "cp1252", + "cp819", + "csisolatin1", + "ibm819", + "iso-8859-1", + "iso-ir-100", + "iso8859-1", + "iso88591", + "iso_8859-1", + "iso_8859-1:1987", + "l1", + "latin1", + "us-ascii", + "windows-1252", + "x-cp1252" + ], + "utf-8": ["unicode-1-1-utf-8", "utf-8", "utf8"] +}; +// We convert these into a Map where every label resolves to its canonical +// encoding type. +const encodings = new Map(); +for (const key of Object.keys(encodingMap)) { + const labels = encodingMap[key]; + for (const label of labels) { + encodings.set(label, key); + } +} + +// A map of functions that return new instances of a decoder indexed by the +// encoding type. +const decoders = new Map Decoder>(); +decoders.set("utf-8", (options: DecoderOptions) => { + return new UTF8Decoder(options); +}); + +// Single byte decoders are an array of code point lookups +const encodingIndexes = new Map(); +// 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]); +for (const [key, index] of encodingIndexes) { + decoders.set(key, (options: DecoderOptions) => { + return new SingleByteDecoder(index, options); + }); +} + +function codePointsToString(codePoints: number[]): string { + let s = ""; + for (const cp of codePoints) { + s += String.fromCodePoint(cp); + } + return s; +} + +class Stream { + private _tokens: number[]; + constructor(tokens: number[] | Uint8Array) { + this._tokens = [].slice.call(tokens); + this._tokens.reverse(); + } + + endOfStream(): boolean { + return !this._tokens.length; + } + + read(): number { + return !this._tokens.length ? END_OF_STREAM : this._tokens.pop()!; + } + + prepend(token: number | number[]): void { + if (Array.isArray(token)) { + while (token.length) { + this._tokens.push(token.pop()!); + } + } else { + this._tokens.push(token); + } + } + + push(token: number | number[]): void { + if (Array.isArray(token)) { + while (token.length) { + this._tokens.unshift(token.shift()!); + } + } else { + this._tokens.unshift(token); + } + } +} + export interface TextDecodeOptions { stream?: false; } diff --git a/js/text_encoding_test.ts b/js/text_encoding_test.ts index f7939499a7..4eab248089 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 9e9c312ee9..d06056cf2a 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(); 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 d40c01376e..d1bce82a9f 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 { 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 329c5db1d6..2d700ab5df 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 { 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]; -} diff --git a/js/url.ts b/js/url.ts index 03c3606c41..235498c400 100644 --- a/js/url.ts +++ b/js/url.ts @@ -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 dec7ca869b..ac4ac01b1a 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 6f8c72f501..e6f38c8e17 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 { resolve: (value?: T | PromiseLike) => 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 1716f8ef62..b2f4231c45 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 { log("workerMain"); while (!isClosing) { diff --git a/js/write_file.ts b/js/write_file.ts index a75da2582a..8c5c7ac0a4 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 { 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]; -} diff --git a/package.json b/package.json index 2952b2028d..695c0d7d7e 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,11 @@ "@types/base64-js": "1.2.5", "@types/flatbuffers": "1.9.1", "@types/prettier": "1.16.1", + "@typescript-eslint/eslint-plugin": "1.4.2", + "@typescript-eslint/parser": "1.4.2", "base64-js": "1.3.0", + "eslint": "5.15.1", + "eslint-config-prettier": "4.1.0", "flatbuffers": "1.9.0", "magic-string": "0.25.2", "prettier": "1.16.4", @@ -20,9 +24,6 @@ "rollup-pluginutils": "2.4.1", "ts-morph": "1.3.0", "ts-node": "8.0.2", - "tslint": "^5.10.0", - "tslint-eslint-rules": "^5.3.1", - "tslint-no-circular-imports": "^0.5.0", "typescript": "3.2.2" } } diff --git a/tests/012_async.ts b/tests/012_async.ts index 57ae355c25..12df73b3ee 100644 --- a/tests/012_async.ts +++ b/tests/012_async.ts @@ -1,6 +1,6 @@ // Check that we can use the async keyword. -async function main() { - await new Promise((resolve, reject) => { +async function main(): Promise { + await new Promise(resolve => { console.log("2"); setTimeout(resolve, 100); }); diff --git a/tests/017_import_redirect.ts b/tests/017_import_redirect.ts index 22003e9dc5..1265dd4edc 100644 --- a/tests/017_import_redirect.ts +++ b/tests/017_import_redirect.ts @@ -1,5 +1,4 @@ // http -> https redirect would happen: -// tslint:disable-next-line:max-line-length import { printHello } from "http://gist.githubusercontent.com/ry/f12b2aa3409e6b52645bc346a9e22929/raw/79318f239f51d764384a8bded8d7c6a833610dde/print_hello.ts"; printHello(); diff --git a/tests/018_async_catch.ts b/tests/018_async_catch.ts index b073654d97..f59c22ee25 100644 --- a/tests/018_async_catch.ts +++ b/tests/018_async_catch.ts @@ -1,7 +1,7 @@ -async function fn() { +async function fn(): Promise { throw new Error("message"); } -async function call() { +async function call(): Promise { try { console.log("before await fn()"); await fn(); diff --git a/tests/019_media_types.ts b/tests/019_media_types.ts index 90eca80bfa..5f1f862a09 100644 --- a/tests/019_media_types.ts +++ b/tests/019_media_types.ts @@ -2,7 +2,6 @@ // based on the URL containing `.t#.` strings, which exercises the different // mapping of media types end to end. -// tslint:disable:max-line-length import { loaded as loadedTs1 } from "http://localhost:4545/tests/subdir/mt_text_typescript.t1.ts"; import { loaded as loadedTs2 } from "http://localhost:4545/tests/subdir/mt_video_vdn.t2.ts"; import { loaded as loadedTs3 } from "http://localhost:4545/tests/subdir/mt_video_mp2t.t3.ts"; diff --git a/tests/async_error.ts b/tests/async_error.ts index 7ce25d0cb6..81c983a504 100644 --- a/tests/async_error.ts +++ b/tests/async_error.ts @@ -1,5 +1,5 @@ console.log("hello"); -const foo = async () => { +const foo = async (): Promise => { console.log("before error"); throw Error("error"); }; diff --git a/tests/cat.ts b/tests/cat.ts index deb2be2f39..756238be61 100644 --- a/tests/cat.ts +++ b/tests/cat.ts @@ -1,6 +1,6 @@ const { stdout, open, copy, args } = Deno; -async function main() { +async function main(): Promise { for (let i = 1; i < args.length; i++) { const filename = args[i]; const file = await open(filename); diff --git a/tests/error_001.ts b/tests/error_001.ts index ab6e17a524..f06f80cb4c 100644 --- a/tests/error_001.ts +++ b/tests/error_001.ts @@ -1,8 +1,8 @@ -function foo() { +function foo(): never { throw Error("bad"); } -function bar() { +function bar(): void { foo(); } diff --git a/tests/error_002.ts b/tests/error_002.ts index 6aa0fcc3b6..eb66764b71 100644 --- a/tests/error_002.ts +++ b/tests/error_002.ts @@ -1,6 +1,6 @@ import { throwsError } from "./subdir/mod1.ts"; -function foo() { +function foo(): void { throwsError(); } diff --git a/tests/error_004_missing_module.ts b/tests/error_004_missing_module.ts index 48623320b6..e74d6b821f 100644 --- a/tests/error_004_missing_module.ts +++ b/tests/error_004_missing_module.ts @@ -1 +1,2 @@ +// eslint-disable-next-line import * as badModule from "bad-module.ts"; diff --git a/tests/error_005_missing_dynamic_import.ts b/tests/error_005_missing_dynamic_import.ts index 3cb081a276..437473b632 100644 --- a/tests/error_005_missing_dynamic_import.ts +++ b/tests/error_005_missing_dynamic_import.ts @@ -1,3 +1,4 @@ (async () => { + // eslint-disable-next-line const badModule = await import("bad-module.ts"); })(); diff --git a/tests/error_008_checkjs.js b/tests/error_008_checkjs.js index 08d4873c78..628d3e3761 100644 --- a/tests/error_008_checkjs.js +++ b/tests/error_008_checkjs.js @@ -2,5 +2,5 @@ consol.log("hello world!"); // the following error should be ignored and not output to the console -// @ts-ignore +// eslint-disable-next-line const foo = new Foo(); diff --git a/tests/fetch_deps.ts b/tests/fetch_deps.ts index 08743e36b2..530a562839 100644 --- a/tests/fetch_deps.ts +++ b/tests/fetch_deps.ts @@ -2,7 +2,7 @@ import { assert } from "../js/deps/https/deno.land/std/testing/asserts.ts"; // TODO Top level await https://github.com/denoland/deno/issues/471 -async function main() { +async function main(): Promise { const response = await fetch("http://localhost:4545/package.json"); const json = await response.json(); const deps = Object.keys(json.devDependencies); diff --git a/tests/https_import.ts b/tests/https_import.ts index 0a5cea3d1b..faaf2175f1 100644 --- a/tests/https_import.ts +++ b/tests/https_import.ts @@ -1,6 +1,5 @@ // TODO Use https://localhost:4555/ but we need more infrastructure to // support verifying self-signed certificates. -// tslint:disable-next-line:max-line-length import { printHello } from "https://gist.githubusercontent.com/ry/f12b2aa3409e6b52645bc346a9e22929/raw/79318f239f51d764384a8bded8d7c6a833610dde/print_hello.ts"; printHello(); diff --git a/third_party b/third_party index 1ba775b7b8..1d46f6634d 160000 --- a/third_party +++ b/third_party @@ -1 +1 @@ -Subproject commit 1ba775b7b8e555fdba7753ef91ac064b597dcbaf +Subproject commit 1d46f6634d7feb9889cf69c14e80803deaeaa68d diff --git a/tools/lint.py b/tools/lint.py index e3e7653874..4ce7900d1b 100755 --- a/tools/lint.py +++ b/tools/lint.py @@ -10,8 +10,8 @@ enable_ansi_colors() third_party_path = os.path.join(root_path, "third_party") cpplint = os.path.join(third_party_path, "cpplint", "cpplint.py") -tslint = os.path.join(third_party_path, "node_modules", "tslint", "bin", - "tslint") +eslint = os.path.join(third_party_path, "node_modules", "eslint", "bin", + "eslint") os.chdir(root_path) run([ @@ -19,10 +19,9 @@ run([ "--repository=libdeno", "--extensions=cc,h", "--recursive", "libdeno" ]) -run(["node", tslint, "-p", ".", "--exclude", "**/gen/**/*.ts"]) run([ - "node", tslint, "./js/**/*_test.ts", "./tests/**/*.ts", "./core/*.js", - "--exclude", "**/gen/**/*.ts", "--project", "tsconfig.json" + "node", eslint, "./js/**/*.{ts,js}", "./core/**/*.{ts,js}", + "./tests/**/*.{ts,js}" ]) run([sys.executable, "third_party/depot_tools/pylint.py"] + diff --git a/tools/ts_library_builder/build_library.ts b/tools/ts_library_builder/build_library.ts index 00f6fccf05..4b331ef02b 100644 --- a/tools/ts_library_builder/build_library.ts +++ b/tools/ts_library_builder/build_library.ts @@ -70,7 +70,6 @@ const { ModuleKind, ModuleResolutionKind, ScriptTarget } = ts; /** * A preamble which is appended to the start of the library. */ -// tslint:disable-next-line:max-line-length const libPreamble = `// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. /// diff --git a/tools/ts_library_builder/main.ts b/tools/ts_library_builder/main.ts index 1d1cf14cb5..ed692d03ab 100644 --- a/tools/ts_library_builder/main.ts +++ b/tools/ts_library_builder/main.ts @@ -12,7 +12,6 @@ let debug = false; let silent = false; process.argv.forEach((arg, i, argv) => { - // tslint:disable-next-line:switch-default switch (arg) { case "--basePath": basePath = path.resolve(argv[i + 1]); diff --git a/tools/ts_library_builder/testdata/globals.ts b/tools/ts_library_builder/testdata/globals.ts index 9d117c7948..c6c6f94760 100644 --- a/tools/ts_library_builder/testdata/globals.ts +++ b/tools/ts_library_builder/testdata/globals.ts @@ -2,7 +2,6 @@ import * as moduleC from "./moduleC"; import * as moduleD from "./moduleD"; import * as moduleE from "./moduleE"; -// tslint:disable-next-line:no-any const foobarbaz: any = {}; foobarbaz.bar = new moduleC.Bar(); foobarbaz.qat = moduleC.qat; diff --git a/tslint.json b/tslint.json deleted file mode 100644 index c2f13854f7..0000000000 --- a/tslint.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "rules": { - "array-type": [true, "array-simple"], - "arrow-return-shorthand": true, - "ban": [ - true, - ["fit"], - ["fdescribe"], - ["xit"], - ["xdescribe"], - ["fitAsync"], - ["xitAsync"], - ["fitFakeAsync"], - ["xitFakeAsync"] - ], - "ban-types": [ - true, - ["Object", "Use {} instead."], - ["String", "Use 'string' instead."], - ["Number", "Use 'number' instead."], - ["Boolean", "Use 'boolean' instead."] - ], - "class-name": true, - "curly": true, - "interface-name": [true, "never-prefix"], - "jsdoc-format": true, - "forin": false, - "label-position": true, - "max-line-length": [true, 80], - "new-parens": true, - "no-angle-bracket-type-assertion": true, - "no-any": true, - "no-construct": true, - "no-consecutive-blank-lines": true, - "no-debugger": true, - "no-default-export": true, - "no-inferrable-types": true, - "no-reference": true, - "no-require-imports": true, - "no-string-throw": true, - "no-unused-expression": true, - "no-var-keyword": true, - "object-literal-shorthand": true, - "only-arrow-functions": [ - true, - "allow-declarations", - "allow-named-functions" - ], - "prefer-const": true, - "quotemark": [true, "double"], - "radix": true, - "restrict-plus-operands": true, - "semicolon": [true, "always", "ignore-bound-class-methods"], - "switch-default": true, - "triple-equals": [true, "allow-null-check"], - "use-isnan": true, - "variable-name": [ - true, - "check-format", - "ban-keywords", - "allow-leading-underscore", - "allow-trailing-underscore" - ] - }, - "extends": ["tslint-no-circular-imports"] -}