Как я могу скрыть вызов функции из переданного кода с использованием исходных карт?

Скажем, у меня есть язык, который выглядит как

print "Hello World"

который преобразуется в

var $__Helpers = {
    print: function(s) {
        if (typeof s != 'string')
            throw new TypeError('String expected');
        console.log(s);
    }
};

$__Helpers.print("Hello World");

Если пользователь этого языка делает

print 5

a TypeError будет выбрано $__Helpers.print, говорящим "String expected". Я хочу, чтобы инструменты разработчика отображали строку print 5 как исходный вызов этой ошибки. Я знаю, как получить исходную карту, чтобы показать стек вызовов, который выглядит как

transpiled_script.js:2
original_script.os:1

где transpiled_script.js:2 - script и номер строки для вызова функции $__Helpers.print, а original_script.os:1 - это script и номер строки для вызова print 5. Я хочу, чтобы инструменты dev просто игнорировали верхний вызов transpiled_script.js (который является только деталью реализации моего транспилятора) и показывают только вызов из исходного script (который является частью, которую они должны отлаживать в своих собственных script).

Я явно не могу просто сопоставить transpiled_script.js:2 с original_script.os:1, потому что внутри original_script.os может быть несколько вызовов print, поэтому это не отношение 1 к 1.

Есть ли способ сделать это?

(Я использую escodegen для генерации моего источника и моей исходной карты (escodegen использует модуль Node mozilla/source-map), поэтому для того, чтобы сказать, что escodegen или mozilla/source-map сделали это, было бы идеально, но я могу переопределить вывод escodegen, если это невозможно.)

Ответ 1

Вы можете разделить трассировку и напечатать требуемые строки

var $__Helpers = {
    print: function(s) {
        if (typeof s != 'string'){
            var err = new TypeError('String expected');
            var trace = err.stack.split('\n')
            console.error(trace[0]); // TypeError: string expected
            console.error(trace[2]); // the line who called the function, probably 
            //original_script.os:1, or whatever line number the call was from
            //quit the script

        }
        console.log(s);
    } };

EDIT: лучшее решение - заменить след ошибки, чем выбросить, теперь код выглядит следующим образом:

var $__Helpers = {
    print: function(s) {
        if (typeof s != 'string'){
            var err = new TypeError('String expected: Got'+s);
            err.stack = err.stack.replace(/\n.*transpiled_script\.js.*?\n/g,"\n");
            throw err;

        }
        console.log(s);
    } };

это тоже будет работать для ошибок в вложенных вызовах.