[英]How to use sourcemap with evaluation TypeScript from string
I'll show the code first (node 10.15.3): 我将首先显示代码(节点10.15.3):
var ts = require("typescript");
require('source-map-support').install({
environment: 'node',
hookRequire: true
})
var content = "let a = 0;\n\nb = b * a";
var compilerOptions = {
module: ts.ModuleKind.CommonJS,
inlineSourceMap: true
};
var res1 = ts.transpileModule(content, {
compilerOptions: compilerOptions,
moduleName: "myModule2"
});
console.log(res1);
console.log('-------')
console.log(content)
console.log('-------')
console.log(res1.outputText)
console.log('-------')
eval(res1.outputText)
As a result of executing this code I want to have a traceback related to a given content variable (Error in line 3), but I constantly receive an error in line 2 - which is line of error in compiled version of code. 由于执行此代码,我希望有一个与给定内容变量相关的回溯(第3行中的错误),但我经常在第2行收到错误 - 这是编译版本代码中的错误行。
Here is an output 这是一个输出
{ outputText:
'var a = 0;\nb = b * a;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUVWLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBIn0=',
diagnostics: [],
sourceMapText: undefined }
-------
let a = 0;
b = b * a
-------
var a = 0;
b = b * a;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUVWLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBIn0=
-------
SS: /root/ts-eval/exal.js undefined
SS: internal/modules/cjs/loader.js undefined
SS: internal/bootstrap/node.js undefined
ReferenceError: b is not defined
at eval (eval at <anonymous> (/root/ts-eval/exal.js:24:1), <anonymous>:2:1)
at Object.<anonymous> (/root/ts-eval/exal.js:24:1)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
You are using inline source maps, and the documentation for source-map-support
states: 您正在使用内联源映射,以及
source-map-support
状态的文档 :
To support files with inline source maps, the
hookRequire
options can be specified, which will monitor all source files for inline source maps.要支持具有内联源映射的文件,可以指定
hookRequire
选项,该选项将监视内联源映射的所有源文件。
You've set hookRequire
to true. 你已经将
hookRequire
设置为true。 However, the passage I've quoted indicates source-map-support
relies on hooking into require
to detect inline source maps, and so if your code executes without passing through require
then its source map won't be detected and source-map-support
won't be able to fix the stack trace. 但是,我引用的段落表明
source-map-support
依赖于挂钩到require
检测内联源映射,因此如果您的代码执行而不通过require
那么它的源映射将不会被检测到并且source-map-support
将无法修复堆栈跟踪。 Indeed if I replace your eval
call with this code: 确实,如果我用这段代码替换你的
eval
调用:
fs.writeFileSync("myModule2.js", res1.outputText);
require("./myModule2");
I get a stack trace like this, with the correct line number: 我得到这样的堆栈跟踪,使用正确的行号:
ReferenceError: b is not defined
at Object.<anonymous> (/tmp/t4/module.ts:3:1)
[...]
The file name is module.ts
because the option fileName
has not been specified to ts.transpileModule
. 文件名是
module.ts
因为没有为ts.transpileModule
指定选项fileName
。 You could set it to myModule2.ts
for consistency with moduleName
. 您可以将其设置为
myModule2.ts
以与moduleName
保持一致。
Also, if you change your compiler options to also inline the sources, like this: 此外,如果您将编译器选项更改为也内联源,如下所示:
var compilerOptions = {
module: ts.ModuleKind.CommonJS,
inlineSourceMap: true,
inlineSources: true,
};
You get a bit of a nicer stack trace. 你会得到一些更好的堆栈跟踪。 With
compilerOptions
like shown above and fileName
as I suggested earlier, the trace is: 使用如上所示的
compilerOptions
和我之前建议的fileName
,跟踪是:
/tmp/t4/myModule2.ts:3
b = b * a
^
ReferenceError: b is not defined
at Object.<anonymous> (/tmp/t4/myModule2.ts:3:1)
You can see before the ReferenceError
a reference to the line of code that caused the problem. 您可以在
ReferenceError
之前看到对导致问题的代码行的引用。
The approach above is the simplest one that results in source-map-support
fixing source references. 上面的方法是最简单的方法,导致
source-map-support
修复源引用。 Here is another, more complicated approach, which does not require saving any files to disk but requires customizing how source-map-support
gets source code from a source file path. 这是另一种更复杂的方法,它不需要将任何文件保存到磁盘,但需要定制
source-map-support
如何从源文件路径获取源代码。 The comments in the source indicate what the new part do. 源中的注释表明新部分的作用。
const fs = require("fs");
const ts = require("typescript");
const vm = require("vm");
const path = require("path");
// This establishes a mapping between sourcePaths and the actual source.
const sourcePathToSource = Object.create(null);
require("source-map-support").install({
environment: "node",
// Pass to source-map-support a custom function for retreiving sources
// from source paths. This runs after source-map-support's default logic,
// only if that logic fails to find the requested source.
retrieveFile: (sourcePath) => sourcePathToSource[sourcePath],
});
const content = "let a = 0;\n\nb = b * a";
const compilerOptions = {
module: ts.ModuleKind.CommonJS,
sourceMap: true,
inlineSources: true,
};
// The path that the ts module would have.
const tsPath = path.resolve("myModule2.ts");
const res1 = ts.transpileModule(content, {
compilerOptions: compilerOptions,
fileName: tsPath,
moduleName: "myModule2"
});
console.log(res1);
console.log("-------");
console.log(content);
console.log("-------");
console.log(res1.outputText);
console.log("-------");
// The path that the compiled module would have.
const jsPath = path.resolve("myModule2.js");
// Establish the relationship between the path and the source.
sourcePathToSource[jsPath] = res1.outputText;
// Ditto for the source map file.
sourcePathToSource[path.resolve("myModule2.js.map")] = res1.sourceMapText;
vm.runInThisContext(res1.outputText, {
filename: jsPath,
});
Running the code above results in this output: 运行上面的代码会导致此输出:
/tmp/t4/myModule2.js:2
b = b * a;
^
ReferenceError: b is not defined
at /tmp/t4/myModule2.ts:3:1
at Script.runInThisContext (vm.js:123:20)
[...]
The source line numbers in the stack trace are modified by source-map-support
to point to the right place but the source reference at the very beginning is not modified. 堆栈跟踪中的源行号由
source-map-support
修改为指向正确的位置,但最初的源引用不会被修改。 The problem is with the regular expression that source-map-support
uses. 问题在于
source-map-support
使用的正则表达式。 The regular expression requires the source file reference to be in parentheses (like (vm.js:123:20)
). 正则表达式要求源文件引用在括号中(如
(vm.js:123:20)
)。 I've tried transforming the exception before source-map-support
gets to it so that it fits the regular expression but source-map-support
does not see the transformation. 我已经尝试在
source-map-support
到达它之前转换异常,以便它适合正则表达式,但source-map-support
没有看到转换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.