summaryrefslogtreecommitdiff
path: root/cli/js
diff options
context:
space:
mode:
Diffstat (limited to 'cli/js')
-rw-r--r--cli/js/compiler.ts520
-rw-r--r--cli/js/compiler_bootstrap.ts31
-rw-r--r--cli/js/compiler_bundler.ts4
-rw-r--r--cli/js/compiler_util.ts15
-rw-r--r--cli/js/globals.ts97
-rw-r--r--cli/js/lib.deno_main.d.ts4
-rw-r--r--cli/js/main.ts59
-rw-r--r--cli/js/os.ts68
-rw-r--r--cli/js/runtime.ts90
-rw-r--r--cli/js/runtime_main.ts85
-rw-r--r--cli/js/runtime_worker.ts126
-rw-r--r--cli/js/worker_main.ts89
12 files changed, 653 insertions, 535 deletions
diff --git a/cli/js/compiler.ts b/cli/js/compiler.ts
index 2807422e2..394c6cf52 100644
--- a/cli/js/compiler.ts
+++ b/cli/js/compiler.ts
@@ -1,12 +1,20 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// TODO(ry) Combine this implementation with //deno_typescript/compiler_main.js
-// these are imported for their side effects
-import "./globals.ts";
+// This module is the entry point for "compiler" isolate, ie. the one
+// that is created when Deno needs to compile TS/WASM to JS.
+//
+// It provides a two functions that should be called by Rust:
+// - `bootstrapTsCompilerRuntime`
+// - `bootstrapWasmCompilerRuntime`
+// Either of these functions must be called when creating isolate
+// to properly setup runtime.
+
+// NOTE: this import has side effects!
import "./ts_global.d.ts";
import { TranspileOnlyResult } from "./compiler_api.ts";
-import { oldProgram } from "./compiler_bootstrap.ts";
+import { TS_SNAPSHOT_PROGRAM } from "./compiler_bootstrap.ts";
import { setRootExports } from "./compiler_bundler.ts";
import {
CompilerHostTarget,
@@ -30,16 +38,12 @@ import {
} from "./compiler_util.ts";
import { Diagnostic } from "./diagnostics.ts";
import { fromTypeScriptDiagnostic } from "./diagnostics_util.ts";
-import * as os from "./os.ts";
import { assert } from "./util.ts";
import * as util from "./util.ts";
import {
- postMessage,
- workerClose,
- bootstrapWorkerRuntime
-} from "./worker_main.ts";
-
-const self = globalThis;
+ bootstrapWorkerRuntime,
+ runWorkerMessageLoop
+} from "./runtime_worker.ts";
interface CompilerRequestCompile {
type: CompilerRequestType.Compile;
@@ -80,274 +84,280 @@ interface CompileResult {
diagnostics?: Diagnostic;
}
-// bootstrap the runtime environment, this gets called as the isolate is setup
-self.bootstrapCompilerRuntime = function bootstrapCompilerRuntime(
- compilerType: string
-): void {
- os.start(true, compilerType);
-};
-
-// bootstrap the worker environment, this gets called as the isolate is setup
-self.bootstrapWorkerRuntime = bootstrapWorkerRuntime;
-
-// provide the "main" function that will be called by the privileged side when
-// lazy instantiating the compiler web worker
-self.bootstrapTsCompiler = function tsCompilerMain(): void {
- // bootstrapWorkerRuntime should have already been called since a compiler is a worker.
- self.onmessage = async ({
- data: request
- }: {
- data: CompilerRequest;
- }): Promise<void> => {
- switch (request.type) {
- // `Compile` are requests from the internals to Deno, generated by both
- // the `run` and `bundle` sub command.
- case CompilerRequestType.Compile: {
- const {
- bundle,
- config,
- configPath,
- outFile,
- rootNames,
- target
- } = request;
- util.log(">>> compile start", {
+// TODO(bartlomieju): refactor this function into multiple functions
+// per CompilerRequestType
+async function tsCompilerOnMessage({
+ data: request
+}: {
+ data: CompilerRequest;
+}): Promise<void> {
+ switch (request.type) {
+ // `Compile` are requests from the internals to Deno, generated by both
+ // the `run` and `bundle` sub command.
+ case CompilerRequestType.Compile: {
+ const {
+ bundle,
+ config,
+ configPath,
+ outFile,
+ rootNames,
+ target
+ } = request;
+ util.log(">>> compile start", {
+ rootNames,
+ type: CompilerRequestType[request.type]
+ });
+
+ // This will recursively analyse all the code for other imports,
+ // requesting those from the privileged side, populating the in memory
+ // cache which will be used by the host, before resolving.
+ const resolvedRootModules = await processImports(
+ rootNames.map(rootName => [rootName, rootName])
+ );
+
+ // When a programme is emitted, TypeScript will call `writeFile` with
+ // each file that needs to be emitted. The Deno compiler host delegates
+ // this, to make it easier to perform the right actions, which vary
+ // based a lot on the request. For a `Compile` request, we need to
+ // cache all the files in the privileged side if we aren't bundling,
+ // and if we are bundling we need to enrich the bundle and either write
+ // out the bundle or log it to the console.
+ const state: WriteFileState = {
+ type: request.type,
+ bundle,
+ host: undefined,
+ outFile,
+ rootNames
+ };
+ const writeFile = createWriteFile(state);
+
+ const host = (state.host = new Host({
+ bundle,
+ target,
+ writeFile
+ }));
+ let diagnostics: readonly ts.Diagnostic[] | undefined;
+
+ // if there is a configuration supplied, we need to parse that
+ if (config && config.length && configPath) {
+ const configResult = host.configure(configPath, config);
+ diagnostics = processConfigureResponse(configResult, configPath);
+ }
+
+ let emitSkipped = true;
+ // if there was a configuration and no diagnostics with it, we will continue
+ // to generate the program and possibly emit it.
+ if (!diagnostics || (diagnostics && diagnostics.length === 0)) {
+ const options = host.getCompilationSettings();
+ const program = ts.createProgram({
rootNames,
- type: CompilerRequestType[request.type]
+ options,
+ host,
+ oldProgram: TS_SNAPSHOT_PROGRAM
});
- // This will recursively analyse all the code for other imports,
- // requesting those from the privileged side, populating the in memory
- // cache which will be used by the host, before resolving.
- const resolvedRootModules = await processImports(
- rootNames.map(rootName => [rootName, rootName])
- );
-
- // When a programme is emitted, TypeScript will call `writeFile` with
- // each file that needs to be emitted. The Deno compiler host delegates
- // this, to make it easier to perform the right actions, which vary
- // based a lot on the request. For a `Compile` request, we need to
- // cache all the files in the privileged side if we aren't bundling,
- // and if we are bundling we need to enrich the bundle and either write
- // out the bundle or log it to the console.
- const state: WriteFileState = {
- type: request.type,
- bundle,
- host: undefined,
- outFile,
- rootNames
- };
- const writeFile = createWriteFile(state);
-
- const host = (state.host = new Host({
- bundle,
- target,
- writeFile
- }));
- let diagnostics: readonly ts.Diagnostic[] | undefined;
-
- // if there is a configuration supplied, we need to parse that
- if (config && config.length && configPath) {
- const configResult = host.configure(configPath, config);
- diagnostics = processConfigureResponse(configResult, configPath);
- }
+ diagnostics = ts
+ .getPreEmitDiagnostics(program)
+ .filter(({ code }) => !ignoredDiagnostics.includes(code));
- let emitSkipped = true;
- // if there was a configuration and no diagnostics with it, we will continue
- // to generate the program and possibly emit it.
- if (!diagnostics || (diagnostics && diagnostics.length === 0)) {
- const options = host.getCompilationSettings();
- const program = ts.createProgram({
- rootNames,
- options,
- host,
- oldProgram
- });
-
- diagnostics = ts
- .getPreEmitDiagnostics(program)
- .filter(({ code }) => !ignoredDiagnostics.includes(code));
-
- // We will only proceed with the emit if there are no diagnostics.
- if (diagnostics && diagnostics.length === 0) {
- if (bundle) {
- // we only support a single root module when bundling
- assert(resolvedRootModules.length === 1);
- // warning so it goes to stderr instead of stdout
- console.warn(`Bundling "${resolvedRootModules[0]}"`);
- setRootExports(program, resolvedRootModules[0]);
- }
- const emitResult = program.emit();
- emitSkipped = emitResult.emitSkipped;
- // emitResult.diagnostics is `readonly` in TS3.5+ and can't be assigned
- // without casting.
- diagnostics = emitResult.diagnostics;
+ // We will only proceed with the emit if there are no diagnostics.
+ if (diagnostics && diagnostics.length === 0) {
+ if (bundle) {
+ // we only support a single root module when bundling
+ assert(resolvedRootModules.length === 1);
+ // warning so it goes to stderr instead of stdout
+ console.warn(`Bundling "${resolvedRootModules[0]}"`);
+ setRootExports(program, resolvedRootModules[0]);
}
+ const emitResult = program.emit();
+ emitSkipped = emitResult.emitSkipped;
+ // emitResult.diagnostics is `readonly` in TS3.5+ and can't be assigned
+ // without casting.
+ diagnostics = emitResult.diagnostics;
}
+ }
- const result: CompileResult = {
- emitSkipped,
- diagnostics: diagnostics.length
- ? fromTypeScriptDiagnostic(diagnostics)
- : undefined
- };
- postMessage(result);
-
- util.log("<<< compile end", {
- rootNames,
- type: CompilerRequestType[request.type]
- });
- break;
+ const result: CompileResult = {
+ emitSkipped,
+ diagnostics: diagnostics.length
+ ? fromTypeScriptDiagnostic(diagnostics)
+ : undefined
+ };
+ globalThis.postMessage(result);
+
+ util.log("<<< compile end", {
+ rootNames,
+ type: CompilerRequestType[request.type]
+ });
+ break;
+ }
+ case CompilerRequestType.RuntimeCompile: {
+ // `RuntimeCompile` are requests from a runtime user, both compiles and
+ // bundles. The process is similar to a request from the privileged
+ // side, but also returns the output to the on message.
+ const { rootName, sources, options, bundle, target } = request;
+
+ util.log(">>> runtime compile start", {
+ rootName,
+ bundle,
+ sources: sources ? Object.keys(sources) : undefined
+ });
+
+ const resolvedRootName = sources
+ ? rootName
+ : resolveModules([rootName])[0];
+
+ const rootNames = sources
+ ? processLocalImports(sources, [[resolvedRootName, resolvedRootName]])
+ : await processImports([[resolvedRootName, resolvedRootName]]);
+
+ const state: WriteFileState = {
+ type: request.type,
+ bundle,
+ host: undefined,
+ rootNames,
+ sources,
+ emitMap: {},
+ emitBundle: undefined
+ };
+ const writeFile = createWriteFile(state);
+
+ const host = (state.host = new Host({
+ bundle,
+ target,
+ writeFile
+ }));
+ const compilerOptions = [defaultRuntimeCompileOptions];
+ if (options) {
+ compilerOptions.push(convertCompilerOptions(options));
}
- case CompilerRequestType.RuntimeCompile: {
- // `RuntimeCompile` are requests from a runtime user, both compiles and
- // bundles. The process is similar to a request from the privileged
- // side, but also returns the output to the on message.
- const { rootName, sources, options, bundle, target } = request;
-
- util.log(">>> runtime compile start", {
- rootName,
- bundle,
- sources: sources ? Object.keys(sources) : undefined
- });
+ if (bundle) {
+ compilerOptions.push(defaultBundlerOptions);
+ }
+ host.mergeOptions(...compilerOptions);
- const resolvedRootName = sources
- ? rootName
- : resolveModules([rootName])[0];
+ const program = ts.createProgram({
+ rootNames,
+ options: host.getCompilationSettings(),
+ host,
+ oldProgram: TS_SNAPSHOT_PROGRAM
+ });
- const rootNames = sources
- ? processLocalImports(sources, [[resolvedRootName, resolvedRootName]])
- : await processImports([[resolvedRootName, resolvedRootName]]);
+ if (bundle) {
+ setRootExports(program, rootNames[0]);
+ }
- const state: WriteFileState = {
- type: request.type,
- bundle,
- host: undefined,
- rootNames,
- sources,
- emitMap: {},
- emitBundle: undefined
- };
- const writeFile = createWriteFile(state);
-
- const host = (state.host = new Host({
- bundle,
- target,
- writeFile
- }));
- const compilerOptions = [defaultRuntimeCompileOptions];
- if (options) {
- compilerOptions.push(convertCompilerOptions(options));
- }
- if (bundle) {
- compilerOptions.push(defaultBundlerOptions);
- }
- host.mergeOptions(...compilerOptions);
+ const diagnostics = ts
+ .getPreEmitDiagnostics(program)
+ .filter(({ code }) => !ignoredDiagnostics.includes(code));
- const program = ts.createProgram({
- rootNames,
- options: host.getCompilationSettings(),
- host,
- oldProgram
- });
+ const emitResult = program.emit();
- if (bundle) {
- setRootExports(program, rootNames[0]);
- }
+ assert(emitResult.emitSkipped === false, "Unexpected skip of the emit.");
+ const result = [
+ diagnostics.length ? fromTypeScriptDiagnostic(diagnostics) : undefined,
+ bundle ? state.emitBundle : state.emitMap
+ ];
+ globalThis.postMessage(result);
- const diagnostics = ts
- .getPreEmitDiagnostics(program)
- .filter(({ code }) => !ignoredDiagnostics.includes(code));
+ assert(state.emitMap);
+ util.log("<<< runtime compile finish", {
+ rootName,
+ sources: sources ? Object.keys(sources) : undefined,
+ bundle,
+ emitMap: Object.keys(state.emitMap)
+ });
- const emitResult = program.emit();
-
- assert(
- emitResult.emitSkipped === false,
- "Unexpected skip of the emit."
+ break;
+ }
+ case CompilerRequestType.RuntimeTranspile: {
+ const result: Record<string, TranspileOnlyResult> = {};
+ const { sources, options } = request;
+ const compilerOptions = options
+ ? Object.assign(
+ {},
+ defaultTranspileOptions,
+ convertCompilerOptions(options)
+ )
+ : defaultTranspileOptions;
+
+ for (const [fileName, inputText] of Object.entries(sources)) {
+ const { outputText: source, sourceMapText: map } = ts.transpileModule(
+ inputText,
+ {
+ fileName,
+ compilerOptions
+ }
);
- const result = [
- diagnostics.length
- ? fromTypeScriptDiagnostic(diagnostics)
- : undefined,
- bundle ? state.emitBundle : state.emitMap
- ];
- postMessage(result);
-
- assert(state.emitMap);
- util.log("<<< runtime compile finish", {
- rootName,
- sources: sources ? Object.keys(sources) : undefined,
- bundle,
- emitMap: Object.keys(state.emitMap)
- });
-
- break;
+ result[fileName] = { source, map };
}
- case CompilerRequestType.RuntimeTranspile: {
- const result: Record<string, TranspileOnlyResult> = {};
- const { sources, options } = request;
- const compilerOptions = options
- ? Object.assign(
- {},
- defaultTranspileOptions,
- convertCompilerOptions(options)
- )
- : defaultTranspileOptions;
-
- for (const [fileName, inputText] of Object.entries(sources)) {
- const { outputText: source, sourceMapText: map } = ts.transpileModule(
- inputText,
- {
- fileName,
- compilerOptions
- }
- );
- result[fileName] = { source, map };
- }
- postMessage(result);
+ globalThis.postMessage(result);
- break;
- }
- default:
- util.log(
- `!!! unhandled CompilerRequestType: ${
- (request as CompilerRequest).type
- } (${CompilerRequestType[(request as CompilerRequest).type]})`
- );
+ break;
}
+ default:
+ util.log(
+ `!!! unhandled CompilerRequestType: ${
+ (request as CompilerRequest).type
+ } (${CompilerRequestType[(request as CompilerRequest).type]})`
+ );
+ }
+
+ // The compiler isolate exits after a single message.
+ globalThis.workerClose();
+}
+
+async function wasmCompilerOnMessage({
+ data: binary
+}: {
+ data: string;
+}): Promise<void> {
+ const buffer = util.base64ToUint8Array(binary);
+ // @ts-ignore
+ const compiled = await WebAssembly.compile(buffer);
+
+ util.log(">>> WASM compile start");
- // The compiler isolate exits after a single message.
- workerClose();
- };
-};
-
-self.bootstrapWasmCompiler = function wasmCompilerMain(): void {
- // bootstrapWorkerRuntime should have already been called since a compiler is a worker.
- self.onmessage = async ({
- data: binary
- }: {
- data: string;
- }): Promise<void> => {
- const buffer = util.base64ToUint8Array(binary);
+ const importList = Array.from(
// @ts-ignore
- const compiled = await WebAssembly.compile(buffer);
+ new Set(WebAssembly.Module.imports(compiled).map(({ module }) => module))
+ );
+ const exportList = Array.from(
+ // @ts-ignore
+ new Set(WebAssembly.Module.exports(compiled).map(({ name }) => name))
+ );
- util.log(">>> WASM compile start");
+ globalThis.postMessage({ importList, exportList });
- const importList = Array.from(
- // @ts-ignore
- new Set(WebAssembly.Module.imports(compiled).map(({ module }) => module))
- );
- const exportList = Array.from(
- // @ts-ignore
- new Set(WebAssembly.Module.exports(compiled).map(({ name }) => name))
- );
+ util.log("<<< WASM compile end");
- postMessage({ importList, exportList });
+ // The compiler isolate exits after a single message.
+ globalThis.workerClose();
+}
- util.log("<<< WASM compile end");
+function bootstrapTsCompilerRuntime(): void {
+ bootstrapWorkerRuntime("TS");
+ globalThis.onmessage = tsCompilerOnMessage;
+ runWorkerMessageLoop();
+}
+
+function bootstrapWasmCompilerRuntime(): void {
+ bootstrapWorkerRuntime("WASM");
+ globalThis.onmessage = wasmCompilerOnMessage;
+ runWorkerMessageLoop();
+}
- // The compiler isolate exits after a single message.
- workerClose();
- };
-};
+Object.defineProperties(globalThis, {
+ bootstrapWasmCompilerRuntime: {
+ value: bootstrapWasmCompilerRuntime,
+ enumerable: false,
+ writable: false,
+ configurable: false
+ },
+ bootstrapTsCompilerRuntime: {
+ value: bootstrapTsCompilerRuntime,
+ enumerable: false,
+ writable: false,
+ configurable: false
+ }
+});
diff --git a/cli/js/compiler_bootstrap.ts b/cli/js/compiler_bootstrap.ts
index a5c7eb029..afb3d2be5 100644
--- a/cli/js/compiler_bootstrap.ts
+++ b/cli/js/compiler_bootstrap.ts
@@ -1,20 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { ASSETS, CompilerHostTarget, Host } from "./compiler_host.ts";
-import { core } from "./core.ts";
-import * as dispatch from "./dispatch.ts";
import { getAsset } from "./compiler_util.ts";
-// This registers ops that are available during the snapshotting process.
-const ops = core.ops();
-for (const [name, opId] of Object.entries(ops)) {
- const opName = `OP_${name.toUpperCase()}`;
- // TODO This type casting is dangerous, and should be improved when the same
- // code in `os.ts` is done.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (dispatch as any)[opName] = opId;
-}
-
+// NOTE: target doesn't really matter here,
+// this is in fact a mock host created just to
+// load all type definitions and snapshot them.
const host = new Host({
target: CompilerHostTarget.Main,
writeFile(): void {}
@@ -35,11 +26,15 @@ const options = host.getCompilationSettings();
host.getSourceFile(`${ASSETS}/lib.deno_main.d.ts`, ts.ScriptTarget.ESNext);
host.getSourceFile(`${ASSETS}/lib.deno_worker.d.ts`, ts.ScriptTarget.ESNext);
host.getSourceFile(`${ASSETS}/lib.deno.d.ts`, ts.ScriptTarget.ESNext);
-host.getSourceFile(`${ASSETS}/lib.webworker.d.ts`, ts.ScriptTarget.ESNext);
-/** Used to generate the foundational AST for all other compilations, so it can
- * be cached as part of the snapshot and available to speed up startup */
-export const oldProgram = ts.createProgram({
+/**
+ * This function spins up TS compiler and loads all available libraries
+ * into memory (including ones specified above).
+ *
+ * Used to generate the foundational AST for all other compilations, so it can
+ * be cached as part of the snapshot and available to speed up startup.
+ */
+export const TS_SNAPSHOT_PROGRAM = ts.createProgram({
rootNames: [`${ASSETS}/bootstrap.ts`],
options,
host
@@ -49,5 +44,5 @@ export const oldProgram = ts.createProgram({
*
* We read all static assets during the snapshotting process, which is
* why this is located in compiler_bootstrap.
- **/
-export const bundleLoader = getAsset("bundle_loader.js");
+ */
+export const BUNDLE_LOADER = getAsset("bundle_loader.js");
diff --git a/cli/js/compiler_bundler.ts b/cli/js/compiler_bundler.ts
index 8fb68cc7a..d334b0fc3 100644
--- a/cli/js/compiler_bundler.ts
+++ b/cli/js/compiler_bundler.ts
@@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { bundleLoader } from "./compiler_bootstrap.ts";
+import { BUNDLE_LOADER } from "./compiler_bootstrap.ts";
import {
assert,
commonPath,
@@ -55,7 +55,7 @@ export function buildBundle(
} else {
instantiate = `instantiate("${rootName}");\n`;
}
- return `${bundleLoader}\n${data}\n${instantiate}`;
+ return `${BUNDLE_LOADER}\n${data}\n${instantiate}`;
}
/** Set the rootExports which will by the `emitBundle()` */
diff --git a/cli/js/compiler_util.ts b/cli/js/compiler_util.ts
index fbb30d67d..f541ea46f 100644
--- a/cli/js/compiler_util.ts
+++ b/cli/js/compiler_util.ts
@@ -90,6 +90,9 @@ function cache(
assert(false, `Trying to cache unhandled file type "${emittedFileName}"`);
}
}
+
+let OP_FETCH_ASSET: number;
+
/**
* This op is called only during snapshotting.
*
@@ -98,12 +101,16 @@ function cache(
* as raw byte arrays.
*/
export function getAsset(name: string): string {
+ if (!OP_FETCH_ASSET) {
+ const ops = core.ops();
+ const opFetchAsset = ops["fetch_asset"];
+ assert(opFetchAsset, "OP_FETCH_ASSET is not registered");
+ OP_FETCH_ASSET = opFetchAsset;
+ }
+
const encoder = new TextEncoder();
const decoder = new TextDecoder();
- const sourceCodeBytes = core.dispatch(
- dispatch.OP_FETCH_ASSET,
- encoder.encode(name)
- );
+ const sourceCodeBytes = core.dispatch(OP_FETCH_ASSET, encoder.encode(name));
return decoder.decode(sourceCodeBytes!);
}
diff --git a/cli/js/globals.ts b/cli/js/globals.ts
index cb1b17678..e6c1e855c 100644
--- a/cli/js/globals.ts
+++ b/cli/js/globals.ts
@@ -1,15 +1,8 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-// This is a "special" module, in that it define the global runtime scope of
-// Deno, and therefore it defines a lot of the runtime environment that code
-// is evaluated in.
-
-// By convention we import those items that are globally exposed as namespaces
import * as blob from "./blob.ts";
import * as consoleTypes from "./console.ts";
-import * as csprng from "./get_random_values.ts";
import * as customEvent from "./custom_event.ts";
-import * as Deno from "./deno.ts";
import * as domTypes from "./dom_types.ts";
import * as domFile from "./dom_file.ts";
import * as event from "./event.ts";
@@ -21,7 +14,6 @@ import * as textEncoding from "./text_encoding.ts";
import * as timers from "./timers.ts";
import * as url from "./url.ts";
import * as urlSearchParams from "./url_search_params.ts";
-import * as workerRuntime from "./worker_main.ts";
import * as workers from "./workers.ts";
import * as performanceUtil from "./performance.ts";
import * as request from "./request.ts";
@@ -29,7 +21,6 @@ import * as request from "./request.ts";
// These imports are not exposed and therefore are fine to just import the
// symbols required.
import { core } from "./core.ts";
-import { internalObject } from "./internals.ts";
// This global augmentation is just enough types to be able to build Deno,
// the runtime types are fully defined in `lib.deno_runtime.d.ts`.
@@ -111,14 +102,23 @@ declare global {
callback: (event: domTypes.Event) => void | null,
options?: boolean | domTypes.AddEventListenerOptions | undefined
) => void;
- var bootstrapTsCompiler: (() => void) | undefined;
+ var queueMicrotask: (callback: () => void) => void;
var console: consoleTypes.Console;
+ var location: domTypes.Location;
+
+ // Assigned to `window` global - main runtime
var Deno: {
core: DenoCore;
};
- var bootstrapCompilerRuntime: ((compilerType: string) => void) | undefined;
+ var onload: ((e: domTypes.Event) => void) | undefined;
+ var onunload: ((e: domTypes.Event) => void) | undefined;
var bootstrapMainRuntime: (() => void) | undefined;
- var location: domTypes.Location;
+
+ // Assigned to `self` global - worker runtime and compiler
+ var bootstrapWorkerRuntime:
+ | ((name: string) => Promise<void> | void)
+ | undefined;
+ var runWorkerMessageLoop: (() => Promise<void> | void) | undefined;
var onerror:
| ((
msg: string,
@@ -128,22 +128,20 @@ declare global {
e: domTypes.Event
) => boolean | void)
| undefined;
- var onload: ((e: domTypes.Event) => void) | undefined;
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var onmessage: ((e: { data: any }) => Promise<void> | void) | undefined;
- var onunload: ((e: domTypes.Event) => void) | undefined;
- var queueMicrotask: (callback: () => void) => void;
- var bootstrapWasmCompiler: (() => void) | undefined;
- var bootstrapWorkerRuntime: (() => Promise<void> | void) | undefined;
+ // Called in compiler
+ var workerClose: () => void;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ var postMessage: (msg: any) => void;
+ // Assigned to `self` global - compiler
+ var bootstrapTsCompilerRuntime: (() => void) | undefined;
+ var bootstrapWasmCompilerRuntime: (() => void) | undefined;
/* eslint-enable */
}
-// Add internal object to Deno object.
-// This is not exposed as part of the Deno types.
-// @ts-ignore
-Deno[Deno.symbols.internal] = internalObject;
-
-function writable(value: unknown): PropertyDescriptor {
+export function writable(value: unknown): PropertyDescriptor {
return {
value,
writable: true,
@@ -152,7 +150,7 @@ function writable(value: unknown): PropertyDescriptor {
};
}
-function nonEnumerable(value: unknown): PropertyDescriptor {
+export function nonEnumerable(value: unknown): PropertyDescriptor {
return {
value,
writable: true,
@@ -160,27 +158,28 @@ function nonEnumerable(value: unknown): PropertyDescriptor {
};
}
-function readOnly(value: unknown): PropertyDescriptor {
+export function readOnly(value: unknown): PropertyDescriptor {
return {
value,
enumerable: true
};
}
-const globalProperties = {
- window: readOnly(globalThis),
- Deno: readOnly(Deno),
+// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
+export const windowOrWorkerGlobalScopeMethods = {
atob: writable(textEncoding.atob),
btoa: writable(textEncoding.btoa),
- fetch: writable(fetchTypes.fetch),
- clearTimeout: writable(timers.clearTimeout),
clearInterval: writable(timers.clearInterval),
- console: writable(new consoleTypes.Console(core.print)),
- setTimeout: writable(timers.setTimeout),
+ clearTimeout: writable(timers.clearTimeout),
+ fetch: writable(fetchTypes.fetch),
+ // queueMicrotask is bound in Rust
setInterval: writable(timers.setInterval),
- onload: writable(undefined),
- onunload: writable(undefined),
- crypto: readOnly(csprng),
+ setTimeout: writable(timers.setTimeout)
+};
+
+// Other properties shared between WindowScope and WorkerGlobalScope
+export const windowOrWorkerGlobalScopeProperties = {
+ console: writable(new consoleTypes.Console(core.print)),
Blob: nonEnumerable(blob.DenoBlob),
File: nonEnumerable(domFile.DomFileImpl),
CustomEvent: nonEnumerable(customEvent.CustomEvent),
@@ -195,15 +194,10 @@ const globalProperties = {
Request: nonEnumerable(request.Request),
Response: nonEnumerable(fetchTypes.Response),
performance: writable(new performanceUtil.Performance()),
+ Worker: nonEnumerable(workers.WorkerImpl)
+};
- onmessage: writable(workerRuntime.onmessage),
- onerror: writable(workerRuntime.onerror),
-
- bootstrapWorkerRuntime: nonEnumerable(workerRuntime.bootstrapWorkerRuntime),
- workerClose: nonEnumerable(workerRuntime.workerClose),
- postMessage: writable(workerRuntime.postMessage),
- Worker: nonEnumerable(workers.WorkerImpl),
-
+export const eventTargetProperties = {
[domTypes.eventTargetHost]: nonEnumerable(null),
[domTypes.eventTargetListeners]: nonEnumerable({}),
[domTypes.eventTargetMode]: nonEnumerable(""),
@@ -219,20 +213,3 @@ const globalProperties = {
eventTarget.EventTarget.prototype.removeEventListener
)
};
-
-Object.defineProperties(globalThis, globalProperties);
-
-// Registers the handler for window.onload function.
-globalThis.addEventListener("load", (e: domTypes.Event): void => {
- const { onload } = globalThis;
- if (typeof onload === "function") {
- onload(e);
- }
-});
-// Registers the handler for window.onunload function.
-globalThis.addEventListener("unload", (e: domTypes.Event): void => {
- const { onunload } = globalThis;
- if (typeof onunload === "function") {
- onunload(e);
- }
-});
diff --git a/cli/js/lib.deno_main.d.ts b/cli/js/lib.deno_main.d.ts
index ec050fc1e..52b6fb7f5 100644
--- a/cli/js/lib.deno_main.d.ts
+++ b/cli/js/lib.deno_main.d.ts
@@ -36,7 +36,6 @@ declare interface Window {
performance: __performanceUtil.Performance;
onmessage: (e: { data: any }) => void;
onerror: undefined | typeof onerror;
- bootstrapWorkerRuntime: typeof __workerMain.bootstrapWorkerRuntime;
workerClose: typeof __workerMain.workerClose;
postMessage: typeof __workerMain.postMessage;
Worker: typeof __workers.WorkerImpl;
@@ -95,7 +94,6 @@ declare let onerror:
e: Event
) => boolean | void)
| undefined;
-declare const bootstrapWorkerRuntime: typeof __workerMain.bootstrapWorkerRuntime;
declare const workerClose: typeof __workerMain.workerClose;
declare const postMessage: typeof __workerMain.postMessage;
declare const Worker: typeof __workers.WorkerImpl;
@@ -1525,9 +1523,7 @@ declare namespace __workerMain {
export let onmessage: (e: { data: any }) => void;
export function postMessage(data: any): void;
export function getMessage(): Promise<any>;
- export let isClosing: boolean;
export function workerClose(): void;
- export function bootstrapWorkerRuntime(): Promise<void>;
}
declare namespace __workers {
diff --git a/cli/js/main.ts b/cli/js/main.ts
index 1da56eaa5..b48277960 100644
--- a/cli/js/main.ts
+++ b/cli/js/main.ts
@@ -1,38 +1,27 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import "./globals.ts";
+import { bootstrapMainRuntime } from "./runtime_main.ts";
+import {
+ bootstrapWorkerRuntime,
+ runWorkerMessageLoop
+} from "./runtime_worker.ts";
-import { assert, log } from "./util.ts";
-import * as os from "./os.ts";
-import { args } from "./deno.ts";
-import { setPrepareStackTrace } from "./error_stack.ts";
-import { replLoop } from "./repl.ts";
-import { setVersions } from "./version.ts";
-import { setLocation } from "./location.ts";
-import { setBuildInfo } from "./build.ts";
-import { setSignals } from "./process.ts";
-
-function bootstrapMainRuntime(): void {
- const s = os.start(true);
-
- setBuildInfo(s.os, s.arch);
- setSignals();
- setVersions(s.denoVersion, s.v8Version, s.tsVersion);
-
- setPrepareStackTrace(Error);
-
- if (s.mainModule) {
- assert(s.mainModule.length > 0);
- setLocation(s.mainModule);
- }
- log("cwd", s.cwd);
- for (let i = 0; i < s.argv.length; i++) {
- args.push(s.argv[i]);
- }
- log("args", args);
- Object.freeze(args);
-
- if (!s.mainModule) {
- replLoop();
+Object.defineProperties(globalThis, {
+ bootstrapMainRuntime: {
+ value: bootstrapMainRuntime,
+ enumerable: false,
+ writable: false,
+ configurable: false
+ },
+ bootstrapWorkerRuntime: {
+ value: bootstrapWorkerRuntime,
+ enumerable: false,
+ writable: false,
+ configurable: false
+ },
+ runWorkerMessageLoop: {
+ value: runWorkerMessageLoop,
+ enumerable: false,
+ writable: false,
+ configurable: false
}
-}
-globalThis["bootstrapMainRuntime"] = bootstrapMainRuntime;
+});
diff --git a/cli/js/os.ts b/cli/js/os.ts
index cf522f857..554d4f78d 100644
--- a/cli/js/os.ts
+++ b/cli/js/os.ts
@@ -1,11 +1,8 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { core } from "./core.ts";
import * as dispatch from "./dispatch.ts";
import { sendSync } from "./dispatch_json.ts";
import { ErrorKind } from "./errors.ts";
-import { assert } from "./util.ts";
import * as util from "./util.ts";
-import { OperatingSystem, Arch } from "./build.ts";
/** Check if running in terminal.
*
@@ -67,71 +64,6 @@ export function env(
});
}
-interface Start {
- cwd: string;
- pid: number;
- argv: string[];
- mainModule: string; // Absolute URL.
- debugFlag: boolean;
- depsFlag: boolean;
- typesFlag: boolean;
- versionFlag: boolean;
- denoVersion: string;
- v8Version: string;
- tsVersion: string;
- noColor: boolean;
- os: OperatingSystem;
- arch: Arch;
-}
-
-// TODO(bartlomieju): temporary solution, must be fixed when moving
-// dispatches to separate crates
-export function initOps(): void {
- const ops = core.ops();
- for (const [name, opId] of Object.entries(ops)) {
- const opName = `OP_${name.toUpperCase()}`;
- // Assign op ids to actual variables
- // TODO(ry) This type casting is gross and should be fixed.
- ((dispatch as unknown) as { [key: string]: number })[opName] = opId;
- core.setAsyncHandler(opId, dispatch.getAsyncHandler(opName));
- }
-}
-
-// This function bootstraps an environment within Deno, it is shared both by
-// the runtime and the compiler environments.
-// @internal
-export function start(preserveDenoNamespace = true, source?: string): Start {
- initOps();
- // First we send an empty `Start` message to let the privileged side know we
- // are ready. The response should be a `StartRes` message containing the CLI
- // args and other info.
- const startResponse = sendSync(dispatch.OP_START);
- const { pid, noColor, debugFlag } = startResponse;
-
- util.setLogDebug(debugFlag, source);
-
- // pid and noColor need to be set in the Deno module before it's set to be
- // frozen.
- util.immutableDefine(globalThis.Deno, "pid", pid);
- util.immutableDefine(globalThis.Deno, "noColor", noColor);
- Object.freeze(globalThis.Deno);
-
- if (preserveDenoNamespace) {
- util.immutableDefine(globalThis, "Deno", globalThis.Deno);
- // Deno.core could ONLY be safely frozen here (not in globals.ts)
- // since shared_queue.js will modify core properties.
- Object.freeze(globalThis.Deno.core);
- // core.sharedQueue is an object so we should also freeze it.
- Object.freeze(globalThis.Deno.core.sharedQueue);
- } else {
- // Remove globalThis.Deno
- delete globalThis.Deno;
- assert(globalThis.Deno === undefined);
- }
-
- return startResponse;
-}
-
type DirKind =
| "home"
| "cache"
diff --git a/cli/js/runtime.ts b/cli/js/runtime.ts
new file mode 100644
index 000000000..8cebf5dca
--- /dev/null
+++ b/cli/js/runtime.ts
@@ -0,0 +1,90 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+import { core } from "./core.ts";
+import * as dispatch from "./dispatch.ts";
+import { sendSync } from "./dispatch_json.ts";
+import { assert } from "./util.ts";
+import * as util from "./util.ts";
+import { OperatingSystem, Arch } from "./build.ts";
+import { setBuildInfo } from "./build.ts";
+import { setVersions } from "./version.ts";
+import { setLocation } from "./location.ts";
+import { setPrepareStackTrace } from "./error_stack.ts";
+
+interface Start {
+ cwd: string;
+ pid: number;
+ argv: string[];
+ mainModule: string; // Absolute URL.
+ debugFlag: boolean;
+ depsFlag: boolean;
+ typesFlag: boolean;
+ versionFlag: boolean;
+ denoVersion: string;
+ v8Version: string;
+ tsVersion: string;
+ noColor: boolean;
+ os: OperatingSystem;
+ arch: Arch;
+}
+
+// TODO(bartlomieju): temporary solution, must be fixed when moving
+// dispatches to separate crates
+export function initOps(): void {
+ const ops = core.ops();
+ for (const [name, opId] of Object.entries(ops)) {
+ const opName = `OP_${name.toUpperCase()}`;
+ // Assign op ids to actual variables
+ // TODO(ry) This type casting is gross and should be fixed.
+ ((dispatch as unknown) as { [key: string]: number })[opName] = opId;
+ core.setAsyncHandler(opId, dispatch.getAsyncHandler(opName));
+ }
+}
+
+/**
+ * This function bootstraps JS runtime, unfortunately some of runtime
+ * code depends on information like "os" and thus getting this information
+ * is required at startup.
+ */
+export function start(preserveDenoNamespace = true, source?: string): Start {
+ initOps();
+ // First we send an empty `Start` message to let the privileged side know we
+ // are ready. The response should be a `StartRes` message containing the CLI
+ // args and other info.
+ const s = sendSync(dispatch.OP_START);
+
+ setVersions(s.denoVersion, s.v8Version, s.tsVersion);
+ setBuildInfo(s.os, s.arch);
+ util.setLogDebug(s.debugFlag, source);
+
+ // TODO(bartlomieju): this field should always be set
+ if (s.mainModule) {
+ assert(s.mainModule.length > 0);
+ setLocation(s.mainModule);
+ }
+ setPrepareStackTrace(Error);
+
+ // TODO(bartlomieju): I don't like that it's mixed in here, when
+ // compiler and worker runtimes call this funtion and they don't use
+ // Deno namespace (sans shared queue - Deno.core)
+
+ // pid and noColor need to be set in the Deno module before it's set to be
+ // frozen.
+ util.immutableDefine(globalThis.Deno, "pid", s.pid);
+ util.immutableDefine(globalThis.Deno, "noColor", s.noColor);
+ Object.freeze(globalThis.Deno);
+
+ if (preserveDenoNamespace) {
+ util.immutableDefine(globalThis, "Deno", globalThis.Deno);
+ // Deno.core could ONLY be safely frozen here (not in globals.ts)
+ // since shared_queue.js will modify core properties.
+ Object.freeze(globalThis.Deno.core);
+ // core.sharedQueue is an object so we should also freeze it.
+ Object.freeze(globalThis.Deno.core.sharedQueue);
+ } else {
+ // Remove globalThis.Deno
+ delete globalThis.Deno;
+ assert(globalThis.Deno === undefined);
+ }
+
+ return s;
+}
diff --git a/cli/js/runtime_main.ts b/cli/js/runtime_main.ts
new file mode 100644
index 000000000..2ede2e20f
--- /dev/null
+++ b/cli/js/runtime_main.ts
@@ -0,0 +1,85 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+
+// This module is the entry point for "main" isolate, ie. the one
+// that is created when you run "deno" executable.
+//
+// It provides a single function that should be called by Rust:
+// - `bootstrapMainRuntime` - must be called once, when Isolate is created.
+// It sets up runtime by providing globals for `WindowScope` and adds `Deno` global.
+
+import {
+ readOnly,
+ writable,
+ windowOrWorkerGlobalScopeMethods,
+ windowOrWorkerGlobalScopeProperties,
+ eventTargetProperties
+} from "./globals.ts";
+import * as domTypes from "./dom_types.ts";
+import { log } from "./util.ts";
+import * as runtime from "./runtime.ts";
+import { args } from "./deno.ts";
+import * as csprng from "./get_random_values.ts";
+import { replLoop } from "./repl.ts";
+import { setSignals } from "./process.ts";
+import * as Deno from "./deno.ts";
+import { internalObject } from "./internals.ts";
+
+// TODO: factor out `Deno` global assignment to separate function
+// Add internal object to Deno object.
+// This is not exposed as part of the Deno types.
+// @ts-ignore
+Deno[Deno.symbols.internal] = internalObject;
+
+export const mainRuntimeGlobalProperties = {
+ window: readOnly(globalThis),
+ Deno: readOnly(Deno),
+
+ crypto: readOnly(csprng),
+ // TODO(bartlomieju): from MDN docs (https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope)
+ // it seems those two properties should be availble to workers as well
+ onload: writable(undefined),
+ onunload: writable(undefined)
+};
+
+let hasBootstrapped = false;
+
+export function bootstrapMainRuntime(): void {
+ if (hasBootstrapped) {
+ throw new Error("Worker runtime already bootstrapped");
+ }
+ log("bootstrapMainRuntime");
+ hasBootstrapped = true;
+ Object.defineProperties(globalThis, windowOrWorkerGlobalScopeMethods);
+ Object.defineProperties(globalThis, windowOrWorkerGlobalScopeProperties);
+ Object.defineProperties(globalThis, eventTargetProperties);
+ Object.defineProperties(globalThis, mainRuntimeGlobalProperties);
+ // Registers the handler for window.onload function.
+ globalThis.addEventListener("load", (e: domTypes.Event): void => {
+ const { onload } = globalThis;
+ if (typeof onload === "function") {
+ onload(e);
+ }
+ });
+ // Registers the handler for window.onunload function.
+ globalThis.addEventListener("unload", (e: domTypes.Event): void => {
+ const { onunload } = globalThis;
+ if (typeof onunload === "function") {
+ onunload(e);
+ }
+ });
+
+ const s = runtime.start(true);
+ setSignals();
+
+ log("cwd", s.cwd);
+ for (let i = 0; i < s.argv.length; i++) {
+ args.push(s.argv[i]);
+ }
+ log("args", args);
+ Object.freeze(args);
+
+ // TODO(bartlomieju): rename to s.repl
+ if (!s.mainModule) {
+ replLoop();
+ }
+}
diff --git a/cli/js/runtime_worker.ts b/cli/js/runtime_worker.ts
new file mode 100644
index 000000000..7f1d1b69c
--- /dev/null
+++ b/cli/js/runtime_worker.ts
@@ -0,0 +1,126 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+
+// This module is the entry point for "worker" isolate, ie. the one
+// that is created using `new Worker()` JS API.
+//
+// It provides two functions that should be called by Rust:
+// - `bootstrapWorkerRuntime` - must be called once, when Isolate is created.
+// It sets up runtime by providing globals for `DedicatedWorkerScope`.
+// - `runWorkerMessageLoop` - starts receiving messages from parent worker,
+// can be called multiple times - eg. to restart worker execution after
+// exception occurred and was handled by parent worker
+
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import {
+ readOnly,
+ writable,
+ nonEnumerable,
+ windowOrWorkerGlobalScopeMethods,
+ windowOrWorkerGlobalScopeProperties,
+ eventTargetProperties
+} from "./globals.ts";
+import * as dispatch from "./dispatch.ts";
+import { sendAsync, sendSync } from "./dispatch_json.ts";
+import { log } from "./util.ts";
+import { TextDecoder, TextEncoder } from "./text_encoding.ts";
+import * as runtime from "./runtime.ts";
+
+const encoder = new TextEncoder();
+const decoder = new TextDecoder();
+
+// TODO(bartlomieju): remove these funtions
+// Stuff for workers
+export const onmessage: (e: { data: any }) => void = (): void => {};
+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(dispatch.OP_WORKER_POST_MESSAGE, {}, dataIntArray);
+}
+
+export async function getMessage(): Promise<any> {
+ log("getMessage");
+ const res = await sendAsync(dispatch.OP_WORKER_GET_MESSAGE);
+ if (res.data != null) {
+ const dataIntArray = new Uint8Array(res.data);
+ const dataJson = decoder.decode(dataIntArray);
+ return JSON.parse(dataJson);
+ } else {
+ return null;
+ }
+}
+
+let isClosing = false;
+let hasBootstrapped = false;
+
+export function workerClose(): void {
+ isClosing = true;
+}
+
+export async function runWorkerMessageLoop(): Promise<void> {
+ while (!isClosing) {
+ const data = await getMessage();
+ if (data == null) {
+ log("runWorkerMessageLoop got null message. quitting.");
+ break;
+ }
+
+ let result: void | Promise<void>;
+ const event = { data };
+
+ try {
+ if (!globalThis["onmessage"]) {
+ break;
+ }
+ result = globalThis.onmessage!(event);
+ if (result && "then" in result) {
+ await result;
+ }
+ if (!globalThis["onmessage"]) {
+ break;
+ }
+ } catch (e) {
+ if (globalThis["onerror"]) {
+ const result = globalThis.onerror(
+ e.message,
+ e.fileName,
+ e.lineNumber,
+ e.columnNumber,
+ e
+ );
+ if (result === true) {
+ continue;
+ }
+ }
+ throw e;
+ }
+ }
+}
+
+export const workerRuntimeGlobalProperties = {
+ self: readOnly(globalThis),
+ onmessage: writable(onmessage),
+ onerror: writable(onerror),
+ workerClose: nonEnumerable(workerClose),
+ postMessage: writable(postMessage)
+};
+
+/**
+ * Main method to initialize worker runtime.
+ *
+ * It sets up global variables for DedicatedWorkerScope,
+ * and initializes ops.
+ */
+export function bootstrapWorkerRuntime(name: string): void {
+ if (hasBootstrapped) {
+ throw new Error("Worker runtime already bootstrapped");
+ }
+ log("bootstrapWorkerRuntime");
+ hasBootstrapped = true;
+ Object.defineProperties(globalThis, windowOrWorkerGlobalScopeMethods);
+ Object.defineProperties(globalThis, windowOrWorkerGlobalScopeProperties);
+ Object.defineProperties(globalThis, workerRuntimeGlobalProperties);
+ Object.defineProperties(globalThis, eventTargetProperties);
+ runtime.start(false, name);
+}
diff --git a/cli/js/worker_main.ts b/cli/js/worker_main.ts
deleted file mode 100644
index 16d1ef24e..000000000
--- a/cli/js/worker_main.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import * as dispatch from "./dispatch.ts";
-import { sendAsync, sendSync } from "./dispatch_json.ts";
-import { log } from "./util.ts";
-import { TextDecoder, TextEncoder } from "./text_encoding.ts";
-import { initOps } from "./os.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);
-}
-
-// Stuff for workers
-export const onmessage: (e: { data: any }) => void = (): void => {};
-export const onerror: (e: { data: any }) => void = (): void => {};
-
-export function postMessage(data: any): void {
- const dataIntArray = encodeMessage(data);
- sendSync(dispatch.OP_WORKER_POST_MESSAGE, {}, dataIntArray);
-}
-
-export async function getMessage(): Promise<any> {
- log("getMessage");
- const res = await sendAsync(dispatch.OP_WORKER_GET_MESSAGE);
- if (res.data != null) {
- return decodeMessage(new Uint8Array(res.data));
- } else {
- return null;
- }
-}
-
-export let isClosing = false;
-
-export function workerClose(): void {
- isClosing = true;
-}
-
-export async function bootstrapWorkerRuntime(): Promise<void> {
- initOps();
-
- log("bootstrapWorkerRuntime");
-
- while (!isClosing) {
- const data = await getMessage();
- if (data == null) {
- log("bootstrapWorkerRuntime got null message. quitting.");
- break;
- }
-
- let result: void | Promise<void>;
- const event = { data };
-
- try {
- if (!globalThis["onmessage"]) {
- break;
- }
- result = globalThis.onmessage!(event);
- if (result && "then" in result) {
- await result;
- }
- if (!globalThis["onmessage"]) {
- break;
- }
- } catch (e) {
- if (globalThis["onerror"]) {
- const result = globalThis.onerror(
- e.message,
- e.fileName,
- e.lineNumber,
- e.columnNumber,
- e
- );
- if (result === true) {
- continue;
- }
- }
- throw e;
- }
- }
-}