Improve preparing stack traces

This commit is contained in:
Kitson Kelly 2018-11-06 15:08:25 +11:00 committed by Ryan Dahl
parent 7a17e2aec6
commit f477b45a0a
4 changed files with 97 additions and 97 deletions

View file

@ -10,7 +10,6 @@ import { window } from "./globals";
import * as os from "./os";
import { RawSourceMap } from "./types";
import { assert, log, notImplemented } from "./util";
import * as sourceMaps from "./v8_source_maps";
const EOL = "\n";
const ASSETS = "$asset$";
@ -91,7 +90,7 @@ export class ModuleMetaData implements ts.IScriptSnapshot {
public readonly mediaType: MediaType,
public readonly sourceCode: SourceCode = "",
public outputCode: OutputCode = "",
public sourceMap: SourceMap = ""
public sourceMap: SourceMap | RawSourceMap = ""
) {
if (outputCode !== "" || fileName.endsWith(".d.ts")) {
this.scriptVersion = "1";
@ -153,6 +152,8 @@ export class DenoCompiler
>();
// A reference to global eval, so it can be monkey patched during testing
private _globalEval = globalEval;
// Keep track of state of the last module requested via `getGeneratedContents`
private _lastModule: ModuleMetaData | undefined;
// A reference to the log utility, so it can be monkey patched during testing
private _log = log;
// A map of module file names to module meta data
@ -376,63 +377,11 @@ export class DenoCompiler
innerMap.set(moduleSpecifier, fileName);
}
/** Setup being able to map back source references back to their source
*
* TODO is this the best place for this? It is tightly coupled to how the
* compiler works, but it is also tightly coupled to how the whole runtime
* environment is bootstrapped. It also needs efficient access to the
* `outputCode` of the module information, which exists inside of the
* compiler instance.
*/
private _setupSourceMaps(): void {
let lastModule: ModuleMetaData | undefined;
sourceMaps.install({
installPrepareStackTrace: true,
getGeneratedContents: (fileName: string): string | RawSourceMap => {
this._log("compiler.getGeneratedContents", fileName);
if (fileName === "gen/bundle/main.js") {
assert(libdeno.mainSource.length > 0);
return libdeno.mainSource;
} else if (fileName === "main.js.map") {
return libdeno.mainSourceMap;
} else if (fileName === "deno_main.js") {
return "";
} else if (!fileName.endsWith(".map")) {
const moduleMetaData = this._moduleMetaDataMap.get(fileName);
if (!moduleMetaData) {
lastModule = undefined;
return "";
}
lastModule = moduleMetaData;
return moduleMetaData.outputCode;
} else {
if (lastModule && lastModule.sourceMap) {
// Assuming the the map will always be asked for after the source
// code.
const { sourceMap } = lastModule;
lastModule = undefined;
return sourceMap;
} else {
// Errors thrown here are caught by source-map.
throw new Error(`Unable to find source map: "${fileName}"`);
}
}
}
});
// Pre-compute source maps for main.js.map. This will happen at compile-time
// as long as Compiler is instanciated before the snapshot is created..
const consumer = sourceMaps.loadConsumer("gen/bundle/main.js");
assert(consumer != null);
consumer!.computeColumnSpans();
}
private constructor() {
if (DenoCompiler._instance) {
throw new TypeError("Attempt to create an additional compiler.");
}
this._service = this._ts.createLanguageService(this);
this._setupSourceMaps();
}
// Deno specific compiler API
@ -503,19 +452,55 @@ export class DenoCompiler
moduleMetaData.outputCode = `${
outputFile.text
}\n//# sourceURL=${fileName}`;
moduleMetaData.sourceMap = sourceMapFile.text;
moduleMetaData.sourceMap = JSON.parse(sourceMapFile.text);
}
moduleMetaData.scriptVersion = "1";
const sourceMap =
moduleMetaData.sourceMap === "string"
? moduleMetaData.sourceMap
: JSON.stringify(moduleMetaData.sourceMap);
this._os.codeCache(
fileName,
sourceCode,
moduleMetaData.outputCode,
moduleMetaData.sourceMap
sourceMap
);
return moduleMetaData.outputCode;
}
/** Given a fileName, return what was generated by the compiler. */
getGeneratedContents = (fileName: string): string | RawSourceMap => {
this._log("compiler.getGeneratedContents", fileName);
if (fileName === "gen/bundle/main.js") {
assert(libdeno.mainSource.length > 0);
return libdeno.mainSource;
} else if (fileName === "main.js.map") {
return libdeno.mainSourceMap;
} else if (fileName === "deno_main.js") {
return "";
} else if (!fileName.endsWith(".map")) {
const moduleMetaData = this._moduleMetaDataMap.get(fileName);
if (!moduleMetaData) {
this._lastModule = undefined;
return "";
}
this._lastModule = moduleMetaData;
return moduleMetaData.outputCode;
} else {
if (this._lastModule && this._lastModule.sourceMap) {
// Assuming the the map will always be asked for after the source
// code.
const { sourceMap } = this._lastModule;
this._lastModule = undefined;
return sourceMap;
} else {
// Errors thrown here are caught by source-map.
throw new Error(`Unable to find source map: "${fileName}"`);
}
}
};
/** For a given module specifier and containing file, return a list of
* absolute identifiers for dependent modules that are required by this
* module.
@ -586,7 +571,8 @@ export class DenoCompiler
mediaType = fetchResponse.mediaType;
sourceCode = fetchResponse.sourceCode;
outputCode = fetchResponse.outputCode;
sourceMap = fetchResponse.sourceMap;
sourceMap =
fetchResponse.sourceMap && JSON.parse(fetchResponse.sourceMap);
}
assert(moduleId != null, "No module ID.");
assert(fileName != null, "No file name.");