0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

reorg: move JS ops implementations to cli/js/ops/, part 2 (#4283)

Following JS ops were moved to separate files in cli/js/ops directory:
- io
- process
- worker_host
- web_worker
- plugins
- timers
- signal
- permissions
This commit is contained in:
Bartek Iwańczuk 2020-03-09 15:18:02 +01:00 committed by GitHub
parent 1b6fc87b71
commit 886f330ec8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 287 additions and 194 deletions

View file

@ -33,15 +33,12 @@ export {
stdin,
stdout,
stderr,
read,
readSync,
write,
writeSync,
seek,
seekSync,
OpenOptions,
OpenMode
} from "./files.ts";
export { read, readSync, write, writeSync } from "./ops/io.ts";
export { FsEvent, fsEvents } from "./ops/fs_events.ts";
export {
EOF,
@ -101,14 +98,8 @@ export {
Permissions
} from "./permissions.ts";
export { openPlugin } from "./plugins.ts";
export {
kill,
run,
RunOptions,
Process,
ProcessStatus,
Signal
} from "./process.ts";
export { kill } from "./ops/process.ts";
export { run, RunOptions, Process, ProcessStatus, Signal } from "./process.ts";
export { readdirSync, readdir } from "./read_dir.ts";
export { readFileSync, readFile } from "./read_file.ts";
export { readlinkSync, readlink } from "./read_link.ts";

View file

@ -10,7 +10,7 @@ const readErrorStackPattern = new RegExp(
`^.*
at unwrapResponse \\(.*dispatch_minimal\\.ts:.*\\)
at Object.sendAsyncMinimal \\(.*dispatch_minimal\\.ts:.*\\)
at async Object\\.read \\(.*files\\.ts:.*\\).*$`,
at async Object\\.read \\(.*io\\.ts:.*\\).*$`,
"ms"
);

View file

@ -10,17 +10,12 @@ import {
SyncWriter,
SyncSeeker
} from "./io.ts";
import { sendAsyncMinimal, sendSyncMinimal } from "./ops/dispatch_minimal.ts";
import {
sendSync as sendSyncJson,
sendAsync as sendAsyncJson
} from "./ops/dispatch_json.ts";
import { close } from "./ops/resources.ts";
import { OPS_CACHE } from "./runtime.ts";
// This is done because read/write are extremely performance sensitive.
let OP_READ = -1;
let OP_WRITE = -1;
import { read, readSync, write, writeSync } from "./ops/io.ts";
/** Synchronously open a file and return an instance of the `File` object.
*
@ -118,100 +113,6 @@ export function create(path: string): Promise<File> {
return open(path, "w+");
}
/** Synchronously read from a file ID into an array buffer.
*
* Returns `number | EOF` for the operation.
*
* const file = Deno.openSync("/foo/bar.txt");
* const buf = new Uint8Array(100);
* const nread = Deno.readSync(file.rid, buf);
* const text = new TextDecoder().decode(buf);
*/
export function readSync(rid: number, p: Uint8Array): number | EOF {
if (p.length == 0) {
return 0;
}
if (OP_READ < 0) {
OP_READ = OPS_CACHE["op_read"];
}
const nread = sendSyncMinimal(OP_READ, rid, p);
if (nread < 0) {
throw new Error("read error");
} else if (nread == 0) {
return EOF;
} else {
return nread;
}
}
/** Read from a resource ID into an array buffer.
*
* Resolves to the `number | EOF` for the operation.
*
* const file = await Deno.open("/foo/bar.txt");
* const buf = new Uint8Array(100);
* const nread = await Deno.read(file.rid, buf);
* const text = new TextDecoder().decode(buf);
*/
export async function read(rid: number, p: Uint8Array): Promise<number | EOF> {
if (p.length == 0) {
return 0;
}
if (OP_READ < 0) {
OP_READ = OPS_CACHE["op_read"];
}
const nread = await sendAsyncMinimal(OP_READ, rid, p);
if (nread < 0) {
throw new Error("read error");
} else if (nread == 0) {
return EOF;
} else {
return nread;
}
}
/** Synchronously write to the resource ID the contents of the array buffer.
*
* Resolves to the number of bytes written.
*
* const encoder = new TextEncoder();
* const data = encoder.encode("Hello world\n");
* const file = Deno.openSync("/foo/bar.txt", {create: true, write: true});
* Deno.writeSync(file.rid, data);
*/
export function writeSync(rid: number, p: Uint8Array): number {
if (OP_WRITE < 0) {
OP_WRITE = OPS_CACHE["op_write"];
}
const result = sendSyncMinimal(OP_WRITE, rid, p);
if (result < 0) {
throw new Error("write error");
} else {
return result;
}
}
/** Write to the resource ID the contents of the array buffer.
*
* Resolves to the number of bytes written.
*
* const encoder = new TextEncoder();
* const data = encoder.encode("Hello world\n");
* const file = await Deno.open("/foo/bar.txt", {create: true, write: true});
* await Deno.write(file.rid, data);
*/
export async function write(rid: number, p: Uint8Array): Promise<number> {
if (OP_WRITE < 0) {
OP_WRITE = OPS_CACHE["op_write"];
}
const result = await sendAsyncMinimal(OP_WRITE, rid, p);
if (result < 0) {
throw new Error("write error");
} else {
return result;
}
}
/** Synchronously seek a file ID to the given offset under mode given by `whence`.
*
* Returns the number of cursor position.

View file

@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { EOF, Reader, Writer, Closer } from "./io.ts";
import { read, write } from "./files.ts";
import { read, write } from "./ops/io.ts";
import { close } from "./ops/resources.ts";
import { sendSync, sendAsync } from "./ops/dispatch_json.ts";

105
cli/js/ops/io.ts Normal file
View file

@ -0,0 +1,105 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendAsyncMinimal, sendSyncMinimal } from "./dispatch_minimal.ts";
import { EOF } from "../io.ts";
// TODO(bartlomieju): remove this import and maybe lazy-initialize
// OPS_CACHE that belongs only to this module
import { OPS_CACHE } from "../runtime.ts";
// This is done because read/write are extremely performance sensitive.
let OP_READ = -1;
let OP_WRITE = -1;
/** Synchronously read from a file ID into an array buffer.
*
* Returns `number | EOF` for the operation.
*
* const file = Deno.openSync("/foo/bar.txt");
* const buf = new Uint8Array(100);
* const nread = Deno.readSync(file.rid, buf);
* const text = new TextDecoder().decode(buf);
*/
export function readSync(rid: number, p: Uint8Array): number | EOF {
if (p.length == 0) {
return 0;
}
if (OP_READ < 0) {
OP_READ = OPS_CACHE["op_read"];
}
const nread = sendSyncMinimal(OP_READ, rid, p);
if (nread < 0) {
throw new Error("read error");
} else if (nread == 0) {
return EOF;
} else {
return nread;
}
}
/** Read from a resource ID into an array buffer.
*
* Resolves to the `number | EOF` for the operation.
*
* const file = await Deno.open("/foo/bar.txt");
* const buf = new Uint8Array(100);
* const nread = await Deno.read(file.rid, buf);
* const text = new TextDecoder().decode(buf);
*/
export async function read(rid: number, p: Uint8Array): Promise<number | EOF> {
if (p.length == 0) {
return 0;
}
if (OP_READ < 0) {
OP_READ = OPS_CACHE["op_read"];
}
const nread = await sendAsyncMinimal(OP_READ, rid, p);
if (nread < 0) {
throw new Error("read error");
} else if (nread == 0) {
return EOF;
} else {
return nread;
}
}
/** Synchronously write to the resource ID the contents of the array buffer.
*
* Resolves to the number of bytes written.
*
* const encoder = new TextEncoder();
* const data = encoder.encode("Hello world\n");
* const file = Deno.openSync("/foo/bar.txt", {create: true, write: true});
* Deno.writeSync(file.rid, data);
*/
export function writeSync(rid: number, p: Uint8Array): number {
if (OP_WRITE < 0) {
OP_WRITE = OPS_CACHE["op_write"];
}
const result = sendSyncMinimal(OP_WRITE, rid, p);
if (result < 0) {
throw new Error("write error");
} else {
return result;
}
}
/** Write to the resource ID the contents of the array buffer.
*
* Resolves to the number of bytes written.
*
* const encoder = new TextEncoder();
* const data = encoder.encode("Hello world\n");
* const file = await Deno.open("/foo/bar.txt", {create: true, write: true});
* await Deno.write(file.rid, data);
*/
export async function write(rid: number, p: Uint8Array): Promise<number> {
if (OP_WRITE < 0) {
OP_WRITE = OPS_CACHE["op_write"];
}
const result = await sendAsyncMinimal(OP_WRITE, rid, p);
if (result < 0) {
throw new Error("write error");
} else {
return result;
}
}

24
cli/js/ops/permissions.ts Normal file
View file

@ -0,0 +1,24 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync } from "./dispatch_json.ts";
// TODO(bartlomieju): duplicated in `cli/js/permissions.ts` as
// `PermissionState
export type PermissionResponse = "granted" | "denied" | "prompt";
interface PermissionRequest {
name: string;
url?: string;
path?: string;
}
export function query(desc: PermissionRequest): PermissionResponse {
return sendSync("op_query_permission", desc).state;
}
export function revoke(desc: PermissionRequest): PermissionResponse {
return sendSync("op_revoke_permission", desc).state;
}
export function request(desc: PermissionRequest): PermissionResponse {
return sendSync("op_request_permission", desc).state;
}

12
cli/js/ops/plugins.ts Normal file
View file

@ -0,0 +1,12 @@
import { sendSync } from "./dispatch_json.ts";
interface OpenPluginResponse {
rid: number;
ops: {
[name: string]: number;
};
}
export function openPlugin(filename: string): OpenPluginResponse {
return sendSync("op_open_plugin", { filename });
}

47
cli/js/ops/process.ts Normal file
View file

@ -0,0 +1,47 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./dispatch_json.ts";
import { assert } from "../util.ts";
/** Send a signal to process under given PID. Unix only at this moment.
* If pid is negative, the signal will be sent to the process group identified
* by -pid.
* Requires the `--allow-run` flag.
*/
export function kill(pid: number, signo: number): void {
sendSync("op_kill", { pid, signo });
}
interface RunStatusResponse {
gotSignal: boolean;
exitCode: number;
exitSignal: number;
}
export async function runStatus(rid: number): Promise<RunStatusResponse> {
return await sendAsync("op_run_status", { rid });
}
interface RunRequest {
args: string[];
cwd?: string;
env?: Array<[string, string]>;
stdin: string;
stdout: string;
stderr: string;
stdinRid: number;
stdoutRid: number;
stderrRid: number;
}
interface RunResponse {
rid: number;
pid: number;
stdinRid: number | null;
stdoutRid: number | null;
stderrRid: number | null;
}
export function run(request: RunRequest): RunResponse {
assert(request.args.length > 0);
return sendSync("op_run", request);
}

14
cli/js/ops/signal.ts Normal file
View file

@ -0,0 +1,14 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./dispatch_json.ts";
export function bindSignal(signo: number): { rid: number } {
return sendSync("op_signal_bind", { signo });
}
export async function pollSignal(rid: number): Promise<{ done: boolean }> {
return await sendAsync("op_signal_poll", { rid });
}
export function unbindSignal(rid: number): void {
sendSync("op_signal_unbind", { rid });
}

10
cli/js/ops/timers.ts Normal file
View file

@ -0,0 +1,10 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./dispatch_json.ts";
export function stopGlobalTimer(): void {
sendSync("op_global_timer_stop");
}
export async function startGlobalTimer(timeout: number): Promise<void> {
await sendAsync("op_global_timer", { timeout });
}

11
cli/js/ops/web_worker.ts Normal file
View file

@ -0,0 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync } from "./dispatch_json.ts";
export function postMessage(data: Uint8Array): void {
sendSync("op_worker_post_message", {}, data);
}
export function close(): void {
sendSync("op_worker_close");
}

29
cli/js/ops/worker_host.ts Normal file
View file

@ -0,0 +1,29 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
/* eslint-disable @typescript-eslint/no-explicit-any */
import { sendAsync, sendSync } from "./dispatch_json.ts";
export function createWorker(
specifier: string,
hasSourceCode: boolean,
sourceCode: string,
name?: string
): { id: number } {
return sendSync("op_create_worker", {
specifier,
hasSourceCode,
sourceCode,
name
});
}
export function hostTerminateWorker(id: number): void {
sendSync("op_host_terminate_worker", { id });
}
export function hostPostMessage(id: number, data: Uint8Array): void {
sendSync("op_host_post_message", { id }, data);
}
export async function hostGetMessage(id: number): Promise<any> {
return await sendAsync("op_host_get_message", { id });
}

View file

@ -1,5 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync } from "./ops/dispatch_json.ts";
import * as permissionsOps from "./ops/permissions.ts";
/** Permissions as granted by the caller
* See: https://w3c.github.io/permissions/#permission-registry
@ -60,7 +60,7 @@ export class Permissions {
* }
*/
async query(desc: PermissionDescriptor): Promise<PermissionStatus> {
const { state } = sendSync("op_query_permission", desc);
const state = permissionsOps.query(desc);
return new PermissionStatus(state);
}
@ -69,7 +69,7 @@ export class Permissions {
* assert(status.state !== "granted")
*/
async revoke(desc: PermissionDescriptor): Promise<PermissionStatus> {
const { state } = sendSync("op_revoke_permission", desc);
const state = permissionsOps.revoke(desc);
return new PermissionStatus(state);
}
@ -82,7 +82,7 @@ export class Permissions {
* }
*/
async request(desc: PermissionDescriptor): Promise<PermissionStatus> {
const { state } = sendSync("op_request_permission", desc);
const state = permissionsOps.request(desc);
return new PermissionStatus(state);
}
}

View file

@ -1,4 +1,4 @@
import { sendSync } from "./ops/dispatch_json.ts";
import { openPlugin as openPluginOp } from "./ops/plugins.ts";
import { core } from "./core.ts";
export interface AsyncHandler {
@ -50,16 +50,7 @@ class PluginImpl implements Plugin {
}
}
interface OpenPluginResponse {
rid: number;
ops: {
[name: string]: number;
};
}
export function openPlugin(filename: string): Plugin {
const response: OpenPluginResponse = sendSync("op_open_plugin", {
filename
});
const response = openPluginOp(filename);
return new PluginImpl(response.rid, response.ops);
}

View file

@ -1,11 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./ops/dispatch_json.ts";
import { File } from "./files.ts";
import { close } from "./ops/resources.ts";
import { ReadCloser, WriteCloser } from "./io.ts";
import { readAll } from "./buffer.ts";
import { assert, unreachable } from "./util.ts";
import { build } from "./build.ts";
import { kill, runStatus as runStatusOp, run as runOp } from "./ops/process.ts";
/** How to handle subprocess stdio.
*
@ -31,16 +31,8 @@ export interface RunOptions {
stdin?: ProcessStdio | number;
}
interface RunStatusResponse {
gotSignal: boolean;
exitCode: number;
exitSignal: number;
}
async function runStatus(rid: number): Promise<ProcessStatus> {
const res = (await sendAsync("op_run_status", {
rid
})) as RunStatusResponse;
const res = await runStatusOp(rid);
if (res.gotSignal) {
const signal = res.exitSignal;
@ -51,15 +43,6 @@ async function runStatus(rid: number): Promise<ProcessStatus> {
}
}
/** Send a signal to process under given PID. Unix only at this moment.
* If pid is negative, the signal will be sent to the process group identified
* by -pid.
* Requires the `--allow-run` flag.
*/
export function kill(pid: number, signo: number): void {
sendSync("op_kill", { pid, signo });
}
export class Process {
readonly rid: number;
readonly pid: number;
@ -220,7 +203,7 @@ export function run(opt: RunOptions): Process {
stderrRid
};
const res = sendSync("op_run", req) as RunResponse;
const res = runOp(req);
return new Process(res);
}

View file

@ -16,7 +16,7 @@ import {
windowOrWorkerGlobalScopeProperties,
eventTargetProperties
} from "./globals.ts";
import { sendSync } from "./ops/dispatch_json.ts";
import * as webWorkerOps from "./ops/web_worker.ts";
import { log } from "./util.ts";
import { TextEncoder } from "./web/text_encoding.ts";
import * as runtime from "./runtime.ts";
@ -31,7 +31,7 @@ export const onerror: (e: { data: any }) => void = (): void => {};
export function postMessage(data: any): void {
const dataJson = JSON.stringify(data);
const dataIntArray = encoder.encode(dataJson);
sendSync("op_worker_post_message", {}, dataIntArray);
webWorkerOps.postMessage(dataIntArray);
}
let isClosing = false;
@ -43,7 +43,7 @@ export function close(): void {
}
isClosing = true;
sendSync("op_worker_close");
webWorkerOps.close();
}
export async function workerMessageRecvCallback(data: string): Promise<void> {

View file

@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { Signal } from "./process.ts";
import { sendSync, sendAsync } from "./ops/dispatch_json.ts";
import { bindSignal, pollSignal, unbindSignal } from "./ops/signal.ts";
import { build } from "./build.ts";
/**
@ -105,16 +105,13 @@ export class SignalStream
/** The flag, which is true when the stream is disposed. */
private disposed = false;
constructor(signo: number) {
this.rid = sendSync("op_signal_bind", { signo }).rid;
this.rid = bindSignal(signo).rid;
this.loop();
}
private async pollSignal(): Promise<boolean> {
return (
await sendAsync("op_signal_poll", {
rid: this.rid
})
).done;
const res = await pollSignal(this.rid);
return res.done;
}
private async loop(): Promise<void> {
@ -143,6 +140,6 @@ export class SignalStream
throw new Error("The stream has already been disposed.");
}
this.disposed = true;
sendSync("op_signal_unbind", { rid: this.rid });
unbindSignal(this.rid);
}
}

View file

@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { assert } from "./util.ts";
import { sendSync, sendAsync } from "./ops/dispatch_json.ts";
import { startGlobalTimer, stopGlobalTimer } from "./ops/timers.ts";
import { RBTree } from "./rbtree.ts";
const { console } = globalThis;
@ -26,7 +26,7 @@ const dueTree = new RBTree<DueNode>((a, b) => a.due - b.due);
function clearGlobalTimeout(): void {
globalTimeoutDue = null;
sendSync("op_global_timer_stop");
stopGlobalTimer();
}
let pendingEvents = 0;
@ -51,7 +51,7 @@ async function setGlobalTimeout(due: number, now: number): Promise<void> {
// some timeout/defer is put in place to allow promise resolution.
// Ideally `clearGlobalTimeout` doesn't return until this op is resolved, but
// I'm not if that's possible.
await sendAsync("op_global_timer", { timeout });
await startGlobalTimer(timeout);
pendingEvents--;
// eslint-disable-next-line @typescript-eslint/no-use-before-define
fireTimers();

View file

@ -10,7 +10,7 @@ import { TextDecoder, TextEncoder } from "./text_encoding.ts";
import { DenoBlob, bytesSymbol as blobBytesSymbol } from "./blob.ts";
import { Headers } from "./headers.ts";
import * as io from "../io.ts";
import { read } from "../files.ts";
import { read } from "../ops/io.ts";
import { close } from "../ops/resources.ts";
import { Buffer } from "../buffer.ts";
import { FormData } from "./form_data.ts";

View file

@ -1,6 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
/* eslint-disable @typescript-eslint/no-explicit-any */
import { sendAsync, sendSync } from "./ops/dispatch_json.ts";
import {
createWorker,
hostTerminateWorker,
hostPostMessage,
hostGetMessage
} from "./ops/worker_host.ts";
import { log } from "./util.ts";
import { TextDecoder, TextEncoder } from "./web/text_encoding.ts";
/*
@ -23,39 +28,12 @@ function decodeMessage(dataIntArray: Uint8Array): any {
return JSON.parse(dataJson);
}
function createWorker(
specifier: string,
hasSourceCode: boolean,
sourceCode: Uint8Array,
name?: string
): { id: number } {
return sendSync("op_create_worker", {
specifier,
hasSourceCode,
sourceCode: new TextDecoder().decode(sourceCode),
name
});
}
function hostTerminateWorker(id: number): void {
sendSync("op_host_terminate_worker", { id });
}
function hostPostMessage(id: number, data: any): void {
const dataIntArray = encodeMessage(data);
sendSync("op_host_post_message", { id }, dataIntArray);
}
interface WorkerEvent {
event: "error" | "msg" | "close";
data?: any;
error?: any;
}
async function hostGetMessage(id: number): Promise<any> {
return await sendAsync("op_host_get_message", { id });
}
export interface Worker {
onerror?: (e: any) => void;
onmessage?: (e: { data: any }) => void;
@ -95,7 +73,7 @@ export class WorkerImpl extends EventTarget implements Worker {
this.name = options?.name ?? "unknown";
const hasSourceCode = false;
const sourceCode = new Uint8Array();
const sourceCode = decoder.decode(new Uint8Array());
/* TODO(bartlomieju):
// Handle blob URL.
@ -185,7 +163,7 @@ export class WorkerImpl extends EventTarget implements Worker {
return;
}
hostPostMessage(this.id, data);
hostPostMessage(this.id, encodeMessage(data));
}
terminate(): void {