@@ -9,8 +9,10 @@ import R from 'ramda';
99import workerpool from 'workerpool' ;
1010
1111import { getEnv , isNativeSupported } from '@cubejs-backend/shared' ;
12+ import { transpileJs } from '@cubejs-backend/native' ;
1213import { UserError } from './UserError' ;
1314import { ErrorReporter } from './ErrorReporter' ;
15+ import { CONTEXT_SYMBOLS } from './CubeSymbols' ;
1416
1517const NATIVE_IS_SUPPORTED = isNativeSupported ( ) ;
1618
@@ -91,7 +93,10 @@ export class DataSchemaCompiler {
9193 const errorsReport = new ErrorReporter ( null , [ ] , this . errorReport ) ;
9294 this . errorsReport = errorsReport ;
9395
94- if ( getEnv ( 'transpilationWorkerThreads' ) ) {
96+ const transpilationWorkerThreads = getEnv ( 'transpilationWorkerThreads' ) ;
97+ const transpilationNative = getEnv ( 'transpilationNative' ) ;
98+
99+ if ( ! transpilationNative && transpilationWorkerThreads ) {
95100 const wc = getEnv ( 'transpilationWorkerThreadsCount' ) ;
96101 this . workerPool = workerpool . pool (
97102 path . join ( __dirname , 'transpilers/transpiler_worker' ) ,
@@ -101,26 +106,47 @@ export class DataSchemaCompiler {
101106
102107 const transpile = async ( ) => {
103108 let cubeNames ;
104- let cubeSymbolsNames ;
109+ let cubeSymbols ;
110+ let transpilerNames ;
111+ let results ;
105112
106- if ( getEnv ( ' transpilationWorkerThreads' ) ) {
113+ if ( transpilationNative || transpilationWorkerThreads ) {
107114 cubeNames = Object . keys ( this . cubeDictionary . byId ) ;
108115 // We need only cubes and all its member names for transpiling.
109116 // Cubes doesn't change during transpiling, but are changed during compilation phase,
110117 // so we can prepare them once for every phase.
111118 // Communication between main and worker threads uses
112119 // The structured clone algorithm (@see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm)
113120 // which doesn't allow passing any function objects, so we need to sanitize the symbols.
114- cubeSymbolsNames = Object . fromEntries (
121+ cubeSymbols = Object . fromEntries (
115122 Object . entries ( this . cubeSymbols . symbols )
116123 . map (
117124 ( [ key , value ] ) => [ key , Object . fromEntries (
118125 Object . keys ( value ) . map ( ( k ) => [ k , true ] ) ,
119126 ) ] ,
120127 ) ,
121128 ) ;
129+
130+ // Transpilers are the same for all files within phase.
131+ transpilerNames = this . transpilers . map ( t => t . constructor . name ) ;
132+ }
133+
134+ if ( transpilationNative ) {
135+ // Warming up swc compiler cache
136+ const dummyFile = {
137+ fileName : 'dummy.js' ,
138+ content : ';' ,
139+ } ;
140+
141+ await this . transpileJsFile ( dummyFile , errorsReport , { cubeNames, cubeSymbols, transpilerNames, contextSymbols : CONTEXT_SYMBOLS } ) ;
142+
143+ results = await Promise . all ( toCompile . map ( f => this . transpileFile ( f , errorsReport , { transpilerNames } ) ) ) ;
144+ } else if ( transpilationWorkerThreads ) {
145+ results = await Promise . all ( toCompile . map ( f => this . transpileFile ( f , errorsReport , { cubeNames, cubeSymbols, transpilerNames } ) ) ) ;
146+ } else {
147+ results = await Promise . all ( toCompile . map ( f => this . transpileFile ( f , errorsReport , { } ) ) ) ;
122148 }
123- const results = await Promise . all ( toCompile . map ( f => this . transpileFile ( f , errorsReport , { cubeNames , cubeSymbolsNames } ) ) ) ;
149+
124150 return results . filter ( f => ! ! f ) ;
125151 } ;
126152
@@ -133,9 +159,19 @@ export class DataSchemaCompiler {
133159 contextCompilers : this . contextCompilers ,
134160 } ) )
135161 . then ( ( ) => {
136- if ( this . workerPool ) {
162+ if ( transpilationNative ) {
163+ // Clean up cache
164+ const dummyFile = {
165+ fileName : 'terminate.js' ,
166+ content : ';' ,
167+ } ;
168+
169+ return this . transpileJsFile ( dummyFile , errorsReport , { cubeNames : [ ] , cubeSymbols : { } , transpilerNames : [ ] , contextSymbols : { } } ) ;
170+ } else if ( transpilationWorkerThreads && this . workerPool ) {
137171 this . workerPool . terminate ( ) ;
138172 }
173+
174+ return Promise . resolve ( ) ;
139175 } ) ;
140176 }
141177
@@ -177,15 +213,35 @@ export class DataSchemaCompiler {
177213 }
178214 }
179215
180- async transpileJsFile ( file , errorsReport , { cubeNames, cubeSymbolsNames } ) {
216+ async transpileJsFile ( file , errorsReport , { cubeNames, cubeSymbols , contextSymbols , transpilerNames } ) {
181217 try {
182- if ( getEnv ( 'transpilationWorkerThreads' ) ) {
218+ if ( getEnv ( 'transpilationNative' ) ) {
219+ const reqData = {
220+ fileName : file . fileName ,
221+ transpilers : transpilerNames ,
222+ ...( cubeNames && {
223+ metaData : {
224+ cubeNames,
225+ cubeSymbols,
226+ contextSymbols,
227+ } ,
228+ } ) ,
229+ } ;
230+
231+ errorsReport . inFile ( file ) ;
232+ const res = await transpileJs ( file . content , reqData ) ;
233+ errorsReport . addErrors ( res . errors ) ;
234+ errorsReport . addWarnings ( res . warnings ) ;
235+ errorsReport . exitFile ( ) ;
236+
237+ return Object . assign ( { } , file , { content : res . code } ) ;
238+ } else if ( getEnv ( 'transpilationWorkerThreads' ) ) {
183239 const data = {
184240 fileName : file . fileName ,
185241 content : file . content ,
186- transpilers : this . transpilers . map ( t => t . constructor . name ) ,
242+ transpilers : transpilerNames ,
187243 cubeNames,
188- cubeSymbolsNames ,
244+ cubeSymbols ,
189245 } ;
190246
191247 const res = await this . workerPool . exec ( 'transpile' , [ data ] ) ;
@@ -203,11 +259,11 @@ export class DataSchemaCompiler {
203259 } ,
204260 ) ;
205261
262+ errorsReport . inFile ( file ) ;
206263 this . transpilers . forEach ( ( t ) => {
207- errorsReport . inFile ( file ) ;
208264 babelTraverse ( ast , t . traverseObject ( errorsReport ) ) ;
209- errorsReport . exitFile ( ) ;
210265 } ) ;
266+ errorsReport . exitFile ( ) ;
211267
212268 const content = babelGenerator ( ast , { } , file . content ) . code ;
213269 return Object . assign ( { } , file , { content } ) ;
0 commit comments