diff options
author | Bartek Iwańczuk <biwanczuk@gmail.com> | 2020-03-08 13:09:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-08 13:09:22 +0100 |
commit | 1b6f8318750d319d689f7eeef9e7e1f2e56b94a6 (patch) | |
tree | b2e182b77cfbcd25ee893113de9f61509e16e787 /cli/js/ops | |
parent | b9037c86ed8d1d55a59a1c1298fa12bbfcae6873 (diff) |
reorg: move JS ops implementations to cli/js/ops/, part 1 (#4264)
Following JS ops were moved to separate files in cli/js/ops directory:
- compiler
- dispatch_json
- dispatch_minimal
- errors
- fetch
- fs_events
- os
- random
- repl
- resources
- runtime_compiler
- runtime
- tty
Diffstat (limited to 'cli/js/ops')
-rw-r--r-- | cli/js/ops/compiler.ts | 55 | ||||
-rw-r--r-- | cli/js/ops/dispatch_json.ts | 97 | ||||
-rw-r--r-- | cli/js/ops/dispatch_minimal.ts | 115 | ||||
-rw-r--r-- | cli/js/ops/errors.ts | 61 | ||||
-rw-r--r-- | cli/js/ops/fetch.ts | 28 | ||||
-rw-r--r-- | cli/js/ops/fs_events.ts | 39 | ||||
-rw-r--r-- | cli/js/ops/get_random_values.ts | 30 | ||||
-rw-r--r-- | cli/js/ops/os.ts | 227 | ||||
-rw-r--r-- | cli/js/ops/repl.ts | 11 | ||||
-rw-r--r-- | cli/js/ops/resources.ts | 23 | ||||
-rw-r--r-- | cli/js/ops/runtime.ts | 67 | ||||
-rw-r--r-- | cli/js/ops/runtime_compiler.ts | 23 | ||||
-rw-r--r-- | cli/js/ops/tty.ts | 14 |
13 files changed, 790 insertions, 0 deletions
diff --git a/cli/js/ops/compiler.ts b/cli/js/ops/compiler.ts new file mode 100644 index 000000000..b45ad42b2 --- /dev/null +++ b/cli/js/ops/compiler.ts @@ -0,0 +1,55 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +import { sendAsync, sendSync } from "./dispatch_json.ts"; +import { TextDecoder, TextEncoder } from "../web/text_encoding.ts"; +import { core } from "../core.ts"; + +/** Ops to Rust to resolve modules' URLs. */ +export function resolveModules( + specifiers: string[], + referrer?: string +): string[] { + return sendSync("op_resolve_modules", { specifiers, referrer }); +} + +/** Ops to Rust to fetch modules meta data. */ +export function fetchSourceFiles( + specifiers: string[], + referrer?: string +): Promise< + Array<{ + url: string; + filename: string; + mediaType: number; + sourceCode: string; + }> +> { + return sendAsync("op_fetch_source_files", { + specifiers, + referrer + }); +} + +const encoder = new TextEncoder(); +const decoder = new TextDecoder(); + +/** This op is also used during snapshotting */ +export function getAsset(name: string): string { + const opId = core.ops()["op_fetch_asset"]; + // We really don't want to depend on JSON dispatch during snapshotting, so + // this op exchanges strings with Rust as raw byte arrays. + const sourceCodeBytes = core.dispatch(opId, encoder.encode(name)); + return decoder.decode(sourceCodeBytes!); +} + +export function cache( + extension: string, + moduleId: string, + contents: string +): void { + sendSync("op_cache", { + extension, + moduleId, + contents + }); +} diff --git a/cli/js/ops/dispatch_json.ts b/cli/js/ops/dispatch_json.ts new file mode 100644 index 000000000..6fb9007df --- /dev/null +++ b/cli/js/ops/dispatch_json.ts @@ -0,0 +1,97 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import * as util from "../util.ts"; +import { TextEncoder, TextDecoder } from "../web/text_encoding.ts"; +import { core } from "../core.ts"; +import { OPS_CACHE } from "../runtime.ts"; +import { ErrorKind, getErrorClass } from "../errors.ts"; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type Ok = any; + +interface JsonError { + kind: ErrorKind; + message: string; +} + +interface JsonResponse { + ok?: Ok; + err?: JsonError; + promiseId?: number; // Only present in async messages. +} + +const promiseTable = new Map<number, util.Resolvable<JsonResponse>>(); +let _nextPromiseId = 1; + +function nextPromiseId(): number { + return _nextPromiseId++; +} + +function decode(ui8: Uint8Array): JsonResponse { + const s = new TextDecoder().decode(ui8); + return JSON.parse(s) as JsonResponse; +} + +function encode(args: object): Uint8Array { + const s = JSON.stringify(args); + return new TextEncoder().encode(s); +} + +function unwrapResponse(res: JsonResponse): Ok { + if (res.err != null) { + throw new (getErrorClass(res.err.kind))(res.err.message); + } + util.assert(res.ok != null); + return res.ok; +} + +export function asyncMsgFromRust(resUi8: Uint8Array): void { + const res = decode(resUi8); + util.assert(res.promiseId != null); + + const promise = promiseTable.get(res.promiseId!); + util.assert(promise != null); + promiseTable.delete(res.promiseId!); + promise.resolve(res); +} + +export function sendSync( + opName: string, + args: object = {}, + zeroCopy?: Uint8Array +): Ok { + const opId = OPS_CACHE[opName]; + util.log("sendSync", opName, opId); + const argsUi8 = encode(args); + const resUi8 = core.dispatch(opId, argsUi8, zeroCopy); + util.assert(resUi8 != null); + + const res = decode(resUi8); + util.assert(res.promiseId == null); + return unwrapResponse(res); +} + +export async function sendAsync( + opName: string, + args: object = {}, + zeroCopy?: Uint8Array +): Promise<Ok> { + const opId = OPS_CACHE[opName]; + util.log("sendAsync", opName, opId); + const promiseId = nextPromiseId(); + args = Object.assign(args, { promiseId }); + const promise = util.createResolvable<Ok>(); + + const argsUi8 = encode(args); + const buf = core.dispatch(opId, argsUi8, zeroCopy); + if (buf) { + // Sync result. + const res = decode(buf); + promise.resolve(res); + } else { + // Async result. + promiseTable.set(promiseId, promise); + } + + const res = await promise; + return unwrapResponse(res); +} diff --git a/cli/js/ops/dispatch_minimal.ts b/cli/js/ops/dispatch_minimal.ts new file mode 100644 index 000000000..7aec4683c --- /dev/null +++ b/cli/js/ops/dispatch_minimal.ts @@ -0,0 +1,115 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import * as util from "../util.ts"; +import { core } from "../core.ts"; +import { TextDecoder } from "../web/text_encoding.ts"; +import { ErrorKind, errors, getErrorClass } from "../errors.ts"; + +const promiseTableMin = new Map<number, util.Resolvable<RecordMinimal>>(); +// Note it's important that promiseId starts at 1 instead of 0, because sync +// messages are indicated with promiseId 0. If we ever add wrap around logic for +// overflows, this should be taken into account. +let _nextPromiseId = 1; + +const decoder = new TextDecoder(); + +function nextPromiseId(): number { + return _nextPromiseId++; +} + +export interface RecordMinimal { + promiseId: number; + arg: number; + result: number; + err?: { + kind: ErrorKind; + message: string; + }; +} + +export function recordFromBufMinimal(ui8: Uint8Array): RecordMinimal { + const header = ui8.subarray(0, 12); + const buf32 = new Int32Array( + header.buffer, + header.byteOffset, + header.byteLength / 4 + ); + const promiseId = buf32[0]; + const arg = buf32[1]; + const result = buf32[2]; + let err; + + if (arg < 0) { + const kind = result as ErrorKind; + const message = decoder.decode(ui8.subarray(12)); + err = { kind, message }; + } else if (ui8.length != 12) { + throw new errors.InvalidData("BadMessage"); + } + + return { + promiseId, + arg, + result, + err + }; +} + +function unwrapResponse(res: RecordMinimal): number { + if (res.err != null) { + throw new (getErrorClass(res.err.kind))(res.err.message); + } + return res.result; +} + +const scratch32 = new Int32Array(3); +const scratchBytes = new Uint8Array( + scratch32.buffer, + scratch32.byteOffset, + scratch32.byteLength +); +util.assert(scratchBytes.byteLength === scratch32.length * 4); + +export function asyncMsgFromRust(ui8: Uint8Array): void { + const record = recordFromBufMinimal(ui8); + const { promiseId } = record; + const promise = promiseTableMin.get(promiseId); + promiseTableMin.delete(promiseId); + util.assert(promise); + promise.resolve(record); +} + +export async function sendAsyncMinimal( + opId: number, + arg: number, + zeroCopy: Uint8Array +): Promise<number> { + const promiseId = nextPromiseId(); // AKA cmdId + scratch32[0] = promiseId; + scratch32[1] = arg; + scratch32[2] = 0; // result + const promise = util.createResolvable<RecordMinimal>(); + const buf = core.dispatch(opId, scratchBytes, zeroCopy); + if (buf) { + const record = recordFromBufMinimal(buf); + // Sync result. + promise.resolve(record); + } else { + // Async result. + promiseTableMin.set(promiseId, promise); + } + + const res = await promise; + return unwrapResponse(res); +} + +export function sendSyncMinimal( + opId: number, + arg: number, + zeroCopy: Uint8Array +): number { + scratch32[0] = 0; // promiseId 0 indicates sync + scratch32[1] = arg; + const res = core.dispatch(opId, scratchBytes, zeroCopy)!; + const resRecord = recordFromBufMinimal(res); + return unwrapResponse(resRecord); +} diff --git a/cli/js/ops/errors.ts b/cli/js/ops/errors.ts new file mode 100644 index 000000000..f96e376d6 --- /dev/null +++ b/cli/js/ops/errors.ts @@ -0,0 +1,61 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import { DiagnosticItem } from "../diagnostics.ts"; +import { sendSync } from "./dispatch_json.ts"; + +/** + * Format an array of diagnostic items and return them as a single string. + * @param items An array of diagnostic items to format + */ +export function formatDiagnostics(items: DiagnosticItem[]): string { + return sendSync("op_format_diagnostic", { items }); +} + +export interface Location { + /** The full url for the module, e.g. `file://some/file.ts` or + * `https://some/file.ts`. */ + filename: string; + + /** The line number in the file. It is assumed to be 1-indexed. */ + line: number; + + /** The column number in the file. It is assumed to be 1-indexed. */ + column: number; +} + +/** Given a current location in a module, lookup the source location and + * return it. + * + * When Deno transpiles code, it keep source maps of the transpiled code. This + * function can be used to lookup the original location. This is automatically + * done when accessing the `.stack` of an error, or when an uncaught error is + * logged. This function can be used to perform the lookup for creating better + * error handling. + * + * **Note:** `line` and `column` are 1 indexed, which matches display + * expectations, but is not typical of most index numbers in Deno. + * + * An example: + * + * const orig = Deno.applySourceMap({ + * location: "file://my/module.ts", + * line: 5, + * column: 15 + * }); + * console.log(`${orig.filename}:${orig.line}:${orig.column}`); + * + */ +export function applySourceMap(location: Location): Location { + const { filename, line, column } = location; + // On this side, line/column are 1 based, but in the source maps, they are + // 0 based, so we have to convert back and forth + const res = sendSync("op_apply_source_map", { + filename, + line: line - 1, + column: column - 1 + }); + return { + filename: res.filename, + line: res.line + 1, + column: res.column + 1 + }; +} diff --git a/cli/js/ops/fetch.ts b/cli/js/ops/fetch.ts new file mode 100644 index 000000000..c5c0cb883 --- /dev/null +++ b/cli/js/ops/fetch.ts @@ -0,0 +1,28 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +import { sendAsync } from "./dispatch_json.ts"; + +interface FetchRequest { + url: string; + method: string | null; + headers: Array<[string, string]>; +} + +export interface FetchResponse { + bodyRid: number; + status: number; + statusText: string; + headers: Array<[string, string]>; +} + +export async function fetch( + args: FetchRequest, + body: ArrayBufferView | undefined +): Promise<FetchResponse> { + let zeroCopy = undefined; + if (body) { + zeroCopy = new Uint8Array(body.buffer, body.byteOffset, body.byteLength); + } + + return await sendAsync("op_fetch", args, zeroCopy); +} diff --git a/cli/js/ops/fs_events.ts b/cli/js/ops/fs_events.ts new file mode 100644 index 000000000..09e82c515 --- /dev/null +++ b/cli/js/ops/fs_events.ts @@ -0,0 +1,39 @@ +// Copyright 2019 the Deno authors. All rights reserved. MIT license. +import { sendSync, sendAsync } from "./dispatch_json.ts"; +import { close } from "./resources.ts"; + +export interface FsEvent { + kind: "any" | "access" | "create" | "modify" | "remove"; + paths: string[]; +} + +class FsEvents implements AsyncIterableIterator<FsEvent> { + readonly rid: number; + + constructor(paths: string[], options: { recursive: boolean }) { + const { recursive } = options; + this.rid = sendSync("op_fs_events_open", { recursive, paths }); + } + + async next(): Promise<IteratorResult<FsEvent>> { + return await sendAsync("op_fs_events_poll", { + rid: this.rid + }); + } + + async return(value?: FsEvent): Promise<IteratorResult<FsEvent>> { + close(this.rid); + return { value, done: true }; + } + + [Symbol.asyncIterator](): AsyncIterableIterator<FsEvent> { + return this; + } +} + +export function fsEvents( + paths: string | string[], + options = { recursive: true } +): AsyncIterableIterator<FsEvent> { + return new FsEvents(Array.isArray(paths) ? paths : [paths], options); +} diff --git a/cli/js/ops/get_random_values.ts b/cli/js/ops/get_random_values.ts new file mode 100644 index 000000000..0e384c259 --- /dev/null +++ b/cli/js/ops/get_random_values.ts @@ -0,0 +1,30 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import { sendSync } from "./dispatch_json.ts"; +import { assert } from "../util.ts"; + +/** Synchronously collects cryptographically secure random values. The + * underlying CSPRNG in use is Rust's `rand::rngs::ThreadRng`. + * + * const arr = new Uint8Array(32); + * crypto.getRandomValues(arr); + */ +export function getRandomValues< + T extends + | Int8Array + | Uint8Array + | Uint8ClampedArray + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array +>(typedArray: T): T { + assert(typedArray !== null, "Input must not be null"); + assert(typedArray.length <= 65536, "Input must not be longer than 65536"); + const ui8 = new Uint8Array( + typedArray.buffer, + typedArray.byteOffset, + typedArray.byteLength + ); + sendSync("op_get_random_values", {}, ui8); + return typedArray; +} diff --git a/cli/js/ops/os.ts b/cli/js/ops/os.ts new file mode 100644 index 000000000..2d27f7ef5 --- /dev/null +++ b/cli/js/ops/os.ts @@ -0,0 +1,227 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import { sendSync } from "./dispatch_json.ts"; +import { errors } from "../errors.ts"; +import * as util from "../util.ts"; + +/** Get the loadavg. + * Requires the `--allow-env` flag. + * + * console.log(Deno.loadavg()); + */ +export function loadavg(): number[] { + return sendSync("op_loadavg"); +} + +/** Get the hostname. + * Requires the `--allow-env` flag. + * + * console.log(Deno.hostname()); + */ +export function hostname(): string { + return sendSync("op_hostname"); +} + +/** Get OS release. + * Requires the `--allow-env` flag. + * + * console.log(Deno.osRelease()); + */ +export function osRelease(): string { + return sendSync("op_os_release"); +} + +/** Exit the Deno process with optional exit code. */ +export function exit(code = 0): never { + sendSync("op_exit", { code }); + return util.unreachable(); +} + +function setEnv(key: string, value: string): void { + sendSync("op_set_env", { key, value }); +} + +function getEnv(key: string): string | undefined { + return sendSync("op_get_env", { key })[0]; +} + +/** 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 + * as values. + * + * console.log(Deno.env("SHELL")); + * const myEnv = Deno.env(); + * console.log(myEnv.SHELL); + * myEnv.TEST_VAR = "HELLO"; + * const newEnv = Deno.env(); + * console.log(myEnv.TEST_VAR == newEnv.TEST_VAR); + */ +export function env(): { [index: string]: string }; +export function env(key: string): string | undefined; +export function env( + key?: string +): { [index: string]: string } | string | undefined { + if (key) { + return getEnv(key); + } + const env = sendSync("op_env"); + return new Proxy(env, { + set(obj, prop: string, value: string): boolean { + setEnv(prop, value); + return Reflect.set(obj, prop, value); + } + }); +} + +type DirKind = + | "home" + | "cache" + | "config" + | "executable" + | "data" + | "data_local" + | "audio" + | "desktop" + | "document" + | "download" + | "font" + | "picture" + | "public" + | "template" + | "tmp" + | "video"; + +/** + * Returns the user and platform specific directories. + * Requires the `--allow-env` flag. + * Returns null if there is no applicable directory or if any other error + * occurs. + * + * Argument values: "home", "cache", "config", "executable", "data", + * "data_local", "audio", "desktop", "document", "download", "font", "picture", + * "public", "template", "video" + * + * "cache" + * |Platform | Value | Example | + * | ------- | ----------------------------------- | ---------------------------- | + * | Linux | `$XDG_CACHE_HOME` or `$HOME`/.cache | /home/alice/.cache | + * | macOS | `$HOME`/Library/Caches | /Users/Alice/Library/Caches | + * | Windows | `{FOLDERID_LocalAppData}` | C:\Users\Alice\AppData\Local | + * + * "config" + * |Platform | Value | Example | + * | ------- | ------------------------------------- | -------------------------------- | + * | Linux | `$XDG_CONFIG_HOME` or `$HOME`/.config | /home/alice/.config | + * | macOS | `$HOME`/Library/Preferences | /Users/Alice/Library/Preferences | + * | Windows | `{FOLDERID_RoamingAppData}` | C:\Users\Alice\AppData\Roaming | + * + * "executable" + * |Platform | Value | Example | + * | ------- | --------------------------------------------------------------- | -----------------------| + * | Linux | `XDG_BIN_HOME` or `$XDG_DATA_HOME`/../bin or `$HOME`/.local/bin | /home/alice/.local/bin | + * | macOS | - | - | + * | Windows | - | - | + * + * "data" + * |Platform | Value | Example | + * | ------- | ---------------------------------------- | ---------------------------------------- | + * | Linux | `$XDG_DATA_HOME` or `$HOME`/.local/share | /home/alice/.local/share | + * | macOS | `$HOME`/Library/Application Support | /Users/Alice/Library/Application Support | + * | Windows | `{FOLDERID_RoamingAppData}` | C:\Users\Alice\AppData\Roaming | + * + * "data_local" + * |Platform | Value | Example | + * | ------- | ---------------------------------------- | ---------------------------------------- | + * | Linux | `$XDG_DATA_HOME` or `$HOME`/.local/share | /home/alice/.local/share | + * | macOS | `$HOME`/Library/Application Support | /Users/Alice/Library/Application Support | + * | Windows | `{FOLDERID_LocalAppData}` | C:\Users\Alice\AppData\Local | + * + * "audio" + * |Platform | Value | Example | + * | ------- | ------------------ | -------------------- | + * | Linux | `XDG_MUSIC_DIR` | /home/alice/Music | + * | macOS | `$HOME`/Music | /Users/Alice/Music | + * | Windows | `{FOLDERID_Music}` | C:\Users\Alice\Music | + * + * "desktop" + * |Platform | Value | Example | + * | ------- | -------------------- | ---------------------- | + * | Linux | `XDG_DESKTOP_DIR` | /home/alice/Desktop | + * | macOS | `$HOME`/Desktop | /Users/Alice/Desktop | + * | Windows | `{FOLDERID_Desktop}` | C:\Users\Alice\Desktop | + * + * "document" + * |Platform | Value | Example | + * | ------- | ---------------------- | ------------------------ | + * | Linux | `XDG_DOCUMENTS_DIR` | /home/alice/Documents | + * | macOS | `$HOME`/Documents | /Users/Alice/Documents | + * | Windows | `{FOLDERID_Documents}` | C:\Users\Alice\Documents | + * + * "download" + * |Platform | Value | Example | + * | ------- | ---------------------- | ------------------------ | + * | Linux | `XDG_DOWNLOAD_DIR` | /home/alice/Downloads | + * | macOS | `$HOME`/Downloads | /Users/Alice/Downloads | + * | Windows | `{FOLDERID_Downloads}` | C:\Users\Alice\Downloads | + * + * "font" + * |Platform | Value | Example | + * | ------- | ---------------------------------------------------- | ------------------------------ | + * | Linux | `$XDG_DATA_HOME`/fonts or `$HOME`/.local/share/fonts | /home/alice/.local/share/fonts | + * | macOS | `$HOME/Library/Fonts` | /Users/Alice/Library/Fonts | + * | Windows | – | – | + * + * "picture" + * |Platform | Value | Example | + * | ------- | --------------------- | ----------------------- | + * | Linux | `XDG_PICTURES_DIR` | /home/alice/Pictures | + * | macOS | `$HOME`/Pictures | /Users/Alice/Pictures | + * | Windows | `{FOLDERID_Pictures}` | C:\Users\Alice\Pictures | + * + * "public" + * |Platform | Value | Example | + * | ------- | --------------------- | ------------------- | + * | Linux | `XDG_PUBLICSHARE_DIR` | /home/alice/Public | + * | macOS | `$HOME`/Public | /Users/Alice/Public | + * | Windows | `{FOLDERID_Public}` | C:\Users\Public | + * + * "template" + * |Platform | Value | Example | + * | ------- | ---------------------- | ---------------------------------------------------------- | + * | Linux | `XDG_TEMPLATES_DIR` | /home/alice/Templates | + * | macOS | – | – | + * | Windows | `{FOLDERID_Templates}` | C:\Users\Alice\AppData\Roaming\Microsoft\Windows\Templates | + * + * "tmp" + * + * |Platform | Value | Example | + * | ------- | ---------------------- | ---------------------------------------------------------- | + * | Linux | `TMPDIR` | /tmp | + * | macOS | `TMPDIR` | /tmp | + * | Windows | `{TMP}` | C:\Users\Alice\AppData\Local\Temp | + * + * "video" + * |Platform | Value | Example | + * | ------- | ------------------- | --------------------- | + * | Linux | `XDG_VIDEOS_DIR` | /home/alice/Videos | + * | macOS | `$HOME`/Movies | /Users/Alice/Movies | + * | Windows | `{FOLDERID_Videos}` | C:\Users\Alice\Videos | + */ +export function dir(kind: DirKind): string | null { + try { + return sendSync("op_get_dir", { kind }); + } catch (error) { + if (error instanceof errors.PermissionDenied) { + throw error; + } + return null; + } +} + +/** + * Returns the path to the current deno executable. + * Requires the `--allow-env` flag. + */ +export function execPath(): string { + return sendSync("op_exec_path"); +} diff --git a/cli/js/ops/repl.ts b/cli/js/ops/repl.ts new file mode 100644 index 000000000..3f40f4456 --- /dev/null +++ b/cli/js/ops/repl.ts @@ -0,0 +1,11 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +import { sendSync, sendAsync } from "./dispatch_json.ts"; + +export function startRepl(historyFile: string): number { + return sendSync("op_repl_start", { historyFile }); +} + +export async function readline(rid: number, prompt: string): Promise<string> { + return sendAsync("op_repl_readline", { rid, prompt }); +} diff --git a/cli/js/ops/resources.ts b/cli/js/ops/resources.ts new file mode 100644 index 000000000..b04810989 --- /dev/null +++ b/cli/js/ops/resources.ts @@ -0,0 +1,23 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import { sendSync } from "./dispatch_json.ts"; + +export interface ResourceMap { + [rid: number]: string; +} + +/** Returns a map of open _file like_ resource ids along with their string + * representation. + */ +export function resources(): ResourceMap { + const res = sendSync("op_resources") as Array<[number, string]>; + const resources: ResourceMap = {}; + for (const resourceTuple of res) { + resources[resourceTuple[0]] = resourceTuple[1]; + } + return resources; +} + +/** Close the given resource ID. */ +export function close(rid: number): void { + sendSync("op_close", { rid }); +} diff --git a/cli/js/ops/runtime.ts b/cli/js/ops/runtime.ts new file mode 100644 index 000000000..7538ce12f --- /dev/null +++ b/cli/js/ops/runtime.ts @@ -0,0 +1,67 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +import { sendSync } from "./dispatch_json.ts"; + +// TODO(bartlomieju): these two types are duplicated +// in `cli/js/build.ts` - deduplicate +export type OperatingSystem = "mac" | "win" | "linux"; +export type Arch = "x64" | "arm64"; + +export interface Start { + cwd: string; + pid: number; + args: string[]; + location: string; // Absolute URL. + repl: boolean; + debugFlag: boolean; + depsFlag: boolean; + typesFlag: boolean; + versionFlag: boolean; + denoVersion: string; + v8Version: string; + tsVersion: string; + noColor: boolean; + os: OperatingSystem; + arch: Arch; +} + +export function start(): Start { + return sendSync("op_start"); +} + +export interface Metrics { + opsDispatched: number; + opsDispatchedSync: number; + opsDispatchedAsync: number; + opsDispatchedAsyncUnref: number; + opsCompleted: number; + opsCompletedSync: number; + opsCompletedAsync: number; + opsCompletedAsyncUnref: number; + bytesSentControl: number; + bytesSentData: number; + bytesReceived: number; +} + +/** Receive metrics from the privileged side of Deno. + * + * > console.table(Deno.metrics()) + * ┌─────────────────────────┬────────┐ + * │ (index) │ Values │ + * ├─────────────────────────┼────────┤ + * │ opsDispatched │ 3 │ + * │ opsDispatchedSync │ 2 │ + * │ opsDispatchedAsync │ 1 │ + * │ opsDispatchedAsyncUnref │ 0 │ + * │ opsCompleted │ 3 │ + * │ opsCompletedSync │ 2 │ + * │ opsCompletedAsync │ 1 │ + * │ opsCompletedAsyncUnref │ 0 │ + * │ bytesSentControl │ 73 │ + * │ bytesSentData │ 0 │ + * │ bytesReceived │ 375 │ + * └─────────────────────────┴────────┘ + */ +export function metrics(): Metrics { + return sendSync("op_metrics"); +} diff --git a/cli/js/ops/runtime_compiler.ts b/cli/js/ops/runtime_compiler.ts new file mode 100644 index 000000000..035a4ef59 --- /dev/null +++ b/cli/js/ops/runtime_compiler.ts @@ -0,0 +1,23 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +import { sendAsync } from "./dispatch_json.ts"; + +interface CompileRequest { + rootName: string; + sources?: Record<string, string>; + options?: string; + bundle: boolean; +} + +export async function compile(request: CompileRequest): Promise<string> { + return sendAsync("op_compile", request); +} + +interface TranspileRequest { + sources: Record<string, string>; + options?: string; +} + +export async function transpile(request: TranspileRequest): Promise<string> { + return sendAsync("op_transpile", request); +} diff --git a/cli/js/ops/tty.ts b/cli/js/ops/tty.ts new file mode 100644 index 000000000..2ad44d025 --- /dev/null +++ b/cli/js/ops/tty.ts @@ -0,0 +1,14 @@ +import { sendSync } from "./dispatch_json.ts"; + +/** Check if a given resource is TTY. */ +export function isatty(rid: number): boolean { + return sendSync("op_isatty", { rid }); +} + +/** Set TTY to be under raw mode or not. */ +export function setRaw(rid: number, mode: boolean): void { + sendSync("op_set_raw", { + rid, + mode + }); +} |