简体   繁体   English

如何将sourcemap与字符串中的TypeScript一起使用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM