@@ -6,6 +6,19 @@ const {FuncFiftLibWasm} = require('./wasmlib/funcfiftlib.wasm.js')
6
6
// Prepare binary
7
7
const WasmBinary = base64Decode ( FuncFiftLibWasm )
8
8
9
+ export type SourcesMap = { [ filename : string ] : string }
10
+
11
+ export type SourceResolver = ( path : string ) => string ;
12
+
13
+ export const mapSourceResolver = ( map : SourcesMap ) : SourceResolver => {
14
+ return ( path : string ) => {
15
+ if ( path in map ) {
16
+ return map [ path ] ;
17
+ }
18
+ throw new Error ( 'Cannot find source file ' + path ) ;
19
+ } ;
20
+ } ;
21
+
9
22
/*
10
23
* CompilerConfig example:
11
24
* {
@@ -26,11 +39,9 @@ const WasmBinary = base64Decode(FuncFiftLibWasm)
26
39
* }
27
40
*
28
41
*/
29
- export type SourcesMap = { [ filename : string ] : string }
30
-
31
42
export type CompilerConfig = {
32
43
entryPoints : string [ ] ,
33
- sources : SourcesMap ,
44
+ sources : SourcesMap | SourceResolver ,
34
45
optLevel ?: number
35
46
} ;
36
47
@@ -54,46 +65,85 @@ export type CompilerVersion = {
54
65
funcFiftLibCommitDate : string
55
66
}
56
67
68
+ const copyToCString = ( mod : any , str : string ) => {
69
+ const len = mod . lengthBytesUTF8 ( str ) + 1 ;
70
+ const ptr = mod . _malloc ( len ) ;
71
+ mod . stringToUTF8 ( str , ptr , len ) ;
72
+ return ptr ;
73
+ }
74
+
75
+ const copyToCStringPtr = ( mod : any , str : string , ptr : any ) => {
76
+ const allocated = copyToCString ( mod , str ) ;
77
+ mod . setValue ( ptr , allocated , '*' ) ;
78
+ return allocated ;
79
+ } ;
80
+
81
+ const copyFromCString = ( mod : any , ptr : any ) => {
82
+ return mod . UTF8ToString ( ptr ) ;
83
+ } ;
84
+
57
85
export async function compilerVersion ( ) : Promise < CompilerVersion > {
58
- let mod = await CompilerModule ( { wasmBinary : WasmBinary } ) ;
86
+ const mod = await CompilerModule ( { wasmBinary : WasmBinary } ) ;
59
87
60
- let versionJsonPointer = mod . _version ( ) ;
61
- let versionJson = mod . UTF8ToString ( versionJsonPointer ) ;
88
+ const versionJsonPointer = mod . _version ( ) ;
89
+ const versionJson = copyFromCString ( mod , versionJsonPointer ) ;
62
90
mod . _free ( versionJsonPointer ) ;
63
91
64
92
return JSON . parse ( versionJson ) ;
65
93
}
66
94
67
95
export async function compileFunc ( compileConfig : CompilerConfig ) : Promise < CompileResult > {
68
-
69
- let entryWithNoSource = compileConfig . entryPoints . find ( filename => typeof compileConfig . sources [ filename ] !== 'string' )
96
+ const resolver = typeof compileConfig . sources === 'function' ? compileConfig . sources : mapSourceResolver ( compileConfig . sources ) ;
97
+
98
+ const entryWithNoSource = compileConfig . entryPoints . find ( filename => {
99
+ try {
100
+ resolver ( filename ) ;
101
+ return false ;
102
+ } catch ( e ) {
103
+ return true ;
104
+ }
105
+ } ) ;
70
106
if ( entryWithNoSource ) {
71
107
throw new Error ( `The entry point ${ entryWithNoSource } has not provided in sources.` )
72
108
}
73
109
74
- let mod = await CompilerModule ( { wasmBinary : WasmBinary } ) ;
75
-
76
- // Write sources to virtual FS
77
- for ( let fileName in compileConfig . sources ) {
78
- let source = compileConfig . sources [ fileName ] ;
79
- mod . FS . writeFile ( fileName , source ) ;
80
- }
81
-
82
- let configStr = JSON . stringify ( {
110
+ const mod = await CompilerModule ( { wasmBinary : WasmBinary } ) ;
111
+
112
+ const allocatedPointers = [ ] ;
113
+
114
+ const callbackPtr = mod . addFunction ( ( _kind : any , _data : any , contents : any , error : any ) => {
115
+ const kind : string = copyFromCString ( mod , _kind ) ;
116
+ const data : string = copyFromCString ( mod , _data ) ;
117
+ if ( kind === 'realpath' ) {
118
+ allocatedPointers . push ( copyToCStringPtr ( mod , data , contents ) ) ;
119
+ } else if ( kind === 'source' ) {
120
+ try {
121
+ const source = resolver ( data ) ;
122
+ allocatedPointers . push ( copyToCStringPtr ( mod , source , contents ) ) ;
123
+ } catch ( err ) {
124
+ const e = err as any ;
125
+ allocatedPointers . push ( copyToCStringPtr ( mod , 'message' in e ? e . message : e . toString ( ) , error ) ) ;
126
+ }
127
+ } else {
128
+ allocatedPointers . push ( copyToCStringPtr ( mod , 'Unknown callback kind ' + kind , error ) ) ;
129
+ }
130
+ } , 'viiii' ) ;
131
+
132
+ const configStr = JSON . stringify ( {
83
133
sources : compileConfig . entryPoints ,
84
134
optLevel : compileConfig . optLevel || 2
85
135
} ) ;
86
136
87
- let configStrPointer = mod . _malloc ( configStr . length + 1 ) ;
88
- mod . stringToUTF8 ( configStr , configStrPointer , configStr . length + 1 ) ;
137
+ const configStrPointer = copyToCString ( mod , configStr ) ;
138
+ allocatedPointers . push ( configStrPointer ) ;
89
139
90
- let resultPointer = mod . _func_compile ( configStrPointer ) ;
91
- let retJson = mod . UTF8ToString ( resultPointer ) ;
140
+ const resultPointer = mod . _func_compile ( configStrPointer , callbackPtr ) ;
141
+ allocatedPointers . push ( resultPointer ) ;
142
+ const retJson = copyFromCString ( mod , resultPointer ) ;
92
143
93
144
// Cleanup
94
- mod . _free ( resultPointer ) ;
95
- mod . _free ( configStrPointer ) ;
96
- mod = null
145
+ allocatedPointers . forEach ( ptr => mod . _free ( ptr ) ) ;
146
+ mod . removeFunction ( callbackPtr ) ;
97
147
98
148
return JSON . parse ( retJson ) ;
99
149
}
0 commit comments