11import { CompileBridge , CompileResult } from './CompileBridge' ;
22import { exec , ExecException } from 'child_process' ;
33import { SourceMap } from '../State/SourceMap' ;
4+ import { MappingItem , SourceMapConsumer } from 'source-map' ;
45import * as fs from 'fs' ;
56import { readFileSync } from 'fs' ;
67import { WASMCompilerBridge } from './WASMCompilerBridge' ;
@@ -10,32 +11,20 @@ import * as path from 'path';
1011
1112export class AssemblyScriptCompilerBridge implements CompileBridge {
1213 sourceFilePath : String ;
13- private wat : WASMCompilerBridge ;
1414 private readonly tmpdir : string ;
15+ private readonly wabt : string ;
16+ private readonly workingDir ?: string ;
1517
16- constructor ( sourceFilePath : String , tmpdir : string , wabt : string ) {
18+ constructor ( sourceFilePath : String , tmpdir : string , wabt : string , workingDir ?: string ) {
1719 this . sourceFilePath = sourceFilePath ;
1820 this . tmpdir = tmpdir ;
19- this . wat = new WASMCompilerBridge ( `${ this . tmpdir } /upload.wast` , tmpdir , wabt ) ;
21+ this . wabt = wabt ;
22+ this . workingDir = workingDir ;
2023 }
2124
2225 async compile ( ) : Promise < CompileResult > {
23- return this . wasm ( ) . then ( ( result ) => {
24- return this . lineInformation ( result . sourceMap ) . then ( ( lines ) => {
25- const wasm : Buffer = readFileSync ( `${ this . tmpdir } /upload.wasm` ) ;
26- result . sourceMap . lineInfoPairs = lines ;
27- return Promise . resolve ( { sourceMap : result . sourceMap , wasm : wasm } ) ;
28- } ) ;
29- } ) ;
30- }
31-
32- async clean ( path2makefile : string ) : Promise < void > {
33- return ;
34- }
35-
36- private async wasm ( ) {
3726 return new Promise < void > ( async ( resolve , reject ) => {
38- const command = `cd ${ path . dirname ( this . sourceFilePath . toString ( ) ) } ; ` + await this . getCompilationCommand ( ) ;
27+ const command = await this . getCompilationCommand ( ) ;
3928 let out : String = '' ;
4029 let err : String = '' ;
4130
@@ -53,13 +42,21 @@ export class AssemblyScriptCompilerBridge implements CompileBridge {
5342 }
5443 resolve ( ) ;
5544 } ) ;
56- } ) . then ( ( ) => {
57- return this . wat . compile ( ) ;
45+ } ) . then ( async ( ) => {
46+ const w : Buffer = readFileSync ( `${ this . tmpdir } /upload.wasm` ) ;
47+ return Promise . resolve ( {
48+ sourceMap : await new AsScriptMapper ( this . sourceFilePath . toString ( ) , this . tmpdir , this . wabt ) . mapping ( ) ,
49+ wasm : w
50+ } ) ;
5851 } ) . catch ( ( error ) => {
5952 return Promise . reject ( error ) ;
6053 } ) ;
6154 }
6255
56+ async clean ( path2makefile : string ) : Promise < void > {
57+ return ;
58+ }
59+
6360 // private executeCompileCommand(command: string): Promise<SourceMap> {
6461 // const compiler = this;
6562 // return new Promise(async function (resolve, reject) {
@@ -115,7 +112,7 @@ export class AssemblyScriptCompilerBridge implements CompileBridge {
115112 }
116113 } ) ;
117114
118- return new Promise ( ( resolve , reject ) => {
115+ return new Promise ( ( resolve ) => {
119116 reader . on ( 'close' , ( ) => {
120117 resolve ( mapping ) ;
121118 } ) ;
@@ -124,36 +121,84 @@ export class AssemblyScriptCompilerBridge implements CompileBridge {
124121
125122 private getCompilationCommand ( ) : Promise < string > {
126123 // builds asc command based on the version of asc
127- return new Promise < string > ( ( resolve , reject ) => {
124+ return new Promise < string > ( async ( resolve ) => {
125+ let version : Version = await this . retrieveVersion ( ) ;
126+ resolve ( `${ this . workingDir ? `cd ${ this . workingDir } ; ` : '' } npx asc ${ this . sourceFilePath } --exportTable --disable bulk-memory --sourceMap --debug ` +
127+ `${ ( version . major > 0 || + version . minor >= 20 ) ? '--outFile' : '--binaryFile' } ${ this . tmpdir } /upload.wasm` ) ;
128+ } ) ;
129+ }
130+
131+ private retrieveVersion ( ) : Promise < Version > {
132+ return new Promise < Version > ( ( resolve , reject ) => {
128133 let out : String = '' ;
129134 let err : String = '' ;
135+
130136 function handle ( error : ExecException | null , stdout : String , stderr : any ) {
131137 out = stdout ;
132138 err = error ?. message ?? '' ;
133139 }
134140
135- let compilerVersion = exec ( 'asc --version' , handle ) ;
141+ const command : string = `${ this . workingDir ? `cd ${ this . workingDir } ; ` : '' } npx asc --version` ;
142+ let compilerVersion = exec ( command , handle ) ;
136143 compilerVersion . on ( 'close' , ( code ) => {
137144 if ( code !== 0 ) {
138- reject ( `Compilation to wasm failed: exit code ${ code } . Message : ${ err } ` ) ;
145+ reject ( `asc --version failed: ${ err } ` ) ;
139146 }
140147
141- // build command
142- const versionRegex : RegExp = / ^ V e r s i o n (?< major > [ 0 - 9 ] + ) \. (?< minor > [ 0 - 9 ] + ) \. (?< patch > [ 0 - 9 ] + ) / ;
143- const matched = out . match ( versionRegex ) ;
144- if ( ! matched || ! ! ! matched . groups ?. major || ! ! ! matched . groups ?. minor || ! ! ! matched . groups ?. patch ) {
145- reject ( `Compilation to wasm failed: asc--version did not print expected output format 'Version x.x.x'.Got instead ${ out } ` ) ;
146- }
147- let command = `asc ${ this . sourceFilePath } --exportTable --disable bulk-memory --sourceMap -O3s --debug ` ;
148- if ( + matched ! . groups ! . major > 0 || + matched ! . groups ! . minor >= 20 ) {
149- command += '--outFile ' ;
150- }
151- else {
152- command += '--binaryFile ' ;
148+ const matched = out . match ( / ^ V e r s i o n (?< major > [ 0 - 9 ] + ) \. (?< minor > [ 0 - 9 ] + ) \. (?< patch > [ 0 - 9 ] + ) / ) ;
149+ if ( matched && matched . groups ?. major && matched . groups ?. minor && matched . groups ?. patch ) {
150+ resolve ( { major : + matched . groups . major , minor : + matched . groups . minor , patch : + matched . groups . patch } ) ;
151+ } else {
152+ reject ( `asc --version did not print expected output format 'Version x.x.x'. Got ${ out } instead.` ) ;
153153 }
154- command += `${ this . tmpdir } /upload.wasm --textFile ${ this . tmpdir } /upload.wast` ; // use .wast to get inline sourcemapping
155- resolve ( command ) ;
156154 } ) ;
157155 } ) ;
158156 }
157+ }
158+
159+ interface Version {
160+ major : number ;
161+ minor : number ;
162+ patch : number ;
163+ }
164+
165+ export abstract class SourceMapper {
166+ abstract mapping ( ) : Promise < SourceMap > ;
167+ }
168+
169+ export class AsScriptMapper implements SourceMapper {
170+ private readonly sourceFile : string ;
171+ private readonly tmpdir : string ;
172+ private readonly wabt : string ;
173+
174+ constructor ( sourceFile : string , tmpdir : string , wabt : string ) {
175+ this . sourceFile = sourceFile ;
176+ this . tmpdir = tmpdir ;
177+ this . wabt = wabt ;
178+ }
179+
180+ public mapping ( ) : Promise < SourceMap > {
181+ const input = fs . readFileSync ( `${ this . tmpdir } /upload.wasm.map` ) ;
182+
183+ return new Promise < LineInfoPairs [ ] > ( ( resolve ) => {
184+ new SourceMapConsumer ( input . toString ( ) ) . then ( ( consumer : SourceMapConsumer ) => {
185+ const lineInfoPairs : LineInfoPairs [ ] = [ ] ;
186+ consumer . eachMapping ( function ( item : MappingItem ) {
187+ if ( ! item . source . includes ( '~lib' ) ) {
188+ lineInfoPairs . push ( {
189+ lineInfo : {
190+ line : item . originalLine ,
191+ column : item . originalColumn ,
192+ message : ''
193+ } ,
194+ lineAddress : item . generatedColumn . toString ( 16 )
195+ } ) ;
196+ }
197+ } ) ;
198+ resolve ( lineInfoPairs ) ;
199+ } ) ;
200+ } ) . then ( ( lines : LineInfoPairs [ ] ) => {
201+ return new WASMCompilerBridge ( this . sourceFile , this . tmpdir , this . wabt ) . sourceDump ( lines ) ;
202+ } ) ;
203+ }
159204}
0 commit comments