first commit
This commit is contained in:
177
node_modules/sorcery/src/Node.js
generated
vendored
Normal file
177
node_modules/sorcery/src/Node.js
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
import { dirname, resolve } from 'path';
|
||||
import { readFile, readFileSync, Promise } from 'sander';
|
||||
import { decode } from '@jridgewell/sourcemap-codec';
|
||||
import getMap from './utils/getMap.js';
|
||||
|
||||
export default function Node ({ file, content }) {
|
||||
this.file = file ? resolve( file ) : null;
|
||||
this.content = content || null; // sometimes exists in sourcesContent, sometimes doesn't
|
||||
|
||||
if ( !this.file && this.content === null ) {
|
||||
throw new Error( 'A source must specify either file or content' );
|
||||
}
|
||||
|
||||
// these get filled in later
|
||||
this.map = null;
|
||||
this.mappings = null;
|
||||
this.sources = null;
|
||||
this.isOriginalSource = null;
|
||||
|
||||
this._stats = {
|
||||
decodingTime: 0,
|
||||
encodingTime: 0,
|
||||
tracingTime: 0,
|
||||
|
||||
untraceable: 0
|
||||
};
|
||||
}
|
||||
|
||||
Node.prototype = {
|
||||
load ( sourcesContentByPath, sourceMapByPath ) {
|
||||
return getContent( this, sourcesContentByPath ).then( content => {
|
||||
this.content = sourcesContentByPath[ this.file ] = content;
|
||||
|
||||
return getMap( this, sourceMapByPath ).then( map => {
|
||||
if ( !map ) return null;
|
||||
|
||||
this.map = map;
|
||||
|
||||
let decodingStart = process.hrtime();
|
||||
this.mappings = decode( map.mappings );
|
||||
let decodingTime = process.hrtime( decodingStart );
|
||||
this._stats.decodingTime = 1e9 * decodingTime[0] + decodingTime[1];
|
||||
|
||||
const sourcesContent = map.sourcesContent || [];
|
||||
|
||||
const sourceRoot = resolve( dirname( this.file || '' ), map.sourceRoot || '' );
|
||||
|
||||
this.sources = map.sources.map( ( source, i ) => {
|
||||
return new Node({
|
||||
file: source ? resolve( sourceRoot, source ) : null,
|
||||
content: sourcesContent[i]
|
||||
});
|
||||
});
|
||||
|
||||
const promises = this.sources.map( node => node.load( sourcesContentByPath, sourceMapByPath ) );
|
||||
return Promise.all( promises );
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
loadSync ( sourcesContentByPath, sourceMapByPath ) {
|
||||
if ( !this.content ) {
|
||||
if ( !sourcesContentByPath[ this.file ] ) {
|
||||
sourcesContentByPath[ this.file ] = readFileSync( this.file, { encoding: 'utf-8' });
|
||||
}
|
||||
|
||||
this.content = sourcesContentByPath[ this.file ];
|
||||
} else {
|
||||
sourcesContentByPath[ this.file ] = this.content;
|
||||
}
|
||||
|
||||
const map = getMap( this, sourceMapByPath, true );
|
||||
let sourcesContent;
|
||||
|
||||
if ( !map ) {
|
||||
this.isOriginalSource = true;
|
||||
} else {
|
||||
this.map = map;
|
||||
this.mappings = decode( map.mappings );
|
||||
|
||||
sourcesContent = map.sourcesContent || [];
|
||||
|
||||
const sourceRoot = resolve( dirname( this.file || '' ), map.sourceRoot || '' );
|
||||
|
||||
this.sources = map.sources.map( ( source, i ) => {
|
||||
const node = new Node({
|
||||
file: resolve( sourceRoot, source ),
|
||||
content: sourcesContent[i]
|
||||
});
|
||||
|
||||
node.loadSync( sourcesContentByPath, sourceMapByPath );
|
||||
return node;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Traces a segment back to its origin
|
||||
* @param {number} lineIndex - the zero-based line index of the
|
||||
segment as found in `this`
|
||||
* @param {number} columnIndex - the zero-based column index of the
|
||||
segment as found in `this`
|
||||
* @param {string || null} - if specified, the name that should be
|
||||
(eventually) returned, as it is closest to the generated code
|
||||
* @returns {object}
|
||||
@property {string} source - the filepath of the source
|
||||
@property {number} line - the one-based line index
|
||||
@property {number} column - the zero-based column index
|
||||
@property {string || null} name - the name corresponding
|
||||
to the segment being traced
|
||||
*/
|
||||
trace ( lineIndex, columnIndex, name ) {
|
||||
// If this node doesn't have a source map, we have
|
||||
// to assume it is the original source
|
||||
if ( this.isOriginalSource ) {
|
||||
return {
|
||||
source: this.file,
|
||||
line: lineIndex + 1,
|
||||
column: columnIndex || 0,
|
||||
name: name
|
||||
};
|
||||
}
|
||||
|
||||
// Otherwise, we need to figure out what this position in
|
||||
// the intermediate file corresponds to in *its* source
|
||||
const segments = this.mappings[ lineIndex ];
|
||||
|
||||
if ( !segments || segments.length === 0 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( columnIndex != null ) {
|
||||
let len = segments.length;
|
||||
let i;
|
||||
|
||||
for ( i = 0; i < len; i += 1 ) {
|
||||
let generatedCodeColumn = segments[i][0];
|
||||
|
||||
if ( generatedCodeColumn > columnIndex ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( generatedCodeColumn === columnIndex ) {
|
||||
if ( segments[i].length < 4 ) return null;
|
||||
|
||||
let sourceFileIndex = segments[i][1];
|
||||
let sourceCodeLine = segments[i][2];
|
||||
let sourceCodeColumn = segments[i][3];
|
||||
let nameIndex = segments[i][4];
|
||||
|
||||
let parent = this.sources[ sourceFileIndex ];
|
||||
return parent.trace( sourceCodeLine, sourceCodeColumn, this.map.names[ nameIndex ] || name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fall back to a line mapping
|
||||
let sourceFileIndex = segments[0][1];
|
||||
let sourceCodeLine = segments[0][2];
|
||||
let nameIndex = segments[0][4];
|
||||
|
||||
let parent = this.sources[ sourceFileIndex ];
|
||||
return parent.trace( sourceCodeLine, null, this.map.names[ nameIndex ] || name );
|
||||
}
|
||||
};
|
||||
|
||||
function getContent ( node, sourcesContentByPath ) {
|
||||
if ( node.file in sourcesContentByPath ) {
|
||||
node.content = sourcesContentByPath[ node.file ];
|
||||
}
|
||||
|
||||
if ( !node.content ) {
|
||||
return readFile( node.file, { encoding: 'utf-8' });
|
||||
}
|
||||
|
||||
return Promise.resolve( node.content );
|
||||
}
|
Reference in New Issue
Block a user