Just discovered that you try to read sourcemap while consuming logs.
Though seeing your implementation it can't work with wepback.
this line https://github.com/NativeScript/nativescript-cli/blob/master/lib/services/ios-log-filter.ts#L97 is checking for the file in the project folder. However with wepback that file is in the build folder much deeper.
As far as I can see This code can't work under the new 6.0 default; unless you are using the --env.hiddenSourceMap to generate the source maps externally... As using --env.hiddenSourceMap=blah will then create a blah/*.map files (but NOT put them in the bundle/vendor/worker.js files.)
Using--evn.sourceMap actually embeds the source map inside the bundle.js, vendor.js and *.worker.js files and not a separate .map file.
Several things up for discussion...
--env.sourceMap should be enabled by default in 5.4.x and 6.0 on NON-release builds. This way source maps are ALWAYS available for the CLI in the normal run/debug usage. (i.e. tns run android or tns debug ios) This will also give chrome tools the sourcemap for debug mode. So effectively I think this should probably be the default setting for run or debug under the 6.0 webpack system.Now the logic to grab the source map from the bundle.js (or the other.js files); it is pretty trivial --
// You can wrap this in a promise and do async calls but to show you how to easily I used sync...
// fileName is the path to where "bundle.js", "vendor.js" or "*.worker.js" files...
const data = fs.readFileSync(fileName);
// indexOf is faster than regex and supported on a native Buffer object
const idx = data.indexOf("//# sourceMappingURL=");
if (idx < 0) { return null; /* No Source Map */ }
// This line moves you to the position in the file, and extracts it, converts it from base64 into text string.
const newData = Buffer.from(data.slice(idx+63).toString(), 'base64').toString('binary')
// Finally parse the json data into a source map object...
try {
return JSON.parse(newData);
} catch (err) {
return null;
}
And to parse it (your already including source-map library in the codebase)
new SourceMap.SourceMapConsumer(sourceMap).then((consumer) => {
let output = consumer.originalPositionFor({line: args.line, column: args.column});
console.log(output)...
});
You might consider actually creating a consumer tracking object; and open up the bundle.js, vendor.js and *.worker.js files at startup. Pull out the sourcemaps; then as your logger is going through changing data; you can just do:
output( consumer[JSFileName].originalPositionFor(line, column); )
and it would then do inline replaces for the JS from "bundle.js line 500, column 30" to "app/main-page.ts line 25, column 5"... :grinning:
@NathanaelA you are right indeed. I did not talk about that point cause i am using my own webpack config with external sourceMap already ;)
Most helpful comment
As far as I can see This code can't work under the new 6.0 default; unless you are using the
--env.hiddenSourceMapto generate the source maps externally... As using--env.hiddenSourceMap=blahwill then create ablah/*.mapfiles (but NOT put them in the bundle/vendor/worker.js files.)Using
--evn.sourceMapactually embeds the source map inside thebundle.js,vendor.jsand*.worker.jsfiles and not a separate .map file.Several things up for discussion...
--env.sourceMapshould be enabled by default in 5.4.x and 6.0 on NON-release builds. This way source maps are ALWAYS available for the CLI in the normal run/debug usage. (i.e.tns run androidortns debug ios) This will also give chrome tools the sourcemap for debug mode. So effectively I think this should probably be the default setting forrunordebugunder the 6.0 webpack system.Now the logic to grab the source map from the bundle.js (or the other.js files); it is pretty trivial --
And to parse it (your already including source-map library in the codebase)
You might consider actually creating a consumer tracking object; and open up the bundle.js, vendor.js and *.worker.js files at startup. Pull out the sourcemaps; then as your logger is going through changing data; you can just do:
output( consumer[JSFileName].originalPositionFor(line, column); )
and it would then do inline replaces for the JS from "bundle.js line 500, column 30" to "app/main-page.ts line 25, column 5"... :grinning: