mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 12:19:12 +00:00
reorg: cli/js/compiler/, move more API to cli/js/web/ (#4310)
- moves compiler implementation to "cli/js/compiler/" directory - moves more APIs to "cli/js/web": * "console.ts" * "console_table.ts" * "performance.ts" * "timers.ts" * "workers.ts" - removes some dead code from "cli/js/"
This commit is contained in:
parent
94f4c6807a
commit
99a0c6df79
28 changed files with 83 additions and 89 deletions
170
cli/js/web/workers.ts
Normal file
170
cli/js/web/workers.ts
Normal file
|
@ -0,0 +1,170 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
createWorker,
|
||||
hostTerminateWorker,
|
||||
hostPostMessage,
|
||||
hostGetMessage
|
||||
} from "../ops/worker_host.ts";
|
||||
import { log } from "../util.ts";
|
||||
import { TextDecoder, TextEncoder } from "./text_encoding.ts";
|
||||
/*
|
||||
import { blobURLMap } from "./web/url.ts";
|
||||
import { blobBytesWeakMap } from "./web/blob.ts";
|
||||
*/
|
||||
import { Event } from "./event.ts";
|
||||
import { EventTarget } from "./event_target.ts";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
function encodeMessage(data: any): Uint8Array {
|
||||
const dataJson = JSON.stringify(data);
|
||||
return encoder.encode(dataJson);
|
||||
}
|
||||
|
||||
function decodeMessage(dataIntArray: Uint8Array): any {
|
||||
const dataJson = decoder.decode(dataIntArray);
|
||||
return JSON.parse(dataJson);
|
||||
}
|
||||
|
||||
interface WorkerEvent {
|
||||
event: "error" | "msg" | "close";
|
||||
data?: any;
|
||||
error?: any;
|
||||
}
|
||||
|
||||
export interface Worker {
|
||||
onerror?: (e: any) => void;
|
||||
onmessage?: (e: { data: any }) => void;
|
||||
onmessageerror?: () => void;
|
||||
postMessage(data: any): void;
|
||||
terminate(): void;
|
||||
}
|
||||
|
||||
export interface WorkerOptions {
|
||||
type?: "classic" | "module";
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export class WorkerImpl extends EventTarget implements Worker {
|
||||
private readonly id: number;
|
||||
private isClosing = false;
|
||||
public onerror?: (e: any) => void;
|
||||
public onmessage?: (data: any) => void;
|
||||
public onmessageerror?: () => void;
|
||||
private name: string;
|
||||
private terminated = false;
|
||||
|
||||
constructor(specifier: string, options?: WorkerOptions) {
|
||||
super();
|
||||
const { type = "classic", name = "unknown" } = options ?? {};
|
||||
|
||||
if (type !== "module") {
|
||||
throw new Error(
|
||||
'Not yet implemented: only "module" type workers are supported'
|
||||
);
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
const hasSourceCode = false;
|
||||
const sourceCode = decoder.decode(new Uint8Array());
|
||||
|
||||
/* TODO(bartlomieju):
|
||||
// Handle blob URL.
|
||||
if (specifier.startsWith("blob:")) {
|
||||
hasSourceCode = true;
|
||||
const b = blobURLMap.get(specifier);
|
||||
if (!b) {
|
||||
throw new Error("No Blob associated with the given URL is found");
|
||||
}
|
||||
const blobBytes = blobBytesWeakMap.get(b!);
|
||||
if (!blobBytes) {
|
||||
throw new Error("Invalid Blob");
|
||||
}
|
||||
sourceCode = blobBytes!;
|
||||
}
|
||||
*/
|
||||
|
||||
const { id } = createWorker(
|
||||
specifier,
|
||||
hasSourceCode,
|
||||
sourceCode,
|
||||
options?.name
|
||||
);
|
||||
this.id = id;
|
||||
this.poll();
|
||||
}
|
||||
|
||||
private handleError(e: any): boolean {
|
||||
// TODO: this is being handled in a type unsafe way, it should be type safe
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const event = new Event("error", { cancelable: true }) as any;
|
||||
event.message = e.message;
|
||||
event.lineNumber = e.lineNumber ? e.lineNumber + 1 : null;
|
||||
event.columnNumber = e.columnNumber ? e.columnNumber + 1 : null;
|
||||
event.fileName = e.fileName;
|
||||
event.error = null;
|
||||
|
||||
let handled = false;
|
||||
if (this.onerror) {
|
||||
this.onerror(event);
|
||||
if (event.defaultPrevented) {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
async poll(): Promise<void> {
|
||||
while (!this.terminated) {
|
||||
const event = await hostGetMessage(this.id);
|
||||
|
||||
// If terminate was called then we ignore all messages
|
||||
if (this.terminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
const type = event.type;
|
||||
|
||||
if (type === "msg") {
|
||||
if (this.onmessage) {
|
||||
const message = decodeMessage(new Uint8Array(event.data));
|
||||
this.onmessage({ data: message });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type === "error") {
|
||||
if (!this.handleError(event.error)) {
|
||||
throw Error(event.error.message);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type === "close") {
|
||||
log(`Host got "close" message from worker: ${this.name}`);
|
||||
this.terminated = true;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(`Unknown worker event: "${type}"`);
|
||||
}
|
||||
}
|
||||
|
||||
postMessage(data: any): void {
|
||||
if (this.terminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
hostPostMessage(this.id, encodeMessage(data));
|
||||
}
|
||||
|
||||
terminate(): void {
|
||||
if (!this.terminated) {
|
||||
this.terminated = true;
|
||||
hostTerminateWorker(this.id);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue