diff options
Diffstat (limited to 'js/compiler.ts')
-rw-r--r-- | js/compiler.ts | 135 |
1 files changed, 90 insertions, 45 deletions
diff --git a/js/compiler.ts b/js/compiler.ts index 41f23bcd2..1e1fe3dd3 100644 --- a/js/compiler.ts +++ b/js/compiler.ts @@ -136,18 +136,25 @@ function fetchAsset(name: string): string { return sendSync(dispatch.OP_FETCH_ASSET, { name }); } -/** Ops to Rust to resolve and fetch a modules meta data. */ -function fetchSourceFile(specifier: string, referrer: string): SourceFile { - util.log("compiler.fetchSourceFile", { specifier, referrer }); - const res = sendSync(dispatch.OP_FETCH_SOURCE_FILE, { - specifier, +/** Ops to Rust to resolve and fetch modules meta data. */ +function fetchSourceFiles( + specifiers: string[], + referrer: string +): SourceFile[] { + util.log("compiler.fetchSourceFiles", { specifiers, referrer }); + const res = sendSync(dispatch.OP_FETCH_SOURCE_FILES, { + specifiers, referrer }); - return { - ...res, - typeDirectives: parseTypeDirectives(res.sourceCode) - }; + return res.map( + (sourceFile: SourceFile): SourceFile => { + return { + ...sourceFile, + typeDirectives: parseTypeDirectives(sourceFile.sourceCode) + }; + } + ); } /** Utility function to turn the number of bytes into a human readable @@ -219,34 +226,69 @@ class Host implements ts.CompilerHost { private _sourceFileCache: Record<string, SourceFile> = {}; + private _getAsset(specifier: string): SourceFile { + const moduleName = specifier.split("/").pop()!; + if (moduleName in this._sourceFileCache) { + return this._sourceFileCache[moduleName]; + } + const assetName = moduleName.includes(".") + ? moduleName + : `${moduleName}.d.ts`; + const sourceCode = fetchAsset(assetName); + const sourceFile = { + moduleName, + filename: specifier, + mediaType: MediaType.TypeScript, + sourceCode + }; + this._sourceFileCache[moduleName] = sourceFile; + return sourceFile; + } + private _resolveModule(specifier: string, referrer: string): SourceFile { - util.log("host._resolveModule", { specifier, referrer }); - // Handle built-in assets specially. - if (specifier.startsWith(ASSETS)) { - const moduleName = specifier.split("/").pop()!; - if (moduleName in this._sourceFileCache) { - return this._sourceFileCache[moduleName]; + return this._resolveModules([specifier], referrer)[0]; + } + + private _resolveModules( + specifiers: string[], + referrer: string + ): SourceFile[] { + util.log("host._resolveModules", { specifiers, referrer }); + const resolvedModules: Array<SourceFile | undefined> = []; + const modulesToRequest = []; + + for (const specifier of specifiers) { + // Firstly built-in assets are handled specially, so they should + // be removed from array of files that we'll be requesting from Rust. + if (specifier.startsWith(ASSETS)) { + const assetFile = this._getAsset(specifier); + resolvedModules.push(assetFile); + } else if (specifier in this._sourceFileCache) { + const module = this._sourceFileCache[specifier]; + resolvedModules.push(module); + } else { + // Temporarily fill with undefined, after fetching file from + // Rust it will be filled with proper value. + resolvedModules.push(undefined); + modulesToRequest.push(specifier); } - const assetName = moduleName.includes(".") - ? moduleName - : `${moduleName}.d.ts`; - const sourceCode = fetchAsset(assetName); - const sourceFile = { - moduleName, - filename: specifier, - mediaType: MediaType.TypeScript, - sourceCode - }; - this._sourceFileCache[moduleName] = sourceFile; - return sourceFile; } - const sourceFile = fetchSourceFile(specifier, referrer); - assert(sourceFile.moduleName != null); - const { moduleName } = sourceFile; - if (!(moduleName! in this._sourceFileCache)) { - this._sourceFileCache[moduleName!] = sourceFile; + + // Now get files from Rust. + const sourceFiles = fetchSourceFiles(modulesToRequest, referrer); + + for (const sourceFile of sourceFiles) { + assert(sourceFile.moduleName != null); + const { moduleName } = sourceFile; + if (!(moduleName! in this._sourceFileCache)) { + this._sourceFileCache[moduleName!] = sourceFile; + } + // And fill temporary `undefined`s with actual files. + const index = resolvedModules.indexOf(undefined); + resolvedModules[index] = sourceFile; } - return sourceFile; + + return resolvedModules as SourceFile[]; } /* Deno specific APIs */ @@ -371,22 +413,25 @@ class Host implements ts.CompilerHost { containingFile in this._sourceFileCache ? this._sourceFileCache[containingFile].typeDirectives : undefined; - return moduleNames.map( - (moduleName): ts.ResolvedModuleFull | undefined => { - const mappedModuleName = getMappedModuleName( - moduleName, - containingFile, - typeDirectives - ); - const sourceFile = this._resolveModule( - mappedModuleName, - containingFile - ); + + const mappedModuleNames = moduleNames.map( + (moduleName: string): string => { + return getMappedModuleName(moduleName, containingFile, typeDirectives); + } + ); + + return this._resolveModules(mappedModuleNames, containingFile).map( + ( + sourceFile: SourceFile, + index: number + ): ts.ResolvedModuleFull | undefined => { if (sourceFile.moduleName) { const resolvedFileName = sourceFile.moduleName; // This flags to the compiler to not go looking to transpile functional // code, anything that is in `/$asset$/` is just library code - const isExternalLibraryImport = moduleName.startsWith(ASSETS); + const isExternalLibraryImport = mappedModuleNames[index].startsWith( + ASSETS + ); const extension = getExtension( resolvedFileName, sourceFile.mediaType |