From 82959b6b0edb9d57a2af61525010b59cd433613b Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 12 Mar 2019 00:55:43 +0800 Subject: [PATCH] development - enhancement for sourcemap validator tool (#6277) --- development/sourcemap-validator.js | 91 +++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 21 deletions(-) diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index 143888128..546745f16 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -1,6 +1,9 @@ const fs = require('fs') const { SourceMapConsumer } = require('source-map') const path = require('path') +const pify = require('pify') +const fsAsync = pify(fs) + // // Utility to help check if sourcemaps are working // @@ -9,39 +12,85 @@ const path = require('path') // if not working it may error or print minified garbage // -start() +start().catch(console.error) async function start () { - const rawBuild = fs.readFileSync(path.join(__dirname, '/../dist/chrome/', 'inpage.js') - , 'utf8') - const rawSourceMap = fs.readFileSync(path.join(__dirname, '/../dist/sourcemaps/', 'inpage.js.map'), 'utf8') + const targetFiles = [`inpage.js`, `contentscript.js`, `ui.js`, `background.js`] + for (const buildName of targetFiles) { + await validateSourcemapForFile({ buildName }) + } +} + +async function validateSourcemapForFile ({ buildName }) { + console.log(`build "${buildName}"`) + const platform = `chrome` + // load build and sourcemaps + let rawBuild + try { + const filePath = path.join(__dirname, `/../dist/${platform}/`, `${buildName}`) + rawBuild = await fsAsync.readFile(filePath, 'utf8') + } catch (err) {} + if (!rawBuild) { + throw new Error(`SourcemapValidator - failed to load source file for "${buildName}"`) + } + // attempt to load in dist mode + let rawSourceMap + try { + const filePath = path.join(__dirname, `/../dist/sourcemaps/`, `${buildName}.map`) + rawSourceMap = await fsAsync.readFile(filePath, 'utf8') + } catch (err) {} + // attempt to load in dev mode + try { + const filePath = path.join(__dirname, `/../dist/${platform}/`, `${buildName}.map`) + rawSourceMap = await fsAsync.readFile(filePath, 'utf8') + } catch (err) {} + if (!rawSourceMap) { + throw new Error(`SourcemapValidator - failed to load sourcemaps for "${buildName}"`) + } + const consumer = await new SourceMapConsumer(rawSourceMap) - console.log('hasContentsOfAllSources:', consumer.hasContentsOfAllSources(), '\n') - console.log('sources:') - consumer.sources.map((sourcePath) => console.log(sourcePath)) + const hasContentsOfAllSources = consumer.hasContentsOfAllSources() + if (!hasContentsOfAllSources) console.warn('SourcemapValidator - missing content of some sources...') - console.log('\nexamining "new Error" statements:\n') - const sourceLines = rawBuild.split('\n') - sourceLines.map(line => indicesOf('new Error', line)) - .forEach((errorIndices, lineIndex) => { - // if (errorIndex === null) return console.log('line does not contain "new Error"') - errorIndices.forEach((errorIndex) => { - const position = { line: lineIndex + 1, column: errorIndex } + console.log(` sampling from ${consumer.sources.length} files`) + let sampleCount = 0 + + const buildLines = rawBuild.split('\n') + const targetString = 'new Error' + // const targetString = 'null' + const matchesPerLine = buildLines.map(line => indicesOf(targetString, line)) + matchesPerLine.forEach((matchIndices, lineIndex) => { + matchIndices.forEach((matchColumn) => { + sampleCount++ + const position = { line: lineIndex + 1, column: matchColumn } const result = consumer.originalPositionFor(position) - if (!result.source) return console.warn(`!! missing source for position: ${position}`) - // filter out deps distributed minified without sourcemaps - if (result.source === 'node_modules/browserify/node_modules/browser-pack/_prelude.js') return // minified mess - if (result.source === 'node_modules/web3/dist/web3.min.js') return // minified mess + // warn if source content is missing + if (!result.source) { + console.warn(`!! missing source for position: ${JSON.stringify(position)}`) + // const buildLine = buildLines[position.line - 1] + console.warn(` origin in build:`) + console.warn(` ${buildLines[position.line - 2]}`) + console.warn(`-> ${buildLines[position.line - 1]}`) + console.warn(` ${buildLines[position.line - 0]}`) + return + } const sourceContent = consumer.sourceContentFor(result.source) const sourceLines = sourceContent.split('\n') const line = sourceLines[result.line - 1] - console.log(`\n========================== ${result.source} ====================================\n`) - console.log(line) - console.log(`\n==============================================================================\n`) + // this sometimes includes the whole line though we tried to match somewhere in the middle + const portion = line.slice(result.column) + const isMaybeValid = portion.includes(targetString) + if (!isMaybeValid) { + console.error('Sourcemap seems invalid:') + console.log(`\n========================== ${result.source} ====================================\n`) + console.log(line) + console.log(`\n==============================================================================\n`) + } }) }) + console.log(` checked ${sampleCount} samples`) } function indicesOf (substring, string) {