mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
Improve preparing stack traces
This commit is contained in:
parent
7a17e2aec6
commit
f477b45a0a
4 changed files with 97 additions and 97 deletions
100
js/compiler.ts
100
js/compiler.ts
|
@ -10,7 +10,6 @@ import { window } from "./globals";
|
||||||
import * as os from "./os";
|
import * as os from "./os";
|
||||||
import { RawSourceMap } from "./types";
|
import { RawSourceMap } from "./types";
|
||||||
import { assert, log, notImplemented } from "./util";
|
import { assert, log, notImplemented } from "./util";
|
||||||
import * as sourceMaps from "./v8_source_maps";
|
|
||||||
|
|
||||||
const EOL = "\n";
|
const EOL = "\n";
|
||||||
const ASSETS = "$asset$";
|
const ASSETS = "$asset$";
|
||||||
|
@ -91,7 +90,7 @@ export class ModuleMetaData implements ts.IScriptSnapshot {
|
||||||
public readonly mediaType: MediaType,
|
public readonly mediaType: MediaType,
|
||||||
public readonly sourceCode: SourceCode = "",
|
public readonly sourceCode: SourceCode = "",
|
||||||
public outputCode: OutputCode = "",
|
public outputCode: OutputCode = "",
|
||||||
public sourceMap: SourceMap = ""
|
public sourceMap: SourceMap | RawSourceMap = ""
|
||||||
) {
|
) {
|
||||||
if (outputCode !== "" || fileName.endsWith(".d.ts")) {
|
if (outputCode !== "" || fileName.endsWith(".d.ts")) {
|
||||||
this.scriptVersion = "1";
|
this.scriptVersion = "1";
|
||||||
|
@ -153,6 +152,8 @@ export class DenoCompiler
|
||||||
>();
|
>();
|
||||||
// A reference to global eval, so it can be monkey patched during testing
|
// A reference to global eval, so it can be monkey patched during testing
|
||||||
private _globalEval = globalEval;
|
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
|
// A reference to the log utility, so it can be monkey patched during testing
|
||||||
private _log = log;
|
private _log = log;
|
||||||
// A map of module file names to module meta data
|
// A map of module file names to module meta data
|
||||||
|
@ -376,63 +377,11 @@ export class DenoCompiler
|
||||||
innerMap.set(moduleSpecifier, fileName);
|
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() {
|
private constructor() {
|
||||||
if (DenoCompiler._instance) {
|
if (DenoCompiler._instance) {
|
||||||
throw new TypeError("Attempt to create an additional compiler.");
|
throw new TypeError("Attempt to create an additional compiler.");
|
||||||
}
|
}
|
||||||
this._service = this._ts.createLanguageService(this);
|
this._service = this._ts.createLanguageService(this);
|
||||||
this._setupSourceMaps();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deno specific compiler API
|
// Deno specific compiler API
|
||||||
|
@ -503,19 +452,55 @@ export class DenoCompiler
|
||||||
moduleMetaData.outputCode = `${
|
moduleMetaData.outputCode = `${
|
||||||
outputFile.text
|
outputFile.text
|
||||||
}\n//# sourceURL=${fileName}`;
|
}\n//# sourceURL=${fileName}`;
|
||||||
moduleMetaData.sourceMap = sourceMapFile.text;
|
moduleMetaData.sourceMap = JSON.parse(sourceMapFile.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
moduleMetaData.scriptVersion = "1";
|
moduleMetaData.scriptVersion = "1";
|
||||||
|
const sourceMap =
|
||||||
|
moduleMetaData.sourceMap === "string"
|
||||||
|
? moduleMetaData.sourceMap
|
||||||
|
: JSON.stringify(moduleMetaData.sourceMap);
|
||||||
this._os.codeCache(
|
this._os.codeCache(
|
||||||
fileName,
|
fileName,
|
||||||
sourceCode,
|
sourceCode,
|
||||||
moduleMetaData.outputCode,
|
moduleMetaData.outputCode,
|
||||||
moduleMetaData.sourceMap
|
sourceMap
|
||||||
);
|
);
|
||||||
return moduleMetaData.outputCode;
|
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
|
/** For a given module specifier and containing file, return a list of
|
||||||
* absolute identifiers for dependent modules that are required by this
|
* absolute identifiers for dependent modules that are required by this
|
||||||
* module.
|
* module.
|
||||||
|
@ -586,7 +571,8 @@ export class DenoCompiler
|
||||||
mediaType = fetchResponse.mediaType;
|
mediaType = fetchResponse.mediaType;
|
||||||
sourceCode = fetchResponse.sourceCode;
|
sourceCode = fetchResponse.sourceCode;
|
||||||
outputCode = fetchResponse.outputCode;
|
outputCode = fetchResponse.outputCode;
|
||||||
sourceMap = fetchResponse.sourceMap;
|
sourceMap =
|
||||||
|
fetchResponse.sourceMap && JSON.parse(fetchResponse.sourceMap);
|
||||||
}
|
}
|
||||||
assert(moduleId != null, "No module ID.");
|
assert(moduleId != null, "No module ID.");
|
||||||
assert(fileName != null, "No file name.");
|
assert(fileName != null, "No file name.");
|
||||||
|
|
|
@ -438,7 +438,7 @@ test(function compilerRun() {
|
||||||
assert(moduleMetaData.hasRun);
|
assert(moduleMetaData.hasRun);
|
||||||
assertEqual(moduleMetaData.sourceCode, fooBarTsSource);
|
assertEqual(moduleMetaData.sourceCode, fooBarTsSource);
|
||||||
assertEqual(moduleMetaData.outputCode, fooBarTsOutput);
|
assertEqual(moduleMetaData.outputCode, fooBarTsOutput);
|
||||||
assertEqual(moduleMetaData.sourceMap, fooBarTsSourcemap);
|
assertEqual(JSON.stringify(moduleMetaData.sourceMap), fooBarTsSourcemap);
|
||||||
assertEqual(moduleMetaData.exports, { foo: "bar" });
|
assertEqual(moduleMetaData.exports, { foo: "bar" });
|
||||||
|
|
||||||
assertEqual(
|
assertEqual(
|
||||||
|
@ -550,7 +550,7 @@ test(function compilerResolveModule() {
|
||||||
);
|
);
|
||||||
assertEqual(moduleMetaData.sourceCode, fooBazTsSource);
|
assertEqual(moduleMetaData.sourceCode, fooBazTsSource);
|
||||||
assertEqual(moduleMetaData.outputCode, fooBazTsOutput);
|
assertEqual(moduleMetaData.outputCode, fooBazTsOutput);
|
||||||
assertEqual(moduleMetaData.sourceMap, fooBazTsSourcemap);
|
assertEqual(JSON.stringify(moduleMetaData.sourceMap), fooBazTsSourcemap);
|
||||||
assert(!moduleMetaData.hasRun);
|
assert(!moduleMetaData.hasRun);
|
||||||
assert(!moduleMetaData.deps);
|
assert(!moduleMetaData.deps);
|
||||||
assertEqual(moduleMetaData.exports, {});
|
assertEqual(moduleMetaData.exports, {});
|
||||||
|
|
12
js/main.ts
12
js/main.ts
|
@ -9,11 +9,19 @@ import { args } from "./deno";
|
||||||
import { sendSync, handleAsyncMsgFromRust } from "./dispatch";
|
import { sendSync, handleAsyncMsgFromRust } from "./dispatch";
|
||||||
import { promiseErrorExaminer, promiseRejectHandler } from "./promise_util";
|
import { promiseErrorExaminer, promiseRejectHandler } from "./promise_util";
|
||||||
import { replLoop } from "./repl";
|
import { replLoop } from "./repl";
|
||||||
|
import * as sourceMaps from "./v8_source_maps";
|
||||||
import { version } from "typescript";
|
import { version } from "typescript";
|
||||||
|
|
||||||
// Instantiate compiler at the top-level so it decodes source maps for the main
|
// Install the source maps handler and do some pre-calculations so all of it is
|
||||||
// bundle during snapshot.
|
// available in the snapshot
|
||||||
const compiler = DenoCompiler.instance();
|
const compiler = DenoCompiler.instance();
|
||||||
|
sourceMaps.install({
|
||||||
|
installPrepareStackTrace: true,
|
||||||
|
getGeneratedContents: compiler.getGeneratedContents
|
||||||
|
});
|
||||||
|
const consumer = sourceMaps.loadConsumer("gen/bundle/main.js");
|
||||||
|
assert(consumer != null);
|
||||||
|
consumer!.computeColumnSpans();
|
||||||
|
|
||||||
function sendStart(): msg.StartRes {
|
function sendStart(): msg.StartRes {
|
||||||
const builder = flatbuffers.createBuilder();
|
const builder = flatbuffers.createBuilder();
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
// Originated from source-map-support but has been heavily modified for deno.
|
// Originated from source-map-support but has been heavily modified for deno.
|
||||||
|
|
||||||
import { SourceMapConsumer, MappedPosition } from "source-map";
|
import { SourceMapConsumer, MappedPosition } from "source-map";
|
||||||
import * as base64 from "base64-js";
|
|
||||||
import { arrayToStr } from "./util";
|
|
||||||
import { CallSite, RawSourceMap } from "./types";
|
import { CallSite, RawSourceMap } from "./types";
|
||||||
|
import { atob } from "./text_encoding";
|
||||||
|
|
||||||
const consumers = new Map<string, SourceMapConsumer>();
|
const consumers = new Map<string, SourceMapConsumer>();
|
||||||
|
|
||||||
|
@ -53,9 +52,9 @@ export function prepareStackTraceWrapper(
|
||||||
// @internal
|
// @internal
|
||||||
export function prepareStackTrace(error: Error, stack: CallSite[]): string {
|
export function prepareStackTrace(error: Error, stack: CallSite[]): string {
|
||||||
const frames = stack.map(
|
const frames = stack.map(
|
||||||
(frame: CallSite) => `\n at ${wrapCallSite(frame).toString()}`
|
frame => `\n at ${wrapCallSite(frame).toString()}`
|
||||||
);
|
);
|
||||||
return error.toString() + frames.join("");
|
return `${error.toString()}${frames.join("")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @internal
|
// @internal
|
||||||
|
@ -74,11 +73,13 @@ export function wrapCallSite(frame: CallSite): CallSite {
|
||||||
const column = (frame.getColumnNumber() || 1) - 1;
|
const column = (frame.getColumnNumber() || 1) - 1;
|
||||||
const position = mapSourcePosition({ source, line, column });
|
const position = mapSourcePosition({ source, line, column });
|
||||||
frame = cloneCallSite(frame);
|
frame = cloneCallSite(frame);
|
||||||
frame.getFileName = () => position.source;
|
Object.assign(frame, {
|
||||||
frame.getLineNumber = () => position.line;
|
getFileName: () => position.source,
|
||||||
frame.getColumnNumber = () => Number(position.column) + 1;
|
getLineNumber: () => position.line,
|
||||||
frame.getScriptNameOrSourceURL = () => position.source;
|
getColumnNumber: () => Number(position.column) + 1,
|
||||||
frame.toString = () => CallSiteToString(frame);
|
getScriptNameOrSourceURL: () => position.source,
|
||||||
|
toString: () => CallSiteToString(frame)
|
||||||
|
});
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +88,10 @@ export function wrapCallSite(frame: CallSite): CallSite {
|
||||||
if (origin) {
|
if (origin) {
|
||||||
origin = mapEvalOrigin(origin);
|
origin = mapEvalOrigin(origin);
|
||||||
frame = cloneCallSite(frame);
|
frame = cloneCallSite(frame);
|
||||||
frame.getEvalOrigin = () => origin;
|
Object.assign(frame, {
|
||||||
frame.toString = () => CallSiteToString(frame);
|
getEvalOrigin: () => origin,
|
||||||
|
toString: () => CallSiteToString(frame)
|
||||||
|
});
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,29 +99,30 @@ export function wrapCallSite(frame: CallSite): CallSite {
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cloneCallSite(frame: CallSite): CallSite {
|
function cloneCallSite(
|
||||||
// tslint:disable:no-any
|
frame: CallSite
|
||||||
const obj: any = {};
|
// mixin: Partial<CallSite> & { toString: () => string }
|
||||||
const frame_ = frame as any;
|
): CallSite {
|
||||||
const props = Object.getOwnPropertyNames(Object.getPrototypeOf(frame));
|
const obj = {} as CallSite;
|
||||||
props.forEach(name => {
|
const props = Object.getOwnPropertyNames(
|
||||||
|
Object.getPrototypeOf(frame)
|
||||||
|
) as Array<keyof CallSite>;
|
||||||
|
for (const name of props) {
|
||||||
obj[name] = /^(?:is|get)/.test(name)
|
obj[name] = /^(?:is|get)/.test(name)
|
||||||
? () => frame_[name].call(frame)
|
? () => frame[name].call(frame)
|
||||||
: frame_[name];
|
: frame[name];
|
||||||
});
|
}
|
||||||
return (obj as any) as CallSite;
|
return obj;
|
||||||
// tslint:enable:no-any
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Taken from source-map-support, original copied from V8's messages.js
|
// Taken from source-map-support, original copied from V8's messages.js
|
||||||
// MIT License. Copyright (c) 2014 Evan Wallace
|
// MIT License. Copyright (c) 2014 Evan Wallace
|
||||||
function CallSiteToString(frame: CallSite): string {
|
function CallSiteToString(frame: CallSite): string {
|
||||||
let fileName;
|
|
||||||
let fileLocation = "";
|
let fileLocation = "";
|
||||||
if (frame.isNative()) {
|
if (frame.isNative()) {
|
||||||
fileLocation = "native";
|
fileLocation = "native";
|
||||||
} else {
|
} else {
|
||||||
fileName = frame.getScriptNameOrSourceURL();
|
const fileName = frame.getScriptNameOrSourceURL();
|
||||||
if (!fileName && frame.isEval()) {
|
if (!fileName && frame.isEval()) {
|
||||||
fileLocation = frame.getEvalOrigin() || "";
|
fileLocation = frame.getEvalOrigin() || "";
|
||||||
fileLocation += ", "; // Expecting source position to follow.
|
fileLocation += ", "; // Expecting source position to follow.
|
||||||
|
@ -134,10 +138,10 @@ function CallSiteToString(frame: CallSite): string {
|
||||||
}
|
}
|
||||||
const lineNumber = frame.getLineNumber();
|
const lineNumber = frame.getLineNumber();
|
||||||
if (lineNumber != null) {
|
if (lineNumber != null) {
|
||||||
fileLocation += ":" + String(lineNumber);
|
fileLocation += `:${lineNumber}`;
|
||||||
const columnNumber = frame.getColumnNumber();
|
const columnNumber = frame.getColumnNumber();
|
||||||
if (columnNumber) {
|
if (columnNumber) {
|
||||||
fileLocation += ":" + String(columnNumber);
|
fileLocation += `:${columnNumber}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +160,7 @@ function CallSiteToString(frame: CallSite): string {
|
||||||
const methodName = frame.getMethodName();
|
const methodName = frame.getMethodName();
|
||||||
if (functionName) {
|
if (functionName) {
|
||||||
if (typeName && functionName.indexOf(typeName) !== 0) {
|
if (typeName && functionName.indexOf(typeName) !== 0) {
|
||||||
line += typeName + ".";
|
line += `${typeName}.`;
|
||||||
}
|
}
|
||||||
line += functionName;
|
line += functionName;
|
||||||
if (
|
if (
|
||||||
|
@ -206,8 +210,7 @@ export function loadConsumer(source: string): SourceMapConsumer | null {
|
||||||
if (reSourceMap.test(sourceMappingURL)) {
|
if (reSourceMap.test(sourceMappingURL)) {
|
||||||
// Support source map URL as a data url
|
// Support source map URL as a data url
|
||||||
const rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(",") + 1);
|
const rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(",") + 1);
|
||||||
const ui8 = base64.toByteArray(rawData);
|
sourceMapData = atob(rawData);
|
||||||
sourceMapData = arrayToStr(ui8);
|
|
||||||
sourceMappingURL = source;
|
sourceMappingURL = source;
|
||||||
} else {
|
} else {
|
||||||
// TODO Support source map URLs relative to the source URL
|
// TODO Support source map URLs relative to the source URL
|
||||||
|
@ -217,7 +220,7 @@ export function loadConsumer(source: string): SourceMapConsumer | null {
|
||||||
|
|
||||||
const rawSourceMap =
|
const rawSourceMap =
|
||||||
typeof sourceMapData === "string"
|
typeof sourceMapData === "string"
|
||||||
? JSON.parse(sourceMapData)
|
? (JSON.parse(sourceMapData) as RawSourceMap)
|
||||||
: sourceMapData;
|
: sourceMapData;
|
||||||
consumer = new SourceMapConsumer(rawSourceMap);
|
consumer = new SourceMapConsumer(rawSourceMap);
|
||||||
consumers.set(source, consumer);
|
consumers.set(source, consumer);
|
||||||
|
@ -225,14 +228,14 @@ export function loadConsumer(source: string): SourceMapConsumer | null {
|
||||||
return consumer;
|
return consumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line:max-line-length
|
||||||
|
const sourceMapUrlRe = /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/)[ \t]*$)/gm;
|
||||||
|
|
||||||
function retrieveSourceMapURL(fileData: string): string | null {
|
function retrieveSourceMapURL(fileData: string): string | null {
|
||||||
// Get the URL of the source map
|
|
||||||
// tslint:disable-next-line:max-line-length
|
|
||||||
const re = /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/)[ \t]*$)/gm;
|
|
||||||
// Keep executing the search to find the *last* sourceMappingURL to avoid
|
// Keep executing the search to find the *last* sourceMappingURL to avoid
|
||||||
// picking up sourceMappingURLs from comments, strings, etc.
|
// picking up sourceMappingURLs from comments, strings, etc.
|
||||||
let lastMatch, match;
|
let lastMatch, match;
|
||||||
while ((match = re.exec(fileData))) {
|
while ((match = sourceMapUrlRe.exec(fileData))) {
|
||||||
lastMatch = match;
|
lastMatch = match;
|
||||||
}
|
}
|
||||||
if (!lastMatch) {
|
if (!lastMatch) {
|
||||||
|
@ -249,11 +252,14 @@ export function mapSourcePosition(position: Position): MappedPosition {
|
||||||
return consumer.originalPositionFor(position);
|
return consumer.originalPositionFor(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const stackEvalRe = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/;
|
||||||
|
const nestedEvalRe = /^eval at ([^(]+) \((.+)\)$/;
|
||||||
|
|
||||||
// Parses code generated by FormatEvalOrigin(), a function inside V8:
|
// Parses code generated by FormatEvalOrigin(), a function inside V8:
|
||||||
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js
|
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js
|
||||||
function mapEvalOrigin(origin: string): string {
|
function mapEvalOrigin(origin: string): string {
|
||||||
// Most eval() calls are in this format
|
// Most eval() calls are in this format
|
||||||
let match = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin);
|
let match = stackEvalRe.exec(origin);
|
||||||
if (match) {
|
if (match) {
|
||||||
const position = mapSourcePosition({
|
const position = mapSourcePosition({
|
||||||
source: match[2],
|
source: match[2],
|
||||||
|
@ -269,7 +275,7 @@ function mapEvalOrigin(origin: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse nested eval() calls using recursion
|
// Parse nested eval() calls using recursion
|
||||||
match = /^eval at ([^(]+) \((.+)\)$/.exec(origin);
|
match = nestedEvalRe.exec(origin);
|
||||||
if (match) {
|
if (match) {
|
||||||
return `eval at ${match[1]} (${mapEvalOrigin(match[2])})`;
|
return `eval at ${match[1]} (${mapEvalOrigin(match[2])})`;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue