summaryrefslogtreecommitdiff
path: root/js/runner.ts
diff options
context:
space:
mode:
Diffstat (limited to 'js/runner.ts')
-rw-r--r--js/runner.ts187
1 files changed, 0 insertions, 187 deletions
diff --git a/js/runner.ts b/js/runner.ts
deleted file mode 100644
index 11c47709d..000000000
--- a/js/runner.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2018 the Deno authors. All rights reserved. MIT license.
-// tslint:disable-next-line:no-circular-imports
-import * as deno from "./deno";
-import { globalEval } from "./global_eval";
-import { assert, log } from "./util";
-
-// tslint:disable:no-any
-type AmdCallback = (...args: any[]) => void;
-type AmdDefine = (deps: ModuleSpecifier[], factory: AmdFactory) => void;
-type AmdErrback = (err: any) => void;
-type AmdFactory = (...args: any[]) => object | void;
-type AmdRequire = (
- deps: ModuleSpecifier[],
- callback: AmdCallback,
- errback: AmdErrback
-) => void;
-// tslint:enable:no-any
-
-// tslint:disable-next-line:no-any
-type BuiltinMap = { [moduleSpecifier: string]: any };
-
-// Type aliases to make the code more readable
-type ContainingFile = string;
-type Filename = string;
-type ModuleSpecifier = string;
-type OutputCode = string;
-
-/** Internal representation of a module being loaded */
-class Module {
- deps?: Filename[];
- factory?: AmdFactory;
-
- // tslint:disable-next-line:no-any
- constructor(public filename: Filename, public exports: any) {}
-}
-
-/** External APIs which the runner depends upon to be able to retrieve
- * transpiled modules.
- */
-export interface CodeProvider {
- /** Given a module specifier and a containing file, return the filename. */
- getFilename(
- moduleSpecifier: ModuleSpecifier,
- containingFile: ContainingFile
- ): Filename;
-
- /** Given a filename, return the transpiled output code. */
- getOutput(filename: Filename): OutputCode;
-}
-
-const window = globalEval("this");
-
-/** A class which can load and run modules into the current environment. */
-export class Runner {
- private _globalEval = globalEval;
- /** A map of modules indexed by filename. */
- private _modules = new Map<Filename, Module>();
- private _provider: CodeProvider;
- /** Modules are placed in here to have their factories run after all the
- * the dependencies have been collected.
- */
- private _runQueue: Module[] = [];
-
- private _drainRunQueue(): void {
- log("runner._drainRunQueue", this._runQueue.length);
- let module: Module | undefined;
- while ((module = this._runQueue.shift())) {
- assert(module.factory != null, "Cannot run module without factory.");
- // TypeScript always imports `exports` and mutates it directly, but the
- // AMD specification allows values to be returned from the factory and
- // is the case with JSON modules and potentially other future features.
- const exports = module.factory!(...this._getFactoryArguments(module));
- if (exports != null) {
- module.exports = exports;
- }
- }
- }
-
- private _gatherDependencies(filename: Filename): void {
- log("runner._gatherDependencies", filename);
-
- if (this._modules.has(filename)) {
- log("Module already exists:", filename);
- return;
- }
-
- const module = new Module(filename, {});
- this._modules.set(filename, module);
-
- window.define = this._makeDefine(module);
- this._globalEval(this._provider.getOutput(filename));
- window.define = undefined;
- }
-
- // tslint:disable-next-line:no-any
- private _getFactoryArguments(module: Module): any[] {
- log("runner._getFactoryArguments", module.filename);
- assert(module.deps != null, "Missing dependencies for module.");
- return module.deps!.map(dep => {
- if (dep === "require") {
- return this._makeLocalRequire(module);
- }
- if (dep === "exports") {
- return module.exports;
- }
- if (dep in Runner._builtins) {
- return Runner._builtins[dep];
- }
- const depModule = this._modules.get(dep)!;
- assert(dep != null, `Missing dependency "${dep}"`);
- return depModule.exports;
- });
- }
-
- private _makeDefine(module: Module): AmdDefine {
- log("runner._makeDefine", module.filename);
- return (deps: ModuleSpecifier[], factory: AmdFactory): void => {
- module.factory = factory;
- module.deps = deps.map(dep => {
- if (dep === "require" || dep === "exports" || dep in Runner._builtins) {
- return dep;
- }
- const depFilename = this._provider.getFilename(dep, module.filename);
- if (!this._modules.get(depFilename)) {
- this._gatherDependencies(depFilename);
- }
- return depFilename;
- });
- if (!this._runQueue.includes(module)) {
- this._runQueue.push(module);
- }
- };
- }
-
- private _makeLocalRequire(module: Module): AmdRequire {
- log("runner._makeLocalRequire", module.filename);
- return (
- deps: ModuleSpecifier[],
- callback: AmdCallback,
- errback: AmdErrback
- ): void => {
- log("runner._makeLocalRequire", deps);
- assert(
- deps.length === 1,
- "Local require supports exactly one dependency."
- );
- const [moduleSpecifier] = deps;
- try {
- this.run(moduleSpecifier, module.filename);
- const requiredFilename = this._provider.getFilename(
- moduleSpecifier,
- module.filename
- );
- const requiredModule = this._modules.get(requiredFilename)!;
- assert(requiredModule != null);
- callback(requiredModule.exports);
- } catch (e) {
- errback(e);
- }
- };
- }
-
- constructor(provider: CodeProvider) {
- this._provider = provider;
- }
-
- /** Given a module specifier and the containing file, resolve the module and
- * ensure that it is in the runtime environment, returning the exports of the
- * module.
- */
- // tslint:disable-next-line:no-any
- run(moduleSpecifier: ModuleSpecifier, containingFile: ContainingFile): any {
- log("runner.run", moduleSpecifier, containingFile);
- const filename = this._provider.getFilename(
- moduleSpecifier,
- containingFile
- );
- if (!this._modules.has(filename)) {
- this._gatherDependencies(filename);
- this._drainRunQueue();
- }
- return this._modules.get(filename)!.exports;
- }
-
- /** Builtin modules which can be loaded by user modules. */
- private static _builtins: BuiltinMap = { deno };
-}