如何从字符串中将Sourcemap与评估TypeScript一起使用

Odu*_*van 6 javascript node.js typescript

我将首先显示代码(节点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)
Run Code Online (Sandbox Code Playgroud)

作为执行此代码的结果,我希望具有与给定内容变量相关的回溯(第3行中的错误),但是我不断在第2行中收到错误-这是代码的已编译版本中的错误行。

这是输出

{ 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)
Run Code Online (Sandbox Code Playgroud)

Lou*_*uis 5

您正在使用内联源地图和文件source-map-support规定:

为了支持带有内联源映射的文件,hookRequire可以指定选项,这将监视内联源映射的所有源文件。

您已设置hookRequire为 true。但是,我引用的source-map-support那段话表明依赖挂钩require来检测内联源映射,因此如果您的代码在没有通过的情况下执行,require那么它的源映射将不会被检测到并且source-map-support无法修复堆栈跟踪。事实上,如果我eval用这个代码替换你的电话:

fs.writeFileSync("myModule2.js", res1.outputText);

require("./myModule2");
Run Code Online (Sandbox Code Playgroud)

我得到这样的堆栈跟踪,行号正确:

ReferenceError: b is not defined
    at Object.<anonymous> (/tmp/t4/module.ts:3:1)
[...]
Run Code Online (Sandbox Code Playgroud)

文件名是module.ts因为该选项fileName尚未指定给ts.transpileModule. 您可以将其设置myModule2.ts为与moduleName.

此外,如果您更改编译器选项以同时内联源代码,如下所示:

var compilerOptions = {
  module: ts.ModuleKind.CommonJS,
  inlineSourceMap: true,
  inlineSources: true,
};
Run Code Online (Sandbox Code Playgroud)

你会得到一个更好的堆栈跟踪。随着compilerOptions像上面显示和fileName我前面提出的轨迹是:

/tmp/t4/myModule2.ts:3
b = b * a
^
ReferenceError: b is not defined
    at Object.<anonymous> (/tmp/t4/myModule2.ts:3:1)
Run Code Online (Sandbox Code Playgroud)

您可以在对ReferenceError导致问题的代码行的引用之前看到。


上面的方法是导致source-map-support修复源引用的最简单的方法。这是另一种更复杂的方法,它不需要将任何文件保存到磁盘,但需要自定义如何source-map-support从源文件路径获取源代码。源代码中的注释表明了新部件的作用。

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,
});
Run Code Online (Sandbox Code Playgroud)

运行上面的代码会产生以下输出:

/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)
[...]
Run Code Online (Sandbox Code Playgroud)

堆栈跟踪中的源行号被修改source-map-support为指向正确的位置,但没有修改最开始的源引用。问题在于使用的正则表达式source-map-support。正则表达式要求将源文件引用放在括号中(如(vm.js:123:20))。我已经尝试在处理异常之前对其source-map-support进行转换,使其符合正则表达式但source-map-support看不到转换。