import * as assert from 'assert' ; import * as path from 'path' ; import * as fs from 'fs' ; import * as MozSourceMap from 'source-map' ; import * as testUtils from '../testUtils' ; import { SourceMap } from '../../src/sourceMaps/sourceMap' ; import { ISourceMapPathOverrides } from '../../src/debugAdapterInterfaces' ; /**
 * Unit tests for SourceMap + source-map (the mozilla lib). source-map is included in the test and not mocked
 */ suite ( 'SourceMap' , ( ) => { const GENERATED_PATH = testUtils . pathResolve ( '/project/src/app.js' ) ; const WEBROOT = testUtils . pathResolve ( '/project' ) ; const PATH_MAPPING = { '/' : WEBROOT } ; const SOURCEROOT = '/src/' ; const SOURCES = [ 'source1.ts' , 'source2.ts' ] ; const ABSOLUTE_SOURCES = SOURCES . map ( source => { return testUtils . pathResolve ( path . join ( WEBROOT , SOURCEROOT , source ) ) ; } ) ; const SOURCEMAP_MAPPINGS_JSON = fs . readFileSync ( path . resolve ( __dirname , 'testData/app.js.map' ) ) . toString ( ) ; setup ( ( ) => { testUtils . setupUnhandledRejectionListener ( ) ; } ) ; teardown ( ( ) => { testUtils . removeUnhandledRejectionListener ( ) ; } ) ; suite ( 'constructor' , ( ) => { test ( 'does not crash when sourceRoot is undefined' , ( ) => { const sourceMapJSON = getMockSourceMapJSON ( SOURCES , undefined ) ; const sm = new SourceMap ( GENERATED_PATH , sourceMapJSON , PATH_MAPPING ) ; assert ( sm ) ; } ) ; } ) ; suite ( '.sources' , ( ) => { test ( 'relative sources are made absolute' , ( ) => { const sourceMapJSON = getMockSourceMapJSON ( SOURCES , SOURCEROOT ) ; const sm = new SourceMap ( GENERATED_PATH , sourceMapJSON , PATH_MAPPING ) ; assert . deepEqual ( sm . authoredSources , ABSOLUTE_SOURCES ) ; } ) ; test ( 'sources with absolute paths are used as-is' , ( ) => { const sourceMapJSON = getMockSourceMapJSON ( ABSOLUTE_SOURCES , SOURCEROOT ) ; const sm = new SourceMap ( GENERATED_PATH , sourceMapJSON , PATH_MAPPING ) ; assert . deepEqual ( sm . authoredSources , ABSOLUTE_SOURCES ) ; } ) ; test ( 'file:/// sources are exposed as absolute paths' , ( ) => { const fileSources = ABSOLUTE_SOURCES . map ( source => 'file:///' + source ) ; const sourceMapJSON = getMockSourceMapJSON ( fileSources , SOURCEROOT ) ; const sm = new SourceMap ( GENERATED_PATH , sourceMapJSON , PATH_MAPPING ) ; assert . deepEqual ( sm . authoredSources , ABSOLUTE_SOURCES ) ; } ) ; test ( 'sourceMapPathOverrides are respected' , ( ) => { const sourceMapJSON = getMockSourceMapJSON ( SOURCES , SOURCEROOT ) ; const sm = new SourceMap ( GENERATED_PATH , sourceMapJSON , PATH_MAPPING , < ISourceMapPathOverrides > { '/src/*' : testUtils . pathResolve ( '/project/client/*' ) } ) ; const expectedSources = SOURCES . map ( sourcePath => path . join ( testUtils . pathResolve ( '/project/client' ) , sourcePath ) ) ; assert . deepEqual ( sm . authoredSources , expectedSources ) ; } ) ; } ) ; suite ( 'doesOriginateFrom' , ( ) => { test ( 'returns true for a source that it contains' , ( ) => { const sourceMapJSON = getMockSourceMapJSON ( ABSOLUTE_SOURCES , SOURCEROOT ) ; const sm = new SourceMap ( GENERATED_PATH , sourceMapJSON , PATH_MAPPING ) ; assert ( sm . doesOriginateFrom ( ABSOLUTE_SOURCES [ 0 ] ) ) ; } ) ; test ( 'returns false for a source that it does not contain' , ( ) => { const sourceMapJSON = getMockSourceMapJSON ( ABSOLUTE_SOURCES , SOURCEROOT ) ; const sm = new SourceMap ( GENERATED_PATH , sourceMapJSON , PATH_MAPPING ) ; assert ( ! sm . doesOriginateFrom ( 'c:\\fake\\file.js' ) ) ; } ) ; } ) ; suite ( 'originalPositionFor' , ( ) => { let sm ; setup ( ( ) => { sm = new SourceMap ( GENERATED_PATH , SOURCEMAP_MAPPINGS_JSON , PATH_MAPPING ) ; } ) ; function getExpectedResult ( line , column , source = ABSOLUTE_SOURCES [ 0 ] ) { return { line , column , name : null , source } ; } test ( 'return statement' , ( ) => { assert . deepEqual ( sm . authoredPositionFor ( 11 , 0 ) , getExpectedResult ( 13 , 8 ) ) ; assert . deepEqual ( sm . authoredPositionFor ( 11 , 8 ) , getExpectedResult ( 13 , 8 ) ) ; assert . deepEqual ( sm . authoredPositionFor ( 11 , 17 ) , getExpectedResult ( 13 , 17 ) ) ; } ) ; test ( 'first line of a method' , ( ) => { assert . deepEqual ( sm . authoredPositionFor ( 9 , 0 ) , getExpectedResult ( 11 , 8 ) ) ; assert . deepEqual ( sm . authoredPositionFor ( 9 , 8 ) , getExpectedResult ( 11 , 8 ) ) ; assert . deepEqual ( sm . authoredPositionFor ( 9 , 12 ) , getExpectedResult ( 11 , 12 ) ) ; } ) ; test ( 'private field initializer' , ( ) => { assert . deepEqual ( sm . authoredPositionFor ( 5 , 0 ) , getExpectedResult ( 4 , 12 ) ) ; assert . deepEqual ( sm . authoredPositionFor ( 5 , 4 ) , getExpectedResult ( 4 , 12 ) ) ; assert . deepEqual ( sm . authoredPositionFor ( 5 , 17 ) , getExpectedResult ( 4 , 14 ) ) ; } ) ; test ( 'first line of file' , ( ) => { const expected = getExpectedResult ( 0 , 0 , ABSOLUTE_SOURCES [ 1 ] ) ; assert . deepEqual ( sm . authoredPositionFor ( 18 , 0 ) , expected ) ; assert . deepEqual ( sm . authoredPositionFor ( 18 , 9 ) , expected ) ; assert . deepEqual ( sm . authoredPositionFor ( 18 , 14 ) , expected ) ; } ) ; test ( 'last line of file' , ( ) => { assert . deepEqual ( sm . authoredPositionFor ( 22 , 0 ) , getExpectedResult ( 5 , 0 , ABSOLUTE_SOURCES [ 1 ] ) ) ; assert . deepEqual ( sm . authoredPositionFor ( 22 , 1 ) , getExpectedResult ( 5 , 1 , ABSOLUTE_SOURCES [ 1 ] ) ) ; assert . deepEqual ( sm . authoredPositionFor ( 22 , 5 ) , getExpectedResult ( 5 , 4 , ABSOLUTE_SOURCES [ 1 ] ) ) ; } ) ; test ( 'return null when there is no matching mapping' , ( ) => { assert . deepEqual ( sm . authoredPositionFor ( 1000 , 0 ) , null ) ; } ) ; } ) ; suite ( 'generatedPositionFor' , ( ) => { let sm ; setup ( ( ) => { sm = new SourceMap ( GENERATED_PATH , SOURCEMAP_MAPPINGS_JSON , PATH_MAPPING ) ; } ) ; function getExpectedResult ( line , column ) { return < any > { line , column , source : GENERATED_PATH } ; } test ( 'return statement' , ( ) => { assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 13 , 0 ) , getExpectedResult ( 11 , 8 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 13 , 8 ) , getExpectedResult ( 11 , 8 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 13 , 17 ) , getExpectedResult ( 11 , 17 ) ) ; } ) ; test ( 'first line of a method' , ( ) => { assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 11 , 0 ) , getExpectedResult ( 9 , 8 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 11 , 8 ) , getExpectedResult ( 9 , 8 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 11 , 19 ) , getExpectedResult ( 9 , 20 ) ) ; } ) ; test ( 'private field initializer' , ( ) => { assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 4 , 0 ) , getExpectedResult ( 5 , 8 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 4 , 4 ) , getExpectedResult ( 5 , 8 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 4 , 20 ) , getExpectedResult ( 5 , 18 ) ) ; } ) ; test ( 'first line of file' , ( ) => { assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 1 ] , 0 , 0 ) , getExpectedResult ( 18 , 0 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 1 ] , 0 , 1 ) , getExpectedResult ( 19 , 4 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 1 ] , 0 , 14 ) , getExpectedResult ( 19 , 4 ) ) ; } ) ; test ( 'last line of file' , ( ) => { assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 1 ] , 5 , 0 ) , getExpectedResult ( 22 , 0 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 1 ] , 5 , 1 ) , getExpectedResult ( 22 , 1 ) ) ; assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 1 ] , 5 , 5 ) , getExpectedResult ( 22 , 4 ) ) ; } ) ; test ( 'returns the last mapping when there is no matching mapping' , ( ) => { assert . deepEqual ( sm . generatedPositionFor ( ABSOLUTE_SOURCES [ 0 ] , 1000 , 0 ) , getExpectedResult ( 17 , 1 ) ) ; } ) ; } ) ; } ) ; function getMockSourceMapJSON ( sources , sourceRoot ? ) { return JSON . stringify ( { sources , sourceRoot , version : 3 , mappings : [ ] } ) ; }